Skip to content

Commit

Permalink
feat(TS): expose TS interfaces, add type tests (#128)
Browse files Browse the repository at this point in the history
fix: change `skipComments` option type to `boolean | string`
  • Loading branch information
BendingBender committed May 3, 2019
1 parent 73dcfe1 commit 5e0c6cd
Show file tree
Hide file tree
Showing 6 changed files with 898 additions and 57 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
language: node_js
node_js:
- 12
- 10
- 8
- 6
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,13 @@ csv({ separator: '\t' });

## API

### csv([options|headers])
### csv([options | headers])

Returns: `Array[object]`
Returns: `Array[Object]`

#### options

Type: `object`
Type: `Object`

As an alternative to passing an `options` object, you may pass an `Array[String]`
which specifies the headers to use. For example:
Expand All @@ -140,7 +140,7 @@ in a CSV row.

##### headers

Type: `Array[String]|boolean`
Type: `Array[String] | Boolean`

Specifies the headers to use. Headers define the property key for each value in
a CSV row. If no `headers` option is provided, `csv-parser` will use the first
Expand Down
165 changes: 143 additions & 22 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,146 @@
declare module 'csv-parser' {
import { Transform } from 'stream';

interface CsvParser extends Transform {}
interface CsvParserOptions {
escape?: string;
headers?: ReadonlyArray<string> | boolean;
mapHeaders?: (args: { header: string; index: number }) => string | null;
mapValues?: (args: { header: string; index: number; value: any }) => any;
newline?: string;
quote?: string;
raw?: boolean;
separator?: string;
skipComments?: number | string;
skipLines?: number;
maxRowBytes?: number;
strict?: boolean;
}
/// <reference types="node"/>
import { Transform } from 'stream';

declare namespace csvParser {
type CsvParser = Transform;

interface Options {
/**
* A single-character string used to specify the character used to escape strings in a CSV row.
*
* @default '"'
*/
readonly escape?: string;

/**
* Specifies the headers to use. Headers define the property key for each value in a CSV row. If no `headers` option is provided, `csv-parser` will use the first line in a CSV file as the header specification.
*
* If `false`, specifies that the first row in a data file does _not_ contain headers, and instructs the parser to use the row index as the key for each row.
*
* Suppose you have a CSV file `data.csv` which contains the data:
*
* ```
NAME,AGE
Daffy Duck,24
Bugs Bunny,22
```
* Using `headers: false` with the data from `data.csv` would yield:
* ```
[
{ '0': 'Daffy Duck', '1': 24 },
{ '0': 'Bugs Bunny', '1': 22 }
]
```
*/
readonly headers?: ReadonlyArray<string> | boolean;

/**
* A function that can be used to modify the values of each header. Return `null` to remove the header, and it's column, from the results.
*
* @example
*
* csv({
* mapHeaders: ({ header, index }) => header.toLowerCase()
* });
*/
readonly mapHeaders?: (args: { header: string; index: number }) => string | null;

/**
* A function that can be used to modify the value of each column value.
*
* @example
*
* csv({
* mapValues: ({ header, index, value }) => value.toLowerCase()
* });
*/
readonly mapValues?: (args: { header: string; index: number; value: any }) => any;

/**
* Specifies a single-character string to denote the end of a line in a CSV file.
*
* @default '\n'
*/
readonly newline?: string;

/**
* Specifies a single-character string to denote a quoted string.
*
* @default '"'
*/
readonly quote?: string;

const csvParser: (
optionsOrHeaders?: CsvParserOptions | ReadonlyArray<string>
) => CsvParser;
/**
* If `true`, instructs the parser not to decode UTF-8 strings.
*/
readonly raw?: boolean;

export = csvParser;
/**
* Specifies a single-character string to use as the column separator for each row.
*
* @default ','
*/
readonly separator?: string;

/**
* Instructs the parser to ignore lines which represent comments in a CSV file. Since there is no specification that dictates what a CSV comment looks like, comments should be considered non-standard. The "most common" character used to signify a comment in a CSV file is `"#"`. If this option is set to `true`, lines which begin with `#` will be skipped. If a custom character is needed to denote a commented line, this option may be set to a string which represents the leading character(s) signifying a comment line.
*
* @default false
*/
readonly skipComments?: boolean | string;

/**
* Specifies the number of lines at the beginning of a data file that the parser should skip over, prior to parsing headers.
*
* @default 0
*/
readonly skipLines?: number;

/**
* Maximum number of bytes per row. An error is thrown if a line exeeds this value. The default value is on 8 peta byte.
*
* @default Number.MAX_SAFE_INTEGER
*/
readonly maxRowBytes?: number;

/**
* If `true`, instructs the parser that the number of columns in each row must match the number of `headers` specified.
*/
readonly strict?: boolean;
}
}

/**
* Streaming CSV parser that aims for maximum speed as well as compatibility with the [csv-spectrum](https://npmjs.org/csv-spectrum) CSV acid test suite.
*
* @param optionsOrHeaders - As an alternative to passing an `options` object, you may pass an `Array[String]` which specifies the headers to use. If you need to specify options _and_ headers, please use the the object notation with the `headers` property.
*
* @example
*
* // data.csv:
* //
* // NAME,AGE
* // Daffy Duck,24
* // Bugs Bunny,22
*
* import csv = require('csv-parser');
* import * as fs from 'fs';
*
* const results = [];
*
* fs.createReadStream('data.csv')
* .pipe(csv())
* .on('data', (data) => results.push(data))
* .on('end', () => {
* console.log(results);
* // [
* // { NAME: 'Daffy Duck', AGE: '24' },
* // { NAME: 'Bugs Bunny', AGE: '22' }
* // ]
* });
*/
declare const csvParser: (
optionsOrHeaders?: csvParser.Options | ReadonlyArray<string>
) => csvParser.CsvParser;

export = csvParser;
40 changes: 40 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { expectType } from 'tsd';
import csvParser = require('.');

const options: csvParser.Options = {};

expectType<csvParser.CsvParser>(csvParser(['Name', 'Age']));
expectType<csvParser.CsvParser>(csvParser({ escape: '"' }));
expectType<csvParser.CsvParser>(csvParser({ headers: ['Name', 'Age'] }));
expectType<csvParser.CsvParser>(csvParser({ headers: false }));
expectType<csvParser.CsvParser>(
csvParser({
mapHeaders: ({ header, index }) => {
expectType<string>(header);
expectType<number>(index);
return header.toLowerCase();
},
})
);
expectType<csvParser.CsvParser>(csvParser({ mapHeaders: ({ header, index }) => null }));
expectType<csvParser.CsvParser>(
csvParser({
mapValues: ({ header, index, value }) => {
expectType<string>(header);
expectType<number>(index);
expectType<any>(value);

return value.toLowerCase();
},
})
);
expectType<csvParser.CsvParser>(csvParser({ mapValues: ({ header, index, value }) => null }));
expectType<csvParser.CsvParser>(csvParser({ newline: '\n' }));
expectType<csvParser.CsvParser>(csvParser({ quote: '"' }));
expectType<csvParser.CsvParser>(csvParser({ raw: true }));
expectType<csvParser.CsvParser>(csvParser({ separator: ',' }));
expectType<csvParser.CsvParser>(csvParser({ skipComments: true }));
expectType<csvParser.CsvParser>(csvParser({ skipComments: '#' }));
expectType<csvParser.CsvParser>(csvParser({ skipLines: 1 }));
expectType<csvParser.CsvParser>(csvParser({ maxRowBytes: 1 }));
expectType<csvParser.CsvParser>(csvParser({ strict: true }));
Loading

0 comments on commit 5e0c6cd

Please sign in to comment.