API · Formats
csvStringify()
Serialize each array or object as one CSV record and emit it incrementally.
Signature
csvStringify<H extends readonly PropertyKey[] | boolean = false>(
options?: CsvStringifyOptions<H> | null,
): Exstream<string | Uint8Array, C>
interface CsvStringifyOptions<H extends readonly PropertyKey[] | boolean = false> {
encoding?: string
separator?: string
quote?: string
escape?: string
lineEnding?: string
header?: H
quoted?: boolean
quotedEmpty?: boolean
maxColumns?: number
maxRecordBytes?: number
} Example
await exstream([
{ id: 1, name: 'Ada' },
{ id: 2, name: 'Linus' },
])
.csvStringify({ header: true })
.pipeTo(destination) Parameters
encodingAny non-empty encoding supported by the runtime. The exact label
'utf8'emits strings; every other label, including'utf-8', emits byte chunks in the selected encoding. Non-UTF-8 output encodings are Node.js-specific; browser builds reject labels their encoder cannot produce.separatorAny non-empty string without CR or LF. Multi-character and Unicode separators are supported.
quoteWraps fields that require quoting and fields selected by
quoted.escapeEscapes quote characters inside quoted fields. When distinct from
quote, literal escape characters are doubled.lineEndingAppended after every emitted record, including a generated header and the final row. Common values are LF and CRLF, but any non-empty string is accepted.
headerControls column discovery and header output. See Header modes. Values other than booleans and arrays are rejected.
quotedWhen true, quotes every non-empty field. Fields containing separator, quote, escape, CR, or LF are quoted automatically regardless.
quotedEmptyWhen true, serializes cells whose string representation is empty between a pair of configured quote characters,
""with the default, instead of as a bare empty field. It does not changenull,undefined,false, or0; those use normal JavaScript string coercion.maxColumnsLimits discovered output columns. Crossing it emits
CsvStringifyErrorwith codeEXSTREAM_CSV_MAX_COLUMNS.maxRecordBytesLimits each encoded record including separators and its line ending. A generated header counts as a record. Crossing it uses code
EXSTREAM_CSV_MAX_RECORD_BYTES.
Passing null or undefined applies all defaults. Other non-object values and arrays are rejected.
Both numeric limits are normalized with Number() at runtime, so any value coercing to a positive integer is accepted. TypeScript intentionally requires numbers.
Header modes
With header: false, the first row determines the columns but no header record is emitted. Array columns use numeric indexes; object columns use the first object’s enumerable own string keys.
With header: true, object input uses the first object’s keys and emits them before that object. Array input is invalid because there are no names to discover.
An explicit header array both selects columns and emits a header. For object rows, its entries are property keys. For array rows, array positions correspond to input positions; nullish header entries omit those positions. String and number keys are serializable; a symbol header key cannot be converted into CSV header text and throws.
Later rows always follow the selected first-row or explicit columns. Extra object properties and array positions are ignored. A missing selected property or array position is coerced to the literal text undefined; null becomes null. Provide an actual empty string when an empty CSV field is required.
An empty header array selects zero columns and emits an empty header record plus an empty record for every input row. Headers are emitted only after the first input arrives: an empty source emits no header and no chunks, even with an explicit header.
Cells and output
Input rows should be arrays or non-null objects. Cells are converted with JavaScript string coercion: nested objects normally become [object Object], arrays use comma-joined text, dates use their default string form, and symbols throw. The operator does not apply locale, schema, or date formatting; normalize values before serialization.
It emits one complete record chunk at a time, including its configured line ending, preserves order, follows downstream demand, and buffers only the current record. Each emitted row chunk retains its input row context.
Errors
Invalid options throw when attached. Invalid row/header combinations, cell coercion failures, and finite column or record-size violations throw synchronously when that record is processed; they do not enter the recoverable errors() channel. CsvStringifyError exposes code, one-based record, and, for column-limit failures, one-based column. Limit codes are EXSTREAM_CSV_MAX_COLUMNS and EXSTREAM_CSV_MAX_RECORD_BYTES; the general class default is EXSTREAM_CSV_STRINGIFY. Validate rows before serialization when processing must continue after a bad value.
Upstream record errors pass through unchanged and do not produce CSV output. Handle them before or immediately after csvStringify() when the terminal destination should continue.
Forms
csvStringify() is available on streams and reusable pipelines. The direct standalone form takes options before the stream and the curried form composes with through():
stream.csvStringify(options)
exstream.pipeline().csvStringify(options)
exstream.csvStringify(options, stream)
stream.through(exstream.csvStringify(options)) Pass null in the direct standalone form to apply defaults.