NaturalCycles/nodejs-lib

View on GitHub
src/csv/transformToCSV.ts

Summary

Maintainability
A
40 mins
Test Coverage
C
76%
import { Transform } from 'node:stream'
import { AnyObject } from '@naturalcycles/js-lib'
import { TransformTyped } from '../stream/stream.model'
import { CSVWriter, CSVWriterConfig } from './csvWriter'

export interface TransformToCSVOptions extends CSVWriterConfig {
  /**
   * If true - will throw an error on stringify error
   *
   * @default true
   */
  strict?: boolean
}

/**
 * Transforms objects (objectMode=true) into chunks \n-terminated CSV strings (readableObjectMode=false).
 */
export function transformToCSV<IN extends AnyObject = any>(
  opt: TransformToCSVOptions & {
    /**
     * Columns are required, as they cannot be detected on the fly.
     */
    columns: string[]
  },
): TransformTyped<IN, string> {
  const { strict = true } = opt
  const writer = new CSVWriter(opt)
  let firstRow = true

  return new Transform({
    writableObjectMode: true,
    readableObjectMode: false,
    readableHighWaterMark: 64 * 1024,
    transform(chunk: IN, _, cb) {
      try {
        let s = ''

        if (firstRow) {
          s = writer.writeHeader() + '\n'
          firstRow = false
        }

        cb(null, s + writer.writeRow(chunk) + '\n')
      } catch (err) {
        console.error(err)

        if (strict) {
          cb(err as Error) // emit error
        } else {
          cb() // emit no error, but no result neither
        }
      }
    },
  })
}