npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kksiuda/csv

v2.1.1

Published

Csv parsing and stringifying

Downloads

4

Readme

Overview

No dependency CSV parsing and stringifying, synchronously or via stream, typed or untyped

Installation

yarn install @kksiuda/csv

or

npm install @kksiuda/csv

API

parseCsv

Parses string synchronously.

  • input
  • output
    • when columns are specified it returns array of type inferred from columns, otherwise array of records

Example

import { parseCsv, CsvColumns } from '@kksiuda/csv';

const csvString = 'a,b\n1,2\n';
const columns = {
  a: 'integer',
  b: { type: 'string' },
} satisfies CsvColumns;
console.log(parseCsv(csvString)); // [ { a: '1', b: '2' } ]
console.log(parseCsv(csvString, columns)); // [ { a: 1, b: '2' } ]

stringifyCsv

Stringifies array of records. Note: if columns are not specified the columns will be inferred from the first row.

  • input
    • records: when columns are specified array of type inferred from columns, otherwise array of records
    • columns?: CsvColumns
    • params?: CsvParams
  • output
    • string

Example

import { stringifyCsv } from '@kksiuda/csv';

const records = [{ a: 1 }, { a: 1, b: 2 }];
const columns = {
  a: 'integer',
  b: { type: 'integer' },
} satisfies CsvColumns;
console.log(stringifyCsv(records)); // 'a\n1\n'
console.log(stringifyCsv(records, columns)); // 'a,b\n1,\n1,2\n'

createParseCsvStream

Creates a transform stream for parsing csv.

  • input
  • output
    • Transform stream that takes in strings and outputs records in objectMode

Example

import { createParseCsvStream, createStringifyCsvStream } from '@kksiuda/csv';
import { createReadStream, createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream';
const readable = createReadStream('./input.csv');
const writable = createWriteStream('./output.csv');
const parseStream = createParseCsvStream();
const stringifyStream = createStringifyCsvStream();
pipeline(
  readable,
  parseStream,
  stringifyStream,
  writable,
  (err) => (err ? console.log(err) : console.log('done')) // 'done'
);

createStringifyCsvStream

Creates a transform stream for stringifying csv.

  • input
  • output
    • Transform stream that takes records in objectMode and outputs strings

Example: see above

parseCsvFromStream

Takes an string input stream and asynchronously parses csv

  • input
  • output
    • Promise of array of types specified in columns when defined or array of records otherwise

Example:

import { parseCsvFromStream } from '@kksiuda/csv';
import { createReadStream } from 'node:fs';

const readable = createReadStream('./input.csv');
(async () => {
  console.log(await parseCsvFromStream(readable)); // array of records
})();

stringifyCsvFromStream

Takes an objectMode input stream and asynchronously stringifies csv

Example:

import { stringifyCsvFromStream, createParseCsvStream } from '@kksiuda/csv';
import { createReadStream } from 'node:fs';

const readable = createReadStream('./input.csv');
const parseStream = createParseCsvStream();

(async () => {
  readable.pipe(parseStream);
  console.log(await stringifyCsvFromStream(parseStream)); // csv string
})();

Types

CsvColumns

type CsvColumns<T extends Record<string, any> = Record<string, any>> = {
  [P in keyof T]?: CsvColumn<T, P> | CsvColumnType;
};
type CsvColumn<T extends Record<string, any>, P extends keyof T = keyof T> = {
  type: CsvColumnType;
  nullable?: boolean;
  stringify?: (val: T[P]) => string;
  parse?: (str: string) => T[P];
  header?: string;
  index?: number;
};

Note: when parsing empty strings will always be parsed as either null or undefined when useNullForEmpty is true

  • prop: property on the object; when header is not specified it will be used as a header when stringifying csv

  • type:

    • 'text'
      • stringify
        • value is string -> value
        • value is boolean or truthy -> value cast to string
        • else -> ''
      • parse
        • value -> value
    • 'integer'
      • stringify
        • value is number and not NaN -> value.toFixed(0)
        • else -> ''
      • parse
        • value -> parseInt(value, 10)
    • 'float'
      • stringify
        • value is number and not NaN -> value cast to string
        • else -> ''
      • parse
        • value -> value * 1
    • 'percentage'
      • stringify
      • value is number and not NaN -> value * 100 cast to string with '%' at the end
      • else -> ''
      • parse
        • value -> parseInt(value, 10) / 100
    • 'boolean'
      • stringify
        • value is not undefined and not null and falsy -> 'FALSE'
        • value is truthy -> 'TRUE'
        • else -> ''
      • parse
        • value is '0', 'N', 'n', 'false', 'FALSE', 'False', 'no', 'NO', or 'No' -> false
        • else -> true
    • 'date', 'datetime', 'datetimes', 'timestamp'
      • parses using dateClass supplied in csvParams; see for defaults below
      • parse
        • value can be parsed by casting to built-in Date -> number
      • stringify
        • value is NaN or not of type number -> ''
        • date: 'YYYY-MM-DD'
        • datetime: 'YYYY-MM-DD HH:mm'
        • datetimes: 'YYYY-MM-DD HH:mm:SS'
        • timestamp: 'YYYY-MM-DD HH:mm:SS.sss'
    • 'custom'
      • parse
        • uses parse function; defaults to 'string'
      • stringify
        • uses stringify function; defaults to 'string'
  • stringify

    • function that takes value of prop from the record and returns a string
    • only used when type is 'custom'
  • parse

    • function that takes csv string and returns the value of prop to go on the record
    • only used when type is 'custom'
  • header

    • represents header in the csv
    • when not specified defaults to prop

CsvParams

interface CsvParams {
  delimiter?: string;
  quote?: string | null;
  escapeQuote?: string | null;
  rowSeparator?: string;
  ignoreUnderscoredProps?: boolean;
  dateOptions?: {
    locale?: string;
    timezoneOffset?: number | 'local';
    dst?: 'none' | 'eu' | 'us';
  };
  dateFormats?: {
    date?: string;
    dateTime?: string;
    dateTimeSeconds?: string;
    timestamp?: string;
  };
  dateClass?: DateConstructor;
  noHeader?: boolean;
  useNullForEmpty?: boolean;
  titleCaseHeaders?: boolean;
  preserveCarriageReturn?: boolean;
}

Note: when specifying non-default dateOptions or dateFormats dateClass needs to point to a constructor from an external library (see p00dle/datex), otherwise it will throw an error

Note: when both escape and escapeQuote are null no values are considered as quoted in both parsing and stringifying

  • delimiter - string that separates values in a row; default: ','
  • quote - string that wraps the value when value contains delimiter, quote, or rowSeparator; default: '"'
  • escapeQuote - string that is used for escaping quote; default: '""'
  • rowSeparator - string that separates rows; default: '\n'
  • ignoreUnderscoredProps - when columns are not specified during the stringifying process all props starting with an underscore will be ignored; has no effect on parsing; default: false
  • dateOptions
    • locale - determines things like month names, ordinals etc.
    • timezoneOffset - timezone offset in hours or 'local' to use machine's local timezone offset
    • dst - the daylight savings system used to determine when daylight savings are applied
  • dateFormats
    • specify date format for specific column types
  • dateClass - specify when using an external library
  • noHeader - when true headers will not be emitted when stringifying; when parsing columns will be assigned using the order of columns (throws when columns are undefined); default: false
  • useNullForEmpty - when true empty values will be parsed as null, otherwise as undefined; default: true
  • titleCaseHeaders - when columns are not specified the headers will be parsed from camel case to title case; only applies to stringifying; default: false
  • preserveCarriageReturn - when true carriage return (\r) are not removed and considered valid characters; default: false