utilful 2.5.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,13 +13,12 @@ A collection of TypeScript utilities that I use across my projects.
13
13
  - [JSON](#json)
14
14
  - [Module](#module)
15
15
  - [Object](#object)
16
+ - [Path](#path)
16
17
  - [Result](#result)
17
18
  - [String](#string)
18
19
 
19
20
  ## Installation
20
21
 
21
- Run the following command to add `utilful` to your project.
22
-
23
22
  ```bash
24
23
  # npm
25
24
  npm install -D utilful
@@ -105,30 +104,34 @@ const csv = createCSV(rows)
105
104
  Parses a comma-separated values (CSV) string into an array of objects.
106
105
 
107
106
  > [!NOTE]
108
- > The first row of the CSV string is used as the header row.
107
+ > The first row of the CSV string is used as the header row. A leading UTF-8 byte order mark is stripped.
109
108
 
110
109
  ```ts
111
110
  type CSVRow<T extends string = string> = Record<T, string>
112
111
 
112
+ interface CSVParseOptions {
113
+ /** @default ',' */
114
+ delimiter?: string
115
+ /**
116
+ * Trim whitespace from unquoted headers and values.
117
+ * @default false
118
+ */
119
+ trim?: boolean
120
+ /**
121
+ * Throw if a row's field count does not match the header row.
122
+ * @default true
123
+ */
124
+ strict?: boolean
125
+ }
126
+
113
127
  declare function parseCSV<Header extends string>(
114
128
  csv?: string | null | undefined,
115
- options?: {
116
- /** @default ',' */
117
- delimiter?: string
118
- /**
119
- * Trim whitespace from headers and values.
120
- * @default true
121
- */
122
- trim?: boolean
123
- /**
124
- * Throw error if row has more fields than headers.
125
- * @default true
126
- */
127
- strict?: boolean
128
- }
129
+ options?: CSVParseOptions
129
130
  ): CSVRow<Header>[]
130
131
  ```
131
132
 
133
+ The parser accepts a few lenient deviations from RFC 4180: LF, CR, and CRLF line endings are all recognized, whitespace between a closing quote and the next delimiter or line break is ignored, and quotes inside unquoted fields are kept as literal characters (a field only counts as quoted if it starts with a quote).
134
+
132
135
  **Example:**
133
136
 
134
137
  ```ts
@@ -141,6 +144,88 @@ Jane,25
141
144
  const data = parseCSV<'name' | 'age'>(csv) // [{ name: 'John', age: '30' }, { name: 'Jane', age: '25' }]
142
145
  ```
143
146
 
147
+ #### `createCSVStream`
148
+
149
+ Creates a CSV stream from an iterable or async iterable of objects. Yields complete lines (header and/or data rows) including line endings – useful for large datasets that should not be buffered in memory.
150
+
151
+ ```ts
152
+ declare function createCSVStream<T extends Record<string, unknown>>(
153
+ data: AsyncIterable<T> | Iterable<T>,
154
+ columns: readonly (keyof T)[],
155
+ options?: CSVCreateOptions
156
+ ): AsyncIterable<string>
157
+ ```
158
+
159
+ **Example:**
160
+
161
+ ```ts
162
+ for await (const chunk of createCSVStream(rows, ['name', 'age'])) {
163
+ process.stdout.write(chunk)
164
+ }
165
+ ```
166
+
167
+ #### `createCSVAsync`
168
+
169
+ Convenience wrapper around `createCSVStream` that collects all chunks into a single string.
170
+
171
+ > [!NOTE]
172
+ > Unlike `createCSV`, the result has a trailing line ending.
173
+
174
+ ```ts
175
+ declare function createCSVAsync<T extends Record<string, unknown>>(
176
+ data: AsyncIterable<T> | Iterable<T>,
177
+ columns: readonly (keyof T)[],
178
+ options?: CSVCreateOptions
179
+ ): Promise<string>
180
+ ```
181
+
182
+ #### `parseCSVStream`
183
+
184
+ Parses CSV data from an iterable or async iterable of string chunks, yielding rows as soon as they are complete. Chunks do not need to align with row boundaries – quotes and newlines are handled correctly across chunk boundaries.
185
+
186
+ ```ts
187
+ declare function parseCSVStream<Header extends string>(
188
+ chunks: AsyncIterable<string> | Iterable<string>,
189
+ options?: CSVParseOptions
190
+ ): AsyncIterable<CSVRow<Header>>
191
+ ```
192
+
193
+ **Example:**
194
+
195
+ ```ts
196
+ const chunks = ['name,age\nJo', 'hn,30\nJane,25']
197
+
198
+ for await (const row of parseCSVStream<'name' | 'age'>(chunks)) {
199
+ console.log(row) // { name: 'John', age: '30' }, then { name: 'Jane', age: '25' }
200
+ }
201
+ ```
202
+
203
+ > [!TIP]
204
+ > `parseCSVStream` accepts any iterable of strings, including an array of lines.
205
+
206
+ #### `escapeCSVValue`
207
+
208
+ Escapes a single value for a CSV string. Returns an empty string for `null` and `undefined`. Values containing delimiters, quotes, or line breaks are quoted; embedded quotes are doubled.
209
+
210
+ ```ts
211
+ declare function escapeCSVValue(
212
+ value: unknown,
213
+ options?: {
214
+ /** @default ',' */
215
+ delimiter?: string
216
+ /** @default false */
217
+ quoteAll?: boolean
218
+ }
219
+ ): string
220
+ ```
221
+
222
+ **Example:**
223
+
224
+ ```ts
225
+ escapeCSVValue('hello, world') // '"hello, world"'
226
+ escapeCSVValue('contains "quotes"') // '"contains ""quotes"""'
227
+ ```
228
+
144
229
  ### Defu
145
230
 
146
231
  Recursively assign default properties. Simplified version based on [unjs/defu](https://github.com/unjs/defu).
@@ -154,10 +239,17 @@ The function replaces `null` and `undefined` values in the source with defaults,
154
239
  ```ts
155
240
  type PlainObject = Record<PropertyKey, any>
156
241
 
157
- declare function defu<T extends PlainObject>(
158
- source: T,
159
- ...defaults: PlainObject[]
160
- ): T
242
+ declare function defu<Source extends PlainObject, Defaults extends PlainObject[]>(
243
+ source: Source,
244
+ ...defaults: Defaults
245
+ ): Defu<Source, Defaults>
246
+ ```
247
+
248
+ The return type is a deep merge of the source over the defaults, so keys that only exist in the defaults are part of the result type:
249
+
250
+ ```ts
251
+ const result = defu({ a: 1 }, { b: 2 })
252
+ result.b // number – no cast needed
161
253
  ```
162
254
 
163
255
  **Example:**
@@ -262,25 +354,14 @@ emitter.off('foo', onFoo) // Unlisten
262
354
 
263
355
  #### `tryParseJSON`
264
356
 
265
- Type-safe wrapper around `JSON.stringify`.
357
+ Type-safe wrapper around `JSON.parse`.
266
358
 
267
- Falls back to the original value if the JSON serialization fails or the value is not a string.
359
+ Falls back to the original value if parsing fails or the value is not a string.
268
360
 
269
361
  ```ts
270
362
  declare function tryParseJSON<T = unknown>(value: unknown): T
271
363
  ```
272
364
 
273
- #### `cloneJSON`
274
-
275
- Clones the given JSON value.
276
-
277
- > [!NOTE]
278
- > The value must not contain circular references as JSON does not support them. It also must contain JSON serializable values.
279
-
280
- ```ts
281
- declare function cloneJSON<T>(value: T): T
282
- ```
283
-
284
365
  ### Module
285
366
 
286
367
  #### `interopDefault`
@@ -312,7 +393,7 @@ A simple general purpose memoizer utility.
312
393
  - Lazily computes a value when accessed
313
394
  - Auto-caches the result by overwriting the getter
314
395
 
315
- Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
396
+ Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invocation, since the getter itself is overwritten with the memoized value.
316
397
 
317
398
  ```ts
318
399
  declare function memoize<T>(getter: () => T): { value: T }
@@ -321,7 +402,7 @@ declare function memoize<T>(getter: () => T): { value: T }
321
402
  **Example:**
322
403
 
323
404
  ```ts
324
- const myValue = lazy(() => 'Hello, World!')
405
+ const myValue = memoize(() => 'Hello, World!')
325
406
  console.log(myValue.value) // Computes value, overwrites getter
326
407
  console.log(myValue.value) // Returns cached value
327
408
  console.log(myValue.value) // Returns cached value
@@ -332,7 +413,7 @@ console.log(myValue.value) // Returns cached value
332
413
  Strictly typed `Object.keys`.
333
414
 
334
415
  ```ts
335
- declare function objectKeys<T extends Record<any, any>>(obj: T): Array<`${keyof T & (string | number | boolean | null | undefined)}`>
416
+ declare function objectKeys<T extends Record<any, any>>(obj: T): Array<`${Extract<keyof T, string | number>}`>
336
417
  ```
337
418
 
338
419
  #### `objectEntries`
@@ -345,12 +426,97 @@ declare function objectEntries<T extends Record<any, any>>(obj: T): Array<[keyof
345
426
 
346
427
  #### `deepApply`
347
428
 
348
- Deeply applies a callback to every key-value pair in the given object, as well as nested objects and arrays.
429
+ Deeply applies a callback to every key-value pair in the given object, as well as nested objects and arrays (including arrays nested inside arrays).
349
430
 
350
431
  ```ts
351
432
  declare function deepApply<T extends Record<any, any>>(data: T, callback: (item: T, key: keyof T, value: T[keyof T]) => void): void
352
433
  ```
353
434
 
435
+ #### `isObject`
436
+
437
+ Checks if a value is an object with the plain `[object Object]` tag. Returns `true` for object literals, class instances, and `null`-prototype objects.
438
+
439
+ ```ts
440
+ declare function isObject(value: unknown): value is Record<any, any>
441
+ ```
442
+
443
+ ### Path
444
+
445
+ Utilities to build and normalize URL paths. All of them are also available from the `utilful/path` subpath export.
446
+
447
+ #### `withoutLeadingSlash` / `withLeadingSlash`
448
+
449
+ Removes or adds a leading slash.
450
+
451
+ ```ts
452
+ declare function withoutLeadingSlash(path?: string): string
453
+ declare function withLeadingSlash(path?: string): string
454
+ ```
455
+
456
+ #### `withoutTrailingSlash` / `withTrailingSlash`
457
+
458
+ Removes or adds a trailing slash, preserving query strings and hash fragments.
459
+
460
+ ```ts
461
+ declare function withoutTrailingSlash(path?: string): string
462
+ declare function withTrailingSlash(path?: string): string
463
+ ```
464
+
465
+ #### `joinURL`
466
+
467
+ Joins the given URL path segments, ensuring that there is only one slash between them.
468
+
469
+ ```ts
470
+ declare function joinURL(...paths: (string | undefined)[]): string
471
+ ```
472
+
473
+ **Example:**
474
+
475
+ ```ts
476
+ joinURL('/api/', '/users', '42') // '/api/users/42'
477
+ ```
478
+
479
+ #### `withBase` / `withoutBase`
480
+
481
+ Adds or removes a base path – each is a no-op if the base is already present (or absent).
482
+
483
+ ```ts
484
+ declare function withBase(input?: string, base?: string): string
485
+ declare function withoutBase(input?: string, base?: string): string
486
+ ```
487
+
488
+ **Example:**
489
+
490
+ ```ts
491
+ withBase('/users', '/api') // '/api/users'
492
+ withoutBase('/api/users', '/api') // '/users'
493
+ ```
494
+
495
+ #### `getPathname`
496
+
497
+ Returns the pathname of the given path – everything before the query string or hash. Absolute URLs (with a scheme, e.g. `https://example.com/foo`) return the URL's pathname; all other inputs are returned unchanged with the query string and hash removed.
498
+
499
+ ```ts
500
+ declare function getPathname(path?: string): string
501
+ ```
502
+
503
+ #### `withQuery`
504
+
505
+ Returns the URL with the given query parameters merged in. `undefined` values remove the parameter, array values append one entry per item, and object values are JSON-stringified.
506
+
507
+ ```ts
508
+ type QueryValue = string | number | boolean | QueryValue[] | Record<string, any> | null | undefined
509
+ type QueryObject = Record<string, QueryValue | QueryValue[]>
510
+
511
+ declare function withQuery(input: string, query?: QueryObject): string
512
+ ```
513
+
514
+ **Example:**
515
+
516
+ ```ts
517
+ withQuery('/api/users', { page: 2, tags: ['a', 'b'] }) // '/api/users?page=2&tags=a&tags=b'
518
+ ```
519
+
354
520
  ### Result
355
521
 
356
522
  The `Result` type represents either success (`Ok`) or failure (`Err`). It provides a type-safe way to handle errors without relying on exceptions.
@@ -492,6 +658,9 @@ declare function toResult<T, E = unknown>(fn: () => T): Result<T, E>
492
658
  declare function toResult<T, E = unknown>(promise: Promise<T>): Promise<Result<T, E>>
493
659
  ```
494
660
 
661
+ > [!NOTE]
662
+ > The function overload must be synchronous. For asynchronous work, pass the promise itself – a function returning a promise throws a `TypeError`, since its rejection could not be captured as `Err`.
663
+
495
664
  **Example:**
496
665
 
497
666
  ```ts
package/dist/array.d.mts CHANGED
@@ -1,11 +1,11 @@
1
1
  //#region src/array.d.ts
2
2
  /**
3
- * Represents a value that can be either a single value or an array of values.
4
- */
3
+ * Represents a value that can be either a single value or an array of values.
4
+ */
5
5
  type MaybeArray<T> = T | T[];
6
6
  /**
7
- * Converts `MaybeArray<T>` to `Array<T>`.
8
- */
7
+ * Converts `MaybeArray<T>` to `Array<T>`.
8
+ */
9
9
  declare function toArray<T>(array?: MaybeArray<T> | null | undefined): T[];
10
10
  //#endregion
11
11
  export { MaybeArray, toArray };
package/dist/csv.d.mts CHANGED
@@ -1,11 +1,11 @@
1
1
  //#region src/csv.d.ts
2
2
  /**
3
- * Represents a row in a CSV file with column names of type T.
4
- */
3
+ * Represents a row in a CSV file with column names of type T.
4
+ */
5
5
  type CSVRow<T extends string = string> = Record<T, string>;
6
6
  /**
7
- * Options for the `createCSV` function.
8
- */
7
+ * Options for the CSV creation functions.
8
+ */
9
9
  interface CSVCreateOptions {
10
10
  /** @default ',' */
11
11
  delimiter?: string;
@@ -17,160 +17,150 @@ interface CSVCreateOptions {
17
17
  lineEnding?: string;
18
18
  }
19
19
  /**
20
- * Converts an array of objects to a comma-separated values (CSV) string.
21
- *
22
- * @remarks
23
- * When `columns` is omitted, the function automatically infers columns by collecting
24
- * the union of all keys across all objects in first-seen order. This means if different
25
- * objects have different keys, all keys will be included in the CSV. Objects missing
26
- * certain keys will have empty values for those columns.
27
- *
28
- * When `columns` is provided explicitly, only those columns are included in the output,
29
- * allowing you to control column order and filter out unwanted properties.
30
- *
31
- * @example
32
- * // With explicit columns
33
- * const data = [
34
- * { name: 'John', age: '30', city: 'New York' },
35
- * { name: 'Jane', age: '25', city: 'Boston' }
36
- * ]
37
- *
38
- * const csv = createCSV(data, ['name', 'age'])
39
- * // name,age
40
- * // John,30
41
- * // Jane,25
42
- *
43
- * @example
44
- * // With inferred columns (union of all keys in first-seen order)
45
- * const rows = [
46
- * { name: 'John', age: '30' },
47
- * { name: 'Jane', city: 'Boston' },
48
- * ]
49
- *
50
- * const csv = createCSV(rows)
51
- * // name,age,city
52
- * // John,30,
53
- * // Jane,,Boston
54
- */
20
+ * Options for the CSV parsing functions.
21
+ */
22
+ interface CSVParseOptions {
23
+ /** @default ',' */
24
+ delimiter?: string;
25
+ /**
26
+ * Trim whitespace from unquoted headers and values.
27
+ * @default false
28
+ */
29
+ trim?: boolean;
30
+ /**
31
+ * Throw if a row's field count does not match the header row.
32
+ * @default true
33
+ */
34
+ strict?: boolean;
35
+ }
36
+ /**
37
+ * Converts an array of objects to a comma-separated values (CSV) string.
38
+ *
39
+ * @remarks
40
+ * When `columns` is omitted, the function automatically infers columns by collecting
41
+ * the union of all keys across all objects in first-seen order. This means if different
42
+ * objects have different keys, all keys will be included in the CSV. Objects missing
43
+ * certain keys will have empty values for those columns.
44
+ *
45
+ * When `columns` is provided explicitly, only those columns are included in the output,
46
+ * allowing you to control column order and filter out unwanted properties.
47
+ *
48
+ * @example
49
+ * // With explicit columns
50
+ * const data = [
51
+ * { name: 'John', age: '30', city: 'New York' },
52
+ * { name: 'Jane', age: '25', city: 'Boston' }
53
+ * ]
54
+ *
55
+ * const csv = createCSV(data, ['name', 'age'])
56
+ * // name,age
57
+ * // John,30
58
+ * // Jane,25
59
+ *
60
+ * @example
61
+ * // With inferred columns (union of all keys in first-seen order)
62
+ * const rows = [
63
+ * { name: 'John', age: '30' },
64
+ * { name: 'Jane', city: 'Boston' },
65
+ * ]
66
+ *
67
+ * const csv = createCSV(rows)
68
+ * // name,age,city
69
+ * // John,30,
70
+ * // Jane,,Boston
71
+ */
55
72
  declare function createCSV<T extends Record<string, unknown>>(data: readonly T[], columns: readonly (keyof T)[], options?: CSVCreateOptions): string;
56
73
  declare function createCSV<T extends Record<string, unknown>>(data: readonly T[], options?: CSVCreateOptions): string;
57
74
  /**
58
- * Creates a CSV stream from an iterable or async iterable of objects.
59
- *
60
- * @remarks
61
- * This function yields CSV content as strings, including line endings.
62
- * Each yielded chunk contains complete lines (header and/or data rows).
63
- *
64
- * @example
65
- * const data = [
66
- * { name: 'John', age: '30' },
67
- * { name: 'Jane', age: '25' }
68
- * ]
69
- *
70
- * for await (const chunk of createCSVStream(data, ['name', 'age'])) {
71
- * console.log(chunk)
72
- * }
73
- */
75
+ * Creates a CSV stream from an iterable or async iterable of objects.
76
+ *
77
+ * @remarks
78
+ * This function yields CSV content as strings, including line endings.
79
+ * Each yielded chunk contains complete lines (header and/or data rows).
80
+ *
81
+ * @example
82
+ * const data = [
83
+ * { name: 'John', age: '30' },
84
+ * { name: 'Jane', age: '25' }
85
+ * ]
86
+ *
87
+ * for await (const chunk of createCSVStream(data, ['name', 'age'])) {
88
+ * console.log(chunk)
89
+ * }
90
+ */
74
91
  declare function createCSVStream<T extends Record<string, unknown>>(data: AsyncIterable<T> | Iterable<T>, columns: readonly (keyof T)[], options?: CSVCreateOptions): AsyncIterable<string>;
75
92
  /**
76
- * Creates a CSV string from an async iterable or iterable of objects.
77
- *
78
- * @remarks
79
- * This is a convenience wrapper around `createCSVStream` that collects
80
- * all chunks into a single string. Note that the result will have a
81
- * trailing line ending, unlike the synchronous `createCSV`.
82
- *
83
- * @example
84
- * const data = [
85
- * { name: 'John', age: '30' },
86
- * { name: 'Jane', age: '25' }
87
- * ]
88
- *
89
- * const csv = await createCSVAsync(data, ['name', 'age'])
90
- */
93
+ * Creates a CSV string from an async iterable or iterable of objects.
94
+ *
95
+ * @remarks
96
+ * This is a convenience wrapper around `createCSVStream` that collects
97
+ * all chunks into a single string. Note that the result will have a
98
+ * trailing line ending, unlike the synchronous `createCSV`.
99
+ *
100
+ * @example
101
+ * const data = [
102
+ * { name: 'John', age: '30' },
103
+ * { name: 'Jane', age: '25' }
104
+ * ]
105
+ *
106
+ * const csv = await createCSVAsync(data, ['name', 'age'])
107
+ */
91
108
  declare function createCSVAsync<T extends Record<string, unknown>>(data: AsyncIterable<T> | Iterable<T>, columns: readonly (keyof T)[], options?: CSVCreateOptions): Promise<string>;
92
109
  /**
93
- * Escapes a value for a CSV string.
94
- *
95
- * @remarks
96
- * Returns an empty string if the value is `null` or `undefined`.
97
- * Values containing delimiters, quotes, or line breaks are quoted.
98
- * Within quoted values, double quotes are escaped by doubling them.
99
- *
100
- * @example
101
- * escapeCSVValue('hello, world') // "hello, world"
102
- * escapeCSVValue('contains "quotes"') // "contains ""quotes"""
103
- */
110
+ * Escapes a value for a CSV string.
111
+ *
112
+ * @remarks
113
+ * Returns an empty string if the value is `null` or `undefined`.
114
+ * Values containing delimiters, quotes, or line breaks are quoted.
115
+ * Within quoted values, double quotes are escaped by doubling them.
116
+ *
117
+ * @example
118
+ * escapeCSVValue('hello, world') // "hello, world"
119
+ * escapeCSVValue('contains "quotes"') // "contains ""quotes"""
120
+ */
104
121
  declare function escapeCSVValue(value: unknown, options?: {
105
- /** @default ',' */delimiter?: string; /** @default false */
122
+ /** @default ',' */
123
+ delimiter?: string;
124
+ /** @default false */
106
125
  quoteAll?: boolean;
107
126
  }): string;
108
127
  /**
109
- * Parses a comma-separated values (CSV) string into an array of objects.
110
- *
111
- * @remarks
112
- * The first row of the CSV string is used as the header row.
113
- *
114
- * @example
115
- * const csv = `name,age
116
- * John,30
117
- * Jane,25`
118
- *
119
- * const data = parseCSV<'name' | 'age'>(csv)
120
- * // [{ name: 'John', age: '30' }, { name: 'Jane', age: '25' }]
121
- */
122
- declare function parseCSV<Header extends string>(csv?: string | null | undefined, options?: {
123
- /** @default ',' */delimiter?: string;
124
- /**
125
- * Trim whitespace from headers and values.
126
- * @default true
127
- */
128
- trim?: boolean;
129
- /**
130
- * Throw error if row has more fields than headers.
131
- * @default true
132
- */
133
- strict?: boolean;
134
- }): CSVRow<Header>[];
128
+ * Parses a comma-separated values (CSV) string into an array of objects.
129
+ *
130
+ * @remarks
131
+ * The first row of the CSV string is used as the header row. A leading
132
+ * UTF-8 byte order mark is stripped.
133
+ *
134
+ * Parsing tolerances (lenient deviations from RFC 4180):
135
+ * - LF, CR, and CRLF line endings are all accepted
136
+ * - Whitespace between a closing quote and the next delimiter or line break is ignored
137
+ * - A field is only treated as quoted if it starts with a quote; quotes inside
138
+ * unquoted fields are kept as literal characters
139
+ *
140
+ * @example
141
+ * const csv = `name,age
142
+ * John,30
143
+ * Jane,25`
144
+ *
145
+ * const data = parseCSV<'name' | 'age'>(csv)
146
+ * // [{ name: 'John', age: '30' }, { name: 'Jane', age: '25' }]
147
+ */
148
+ declare function parseCSV<Header extends string>(csv?: string | null | undefined, options?: CSVParseOptions): CSVRow<Header>[];
135
149
  /**
136
- * Parses CSV data from an async iterable or iterable of string chunks.
137
- *
138
- * @remarks
139
- * This function yields CSV rows as they are parsed. Chunks do not need to
140
- * align with row boundaries; the parser handles quotes and newlines correctly
141
- * across chunk boundaries.
142
- *
143
- * @example
144
- * const chunks = ['name,age\nJo', 'hn,30\nJane,25']
145
- *
146
- * for await (const row of parseCSVStream<'name' | 'age'>(chunks)) {
147
- * console.log(row)
148
- * }
149
- */
150
- declare function parseCSVStream<Header extends string>(chunks: AsyncIterable<string> | Iterable<string>, options?: {
151
- delimiter?: string;
152
- trim?: boolean;
153
- strict?: boolean;
154
- }): AsyncIterable<CSVRow<Header>>;
155
- /**
156
- * Parses CSV data from an async iterable or iterable of lines.
157
- *
158
- * @remarks
159
- * This is a convenience wrapper around `parseCSVStream` that treats each line
160
- * as a chunk. Note that lines do not necessarily correspond to CSV rows due to
161
- * quoted fields containing newlines. The parser handles this correctly.
162
- *
163
- * @example
164
- * const lines = ['name,age', 'John,30', 'Jane,25']
165
- *
166
- * for await (const row of parseCSVFromLines<'name' | 'age'>(lines)) {
167
- * console.log(row)
168
- * }
169
- */
170
- declare function parseCSVFromLines<Header extends string>(lines: AsyncIterable<string> | Iterable<string>, options?: {
171
- delimiter?: string;
172
- trim?: boolean;
173
- strict?: boolean;
174
- }): AsyncIterable<CSVRow<Header>>;
150
+ * Parses CSV data from an async iterable or iterable of string chunks.
151
+ *
152
+ * @remarks
153
+ * This function yields CSV rows as they are parsed. Chunks do not need to
154
+ * align with row boundaries; the parser handles quotes and newlines correctly
155
+ * across chunk boundaries.
156
+ *
157
+ * @example
158
+ * const chunks = ['name,age\nJo', 'hn,30\nJane,25']
159
+ *
160
+ * for await (const row of parseCSVStream<'name' | 'age'>(chunks)) {
161
+ * console.log(row)
162
+ * }
163
+ */
164
+ declare function parseCSVStream<Header extends string>(chunks: AsyncIterable<string> | Iterable<string>, options?: CSVParseOptions): AsyncIterable<CSVRow<Header>>;
175
165
  //#endregion
176
- export { CSVCreateOptions, CSVRow, createCSV, createCSVAsync, createCSVStream, escapeCSVValue, parseCSV, parseCSVFromLines, parseCSVStream };
166
+ export { CSVCreateOptions, CSVParseOptions, CSVRow, createCSV, createCSVAsync, createCSVStream, escapeCSVValue, parseCSV, parseCSVStream };