web-csv-toolbox 0.0.0-next-20231225182210 → 0.0.0-next-20231227082102

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 (4) hide show
  1. package/README.md +117 -64
  2. package/lib/index.d.ts +496 -23
  3. package/lib/index.js +33 -201
  4. package/package.json +5 -4
package/README.md CHANGED
@@ -1,38 +1,73 @@
1
- # web-csv-toolbox
1
+ <div align="center">
2
+
3
+ [![Node.js CI](https://github.com/kamiazya/web-csv-toolbox/actions/workflows/node.js.yaml/badge.svg)](https://github.com/kamiazya/web-csv-toolbox/actions/workflows/node.js.yaml)
4
+ [![npm version](https://badge.fury.io/js/web-csv-toolbox.svg)](https://badge.fury.io/js/web-csv-toolbox)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
7
+ ![node version](https://img.shields.io/node/v/web-csv-toolbox)
8
+ ![npm](https://img.shields.io/npm/dm/web-csv-toolbox)
9
+
10
+ # `🌐 web-csv-toolbox 💽`
2
11
 
3
12
  A CSV Toolbox utilizing Web Standard APIs.
4
13
 
5
- ## Key Concepts
14
+ 🔗
6
15
 
7
- - Web Standards first.
8
- - Using the [Web Streams API](https://streams.spec.whatwg.org/).
9
- - TypeScript friendly & User friendly.
10
- - Fully typed and documented.
11
- - Zero dependencies.
12
- - Using only Web Standards APIs.
13
- - Property-based testing.
14
- - Using [fast-check](https://fast-check.dev/) and [vitest](https://vitest.dev).
15
- - **To Be Tested** Cross platform.
16
- - Works on browsers and Node.js, Deno
17
- - Only web standard APIs are used, so it should work with these Runtimes.
16
+ [![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=GitHub&style=flat)](https://github.com/kamiazya/web-csv-toolbox)
17
+ [![npm](https://img.shields.io/badge/-npm-CB3837?logo=npm&style=flat)](https://www.npmjs.com/package/web-csv-toolbox)
18
+ [![yarn](https://img.shields.io/badge/-yarn-ffffff?logo=Yarn&style=flat)](https://yarnpkg.com/package/web-csv-toolbox)
19
+ [![API Reference](https://img.shields.io/badge/-API%20Refarence-3178C6?logo=TypeScript&style=flat&logoColor=fff)](https://kamiazya.github.io/web-csv-toolbox/)
20
+ [![Sponsor](https://img.shields.io/badge/-GitHub%20Sponsor-fff?logo=GitHub%20Sponsors&style=flat)](https://github.com/sponsors/kamiazya)
21
+
22
+
23
+ [![format: Biome](https://img.shields.io/badge/format%20with-Biome-F7B911?logo=biome&style=flat)](https://biomejs.dev/)
24
+ [![test: Vitest](https://img.shields.io/badge/tested%20with-Vitest-6E9F18?logo=vitest&style=flat)](https://vitest.dev/)
25
+ [![build: Rollup](https://img.shields.io/badge/build%20with-Rollup-EC4A3F?logo=rollup.js&style=flat)](https://rollupjs.org/)
18
26
 
19
- ## Key Features
27
+ </div>
20
28
 
21
- - Parses CSV files using the [WHATWG Streams API](https://streams.spec.whatwg.org/).
22
- - Supports parsing CSV files from strings, `ReadableStream`s, and `Response` objects.
23
- - Supports parsing CSV files with different delimiters and quotation characters.
24
- - Defaults to `,` and `"` respectively.
25
- - Supports parsing TSV files by setting `delimiter` to `\t`.
26
- - Supports parsing with multi-character/multi-byte delimiters and quotation characters.
27
- - Supports parsing binary CSV files.
29
+ ---
28
30
 
29
- ## Installation
31
+ ## Key Concepts ✨
32
+
33
+ - 🌐 **Web Standards first.**
34
+ - Utilizing the Web Standards APIs, such as the [Web Streams API](https://developer.mozilla.org/en/docs/Web/API/Streams_API).
35
+ - ❤️ **TypeScript friendly & User friendly.**
36
+ - Fully typed and documented.
37
+ - 0️⃣ **Zero dependencies.**
38
+ - Using only Web Standards APIs.
39
+ - 💪 **Property-based testing.**
40
+ - Using [fast-check](https://fast-check.dev/) and [vitest](https://vitest.dev).
41
+ - ✅ **_To Be Tested_** **Cross-platform.**
42
+ - Works on browsers, Node.js, and Deno.
43
+ - Only web standard APIs are used, so it should work with these runtimes.
44
+
45
+ ## Key Features 📗
46
+
47
+ - 🌊 **Efficient CSV Parsing with Streams**
48
+ - 💻 Leveraging the [WHATWG Streams API](https://streams.spec.whatwg.org/) and other Web APIs for seamless and efficient data processing.
49
+ - 🎨 **Flexible Source Support**
50
+ - 🧩 Parse CSVs directly from `string`s, `ReadableStream`s, or `Response` objects.
51
+ - ⚙️ **Advanced Parsing Options**: Customize your experience with various delimiters and quotation marks.
52
+ - 🔄 Defaults to `,` and `"` respectively.
53
+ - 🛠️ Use multi-character/multi-byte delimiters and quotations.
54
+ - 💾 **Specialized Binary CSV Parsing**: Leverage Stream-based processing for versatility and strength.
55
+ - 🔄 Flexible BOM handling.
56
+ - 🗜️ Supports various compression formats.
57
+ - 🔤 Charset specification for diverse encoding.
58
+
59
+ ## Installation 📥
30
60
 
31
61
  ```sh
32
- npm install web-csv-toolbox
62
+ # Install with npm
63
+ $ npm install web-csv-toolbox
64
+ # Or Yarn
65
+ $ yarn add web-csv-toolbox
66
+ # Or pnpm
67
+ $ pnpm add web-csv-toolbox
33
68
  ```
34
69
 
35
- ## Usage
70
+ ## Usage 📘
36
71
 
37
72
  ### Parsing CSV files from strings
38
73
 
@@ -107,7 +142,7 @@ for await (const record of parse(csv, { delimiter: '\t' })) {
107
142
  // { name: 'Bob', age: '69' }
108
143
  ```
109
144
 
110
- ### Parsing CSV files with different headers
145
+ ### Parsing CSV files with headers
111
146
 
112
147
  ```js
113
148
  import { parse } from 'web-csv-toolbox';
@@ -123,69 +158,87 @@ for await (const record of parse(csv, { headers: ['name', 'age'] })) {
123
158
  // { name: 'Bob', age: '69' }
124
159
  ```
125
160
 
126
- ## APIs
127
-
128
- ### High-level APIs
129
-
130
- #### `parse(input[, options]): AsyncIterableIterator<Record>` function
131
-
132
- Returns an asynchronous iterable of records.
161
+ ## APIs 🧑‍💻
133
162
 
134
- ##### `input` parameter
163
+ ### High-level APIs 🚀
135
164
 
136
- The input to parse. This can be a `string`, a `ReadableStream` of `string`s or `Uint8Array`s, or a `Response` object.
165
+ These APIs are designed for **Simplicity and Ease of Use**,
166
+ providing an intuitive and straightforward experience for users.
137
167
 
138
- ##### `options` parameter
168
+ - **`function parse(input[, options]): AsyncIterableIterator<CSVRecord>`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parse-1.html)
169
+ - Parses various CSV input formats into an asynchronous iterable of records.
170
+ - **`function parse.toArray(input[, options]): Promise<CSVRecord[]>`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parse.toArray.html)
171
+ - Parses CSV input into an array of records, ideal for smaller data sets.
139
172
 
140
- An optional object with the following properties:
173
+ The `input` paramater can be a `string`, a [ReadableStream](https://developer.mozilla.org/docs/Web/API/ReadableStream)
174
+ of `string`s or [Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)s,
175
+ or a [Response](https://developer.mozilla.org/docs/Web/API/Response) object.
141
176
 
142
- ###### `options.delimiter`
177
+ ### Middle-level APIs 🧱
143
178
 
144
- The character used to separate fields in the CSV input. Defaults to `,`.
179
+ These APIs are optimized for **Enhanced Performance and Control**,
180
+ catering to users who need more detailed and fine-tuned functionality.
145
181
 
146
- ###### `options.quotation`
182
+ - **`function parseBinaryStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseBinaryStream-1.html)
183
+ - Parses binary streams with precise control over data types.
184
+ - **`function parseResponse(response[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseResponse-1.html)
185
+ - Customized parsing directly from `Response` objects.
186
+ - **`function parseStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStream-1.html)
187
+ - Stream-based parsing for larger or continuous data.
188
+ - **`function parseString(string[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseString-1.html)
189
+ - Efficient parsing of CSV strings.
190
+ - **`function parseStringStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStringStream-1.html)
191
+ - Combines string-based parsing with stream processing.
147
192
 
148
- The character used to quote fields in the CSV input. Defaults to `"`.
193
+ ### Low-level APIs ⚙️
149
194
 
150
- ###### `options.headers`
195
+ These APIs are built for **Advanced Customization and Pipeline Design**,
196
+ ideal for developers looking for in-depth control and flexibility.
151
197
 
152
- An optional array of strings to use as the headers for the parsed records.
198
+ - **`class LexerTransformer`**: [📑](https://kamiazya.github.io/web-csv-toolbox/classes/LexerTransformer.html)
199
+ - A TransformStream class for lexical analysis of CSV data.
200
+ - **`class RecordAssemblerTransformer`**: [📑](https://kamiazya.github.io/web-csv-toolbox/classes/RecordAssemblerTransformar.html)
201
+ - Handles the assembly of parsed data into records.
153
202
 
154
- If not provided, the first record will be used as the headers.
203
+ ## Options Configuration 🛠️
155
204
 
156
- ###### `options.decompression`
205
+ ### Common Options ⚙️
157
206
 
158
- The decompression format to use when parsing the binary CSV input.
207
+ | Option | Description | Default | Notes |
208
+ | -------------- | ------------------------------------- | ----------- | ----- |
209
+ | `delimiter` | Character to separate fields | `,` | |
210
+ | `quotation` | Character used for quoting fields | `"` | |
211
+ | `headers` | Custom headers for the parsed records | First row | If not provided, the first row is used as headers |
159
212
 
160
- If not provided, the input will be treated as text.
213
+ ### Advanced Options (Binary-Specific) 🧬
161
214
 
162
- Possible values are:
215
+ | Option | Description | Default | Notes |
216
+ | --------------- | ------------------------------------------------- | --------- | ---------------------- |
217
+ | `charset` | Character encoding for binary CSV inputs | `utf-8` | See [Encoding API Compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings) for the encoding formats that can be specified. |
218
+ | `decompression` | Decompression algorithm for compressed CSV inputs | | See [DecompressionStream Compatibility](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream#browser_compatibilit). |
219
+ | `ignoreBOM` | Whether to ignore Byte Order Mark (BOM) | `false` | See [TextDecoderOptions.ignoreBOM](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream/ignoreBOM) for more information about the BOM. |
220
+ | `fatal` | Throw an error on invalid characters | `false` | See [TextDecoderOptions.fatal](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream/fatal) for more information. |
163
221
 
164
- - `gzip`
165
- - `deflate`
166
- - `deflate-raw`
167
- - Note: This format is supported in Node.js v21.2.0 and above.
222
+ ## How to Contribute 💪
168
223
 
169
- ###### `options.charset`
224
+ ## Star ⭐
170
225
 
171
- The character set to use when parsing the binary CSV input.
226
+ The easiest way to contribute is to use the library and star [repository](https://github.com/kamiazya/web-csv-toolbox/).
172
227
 
173
- Defaults to `utf-8`.
228
+ ### Questions 💭
174
229
 
175
- ###### `options.ignoreBOM`
230
+ Feel free to ask questions on [GitHub Discussions](https://github.com/kamiazya/web-csv-toolbox/discussions).
176
231
 
177
- Whether to ignore a leading BOM in the CSV input.
178
- Defaults to `false`.
232
+ ### Report bugs / request additional features 💡
179
233
 
180
- ###### `options.fatal`
234
+ Please register at [GitHub Issues](https://github.com/kamiazya/web-csv-toolbox/issues/new/choose).
181
235
 
182
- Whether to throw an error if the CSV input is invalid.
183
- Defaults to `false`.
236
+ ### Financial Support 💸
184
237
 
185
- ### Low-level APIs
238
+ Please support [kamiazya](https://github.com/sponsors/kamiazya).
186
239
 
187
- For low-level API details, please refer to [source code](https://github.com/kamiazya/web-csv-toolbox).
240
+ > Even just a dollar is enough motivation to develop 😊
188
241
 
189
- ## License
242
+ ## License ⚖️
190
243
 
191
- [MIT](./LICENSE)
244
+ This software is released under the MIT License, see [LICENSE](https://github.com/kamiazya/web-csv-toolbox?tab=MIT-1-ov-file).
package/lib/index.d.ts CHANGED
@@ -1,19 +1,23 @@
1
1
  /**
2
2
  * FiledDelimiter is a symbol for field delimiter of CSV.
3
+ * @category Constants
3
4
  */
4
5
  declare const FieldDelimiter: unique symbol;
5
6
  /**
6
7
  * RecordDelimiter is a symbol for record delimiter of CSV.
8
+ * @category Constants
7
9
  */
8
10
  declare const RecordDelimiter: unique symbol;
9
11
  /**
10
12
  * Field is a symbol for field of CSV.
13
+ * @category Constants
11
14
  */
12
15
  declare const Field: unique symbol;
13
16
 
14
17
  /**
15
18
  * Token is a atomic unit of a CSV file.
16
19
  * It can be a field, field delimiter, or record delimiter.
20
+ * @category Types
17
21
  *
18
22
  * @example
19
23
  * ```ts
@@ -28,10 +32,12 @@ interface Token<T extends TokenType = TokenType> {
28
32
  }
29
33
  /**
30
34
  * Type of a token for CSV.
35
+ * @category Types
31
36
  */
32
37
  type TokenType = typeof FieldDelimiter | typeof RecordDelimiter | typeof Field;
33
38
  /**
34
39
  * CSV Common Options.
40
+ * @category Types
35
41
  */
36
42
  interface CommonOptions {
37
43
  /**
@@ -56,6 +62,7 @@ interface CommonOptions {
56
62
  }
57
63
  /**
58
64
  * CSV Parsing Options for binary.
65
+ * @category Types
59
66
  */
60
67
  interface BinaryOptions {
61
68
  /**
@@ -64,6 +71,7 @@ interface BinaryOptions {
64
71
  *
65
72
  * @remarks
66
73
  * Make sure the runtime you are running supports stream decompression.
74
+ *
67
75
  * See {@link https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream#browser_compatibility | DecompressionStream Compatibility}.
68
76
  */
69
77
  decomposition?: CompressionFormat;
@@ -71,7 +79,8 @@ interface BinaryOptions {
71
79
  * You can specify the character encoding of the binary.
72
80
  *
73
81
  * @remarks
74
- * {@link TextDecoderStream} is used internally.
82
+ * {@link !TextDecoderStream} is used internally.
83
+ *
75
84
  * See {@link https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings | Encoding API Compatibility}
76
85
  * for the encoding formats that can be specified.
77
86
  *
@@ -92,14 +101,21 @@ interface BinaryOptions {
92
101
  * If the binary has a invalid character, you can specify whether to throw an error.
93
102
  *
94
103
  * @remarks
95
- * If you specify true, an error will be thrown.
96
- * If you specify false or not specify it, the invalid character will be replaced with `U+FFFD`.
97
- * See {@link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream/fatal | TextDecoderOptions.fatal} for more information about the invalid character.
104
+ * If the property is `true` then a decoder will throw a {@link !TypeError}
105
+ * if it encounters malformed data while decoding.
106
+ *
107
+ * If `false` the decoder will substitute the invalid data
108
+ * with the replacement character `U+FFFD` (�).
109
+ *
110
+ * See {@link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream/fatal | TextDecoderOptions.fatal} for more information.
111
+ *
112
+ * @default false
98
113
  */
99
114
  fatal?: boolean;
100
115
  }
101
116
  /**
102
117
  * Record Assembler Options for CSV.
118
+ * @category Types
103
119
  *
104
120
  * @remarks
105
121
  * If you specify `header: ['foo', 'bar']`,
@@ -125,18 +141,21 @@ interface RecordAssemblerOptions<Header extends ReadonlyArray<string>> {
125
141
  }
126
142
  /**
127
143
  * Parse options for CSV string.
144
+ * @category Types
128
145
  */
129
146
  interface ParseOptions<Header extends ReadonlyArray<string>>
130
147
  extends CommonOptions,
131
148
  RecordAssemblerOptions<Header> {}
132
149
  /**
133
150
  * Parse options for CSV binary.
151
+ * @category Types
134
152
  */
135
153
  interface ParseBinaryOptions<Header extends ReadonlyArray<string>>
136
154
  extends ParseOptions<Header>,
137
155
  BinaryOptions {}
138
156
  /**
139
157
  * CSV Record.
158
+ * @category Types
140
159
  * @template Header Header of the CSV.
141
160
  *
142
161
  * @example Header is ["foo", "bar"]
@@ -155,6 +174,8 @@ type CSVRecord<Header extends ReadonlyArray<string>> = Record<
155
174
  /**
156
175
  * A transform stream that converts a stream of tokens into a stream of rows.
157
176
  *
177
+ * @category Low-level API
178
+ *
158
179
  * @example Parse a CSV with headers by data
159
180
  * ```ts
160
181
  * new ReadableStream({
@@ -189,6 +210,8 @@ declare class LexerTransformer extends TransformStream<string, Token> {
189
210
  * @template Header The type of the header row.
190
211
  * @param options The options for the parser.
191
212
  *
213
+ * @category Low-level API
214
+ *
192
215
  * @example Parse a CSV with headers by data
193
216
  * ```ts
194
217
  * new ReadableStream({
@@ -235,16 +258,55 @@ declare class RecordAssemblerTransformar<
235
258
  /**
236
259
  * Parse CSV string to records.
237
260
  *
261
+ * @category Middle-level API
238
262
  * @param csv CSV string to parse
239
263
  * @param options Parsing options. See {@link ParseOptions}.
264
+ * @returns Async iterable iterator of records.
265
+ *
266
+ * If you want array of records, use {@link parseString.toArray} function.
267
+ * @example Parsing CSV files from strings
268
+ *
269
+ * ```ts
270
+ * import { parseString } from 'web-csv-toolbox';
271
+ *
272
+ * const csv = `name,age
273
+ * Alice,42
274
+ * Bob,69`;
275
+ *
276
+ * for await (const record of parseString(csv)) {
277
+ * console.log(record);
278
+ * }
279
+ * // Prints:
280
+ * // { name: 'Alice', age: '42' }
281
+ * // { name: 'Bob', age: '69' }
282
+ * ```
240
283
  */
241
- declare function streamingParse<Header extends ReadonlyArray<string>>(
284
+ declare function parseString<Header extends ReadonlyArray<string>>(
242
285
  csv: string,
243
286
  options?: ParseOptions<Header>,
244
287
  ): AsyncIterableIterator<CSVRecord<Header>>;
245
- declare namespace streamingParse {
288
+ declare namespace parseString {
289
+ /**
290
+ * Parse CSV string to records.
291
+ *
292
+ * @returns Array of records
293
+ *
294
+ * @example
295
+ * ```ts
296
+ * import { parseString } from 'web-csv-toolbox';
297
+ *
298
+ * const csv = `name,age
299
+ * Alice,42
300
+ * Bob,69`;
301
+ *
302
+ * const records = await parseString.toArray(csv);
303
+ * console.log(records);
304
+ * // Prints:
305
+ * // [ { name: 'Alice', age: '42' }, { name: 'Bob', age: '69' } ]
306
+ * ```
307
+ */
246
308
  function toArray<Header extends ReadonlyArray<string>>(
247
- stream: ReadableStream<Uint8Array>,
309
+ csv: string,
248
310
  options?: ParseOptions<Header>,
249
311
  ): Promise<CSVRecord<Header>[]>;
250
312
  }
@@ -253,16 +315,66 @@ declare namespace streamingParse {
253
315
  * Parse CSV to records.
254
316
  * This function is for parsing a binary stream.
255
317
  *
318
+ * @category Middle-level API
256
319
  * @remarks
257
- * If you want to parse a string, use {@link streamingParse}.
320
+ * If you want to parse a string, use {@link parseStringStream}.
258
321
  * @param stream CSV string to parse
259
322
  * @param options Parsing options. See {@link ParseBinaryOptions}.
323
+ * @returns Async iterable iterator of records.
324
+ *
325
+ * If you want array of records, use {@link parseBinaryStream.toArray} function.
326
+ *
327
+ * @example Parsing CSV binary
328
+ *
329
+ * ```ts
330
+ * import { parseBinaryStream } from 'web-csv-toolbox';
331
+ *
332
+ * const csv = Uint8Array.from([
333
+ * // ...
334
+ * ]);
335
+ *
336
+ * const stream = new ReadableStream({
337
+ * start(controller) {
338
+ * controller.enqueue(csv);
339
+ * controller.close();
340
+ * },
341
+ * });
342
+ *
343
+ * for await (const record of parseBinaryStream(csv)) {
344
+ * console.log(record);
345
+ * }
346
+ * ```
260
347
  */
261
348
  declare function parseBinaryStream<Header extends ReadonlyArray<string>>(
262
349
  stream: ReadableStream<Uint8Array>,
263
350
  options?: ParseBinaryOptions<Header>,
264
351
  ): AsyncIterableIterator<CSVRecord<Header>>;
265
352
  declare namespace parseBinaryStream {
353
+ /**
354
+ * Parse CSV binary to array of records,
355
+ * ideal for smaller data sets.
356
+ *
357
+ * @returns Array of records
358
+ *
359
+ * @example Parsing CSV binary
360
+ * ```ts
361
+ * import { parseBinaryStream } from 'web-csv-toolbox';
362
+ *
363
+ * const csv = Uint8Array.from([
364
+ * // ...
365
+ * ]);
366
+ *
367
+ * const stream = new ReadableStream({
368
+ * start(controller) {
369
+ * controller.enqueue(csv);
370
+ * controller.close();
371
+ * },
372
+ * });
373
+ *
374
+ * const records = await parseBinaryStream.toArray(stream);
375
+ * console.log(records);
376
+ * ```
377
+ */
266
378
  function toArray<Header extends ReadonlyArray<string>>(
267
379
  stream: ReadableStream<Uint8Array>,
268
380
  options?: ParseBinaryOptions<Header>,
@@ -270,48 +382,407 @@ declare namespace parseBinaryStream {
270
382
  }
271
383
 
272
384
  /**
273
- * Parse CSV string to records.
385
+ * Parse CSV string stream to records.
274
386
  *
387
+ * @category Middle-level API
275
388
  * @param stream CSV string stream to parse
276
- * @param options Parsing options. See {@link ParseOptions}.
389
+ * @param options Parsing options.
390
+ * @returns Async iterable iterator of records.
391
+ *
392
+ * If you want array of records, use {@link parseStringStream.toArray} function.
393
+ *
394
+ * @example Parsing CSV files from strings
395
+ *
396
+ * ```ts
397
+ * import { parseStringStream } from 'web-csv-toolbox';
398
+ *
399
+ * const csv = `name,age
400
+ * Alice,42
401
+ * Bob,69`;
402
+ *
403
+ * const stream = new ReadableStream({
404
+ * start(controller) {
405
+ * controller.enqueue(csv);
406
+ * controller.close();
407
+ * },
408
+ * });
409
+ *
410
+ * for await (const record of parseStringStream(csv)) {
411
+ * console.log(record);
412
+ * }
413
+ * // Prints:
414
+ * // { name: 'Alice', age: '42' }
415
+ * // { name: 'Bob', age: '69' }
416
+ * ```
277
417
  */
278
418
  declare function parseStringStream<Header extends ReadonlyArray<string>>(
279
419
  stream: ReadableStream<string>,
280
420
  options?: ParseOptions<Header>,
281
421
  ): AsyncIterableIterator<CSVRecord<Header>>;
282
422
  declare namespace parseStringStream {
423
+ /**
424
+ * Parse CSV string stream to records.
425
+ *
426
+ * @returns Array of records
427
+ *
428
+ * @example
429
+ *
430
+ * ```ts
431
+ * import { parseStringStream } from 'web-csv-toolbox';
432
+ *
433
+ * const csv = `name,age
434
+ * Alice,42
435
+ * Bob,69`;
436
+ *
437
+ * const stream = new ReadableStream({
438
+ * start(controller) {
439
+ * controller.enqueue(csv);
440
+ * controller.close();
441
+ * },
442
+ * });
443
+ *
444
+ * const records = await parseStringStream.toArray(stream);
445
+ * console.log(records);
446
+ * // Prints:
447
+ * // [ { name: 'Alice', age: '42' }, { name: 'Bob', age: '69' } ]
448
+ * ```
449
+ */
283
450
  function toArray<Header extends ReadonlyArray<string>>(
284
- stream: ReadableStream<Uint8Array>,
451
+ stream: ReadableStream<string>,
285
452
  options?: ParseOptions<Header>,
286
453
  ): Promise<CSVRecord<Header>[]>;
287
454
  }
288
455
 
289
456
  /**
290
- * Parse CSV to records.
457
+ * Parse HTTP Response what contains CSV to records,
458
+ * ideal for smaller data sets.
459
+ *
460
+ * @remarks
461
+ * This function automatically treats response headers.
291
462
  *
292
- * {@link String}, {@link Uint8Array}, ReadableStream<string | Uint8Array> and Response are supported.
463
+ * - If `Content-Type` header is not set, it assumes `text/csv`.
464
+ * - If `Content-Type` header is not `text/csv`, it throws an error.
465
+ * - If `Content-Type` header has charset parameter, it uses it for decoding.
466
+ * - If `Content-Encoding` header is set, it decompresses the response.
467
+ * - Should there be any conflicting information between the header and the options, the option's value will take precedence.
468
+ *
469
+ * @category Middle-level API
470
+ * @param response
471
+ * @param options
472
+ * @returns Async iterable iterator of records.
473
+ *
474
+ * If you want array of records, use {@link parseResponse.toArray} function.
475
+ *
476
+ * @example Parsing CSV Response
477
+ *
478
+ * ```ts
479
+ * import { parseResponse } from 'web-csv-toolbox';
480
+ *
481
+ * const response = await fetch('https://example.com/data.csv');
482
+ *
483
+ * for await (const record of parseResponse(response)) {
484
+ * console.log(record);
485
+ * }
486
+ * ```
487
+ */
488
+ declare function parseResponse<Header extends ReadonlyArray<string>>(
489
+ response: Response,
490
+ options?: ParseOptions<Header>,
491
+ ): AsyncIterableIterator<CSVRecord<Header>>;
492
+ declare namespace parseResponse {
493
+ /**
494
+ * Parse CSV Response to array of records.
495
+ *
496
+ * @returns Array of records
497
+ *
498
+ * @example Parsing CSV Response
499
+ *
500
+ * ```ts
501
+ * import { parseResponse } from 'web-csv-toolbox';
502
+ *
503
+ * const response = await fetch('https://example.com/data.csv');
504
+ *
505
+ * const records = await parseResponse.toArray(response);
506
+ * console.log(records);
507
+ * ```
508
+ */
509
+ function toArray<Header extends ReadonlyArray<string>>(
510
+ response: Response,
511
+ options?: ParseOptions<Header>,
512
+ ): Promise<CSVRecord<Header>[]>;
513
+ }
514
+
515
+ /**
516
+ * Parse CSV Stream to records,
517
+ * ideal for smaller data sets.
518
+ *
519
+ * {@link !ReadableStream} of {@link !String} and {@link !Uint8Array} are supported.
293
520
  *
294
521
  * @remarks
295
- * {@link streamingParse}, {@link parseBinaryStream},
296
- * {@link parseStringStream} and {@link parseResponse} are used internally.
522
+ * {@link parseStringStream} and {@link parseBinaryStream} are used internally.
297
523
  * If you known the type of the stream, it performs better to use them directly.
298
524
  *
299
- * If you want to parse a string, use {@link streamingParse}.
300
- * If you want to parse a Uint8Array, use {@link parseStream}.
301
- * If you want to parse a ReadableStream<string>, use {@link parseStringStream}.
302
- * If you want to parse a ReadableStream<Uint8Array>, use {@link parseBinaryStream}.
303
- * If you want to parse a Response, use {@link parseResponse}.
525
+ * If you want to parse a string, use {@link parseStringStream}.
526
+ * If you want to parse a Uint8Array, use {@link parseBinaryStream}.
304
527
  *
528
+ * @category Middle-level API
305
529
  * @param csv CSV string to parse
306
530
  * @param options Parsing options. See {@link ParseOptions}.
531
+ * @returns Async iterable iterator of records.
532
+ *
533
+ * If you want array of records, use {@link parseStream.toArray} function.
534
+ *
535
+ * @example Parsing CSV string stream
536
+ *
537
+ * ```ts
538
+ *
539
+ * import { parseStream } from 'web-csv-toolbox';
540
+ *
541
+ * const csv = `name,age
542
+ * Alice,42
543
+ * Bob,69`;
544
+ *
545
+ * const stream = new ReadableStream({
546
+ * start(controller) {
547
+ * controller.enqueue(csv);
548
+ * controller.close();
549
+ * },
550
+ * });
551
+ *
552
+ * for await (const record of parseStream(stream)) {
553
+ * console.log(record);
554
+ * }
555
+ * // Prints:
556
+ * // { name: 'Alice', age: '42' }
557
+ * // { name: 'Bob', age: '69' }
558
+ * ```
559
+ *
560
+ * @example Parsing CSV binary stream
561
+ *
562
+ * ```ts
563
+ * import { parseStream } from 'web-csv-toolbox';
564
+ *
565
+ * const csv = Uint8Array.from([
566
+ * // ...
567
+ * ]);
568
+ *
569
+ * const stream = new ReadableStream({
570
+ * start(controller) {
571
+ * controller.enqueue(csv);
572
+ * controller.close();
573
+ * },
574
+ * });
575
+ *
576
+ * for await (const record of parseStream(stream)) {
577
+ * console.log(record);
578
+ * }
579
+ * ```
580
+ */
581
+ declare function parseStream<Header extends ReadonlyArray<string>>(
582
+ stream: ReadableStream<Uint8Array | string>,
583
+ options?: ParseBinaryOptions<Header>,
584
+ ): AsyncIterableIterator<CSVRecord<Header>>;
585
+ declare namespace parseStream {
586
+ /**
587
+ * Parse CSV Stream to array of records.
588
+ *
589
+ * @returns Array of records
590
+ */
591
+ function toArray<Header extends ReadonlyArray<string>>(
592
+ stream: ReadableStream<Uint8Array>,
593
+ options?: ParseBinaryOptions<Header>,
594
+ ): Promise<CSVRecord<Header>[]>;
595
+ }
596
+
597
+ /**
598
+ * Parse CSV to records.
599
+ *
600
+ * {@link !String}, {@link !ReadableStream}<string | {@link !Uint8Array}> and {@link !Response} are supported.
601
+ *
602
+ *
603
+ * @typeParam Header Header type like `['name', 'age']`.
604
+ *
605
+ * @param csv CSV string to parse.
606
+ * @param options Parsing options for CSV string parsing.
607
+ * @returns Async iterable iterator of records.
608
+ *
609
+ * If you want array of records, use {@link parse.toArray} function.
610
+ * @category High-level API
611
+ *
612
+ * @remarks
613
+ * {@link parseString}, {@link parseBinaryStream},
614
+ * {@link parseStringStream} and {@link parseResponse} are used internally.
615
+ *
616
+ * If you known the type of the CSV, it performs better to use them directly.
617
+ *
618
+ * | If you want to parse a... | Use... | Data are treated as... |
619
+ * | ----------------------------------- | ------------------------- | ---------------------- |
620
+ * | {@link !String} | {@link parseString} | String |
621
+ * | {@link !ReadableStream}<string> | {@link parseStringStream} | String |
622
+ * | {@link !ReadableStream}<Uint8Array> | {@link parseBinaryStream} | Binary |
623
+ * | {@link !Response} | {@link parseResponse} | Binary |
624
+ *
625
+ * @example Parsing CSV files from strings
626
+ *
627
+ * ```ts
628
+ * import { parse } from 'web-csv-toolbox';
629
+ *
630
+ * const csv = `name,age
631
+ * Alice,42
632
+ * Bob,69`;
633
+ *
634
+ * for await (const record of parse(csv)) {
635
+ * console.log(record);
636
+ * }
637
+ * // Prints:
638
+ * // { name: 'Alice', age: '42' }
639
+ * // { name: 'Bob', age: '69' }
640
+ * ```
641
+ *
642
+ * @example Parsing CSV files from streams
643
+ *
644
+ * ```ts
645
+ * import { parse } from 'web-csv-toolbox';
646
+ *
647
+ * const csv = `name,age
648
+ * Alice,42
649
+ * Bob,69`;
650
+ *
651
+ * const stream = new ReadableStream({
652
+ * start(controller) {
653
+ * controller.enqueue(csv);
654
+ * controller.close();
655
+ * }
656
+ * });
657
+ *
658
+ * for await (const record of parse(stream)) {
659
+ * console.log(record);
660
+ * }
661
+ * // Prints:
662
+ * // { name: 'Alice', age: '42' }
663
+ * // { name: 'Bob', age: '69' }
664
+ * ```
665
+ *
666
+ *
667
+ * @example Parsing CSV files with headers
668
+ *
669
+ * ```ts
670
+ * import { parse } from 'web-csv-toolbox';
671
+ *
672
+ * // This CSV has no header.
673
+ * const csv = `Alice,42
674
+ * Bob,69`;
675
+ *
676
+ * for await (const record of parse(csv, { header: ['name', 'age'] })) {
677
+ * console.log(record);
678
+ * }
679
+ * // Prints:
680
+ * // { name: 'Alice', age: '42' }
681
+ * // { name: 'Bob', age: '69' }
682
+ * ```
683
+ *
684
+ * @example Parsing CSV files with different delimiters characters
685
+ *
686
+ * ```ts
687
+ * import { parse } from 'web-csv-toolbox';
688
+ *
689
+ * const csv = `name\tage
690
+ * Alice\t42
691
+ * Bob\t69`;
692
+ *
693
+ * for await (const record of parse(csv, { delimiter: '\t' })) {
694
+ * console.log(record);
695
+ * }
696
+ * // Prints:
697
+ * // { name: 'Alice', age: '42' }
698
+ * // { name: 'Bob', age: '69' }
699
+ * ```
307
700
  */
308
701
  declare function parse<Header extends ReadonlyArray<string>>(
309
- csv: string | ReadableStream<Uint8Array | string> | Response,
702
+ csv: string | ReadableStream<string>,
310
703
  options?: ParseOptions<Header>,
311
704
  ): AsyncIterableIterator<CSVRecord<Header>>;
705
+ /**
706
+ * Parse CSV binary to records.
707
+ *
708
+ * @param csv CSV binary to parse.
709
+ * @param options Parsing options for CSV binary parsing.
710
+ *
711
+ * @example Parsing CSV files from responses
712
+ *
713
+ * ```ts
714
+ * import { parse } from 'web-csv-toolbox';
715
+ *
716
+ * // This CSV data is not gzipped and encoded in utf-8.
717
+ * const response = await fetch('https://example.com/data.csv');
718
+ *
719
+ * for await (const record of parse(response)) {
720
+ * // ...
721
+ * }
722
+ * ```
723
+ *
724
+ * @example Parsing CSV files with options spcialized for binary
725
+ *
726
+ * ```ts
727
+ * import { parse } from 'web-csv-toolbox';
728
+ *
729
+ * // This CSV data is gzipped and encoded in shift-jis and has BOM.
730
+ * const response = await fetch('https://example.com/data.csv.gz');
731
+ *
732
+ * for await (const record of parse(response, {
733
+ * charset: 'shift-jis',
734
+ * ignoreBOM: true,
735
+ * decomposition: 'gzip',
736
+ * })) {
737
+ * // ...
738
+ * }
739
+ * ```
740
+ */
741
+ declare function parse<Header extends ReadonlyArray<string>>(
742
+ csv: ReadableStream<Uint8Array> | Response,
743
+ options?: ParseBinaryOptions<Header>,
744
+ ): AsyncIterableIterator<CSVRecord<Header>>;
312
745
  declare namespace parse {
746
+ /**
747
+ * Parse CSV string to array of records,
748
+ * ideal for smaller data sets.
749
+ *
750
+ * @example Parse a CSV as array of records
751
+ *
752
+ * ```ts
753
+ * import { parse } from 'web-csv-toolbox';
754
+ *
755
+ * const csv = `name,age
756
+ * Alice,42
757
+ * Bob,69`;
758
+ *
759
+ * const records = await parse.toArray(csv);
760
+ * console.log(records);
761
+ * // Prints:
762
+ * // [ { name: 'Alice', age: '42' }, { name: 'Bob', age: '69' } ]
763
+ * ```
764
+ */
765
+ function toArray<Header extends ReadonlyArray<string>>(
766
+ csv: string | ReadableStream<string>,
767
+ options?: ParseOptions<Header>,
768
+ ): Promise<CSVRecord<Header>[]>;
769
+ /**
770
+ * Parse CSV string to array of records,
771
+ * ideal for smaller data sets.
772
+ *
773
+ * @example Parse a CSV as array of records
774
+ *
775
+ * ```ts
776
+ * import { parse } from 'web-csv-toolbox';
777
+ *
778
+ * const response = await fetch('https://example.com/data.csv');
779
+ *
780
+ * const records = await parse.toArray(response);
781
+ * console.log(records);
782
+ * ```
783
+ */
313
784
  function toArray<Header extends ReadonlyArray<string>>(
314
- csv: string | ReadableStream<string | Uint8Array> | Response,
785
+ csv: ReadableStream<Uint8Array> | Response,
315
786
  options?: ParseOptions<Header>,
316
787
  ): Promise<CSVRecord<Header>[]>;
317
788
  }
@@ -332,6 +803,8 @@ export {
332
803
  type TokenType,
333
804
  parse,
334
805
  parseBinaryStream,
806
+ parseResponse,
807
+ parseStream,
808
+ parseString,
335
809
  parseStringStream,
336
- streamingParse,
337
810
  };
package/lib/index.js CHANGED
@@ -1,33 +1,13 @@
1
- /**
2
- * FiledDelimiter is a symbol for field delimiter of CSV.
3
- */
4
1
  const FieldDelimiter = Symbol.for("web-streams-csv.FieldDelimiter");
5
- /**
6
- * RecordDelimiter is a symbol for record delimiter of CSV.
7
- */
8
2
  const RecordDelimiter = Symbol.for("web-streams-csv.RecordDelimiter");
9
- /**
10
- * Field is a symbol for field of CSV.
11
- */
12
3
  const Field = Symbol.for("web-streams-csv.Field");
13
4
 
14
5
  const CR = "\r";
15
6
  const CRLF = "\r\n";
16
7
  const LF = "\n";
17
- /**
18
- * COMMA is a symbol for comma(,).
19
- */
20
8
  const COMMA = ",";
21
- /**
22
- * DOUBLE_QUATE is a symbol for double quate(").
23
- */
24
9
  const DOUBLE_QUATE = '"';
25
10
 
26
- /**
27
- * Assert that the options are valid.
28
- *
29
- * @param options The options to assert.
30
- */
31
11
  function assertCommonOptions(options) {
32
12
  if (typeof options.quotation === "string" && options.quotation.length === 0) {
33
13
  throw new Error("quotation must not be empty");
@@ -51,41 +31,10 @@ function assertCommonOptions(options) {
51
31
  }
52
32
  }
53
33
 
54
- /**
55
- * Escape a string for use in a regular expression.
56
- *
57
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping Regular expressions#Escaping | MDN}
58
- * @param v string to escape
59
- * @returns escaped string
60
- */
61
34
  function escapeRegExp(v) {
62
35
  return v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
63
36
  }
64
37
 
65
- /**
66
- * A transform stream that converts a stream of tokens into a stream of rows.
67
- *
68
- * @example Parse a CSV with headers by data
69
- * ```ts
70
- * new ReadableStream({
71
- * start(controller) {
72
- * controller.enqueue("name,age\r\n");
73
- * controller.enqueue("Alice,20\r\n");
74
- * controller.close();
75
- * }
76
- * })
77
- * .pipeThrough(new LexerTransformer())
78
- * .pipeTo(new WritableStream({ write(token) { console.log(token); }}));
79
- * // { type: Field, value: "name" }
80
- * // { type: FieldDelimiter, value: "," }
81
- * // { type: Field, value: "age" }
82
- * // { type: RecordDelimiter, value: "\r\n" }
83
- * // { type: Field, value: "Alice" }
84
- * // { type: FieldDelimiter, value: "," }
85
- * // { type: Field, value: "20" }
86
- * // { type: RecordDelimiter, value: "\r\n" }
87
- * ```
88
- */
89
38
  class LexerTransformer extends TransformStream {
90
39
  #demiliter;
91
40
  #demiliterLength;
@@ -161,49 +110,38 @@ class LexerTransformer extends TransformStream {
161
110
  if (this.#buffer.length === 0) {
162
111
  return null;
163
112
  }
164
- // Check for CRLF
165
113
  if (this.#buffer.startsWith(CRLF)) {
166
114
  this.#buffer = this.#buffer.slice(2);
167
115
  return { type: RecordDelimiter, value: CRLF };
168
116
  }
169
- // Check for LF
170
117
  if (this.#buffer.startsWith(LF)) {
171
118
  this.#buffer = this.#buffer.slice(1);
172
119
  return { type: RecordDelimiter, value: LF };
173
120
  }
174
- // Check for Delimiter
175
121
  if (this.#buffer.startsWith(this.#demiliter)) {
176
122
  this.#buffer = this.#buffer.slice(this.#demiliterLength);
177
123
  return { type: FieldDelimiter, value: this.#demiliter };
178
124
  }
179
- // Check for Quoted String
180
125
  if (this.#buffer.startsWith(this.#quotation)) {
181
- // If we're flushing and the buffer doesn't end with a quote, then return null
182
- // because we're not done with the quoted string
183
126
  if (flush === false && this.#buffer.endsWith(this.#quotation)) {
184
127
  return null;
185
128
  }
186
129
  return this.extractQuotedString();
187
130
  }
188
- // Check for Unquoted String
189
131
  const match = this.#matcher.exec(this.#buffer);
190
132
  if (match) {
191
- // If we're flushing and the match doesn't consume the entire buffer,
192
- // then return null
193
133
  if (flush === false && match[0].length === this.#buffer.length) {
194
134
  return null;
195
135
  }
196
136
  this.#buffer = this.#buffer.slice(match[0].length);
197
137
  return { type: Field, value: match[0] };
198
138
  }
199
- // Otherwise, return null
200
139
  return null;
201
140
  }
202
141
  extractQuotedString() {
203
- let end = this.#quotationLength; // Skip the opening quote
142
+ let end = this.#quotationLength;
204
143
  let value = "";
205
144
  while (end < this.#buffer.length) {
206
- // Escaped quote
207
145
  if (
208
146
  this.#buffer.slice(end, end + this.#quotationLength) ===
209
147
  this.quotation &&
@@ -216,7 +154,6 @@ class LexerTransformer extends TransformStream {
216
154
  end += this.#quotationLength * 2;
217
155
  continue;
218
156
  }
219
- // Closing quote
220
157
  if (
221
158
  this.#buffer.slice(end, end + this.#quotationLength) === this.quotation
222
159
  ) {
@@ -226,52 +163,10 @@ class LexerTransformer extends TransformStream {
226
163
  value += this.#buffer[end];
227
164
  end++;
228
165
  }
229
- // If we get here, we've reached the end of the buffer
230
166
  return null;
231
167
  }
232
168
  }
233
169
 
234
- /**
235
- * A transform stream that converts a stream of tokens into a stream of rows.
236
- * @template Header The type of the header row.
237
- * @param options The options for the parser.
238
- *
239
- * @example Parse a CSV with headers by data
240
- * ```ts
241
- * new ReadableStream({
242
- * start(controller) {
243
- * controller.enqueue("name,age\r\n");
244
- * controller.enqueue("Alice,20\r\n");
245
- * controller.enqueue("Bob,25\r\n");
246
- * controller.enqueue("Charlie,30\r\n");
247
- * controller.close();
248
- * })
249
- * .pipeThrough(new LexerTransformer())
250
- * .pipeThrough(new RecordAssemblerTransformar())
251
- * .pipeTo(new WritableStream({ write(row) { console.log(row); }}));
252
- * // { name: "Alice", age: "20" }
253
- * // { name: "Bob", age: "25" }
254
- * // { name: "Charlie", age: "30" }
255
- * ```
256
- *
257
- * @example Parse a CSV with headers by options
258
- * ```ts
259
- * new ReadableStream({
260
- * start(controller) {
261
- * controller.enqueue("Alice,20\r\n");
262
- * controller.enqueue("Bob,25\r\n");
263
- * controller.enqueue("Charlie,30\r\n");
264
- * controller.close();
265
- * }
266
- * })
267
- * .pipeThrough(new LexerTransformer())
268
- * .pipeThrough(new RecordAssemblerTransformar({ header: ["name", "age"] }))
269
- * .pipeTo(new WritableStream({ write(row) { console.log(row); }}));
270
- * // { name: "Alice", age: "20" }
271
- * // { name: "Bob", age: "25" }
272
- * // { name: "Charlie", age: "30" }
273
- * ```
274
- */
275
170
  class RecordAssemblerTransformar extends TransformStream {
276
171
  #fieldIndex = 0;
277
172
  #row = [];
@@ -301,7 +196,6 @@ class RecordAssemblerTransformar extends TransformStream {
301
196
  controller.enqueue(record);
302
197
  }
303
198
  }
304
- // Reset the row fields buffer.
305
199
  this.#fieldIndex = 0;
306
200
  this.#row = new Array(this.#header?.length);
307
201
  this.#darty = false;
@@ -310,7 +204,6 @@ class RecordAssemblerTransformar extends TransformStream {
310
204
  },
311
205
  flush: (controller) => {
312
206
  if (this.#fieldIndex !== 0 && this.#header !== undefined) {
313
- // console.log('B', this.#row)
314
207
  if (this.#darty) {
315
208
  const record = Object.fromEntries(
316
209
  this.#header
@@ -356,12 +249,6 @@ async function toArray(...args) {
356
249
  return rows;
357
250
  }
358
251
 
359
- /**
360
- * Parse CSV string to records.
361
- *
362
- * @param stream CSV string stream to parse
363
- * @param options Parsing options. See {@link ParseOptions}.
364
- */
365
252
  async function* parseStringStream(stream, options) {
366
253
  let controller;
367
254
  const readable = new ReadableStream({
@@ -387,48 +274,30 @@ async function* parseStringStream(stream, options) {
387
274
  reader.releaseLock();
388
275
  }
389
276
  }
390
- (function (parseStringStream) {})(
391
- parseStringStream || (parseStringStream = {}),
392
- );
393
- parseStringStream.toArray = toArray;
277
+ ((parseStringStream) => {
278
+ parseStringStream.toArray = toArray;
279
+ })(parseStringStream || (parseStringStream = {}));
394
280
 
395
- /**
396
- * Parse CSV string to records.
397
- *
398
- * @param csv CSV string to parse
399
- * @param options Parsing options. See {@link ParseOptions}.
400
- */
401
- async function* streamingParse(csv, options) {
281
+ async function* parseString(csv, options) {
402
282
  yield* parseStringStream(new SingleValueReadableStream(csv), options);
403
283
  }
404
- (function (streamingParse) {})(streamingParse || (streamingParse = {}));
405
- streamingParse.toArray = toArray;
284
+ ((parseString) => {
285
+ parseString.toArray = toArray;
286
+ })(parseString || (parseString = {}));
406
287
 
407
- /**
408
- * Parse CSV to records.
409
- * This function is for parsing a binary stream.
410
- *
411
- * @remarks
412
- * If you want to parse a string, use {@link streamingParse}.
413
- * @param stream CSV string to parse
414
- * @param options Parsing options. See {@link ParseBinaryOptions}.
415
- */
416
288
  async function* parseBinaryStream(stream, options) {
417
289
  const { charset, fatal, ignoreBOM, decomposition } = options ?? {};
418
290
  yield* parseStringStream(
419
291
  [
420
- // NOTE: if decompression is undefined, it will be ignored.
421
292
  ...(decomposition ? [new DecompressionStream(decomposition)] : []),
422
- // NOTE: if charset is undefined, it will be decoded as utf-8.
423
293
  new TextDecoderStream(charset, { fatal, ignoreBOM }),
424
294
  ].reduce((stream, transformer) => stream.pipeThrough(transformer), stream),
425
295
  options,
426
296
  );
427
297
  }
428
- (function (parseBinaryStream) {})(
429
- parseBinaryStream || (parseBinaryStream = {}),
430
- );
431
- parseBinaryStream.toArray = toArray;
298
+ ((parseBinaryStream) => {
299
+ parseBinaryStream.toArray = toArray;
300
+ })(parseBinaryStream || (parseBinaryStream = {}));
432
301
 
433
302
  function parseMime(contentType) {
434
303
  const [type, ...parameters] = contentType.split(";");
@@ -452,8 +321,6 @@ function parseResponse(response, options) {
452
321
  }
453
322
  const decomposition = headers.get("content-encoding") ?? undefined;
454
323
  const charset = mime.parameters.charset ?? "utf-8";
455
- // TODO: Support header=present and header=absent
456
- // const header = mime.parameters.header ?? "present";
457
324
  if (response.body === null) {
458
325
  throw new Error("Response body is null");
459
326
  }
@@ -463,74 +330,37 @@ function parseResponse(response, options) {
463
330
  ...options,
464
331
  });
465
332
  }
466
- (function (parseResponse) {})(parseResponse || (parseResponse = {}));
467
- parseResponse.toArray = toArray;
333
+ ((parseResponse) => {
334
+ parseResponse.toArray = toArray;
335
+ })(parseResponse || (parseResponse = {}));
468
336
 
469
- /**
470
- * Parse CSV Stream to records.
471
- * string and Uint8Array are supported.
472
- *
473
- * @remarks
474
- * {@link parseStringStream} and {@link parseBinaryStream} are used internally.
475
- * If you known the type of the stream, it performs better to use them directly.
476
- *
477
- * If you want to parse a string, use {@link parseStringStream}.
478
- * If you want to parse a Uint8Array, use {@link parseBinaryStream}.
479
- *
480
- * @param csv CSV string to parse
481
- * @param options Parsing options. See {@link ParserOptions}.
482
- */
483
337
  async function* parseStream(stream, options) {
484
338
  const [branch1, branch2] = stream.tee();
485
339
  const reader1 = branch1.getReader();
486
340
  const { value: firstChunk } = await reader1.read();
487
341
  reader1.releaseLock();
488
- switch (true) {
489
- case typeof firstChunk === "string":
490
- yield* parseStringStream(branch2, options);
491
- break;
492
- case firstChunk instanceof Uint8Array:
493
- yield* parseBinaryStream(branch2, options);
494
- break;
342
+ if (typeof firstChunk === "string") {
343
+ yield* parseStringStream(branch2, options);
344
+ } else if (firstChunk instanceof Uint8Array) {
345
+ yield* parseBinaryStream(branch2, options);
495
346
  }
496
347
  }
497
- (function (parseStream) {})(parseStream || (parseStream = {}));
498
- parseStream.toArray = toArray;
348
+ ((parseStream) => {
349
+ parseStream.toArray = toArray;
350
+ })(parseStream || (parseStream = {}));
499
351
 
500
- /**
501
- * Parse CSV to records.
502
- *
503
- * {@link String}, {@link Uint8Array}, ReadableStream<string | Uint8Array> and Response are supported.
504
- *
505
- * @remarks
506
- * {@link streamingParse}, {@link parseBinaryStream},
507
- * {@link parseStringStream} and {@link parseResponse} are used internally.
508
- * If you known the type of the stream, it performs better to use them directly.
509
- *
510
- * If you want to parse a string, use {@link streamingParse}.
511
- * If you want to parse a Uint8Array, use {@link parseStream}.
512
- * If you want to parse a ReadableStream<string>, use {@link parseStringStream}.
513
- * If you want to parse a ReadableStream<Uint8Array>, use {@link parseBinaryStream}.
514
- * If you want to parse a Response, use {@link parseResponse}.
515
- *
516
- * @param csv CSV string to parse
517
- * @param options Parsing options. See {@link ParseOptions}.
518
- */
519
352
  async function* parse(csv, options) {
520
- switch (true) {
521
- case typeof csv === "string":
522
- yield* streamingParse(csv, options);
523
- break;
524
- case csv instanceof ReadableStream:
525
- yield* parseStream(csv, options);
526
- break;
527
- case csv instanceof Response:
528
- yield* parseResponse(csv, options);
529
- break;
353
+ if (typeof csv === "string") {
354
+ yield* parseString(csv, options);
355
+ } else if (csv instanceof ReadableStream) {
356
+ yield* parseStream(csv, options);
357
+ } else if (csv instanceof Response) {
358
+ yield* parseResponse(csv, options);
530
359
  }
531
360
  }
532
- (function (parse) {})(parse || (parse = {}));
533
- parse.toArray = toArray;
361
+ ((parse) => {
362
+ parse.toArray = toArray;
363
+ })(parse || (parse = {}));
534
364
 
535
365
  export {
536
366
  Field,
@@ -540,6 +370,8 @@ export {
540
370
  RecordDelimiter,
541
371
  parse,
542
372
  parseBinaryStream,
373
+ parseResponse,
374
+ parseStream,
375
+ parseString,
543
376
  parseStringStream,
544
- streamingParse,
545
377
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-csv-toolbox",
3
- "version": "0.0.0-next-20231225182210",
3
+ "version": "0.0.0-next-20231227082102",
4
4
  "description": "A CSV Toolbox utilizing Web Standard APIs.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -27,7 +27,7 @@
27
27
  "lint": "biome lint .",
28
28
  "check": "biome check src --apply",
29
29
  "check:no-apply": "biome check src",
30
- "build": "rollup -c rollup.config.ts --configPlugin rollup-plugin-typescript2 && biome format lib --write",
30
+ "build": "rollup -c rollup.config.ts --configPlugin rollup-plugin-typescript2 && biome check lib --apply",
31
31
  "prepare": "husky install"
32
32
  },
33
33
  "repository": {
@@ -45,7 +45,7 @@
45
45
  "bugs": {
46
46
  "url": "https://github.com/kamiazya/web-csv-toolbox/issues"
47
47
  },
48
- "homepage": "https://github.com/kamiazya/web-csv-toolbox#readme",
48
+ "homepage": "https://kamiazya.github.io/web-csv-toolbox/",
49
49
  "devDependencies": {
50
50
  "@biomejs/biome": "1.4.1",
51
51
  "@changesets/changelog-github": "^0.5.0",
@@ -60,7 +60,8 @@
60
60
  "rollup-plugin-dts": "^6.1.0",
61
61
  "rollup-plugin-typescript2": "^0.36.0",
62
62
  "typedoc": "^0.25.4",
63
+ "typedoc-plugin-mdn-links": "^3.1.9",
63
64
  "typescript": "^5.3.2",
64
65
  "vitest": "^1.1.0"
65
66
  }
66
- }
67
+ }