Skip to content

Commit

Permalink
Merge pull request #269 from C2FO/v3.3.0-rc
Browse files Browse the repository at this point in the history
v3.3.0
  • Loading branch information
doug-martin committed Jul 29, 2019
2 parents 30c3a99 + 557cf5a commit 475103b
Show file tree
Hide file tree
Showing 14 changed files with 461 additions and 26 deletions.
4 changes: 4 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# v3.3.0

* [FIXED] First row of CSV is removed when headers array is provided [#252](https://github.com/C2FO/fast-csv/issues/252)

# v3.2.0

* [FIXED] Invalid row index doesn't reflect original row count [#130](https://github.com/C2FO/fast-csv/issues/130) [#266](https://github.com/C2FO/fast-csv/pull/266) - [@chrwnsk](https://github.com/chrwnsk)
Expand Down
205 changes: 203 additions & 2 deletions docs/formatting.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
* [Alternate `rowDelimiter`](#examples-alternate-row-delimiter)
* [Alternate `quote`](#examples-alternate-quote)
* [Alternate `escape`](#examples-alternate-escape)
* [Headers](#examples-headers)
* Auto Discovery
* [Object Rows](#headers-auto-discover-object)
* [Hash Array Rows](#headers-auto-discover-hash-array)
* Provide Headers
* [Array Rows](#headers-provided-array)
* [Hash Array Rows](#headers-provided-hash-array)
* [Object Rows - Reorder Columns](#headers-provided-object)
* [Object Rows - Remove Columns](#headers-provided-object-remove-column)
* [`quoteColumns`](#examples-quote-columns)
* [`quoteHeaders`](#examples-quote-headers)
* [Transforming Rows](#examples-transforming)
Expand All @@ -31,9 +40,12 @@
* `includeEndRowDelimiter: {boolean} = false`: Set to `true` to include a row delimiter at the end of the csv.
* `headers: {null|boolean|string[]} = null`:
* If true then the headers will be auto detected from the first row.
* If the row is an object then the keys will be used.
* If the row is an array of two element arrays (`[ ['header', 'column'], ['header2', 'column2'] ]`) then the first element in each array will be used.
* If the row is a one-dimensional array then headers is a no-op
* If the row is an object then the keys will be used.
* If the row is an array of two element arrays (`[ ['header', 'column'], ['header2', 'column2'] ]`) then the first element in each array will be used.
* If there is not a headers row and you want to provide one then set to a `string[]`
* **NOTE** If the row is an object the headers must match fields in the object, otherwise you will end up with empty fields
* **NOTE** If there are more headers than columns then additional empty columns will be added
* `quoteColumns: {boolean|boolean[]|{[string]: boolean} = false`
* If `true` then columns and headers will be quoted (unless `quoteHeaders` is specified).
* If it is an object then each key that has a true value will be quoted ((unless `quoteHeaders` is specified)
Expand Down Expand Up @@ -331,6 +343,195 @@ Expected output
"'"a2'"","'"b2'""
```

<a name="examples-headers"></a>

### Headers

#### Auto Discovery

`fast-csv` will auto-discover headers when the `headers` option is set to `true`.

**NOTE** When working is one-dimensional array rows (e.g. `[ 'a', 'b', 'c' ]`) this is a no-op.

<a name="headers-auto-discover-object"></a>
[`examples/formatting/headers_auto_discovery_object.example.js`](../examples/formatting/headers_auto_discovery_object.example.js)

In this example the headers are auto-discovered from the objects passed in.

```js
const csvStream = csv.format({ headers: true});

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write({ header1: 'value1a', header2: 'value1b' });
csvStream.write({ header1: 'value2a', header2: 'value2b' });
csvStream.write({ header1: 'value3a', header2: 'value3b' });
csvStream.write({ header1: 'value4a', header2: 'value4b' });
csvStream.end();
```

Expected Output:
```
header1,header2
value1a,value1b
value2a,value2b
value3a,value3b
value4a,value4b
```

<a name="headers-auto-discover-hash-array"></a>
[`examples/formatting/headers_auto_discovery_hash_array.example.js`](../examples/formatting/headers_auto_discovery_hash_array.example.js)

In this example the headers are auto-discovered from the hash arrays passed in.

```js
const csvStream = csv.format({ headers: true });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write([ [ 'header1', 'value1a' ], [ 'header2', 'value1b' ] ]);
csvStream.write([ [ 'header1', 'value2a' ], [ 'header2', 'value2b' ] ]);
csvStream.write([ [ 'header1', 'value3a' ], [ 'header2', 'value3b' ] ]);
csvStream.write([ [ 'header1', 'value4a' ], [ 'header2', 'value4b' ] ]);
csvStream.end();
```

Expected Output:
```
header1,header2
value1a,value1b
value2a,value2b
value3a,value3b
value4a,value4b
```

### Provided Headers

You can also provide a set of `headers` by providing an array. This allows you to

* Reorder and/or exclude columns when working when object rows.
* Rename and/or exclude columns when working with hash array rows.
* Specify headers or remove columns when working with array rows.

**NOTE** When working with objects the header names should match keys. The headers option allows you to specify column order.

<a name="headers-provided-array"></a>
[`examples/formatting/headers_provided_array.example.js`](../examples/formatting/headers_provided_array.example.js)

In this example a custom set of headers is provided for rows that are arrays.

```js
const csvStream = csv.format({ headers: [ 'header1', 'header2' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write([ 'value1a', 'value1b' ]);
csvStream.write([ 'value2a', 'value2b' ]);
csvStream.write([ 'value3a', 'value3b' ]);
csvStream.write([ 'value4a', 'value4b' ]);
csvStream.end();
```

Expected Output:
```
header1,header2
value1a,value1b
value2a,value2b
value3a,value3b
value4a,value4b
```

<a name="headers-provided-hash-array"></a>
[`examples/formatting/headers_provided_hash_array.example.js`](../examples/formatting/headers_provided_hash_array.example.js)

In this example the headers are overridden with a custom set of headers

```js
const csvStream = csv.format({ headers: [ 'header1', 'header2' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write([ [ 'h1', 'value1a' ], [ 'h2', 'value1b' ] ]);
csvStream.write([ [ 'h1', 'value2a' ], [ 'h2', 'value2b' ] ]);
csvStream.write([ [ 'h1', 'value3a' ], [ 'h2', 'value3b' ] ]);
csvStream.write([ [ 'h1', 'value4a' ], [ 'h2', 'value4b' ] ]);
csvStream.end();
```

Expected Output:
```
header1,header2
value1a,value1b
value2a,value2b
value3a,value3b
value4a,value4b
```

<a name="headers-provided-object"></a>
[`examples/formatting/headers_provided_object.example.js`](../examples/formatting/headers_provided_object.example.js)

In this example the columns are reordered.

```js
const csvStream = csv.format({ headers: [ 'header2', 'header1' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write({ header1: 'value1a', header2: 'value1b' });
csvStream.write({ header1: 'value2a', header2: 'value2b' });
csvStream.write({ header1: 'value3a', header2: 'value3b' });
csvStream.write({ header1: 'value4a', header2: 'value4b' });
csvStream.end();

```

Expected Output:
```
header2,header1
value1b,value1a
value2b,value2a
value3b,value3a
value4b,value4a
```

<a name="headers-provided-object-remove-column"></a>
[`examples/formatting/headers_provided_object_remove_column.example.js`](../examples/formatting/headers_provided_object_remove_column.example.js)

In this example the one of the columns is removed.

```js
const csvStream = csv.format({ headers: [ 'header2' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write({ header1: 'value1a', header2: 'value1b' });
csvStream.write({ header1: 'value2a', header2: 'value2b' });
csvStream.write({ header1: 'value3a', header2: 'value3b' });
csvStream.write({ header1: 'value4a', header2: 'value4b' });
csvStream.end();
```

Expected Output:
```
header2
value1b
value2b
value3b
value4b
```

<a name="examples-quote-columns"></a>
### `quoteColumns`

Expand Down
13 changes: 13 additions & 0 deletions examples/formatting/headers_auto_discovery_hash_array.example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const csv = require('../../');

const csvStream = csv.format({ headers: true });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write([ [ 'header1', 'value1a' ], [ 'header2', 'value1b' ] ]);
csvStream.write([ [ 'header1', 'value2a' ], [ 'header2', 'value2b' ] ]);
csvStream.write([ [ 'header1', 'value3a' ], [ 'header2', 'value3b' ] ]);
csvStream.write([ [ 'header1', 'value4a' ], [ 'header2', 'value4b' ] ]);
csvStream.end();
13 changes: 13 additions & 0 deletions examples/formatting/headers_auto_discovery_object.example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const csv = require('../../');

const csvStream = csv.format({ headers: true });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write({ header1: 'value1a', header2: 'value1b' });
csvStream.write({ header1: 'value2a', header2: 'value2b' });
csvStream.write({ header1: 'value3a', header2: 'value3b' });
csvStream.write({ header1: 'value4a', header2: 'value4b' });
csvStream.end();
13 changes: 13 additions & 0 deletions examples/formatting/headers_provided_array.example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const csv = require('../../');

const csvStream = csv.format({ headers: [ 'header1', 'header2' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write([ 'value1a', 'value1b' ]);
csvStream.write([ 'value2a', 'value2b' ]);
csvStream.write([ 'value3a', 'value3b' ]);
csvStream.write([ 'value4a', 'value4b' ]);
csvStream.end();
13 changes: 13 additions & 0 deletions examples/formatting/headers_provided_hash_array.example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const csv = require('../../');

const csvStream = csv.format({ headers: [ 'header1', 'header2' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write([ [ 'h1', 'value1a' ], [ 'h2', 'value1b' ] ]);
csvStream.write([ [ 'h1', 'value2a' ], [ 'h2', 'value2b' ] ]);
csvStream.write([ [ 'h1', 'value3a' ], [ 'h2', 'value3b' ] ]);
csvStream.write([ [ 'h1', 'value4a' ], [ 'h2', 'value4b' ] ]);
csvStream.end();
13 changes: 13 additions & 0 deletions examples/formatting/headers_provided_object.example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const csv = require('../../');

const csvStream = csv.format({ headers: [ 'header2', 'header1' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write({ header1: 'value1a', header2: 'value1b' });
csvStream.write({ header1: 'value2a', header2: 'value2b' });
csvStream.write({ header1: 'value3a', header2: 'value3b' });
csvStream.write({ header1: 'value4a', header2: 'value4b' });
csvStream.end();
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const csv = require('../../');

const csvStream = csv.format({ headers: [ 'header2' ] });

csvStream
.pipe(process.stdout)
.on('end', process.exit);

csvStream.write({ header1: 'value1a', header2: 'value1b' });
csvStream.write({ header1: 'value2a', header2: 'value2b' });
csvStream.write({ header1: 'value3a', header2: 'value3b' });
csvStream.write({ header1: 'value4a', header2: 'value4b' });
csvStream.end();
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fast-csv",
"version": "3.2.0",
"version": "3.3.0",
"description": "CSV parser and writer",
"main": "./build/src/index.js",
"types": "./build/src/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions src/formatter/FormatterOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class FormatterOptions {

public readonly transform: RowTransformFunction | null = null;

public readonly hasProvidedHeaders: boolean;
public readonly shouldWriteHeaders: boolean;

public readonly escapedQuote: string;

Expand All @@ -54,7 +54,7 @@ export class FormatterOptions {
this.escape = this.quote;
}
}
this.hasProvidedHeaders = !!this.headers;
this.shouldWriteHeaders = !!this.headers;
this.headers = Array.isArray(this.headers) ? this.headers : null;
this.escapedQuote = `${this.escape}${this.quote}`;
}
Expand Down
Loading

0 comments on commit 475103b

Please sign in to comment.