csv-stream-lite 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EXAMPLES.md +197 -0
- package/LICENSE +21 -0
- package/README.md +273 -0
- package/dist/byte-buffer.d.ts +112 -0
- package/dist/byte-buffer.js +282 -0
- package/dist/defaults.d.ts +8 -0
- package/dist/defaults.js +8 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.js +30 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/parser.d.ts +293 -0
- package/dist/parser.js +596 -0
- package/dist/stringify.d.ts +91 -0
- package/dist/stringify.js +186 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.js +20 -0
- package/package.json +69 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { DEFAULT_MAX_BUFFER_SIZE } from './defaults.js';
|
|
2
|
+
import { BufferSizeExceededError, EofReachedError, NoMoreTokensError, } from './errors.js';
|
|
3
|
+
import { bytesToString, stringToBytes } from './utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Converts a ReadableStream into an AsyncIterable.
|
|
6
|
+
*
|
|
7
|
+
* @param stream - The ReadableStream to convert
|
|
8
|
+
* @returns An AsyncIterable that yields items from the stream
|
|
9
|
+
*/
|
|
10
|
+
function readableStreamToAsyncIterable(stream) {
|
|
11
|
+
const reader = stream.getReader();
|
|
12
|
+
return {
|
|
13
|
+
async *[Symbol.asyncIterator]() {
|
|
14
|
+
while (true) {
|
|
15
|
+
const { done, value } = await reader.read();
|
|
16
|
+
if (done) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
yield value;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A buffer for managing byte-level input with support for async streams.
|
|
26
|
+
* Provides lookahead, consumption tracking, and buffer compaction capabilities.
|
|
27
|
+
*/
|
|
28
|
+
export class ByteBuffer {
|
|
29
|
+
/** Maximum size of the buffer before compaction */
|
|
30
|
+
maxBufferSize = DEFAULT_MAX_BUFFER_SIZE;
|
|
31
|
+
/** Whether end of file has been signaled */
|
|
32
|
+
eof = false;
|
|
33
|
+
/** Current position in the buffer */
|
|
34
|
+
bufferIndex = 0;
|
|
35
|
+
/** Whether the buffer is locked against compaction */
|
|
36
|
+
locked = false;
|
|
37
|
+
/** Whether to allow exceeding the buffer size temporarily */
|
|
38
|
+
allowBufferToBeExceeded = true;
|
|
39
|
+
/** Current position in the input stream */
|
|
40
|
+
inputOffset = 0;
|
|
41
|
+
/** Number of outputs generated */
|
|
42
|
+
outputOffset = 0;
|
|
43
|
+
/** Buffer holding input items */
|
|
44
|
+
buffer = [];
|
|
45
|
+
/** Optional async iterable input source */
|
|
46
|
+
asyncIterable;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new ByteBuffer instance.
|
|
49
|
+
*
|
|
50
|
+
* @param asyncIterable - Optional async iterable source for streaming input
|
|
51
|
+
*/
|
|
52
|
+
constructor(asyncIterable) {
|
|
53
|
+
this.asyncIterable =
|
|
54
|
+
asyncIterable instanceof ReadableStream
|
|
55
|
+
? readableStreamToAsyncIterable(asyncIterable)
|
|
56
|
+
: typeof asyncIterable === 'string'
|
|
57
|
+
? (function* () {
|
|
58
|
+
yield* [asyncIterable];
|
|
59
|
+
})()
|
|
60
|
+
: asyncIterable;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Reads data from the stream into the buffer.
|
|
64
|
+
* Reads up to maxBufferSize bytes at a time.
|
|
65
|
+
*/
|
|
66
|
+
readStream() {
|
|
67
|
+
if (!this.asyncIterable || !(Symbol.iterator in this.asyncIterable)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const iterator = this.asyncIterable[Symbol.iterator]();
|
|
71
|
+
let processed = false;
|
|
72
|
+
while (this.length < this.maxBufferSize || !processed) {
|
|
73
|
+
const next = iterator.next();
|
|
74
|
+
processed = true;
|
|
75
|
+
if (next.done) {
|
|
76
|
+
this.eof = true;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
const value = next.value;
|
|
80
|
+
this.feed(value);
|
|
81
|
+
}
|
|
82
|
+
return processed;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Reads data from the sync or async stream into the buffer.
|
|
86
|
+
* Reads up to maxBufferSize bytes at a time.
|
|
87
|
+
*/
|
|
88
|
+
async readStreamAsync() {
|
|
89
|
+
this.readStream();
|
|
90
|
+
if (!this.asyncIterable ||
|
|
91
|
+
!(Symbol.asyncIterator in this.asyncIterable)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const iterator = this.asyncIterable[Symbol.asyncIterator]();
|
|
95
|
+
let processed = false;
|
|
96
|
+
while (this.length < this.maxBufferSize || !processed) {
|
|
97
|
+
processed = true;
|
|
98
|
+
const next = await iterator.next();
|
|
99
|
+
if (next.done) {
|
|
100
|
+
this.eof = true;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const value = next.value;
|
|
104
|
+
this.feed(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Gets the current length of the buffer.
|
|
109
|
+
*
|
|
110
|
+
* @returns The number of bytes in the buffer
|
|
111
|
+
*/
|
|
112
|
+
get length() {
|
|
113
|
+
return this.buffer.length;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Feeds input items into the parser buffer.
|
|
117
|
+
*
|
|
118
|
+
* @param input - Input items to add to the buffer
|
|
119
|
+
*/
|
|
120
|
+
feed(...input) {
|
|
121
|
+
for (const item of input) {
|
|
122
|
+
if (Array.isArray(item)) {
|
|
123
|
+
for (const subItem of item) {
|
|
124
|
+
this.push(subItem);
|
|
125
|
+
}
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
else if (item instanceof Uint8Array) {
|
|
129
|
+
for (const subItem of item) {
|
|
130
|
+
this.push(subItem);
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
else if (typeof item === 'string') {
|
|
135
|
+
const encoded = stringToBytes(item);
|
|
136
|
+
for (const byte of encoded) {
|
|
137
|
+
this.push(byte);
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
this.push(item);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
push(byte) {
|
|
145
|
+
if (!this.allowBufferToBeExceeded &&
|
|
146
|
+
this.buffer.length >= this.maxBufferSize) {
|
|
147
|
+
throw new BufferSizeExceededError('Buffer size exceeded maximum limit');
|
|
148
|
+
}
|
|
149
|
+
this.buffer.push(byte);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Checks if end of file has been reached and buffer is exhausted.
|
|
153
|
+
*
|
|
154
|
+
* @returns True if no more input is available
|
|
155
|
+
*/
|
|
156
|
+
atEof() {
|
|
157
|
+
return this.eof && this.bufferIndex >= this.buffer.length;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Peeks at an item in the buffer without consuming it.
|
|
161
|
+
*
|
|
162
|
+
* @param ahead - Number of positions to look ahead (default: 0)
|
|
163
|
+
* @returns The item at the peek position, or null if at EOF
|
|
164
|
+
* @throws NoMoreTokensError if more input is needed and EOF not signaled
|
|
165
|
+
*/
|
|
166
|
+
peek(ahead = 0) {
|
|
167
|
+
const index = this.bufferIndex + ahead;
|
|
168
|
+
if (index >= this.buffer.length) {
|
|
169
|
+
if (!this.eof) {
|
|
170
|
+
if (!this.readStream()) {
|
|
171
|
+
throw new NoMoreTokensError('No more items available');
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
return this.peek(ahead);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
return this.buffer[index];
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Consumes and returns the next item from the buffer.
|
|
183
|
+
*
|
|
184
|
+
* @returns The next item
|
|
185
|
+
* @throws NoMoreTokensError if more input is needed and EOF not signaled
|
|
186
|
+
* @throws EofReachedError if at EOF and no more items available
|
|
187
|
+
*/
|
|
188
|
+
next() {
|
|
189
|
+
if (this.bufferIndex >= this.buffer.length) {
|
|
190
|
+
if (this.readStream()) {
|
|
191
|
+
return this.next();
|
|
192
|
+
}
|
|
193
|
+
if (!this.eof) {
|
|
194
|
+
throw new NoMoreTokensError('No more items available');
|
|
195
|
+
}
|
|
196
|
+
throw new EofReachedError('End of file reached');
|
|
197
|
+
}
|
|
198
|
+
this.inputOffset++;
|
|
199
|
+
return this.buffer[this.bufferIndex++];
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Consumes and validates the next item against an expected type or value.
|
|
203
|
+
*
|
|
204
|
+
* @typeParam T - The expected item type
|
|
205
|
+
* @param itemType - Constructor or value to match against
|
|
206
|
+
* @returns The consumed item cast to the expected type
|
|
207
|
+
* @throws Error if the item doesn't match the expected type/value
|
|
208
|
+
*/
|
|
209
|
+
expect(itemType) {
|
|
210
|
+
const item = this.next();
|
|
211
|
+
if (item !== itemType) {
|
|
212
|
+
throw new Error(`Expected ${itemType} but got ${item}`);
|
|
213
|
+
}
|
|
214
|
+
return itemType;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Compacts the buffer by removing consumed items
|
|
218
|
+
*/
|
|
219
|
+
compact() {
|
|
220
|
+
if (!this.locked && this.bufferIndex > 0) {
|
|
221
|
+
this.buffer = this.buffer.slice(this.bufferIndex);
|
|
222
|
+
this.bufferIndex = 0;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Override to customize when to compact the buffer
|
|
227
|
+
* By default, compacts when more than maxBufferSize bytes have been consumed
|
|
228
|
+
*
|
|
229
|
+
* @returns boolean indicating whether to compact the buffer
|
|
230
|
+
*/
|
|
231
|
+
canCompact() {
|
|
232
|
+
return this.bufferIndex > this.maxBufferSize;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Attempts to execute a function, resetting buffer position on failure.
|
|
236
|
+
* Useful for speculative parsing attempts that may need to be retried.
|
|
237
|
+
*
|
|
238
|
+
* @typeParam T - The return type of the try function
|
|
239
|
+
* @param tryFn - Function to attempt execution
|
|
240
|
+
* @param onFail - Optional callback invoked on failure
|
|
241
|
+
* @returns The result of tryFn if successful, undefined if NoMoreTokensError thrown
|
|
242
|
+
*/
|
|
243
|
+
resetOnFail(tryFn, onFail) {
|
|
244
|
+
const bufferIndex = this.bufferIndex;
|
|
245
|
+
try {
|
|
246
|
+
const result = tryFn();
|
|
247
|
+
if (this.canCompact()) {
|
|
248
|
+
this.compact();
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
if (e instanceof NoMoreTokensError) {
|
|
254
|
+
this.bufferIndex = bufferIndex;
|
|
255
|
+
onFail?.(e);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
throw e;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Returns a string representation of the buffer state for debugging.
|
|
265
|
+
*
|
|
266
|
+
* @returns A formatted string showing buffer contents and state
|
|
267
|
+
*/
|
|
268
|
+
toString() {
|
|
269
|
+
return [
|
|
270
|
+
'ByteBuffer {',
|
|
271
|
+
` buffer: [${this.buffer.join(', ')}],`,
|
|
272
|
+
` bufferIndex: ${this.bufferIndex},`,
|
|
273
|
+
` inputOffset: ${this.inputOffset},`,
|
|
274
|
+
` outputOffset: ${this.outputOffset},`,
|
|
275
|
+
` eof: ${this.eof},`,
|
|
276
|
+
` as string: ${bytesToString(new Uint8Array(this.buffer))}`,
|
|
277
|
+
' as string from bufferIndex: ' +
|
|
278
|
+
bytesToString(new Uint8Array(this.buffer.slice(this.bufferIndex))),
|
|
279
|
+
'}',
|
|
280
|
+
].join('\n');
|
|
281
|
+
}
|
|
282
|
+
}
|
package/dist/defaults.js
ADDED
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for CSV Stream Lite errors.
|
|
3
|
+
*/
|
|
4
|
+
export declare class CsvStreamLiteError extends Error {
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when the buffer is empty and more input is needed.
|
|
8
|
+
*/
|
|
9
|
+
export declare class NoMoreTokensError extends CsvStreamLiteError {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Error thrown when the end of file has been reached and no more items are available.
|
|
13
|
+
*/
|
|
14
|
+
export declare class EofReachedError extends CsvStreamLiteError {
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown when the buffer size limit is exceeded.
|
|
18
|
+
*/
|
|
19
|
+
export declare class BufferSizeExceededError extends CsvStreamLiteError {
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Error thrown when a CSV row has more columns than expected when `strictColumns` is enabled.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TooManyColumnsError extends CsvStreamLiteError {
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown when a CSV row has fewer columns than expected when `strictColumns` is enabled.
|
|
28
|
+
*/
|
|
29
|
+
export declare class TooFewColumnsError extends CsvStreamLiteError {
|
|
30
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for CSV Stream Lite errors.
|
|
3
|
+
*/
|
|
4
|
+
export class CsvStreamLiteError extends Error {
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when the buffer is empty and more input is needed.
|
|
8
|
+
*/
|
|
9
|
+
export class NoMoreTokensError extends CsvStreamLiteError {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Error thrown when the end of file has been reached and no more items are available.
|
|
13
|
+
*/
|
|
14
|
+
export class EofReachedError extends CsvStreamLiteError {
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown when the buffer size limit is exceeded.
|
|
18
|
+
*/
|
|
19
|
+
export class BufferSizeExceededError extends CsvStreamLiteError {
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Error thrown when a CSV row has more columns than expected when `strictColumns` is enabled.
|
|
23
|
+
*/
|
|
24
|
+
export class TooManyColumnsError extends CsvStreamLiteError {
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown when a CSV row has fewer columns than expected when `strictColumns` is enabled.
|
|
28
|
+
*/
|
|
29
|
+
export class TooFewColumnsError extends CsvStreamLiteError {
|
|
30
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { ByteBuffer } from './byte-buffer.js';
|
|
2
|
+
import { CsvStringify, CsvStringifyOptions } from './stringify.js';
|
|
3
|
+
import { ByteStream, CsvObjectShape, CsvString } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Options for configuring CSV entity parsing.
|
|
6
|
+
*/
|
|
7
|
+
export interface CsvEntityOptions {
|
|
8
|
+
/** Character used to separate fields. Defaults to ',' */
|
|
9
|
+
separator?: string;
|
|
10
|
+
/** Character used to escape special characters. Defaults to '"' */
|
|
11
|
+
escapeChar?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Abstract base class for CSV entities that supports both synchronous and asynchronous parsing.
|
|
15
|
+
* Provides common functionality for reading and streaming CSV data.
|
|
16
|
+
*
|
|
17
|
+
* @typeParam T - The type returned by read operations
|
|
18
|
+
* @typeParam S - The type yielded by stream operations (defaults to T)
|
|
19
|
+
*/
|
|
20
|
+
export declare abstract class CsvEntity<T, S = T> implements Required<CsvEntityOptions> {
|
|
21
|
+
byteBuffer: ByteBuffer;
|
|
22
|
+
separator: string;
|
|
23
|
+
escapeChar: string;
|
|
24
|
+
consumed: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new CSV entity.
|
|
27
|
+
*
|
|
28
|
+
* @param asyncIterable - Optional byte stream or buffer to parse
|
|
29
|
+
* @param options - Configuration options for parsing
|
|
30
|
+
*/
|
|
31
|
+
constructor(asyncIterable?: ByteStream | ByteBuffer, options?: CsvEntityOptions);
|
|
32
|
+
set maxBufferSize(size: number);
|
|
33
|
+
get maxBufferSize(): number;
|
|
34
|
+
set allowBufferToBeExceeded(value: boolean);
|
|
35
|
+
get allowBufferToBeExceeded(): boolean;
|
|
36
|
+
protected abstract parse(): T;
|
|
37
|
+
protected abstract parseAsync(): Promise<T>;
|
|
38
|
+
protected abstract streamImpl(): Generator<S>;
|
|
39
|
+
/**
|
|
40
|
+
* Reads and parses the entire entity synchronously.
|
|
41
|
+
* Marks the entity as consumed after reading.
|
|
42
|
+
*
|
|
43
|
+
* @returns The parsed result of type T
|
|
44
|
+
*/
|
|
45
|
+
read(): T;
|
|
46
|
+
/**
|
|
47
|
+
* Reads and parses the entire entity asynchronously.
|
|
48
|
+
* Marks the entity as consumed after reading.
|
|
49
|
+
*
|
|
50
|
+
* @returns A promise that resolves to the parsed result of type T
|
|
51
|
+
*/
|
|
52
|
+
readAsync(): Promise<T>;
|
|
53
|
+
/**
|
|
54
|
+
* Returns a synchronous generator that yields chunks of type S.
|
|
55
|
+
* Marks the entity as consumed when iteration completes.
|
|
56
|
+
*
|
|
57
|
+
* @returns A generator that yields values of type S
|
|
58
|
+
*/
|
|
59
|
+
stream(): Generator<S>;
|
|
60
|
+
/**
|
|
61
|
+
* Returns an asynchronous generator that yields chunks of type S.
|
|
62
|
+
* Handles buffering and automatically reads more data as needed.
|
|
63
|
+
*
|
|
64
|
+
* @returns An async generator that yields values of type S
|
|
65
|
+
*/
|
|
66
|
+
streamAsync(): AsyncGenerator<S>;
|
|
67
|
+
/**
|
|
68
|
+
* Consumes the entity if it hasn't been consumed yet.
|
|
69
|
+
* This ensures the buffer advances to the end of this entity.
|
|
70
|
+
*/
|
|
71
|
+
consume(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Asynchronously consumes the entity if it hasn't been consumed yet.
|
|
74
|
+
* This ensures the buffer advances to the end of this entity.
|
|
75
|
+
*
|
|
76
|
+
* @returns A promise that resolves when consumption is complete
|
|
77
|
+
*/
|
|
78
|
+
consumeAsync(): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Makes this entity iterable using the synchronous stream.
|
|
81
|
+
*
|
|
82
|
+
* @returns A generator that yields values of type S
|
|
83
|
+
*/
|
|
84
|
+
[Symbol.iterator](): Generator<S>;
|
|
85
|
+
/**
|
|
86
|
+
* Makes this entity async iterable using the asynchronous stream.
|
|
87
|
+
*
|
|
88
|
+
* @returns An async generator that yields values of type S
|
|
89
|
+
*/
|
|
90
|
+
[Symbol.asyncIterator](): AsyncGenerator<S>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Represents a single CSV cell that can be read as a string or streamed in chunks.
|
|
94
|
+
* Handles quoted cells and escape sequences according to CSV standards.
|
|
95
|
+
*/
|
|
96
|
+
export declare class CsvCell extends CsvEntity<string> {
|
|
97
|
+
chunkSize: number;
|
|
98
|
+
endOfLineReached: boolean;
|
|
99
|
+
protected parse(): string;
|
|
100
|
+
protected parseAsync(): Promise<string>;
|
|
101
|
+
/**
|
|
102
|
+
* Reads the cell value and transforms it using the provided function.
|
|
103
|
+
* Special handling for Boolean transformer: converts 'true'/'false' strings to boolean.
|
|
104
|
+
*
|
|
105
|
+
* @typeParam T - The type to transform the cell value into
|
|
106
|
+
* @param transform - Function to transform the cell string into type T
|
|
107
|
+
* @returns The transformed value of type T
|
|
108
|
+
*/
|
|
109
|
+
readAs<T>(transform: (cell: string) => T): T;
|
|
110
|
+
/**
|
|
111
|
+
* Asynchronously reads the cell value and transforms it using the provided function.
|
|
112
|
+
* Special handling for Boolean transformer: converts 'true'/'false' strings to boolean.
|
|
113
|
+
*
|
|
114
|
+
* @typeParam T - The type to transform the cell value into
|
|
115
|
+
* @param transform - Function to transform the cell string into type T (can be async)
|
|
116
|
+
* @returns A promise that resolves to the transformed value of type T
|
|
117
|
+
*/
|
|
118
|
+
readAsAsync<T>(transform: (cell: string) => Promise<T> | T): Promise<T>;
|
|
119
|
+
protected streamImpl(): Generator<string>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Options for reading a CSV row as an object.
|
|
123
|
+
*
|
|
124
|
+
* @typeParam T - The object type with headers as keys
|
|
125
|
+
* @typeParam O - The output type after optional transformation (defaults to T)
|
|
126
|
+
*/
|
|
127
|
+
export interface CsvRowObjectOptions<T extends object, I = unknown> {
|
|
128
|
+
/** Headers for the CSV row */
|
|
129
|
+
headers: string[];
|
|
130
|
+
/** Shape definition mapping headers to type transformers, or an array of header names */
|
|
131
|
+
shape?: CsvObjectShape<T>;
|
|
132
|
+
/** Optional row index for error messages */
|
|
133
|
+
rowIndex?: number;
|
|
134
|
+
/** Whether to include extra cells beyond defined headers. Defaults to false */
|
|
135
|
+
includeExtraCells?: boolean;
|
|
136
|
+
/** Whether to enforce exact column count matching headers. Defaults to false */
|
|
137
|
+
strictColumns?: boolean;
|
|
138
|
+
/** Optional function to transform the parsed row object */
|
|
139
|
+
transform?: (row: I) => T;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Represents a single CSV row that can be read as an array of strings or streamed as individual cells.
|
|
143
|
+
* Can also be parsed into an object using a shape definition.
|
|
144
|
+
*
|
|
145
|
+
* @typeParam T - The object type when reading as an object
|
|
146
|
+
* @typeParam O - The output type after optional transformation (defaults to T)
|
|
147
|
+
*/
|
|
148
|
+
export declare class CsvRow<T extends object = object, I = unknown> extends CsvEntity<string[], CsvCell> {
|
|
149
|
+
protected parse(): string[];
|
|
150
|
+
protected parseAsync(): Promise<string[]>;
|
|
151
|
+
protected streamImpl(): Generator<CsvCell>;
|
|
152
|
+
/**
|
|
153
|
+
* Reads the row as an object using the provided shape definition.
|
|
154
|
+
* Handles column count validation and extra cells based on options.
|
|
155
|
+
*
|
|
156
|
+
* @param options - Configuration for reading the row as an object
|
|
157
|
+
* @returns The parsed object of type O
|
|
158
|
+
* @throws {TooManyColumnsError} If strictColumns is true and extra cells are found
|
|
159
|
+
* @throws {TooFewColumnsError} If strictColumns is true and cells are missing
|
|
160
|
+
*/
|
|
161
|
+
readObject(options: CsvRowObjectOptions<T, I>): T;
|
|
162
|
+
/**
|
|
163
|
+
* Asynchronously reads the row as an object using the provided shape definition.
|
|
164
|
+
* Automatically handles buffer refills as needed.
|
|
165
|
+
*
|
|
166
|
+
* @param options - Configuration for reading the row as an object
|
|
167
|
+
* @returns A promise that resolves to the parsed object of type O
|
|
168
|
+
*/
|
|
169
|
+
readObjectAsync(options: CsvRowObjectOptions<T, I>): Promise<T>;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Main CSV parser class for parsing complete CSV documents.
|
|
173
|
+
* Supports reading headers, streaming rows, and converting rows to objects.
|
|
174
|
+
*
|
|
175
|
+
* @typeParam T - The object type for each row when reading as objects
|
|
176
|
+
* @typeParam O - The output type after optional transformation (defaults to T)
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* // Parse CSV with headers
|
|
181
|
+
* const csv = new Csv(fileStream)
|
|
182
|
+
* for await (const row of csv.streamObjectsAsync()) {
|
|
183
|
+
* console.log(row)
|
|
184
|
+
* }
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
export declare class Csv<T extends object, I = unknown> extends CsvEntity<T[], CsvRow<T, I>> {
|
|
188
|
+
includeExtraCells: boolean;
|
|
189
|
+
ignoreUtf8Bom: boolean;
|
|
190
|
+
headers?: string[];
|
|
191
|
+
shape?: CsvObjectShape<T>;
|
|
192
|
+
readHeaders: boolean;
|
|
193
|
+
strictColumns: boolean;
|
|
194
|
+
transform?: (row: I) => T;
|
|
195
|
+
/**
|
|
196
|
+
* Creates a new CSV parser.
|
|
197
|
+
*
|
|
198
|
+
* @param asyncIterable - Optional byte stream or buffer containing CSV data
|
|
199
|
+
* @param options - Configuration options for CSV parsing
|
|
200
|
+
* @throws {Error} If both headers and shape options are specified
|
|
201
|
+
*/
|
|
202
|
+
constructor(asyncIterable?: ByteStream<T> | ByteBuffer, options?: CsvEntityOptions & {
|
|
203
|
+
includeExtraCells?: boolean;
|
|
204
|
+
ignoreUtf8Bom?: boolean;
|
|
205
|
+
readHeaders?: boolean;
|
|
206
|
+
headers?: string[];
|
|
207
|
+
shape?: CsvObjectShape<T>;
|
|
208
|
+
strictColumns?: boolean;
|
|
209
|
+
transform?: (row: I) => T;
|
|
210
|
+
});
|
|
211
|
+
private readBom;
|
|
212
|
+
protected parse(): T[];
|
|
213
|
+
protected parseAsync(): Promise<T[]>;
|
|
214
|
+
protected streamImpl(): Generator<CsvRow<T>>;
|
|
215
|
+
/**
|
|
216
|
+
* Synchronously streams CSV rows as objects.
|
|
217
|
+
* Reads headers from the first row if readHeaders is true.
|
|
218
|
+
*
|
|
219
|
+
* @returns A generator that yields parsed objects of type O
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* const csv = new Csv(csvString)
|
|
224
|
+
* for (const row of csv.streamObjects()) {
|
|
225
|
+
* console.log(row)
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
streamObjects(): Generator<T>;
|
|
230
|
+
/**
|
|
231
|
+
* Asynchronously streams CSV rows as objects.
|
|
232
|
+
* Automatically handles buffer refills as needed.
|
|
233
|
+
*
|
|
234
|
+
* @returns An async generator that yields parsed objects of type O
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const csv = new Csv(fileStream)
|
|
239
|
+
* for await (const row of csv.streamObjectsAsync()) {
|
|
240
|
+
* console.log(row)
|
|
241
|
+
* }
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
streamObjectsAsync(): AsyncGenerator<T>;
|
|
245
|
+
/**
|
|
246
|
+
* Static method to stringify an array of objects into CSV format.
|
|
247
|
+
* Returns a synchronous generator that yields CSV string chunks.
|
|
248
|
+
*
|
|
249
|
+
* @typeParam T - The input object type
|
|
250
|
+
* @typeParam O - The output object type after optional transformation (defaults to T)
|
|
251
|
+
* @param values - Array of objects to convert to CSV
|
|
252
|
+
* @param options - Optional configuration for CSV stringification
|
|
253
|
+
* @returns A generator that yields CSV string chunks
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```typescript
|
|
257
|
+
* const data = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]
|
|
258
|
+
* for (const chunk of Csv.stringify(data, { headers: ['name', 'age'] })) {
|
|
259
|
+
* process.stdout.write(chunk)
|
|
260
|
+
* }
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
static stringify<T extends object, O extends object = T>(values: T[], options?: CsvStringifyOptions<T, T extends O ? T : O>): Generator<CsvString<T extends O ? T : O>>;
|
|
264
|
+
/**
|
|
265
|
+
* Static method to stringify an array of objects into CSV format asynchronously.
|
|
266
|
+
* Returns an asynchronous generator that yields CSV string chunks.
|
|
267
|
+
*
|
|
268
|
+
* @typeParam T - The input object type
|
|
269
|
+
* @typeParam O - The output object type after optional transformation (defaults to T)
|
|
270
|
+
* @param values - Array of objects to convert to CSV
|
|
271
|
+
* @param options - Optional configuration for CSV stringification
|
|
272
|
+
* @returns An async generator that yields CSV string chunks
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* const data = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]
|
|
277
|
+
* for await (const chunk of Csv.stringifyAsync(data)) {
|
|
278
|
+
* process.stdout.write(chunk)
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
static stringifyAsync<T extends object, O extends object = T>(values: T[], options?: CsvStringifyOptions<T, T extends O ? T : O>): AsyncGenerator<CsvString<T extends O ? T : O>>;
|
|
283
|
+
/**
|
|
284
|
+
* Static method to create a CsvStringify instance for advanced usage.
|
|
285
|
+
*
|
|
286
|
+
* @typeParam T - The input object type
|
|
287
|
+
* @typeParam O - The output object type after optional transformation (defaults to T)
|
|
288
|
+
* @param values - Array of objects to convert to CSV
|
|
289
|
+
* @param options - Optional configuration for CSV stringification
|
|
290
|
+
* @returns A CsvStringify instance
|
|
291
|
+
*/
|
|
292
|
+
static stringifier<T extends object, O extends object = T>(values: T[], options?: CsvStringifyOptions<T, T extends O ? T : O>): CsvStringify<T, T extends O ? T : O>;
|
|
293
|
+
}
|