From d9eaba6135ec1261aa4bf93bd3f6b6d54094731e Mon Sep 17 00:00:00 2001 From: doug-martin Date: Sat, 21 Dec 2019 17:29:25 -0600 Subject: [PATCH 1/8] Migrate to jest --- .eslintrc.js | 4 +- .mocharc.js | 14 - .nycrc | 24 - {test => __tests__}/RecordingStream.ts | 0 .../formatter/CsvFormatterStream.spec.ts | 906 ++++ .../formatter/FormatterOptions.spec.ts | 85 +- .../formatter/__fixtures__}/.gitkeep | 0 .../formatter/FieldFormatter.spec.ts | 37 +- .../formatter/formatter/RowFormatter.spec.ts | 201 +- .../issues/__fixtures__}/issue102.csv | 0 .../issues/__fixtures__}/issue68-invalid.tsv | 0 .../issues/__fixtures__}/issue68.tsv | 0 .../issues/__fixtures__}/issue87.csv | 0 .../issues/issue102.spec.ts | 11 +- .../issues/issue111.spec.ts | 13 +- .../issues/issue131.spec.ts | 5 +- .../issues/issue150.spec.ts | 3 +- .../issues/issue158.spec.ts | 3 +- .../issues/issue174.spec.ts | 3 +- .../issues/issue214.spec.ts | 9 +- .../issues/issue223.spec.ts | 3 +- .../issues/issue252.spec.ts | 3 +- .../issues/issue68.spec.ts | 28 +- .../issues/issue77.spec.ts | 19 +- .../issues/issue87.spec.ts | 5 +- .../issues/issue93.spec.ts | 5 +- .../issues/issue97.spec.ts | 3 +- .../parser/CsvParsingStream.spec.ts | 495 +- .../parser/ParserOptions.spec.ts | 101 +- .../parser/__fixtures__}/alternateEncoding.ts | 0 .../parser/__fixtures__}/duplicateHeaders.ts | 0 .../parser/__fixtures__}/emptyRows.ts | 0 .../__fixtures__}/headerColumnMismatch.ts | 0 .../parser/__fixtures__}/index.ts | 2 + .../parser/__fixtures__}/malformed.ts | 0 .../__fixtures__}/noHeadersAndQuotes.ts | 0 .../parser/__fixtures__}/skipLines.ts | 0 .../parser/__fixtures__}/trailingComma.ts | 0 .../parser/__fixtures__}/withHeaders.ts | 0 .../withHeadersAlternateDelimiter.ts | 0 .../withHeadersAndAlternateQuote.ts | 0 .../withHeadersAndMissingColumns.ts | 0 .../__fixtures__}/withHeadersAndQuotes.ts | 0 .../__fixtures__}/withHeadersSkippedLines.ts | 0 .../parser/parser/Parser.spec.ts | 235 +- .../parser/parser/RowParser.spec.ts | 65 +- .../parser/parser/Scanner.spec.ts | 99 +- .../parser/parser/column/ColumnParser.spec.ts | 5 +- .../column/NonQuotedColumnParser.spec.ts | 75 +- .../parser/column/QuotedColumnParser.spec.ts | 312 +- .../transforms/HeaderTransformer.spec.ts | 146 +- .../RowTransformerValidator.spec.ts | 88 +- jest.config.js | 11 + package-lock.json | 4813 ++++++++++++++--- package.json | 20 +- test/formatter/CsvFormatterStream.test.ts | 923 ---- tsconfig.json | 2 +- 57 files changed, 5891 insertions(+), 2885 deletions(-) delete mode 100644 .mocharc.js delete mode 100644 .nycrc rename {test => __tests__}/RecordingStream.ts (100%) create mode 100644 __tests__/formatter/CsvFormatterStream.spec.ts rename test/formatter/FormatterOptions.test.ts => __tests__/formatter/FormatterOptions.spec.ts (52%) rename {test/formatter/assets => __tests__/formatter/__fixtures__}/.gitkeep (100%) rename test/formatter/formatter/FieldFormatter.test.ts => __tests__/formatter/formatter/FieldFormatter.spec.ts (73%) rename test/formatter/formatter/RowFormatter.test.ts => __tests__/formatter/formatter/RowFormatter.spec.ts (58%) rename {test/issues/assets => __tests__/issues/__fixtures__}/issue102.csv (100%) rename {test/issues/assets => __tests__/issues/__fixtures__}/issue68-invalid.tsv (100%) rename {test/issues/assets => __tests__/issues/__fixtures__}/issue68.tsv (100%) rename {test/issues/assets => __tests__/issues/__fixtures__}/issue87.csv (100%) rename test/issues/issue102.test.ts => __tests__/issues/issue102.spec.ts (73%) rename test/issues/issue111.test.ts => __tests__/issues/issue111.spec.ts (87%) rename test/issues/issue131.test.ts => __tests__/issues/issue131.spec.ts (79%) rename test/issues/issue150.test.ts => __tests__/issues/issue150.spec.ts (89%) rename test/issues/issue158.test.ts => __tests__/issues/issue158.spec.ts (88%) rename test/issues/issue174.test.ts => __tests__/issues/issue174.spec.ts (91%) rename test/issues/issue214.test.ts => __tests__/issues/issue214.spec.ts (84%) rename test/issues/issue223.test.ts => __tests__/issues/issue223.spec.ts (91%) rename test/issues/issue252.test.ts => __tests__/issues/issue252.spec.ts (81%) rename test/issues/issue68.test.ts => __tests__/issues/issue68.spec.ts (60%) rename test/issues/issue77.test.ts => __tests__/issues/issue77.spec.ts (65%) rename test/issues/issue87.test.ts => __tests__/issues/issue87.spec.ts (87%) rename test/issues/issue93.test.ts => __tests__/issues/issue93.spec.ts (91%) rename test/issues/issue97.test.ts => __tests__/issues/issue97.spec.ts (81%) rename test/parser/CsvParsingStream.test.ts => __tests__/parser/CsvParsingStream.spec.ts (56%) rename test/parser/ParserOptions.test.ts => __tests__/parser/ParserOptions.spec.ts (53%) rename {test/parser/assets => __tests__/parser/__fixtures__}/alternateEncoding.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/duplicateHeaders.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/emptyRows.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/headerColumnMismatch.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/index.ts (95%) rename {test/parser/assets => __tests__/parser/__fixtures__}/malformed.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/noHeadersAndQuotes.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/skipLines.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/trailingComma.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/withHeaders.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/withHeadersAlternateDelimiter.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/withHeadersAndAlternateQuote.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/withHeadersAndMissingColumns.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/withHeadersAndQuotes.ts (100%) rename {test/parser/assets => __tests__/parser/__fixtures__}/withHeadersSkippedLines.ts (100%) rename test/parser/parser/Parser.test.ts => __tests__/parser/parser/Parser.spec.ts (85%) rename test/parser/parser/RowParser.test.ts => __tests__/parser/parser/RowParser.spec.ts (68%) rename test/parser/parser/Scanner.test.ts => __tests__/parser/parser/Scanner.spec.ts (58%) rename test/parser/parser/column/ColumnParser.test.ts => __tests__/parser/parser/column/ColumnParser.spec.ts (88%) rename test/parser/parser/column/NonQuotedColumnParser.test.ts => __tests__/parser/parser/column/NonQuotedColumnParser.spec.ts (69%) rename test/parser/parser/column/QuotedColumnParser.test.ts => __tests__/parser/parser/column/QuotedColumnParser.spec.ts (67%) rename test/parser/transforms/HeaderTransformer.test.ts => __tests__/parser/transforms/HeaderTransformer.spec.ts (50%) rename test/parser/transforms/RowTransformerValidator.test.ts => __tests__/parser/transforms/RowTransformerValidator.spec.ts (66%) create mode 100644 jest.config.js delete mode 100644 test/formatter/CsvFormatterStream.test.ts diff --git a/.eslintrc.js b/.eslintrc.js index 399d0248..6b32f758 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,7 +14,7 @@ module.exports = { ], env: { node: true, - mocha: true, + jest: true, }, settings:{ "import/extensions": [ @@ -65,7 +65,7 @@ module.exports = { overrides: [ { "files": [ - "*.test.ts" + "*.spec.ts" ], "rules": { "@typescript-eslint/explicit-function-return-type": "off", diff --git a/.mocharc.js b/.mocharc.js deleted file mode 100644 index 24dba14a..00000000 --- a/.mocharc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - diff: true, - require: ['ts-node/register', 'source-map-support/register'], - extension: ['ts', 'js'], - package: './package.json', - reporter: 'spec', - slow: 75, - timeout: 5000, - recursive: true, - ui: 'bdd' -}; - -// --recursive -// test/ \ No newline at end of file diff --git a/.nycrc b/.nycrc deleted file mode 100644 index 4e1ecbcc..00000000 --- a/.nycrc +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "@istanbuljs/nyc-config-typescript", - "all": true, - "check-coverage": true, - "lines": 90, - "functions": 90, - "branches": 90, - "statements": 90, - "exclude": [ - "**/*.d.ts", - "coverage/**", - "packages/*/test/**", - "test/**", - "test{,-*}.ts", - "**/*{.,-}{test,spec}.ts", - "**/__tests__/**", - "**/node_modules/**", - "benchmark/**/*", - "examples/**/*", - "docs/**/*", - ".eslintrc.js", - ".mocharc.js" - ] -} diff --git a/test/RecordingStream.ts b/__tests__/RecordingStream.ts similarity index 100% rename from test/RecordingStream.ts rename to __tests__/RecordingStream.ts diff --git a/__tests__/formatter/CsvFormatterStream.spec.ts b/__tests__/formatter/CsvFormatterStream.spec.ts new file mode 100644 index 00000000..f7017a5b --- /dev/null +++ b/__tests__/formatter/CsvFormatterStream.spec.ts @@ -0,0 +1,906 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as csv from '../../src'; +import { FormatterOptions, CsvFormatterStream } from '../../src/formatter'; +import RecordingStream from '../RecordingStream'; + +describe('CsvFormatterStream', () => { + const objectRows = [ + { a: 'a1', b: 'b1' }, + { a: 'a2', b: 'b2' }, + ]; + + const arrayRows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], + ]; + + const multiDimensionalRows = [ + [ + ['a', 'a1'], + ['b', 'b1'], + ], + [ + ['a', 'a2'], + ['b', 'b2'], + ], + ]; + + const pipeToRecordingStream = (formatter: CsvFormatterStream, rows: csv.FormatterRow[]) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + formatter + .on('error', e => rej(e)) + .pipe(rs) + .on('finish', () => { + res(rs.data); + }); + rows.forEach(row => formatter.write(row)); + formatter.end(); + }); + + const formatRows = (rows: csv.FormatterRow[], options: csv.FormatterOptionsArgs = {}) => + pipeToRecordingStream(csv.format(options), rows); + + it('should write an array of arrays', () => + expect(formatRows(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of objects', () => + expect(formatRows(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + describe('transform option', () => { + it('should support transforming an array of arrays', () => + expect( + formatRows(arrayRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + formatRows(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + it('should support transforming an array of objects', () => + expect( + formatRows(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap) { + return { A: row.a, B: row.b }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + }); + describe('#transform', () => { + it('should support transforming an array of arrays', async () => { + const formatter = new CsvFormatterStream( + new FormatterOptions({ headers: true }), + ).transform((row: csv.FormatterRow) => (row as csv.FormatterRowArray).map(entry => entry.toUpperCase())); + await expect(pipeToRecordingStream(formatter, arrayRows)).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2']); + }); + + it('should support transforming an array of multi-dimensional arrays', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( + (row: csv.FormatterRow): csv.FormatterRow => + (row as csv.FormatterRowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]), + ); + await expect(pipeToRecordingStream(formatter, multiDimensionalRows)).resolves.toEqual([ + 'a,b', + '\nA1,B1', + '\nA2,B2', + ]); + }); + + it('should support transforming an array of objects', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( + (row: csv.FormatterRow): csv.FormatterRow => ({ + A: (row as csv.FormatterRowMap).a, + B: (row as csv.FormatterRowMap).b, + }), + ); + await expect(pipeToRecordingStream(formatter, objectRows)).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2']); + }); + + it('should error if the transform fails', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( + (): csv.FormatterRow => { + throw new Error('Expected error'); + }, + ); + await expect(pipeToRecordingStream(formatter, objectRows)).rejects.toThrowError('Expected error'); + }); + }); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect( + formatRows(objectRows, { + headers: true, + rowDelimiter: '\r\n', + }), + ).resolves.toEqual(['a,b', '\r\na1,b1', '\r\na2,b2'])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\n1', b: 'b1' }, + { a: 'a\n2', b: 'b2' }, + ]; + await expect( + formatRows(rows, { + headers: true, + rowDelimiter: '\n', + }), + ).resolves.toEqual(['a,b', '\n"a\n1",b1', '\n"a\n2",b2']); + }); + }); + + describe('quoteColumns option', () => { + describe('quote all columns and headers if quoteColumns is true and quoteHeaders is false', () => { + const opts = { + headers: true, + quoteColumns: true, + }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a","b"', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a","b"', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with multi-dimenional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual([ + '"a","b"', + '\n"a1","b1"', + '\n"a2","b2"', + ])); + }); + + describe('quote headers if quoteHeaders is true and not columns is quoteColumns is undefined', () => { + const opts = { headers: true, quoteHeaders: true }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); + }); + + describe('quote columns if quoteColumns is true and not quote headers if quoteHeaders is false', () => { + const opts = { headers: true, quoteHeaders: false, quoteColumns: true }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); + }); + + describe('if quoteColumns object it should only quote the specified column and header', () => { + const opts = { headers: true, quoteColumns: { a: true } }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteColumns object and quoteHeaders is false it should only quote the specified column and not the header', () => { + const opts = { + headers: true, + quoteHeaders: false, + quoteColumns: { a: true }, + }; + it('should work with objects', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteColumns is an array it should only quote the specified column index', () => { + const opts = { headers: true, quoteColumns: [true] }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteColumns is false and quoteHeaders is an object it should only quote the specified header and not the column', () => { + const opts = { + headers: true, + quoteHeaders: { a: true }, + quoteColumns: false, + }; + it('should work with object', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); + + it('should work with multi-dimenional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); + }); + + describe('if quoteColumns is an object and quoteHeaders is an object it should only quote the specified header and column', () => { + const opts = { + headers: true, + quoteHeaders: { b: true }, + quoteColumns: { a: true }, + }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteHeaders is an array and quoteColumns is an false it should only quote the specified header and not the column', () => { + const opts = { + headers: true, + quoteHeaders: [false, true], + quoteColumns: false, + }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); + + it('should work with arrays of multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); + }); + }); + + describe('header option', () => { + it('should write an array of objects without headers', () => + expect(formatRows(objectRows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2'])); + + it('should write an array of objects with headers', () => + expect(formatRows(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of arrays without headers', async () => { + const rows = [ + ['a1', 'b1'], + ['a2', 'b2'], + ]; + await expect(formatRows(rows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2']); + }); + + it('should write an array of arrays with headers', () => + expect(formatRows(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of multi-dimensional arrays without headers', () => + expect(formatRows(multiDimensionalRows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2'])); + + it('should write an array of multi-dimensional arrays with headers', () => + expect(formatRows(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should not write anything if headers are provided but no rows are provided', () => + expect(formatRows([], { headers: true })).resolves.toEqual([])); + + describe('alwaysWriteHeaders option', () => { + it('should write the headers if rows are not provided', async () => { + const headers = ['h1', 'h2']; + await expect( + formatRows([], { + headers, + alwaysWriteHeaders: true, + }), + ).resolves.toEqual([headers.join(',')]); + }); + + it('should write the headers ones if rows are provided', async () => { + const headers = ['h1', 'h2']; + await expect( + formatRows(arrayRows, { + headers, + alwaysWriteHeaders: true, + }), + ).resolves.toEqual([headers.join(','), '\na,b', '\na1,b1', '\na2,b2']); + }); + + it('should fail if no headers are provided', async () => { + await expect(formatRows([], { alwaysWriteHeaders: true })).rejects.toThrowError( + '`alwaysWriteHeaders` option is set to true but `headers` option not provided.', + ); + }); + + it('should write the headers and an endRowDelimiter if includeEndRowDelimiter is true', async () => { + const headers = ['h1', 'h2']; + await expect( + formatRows([], { + headers, + includeEndRowDelimiter: true, + alwaysWriteHeaders: true, + }), + ).resolves.toEqual([headers.join(','), '\n']); + }); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect( + formatRows(objectRows, { + headers: true, + includeEndRowDelimiter: true, + }), + ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); + + it('should write a BOM character if writeBOM is true', () => + expect( + formatRows(objectRows, { + headers: true, + writeBOM: true, + }), + ).resolves.toEqual(['\ufeff', 'a,b', '\na1,b1', '\na2,b2'])); + + describe('.writeToString', () => { + it('should write an array of arrays', () => + expect(csv.writeToString(arrayRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should support transforming an array of arrays', () => + expect( + csv.writeToString(arrayRows, { + headers: true, + transform(row: csv.FormatterRow): csv.FormatterRow { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual('A,B\nA1,B1\nA2,B2')); + + it('should write an array of multi-dimensional arrays', () => + expect(csv.writeToString(multiDimensionalRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + csv.writeToString(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual('a,b\nA1,B1\nA2,B2')); + + it('should write an array of objects', () => + expect( + csv.writeToString(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual('A,B\na1,b1\na2,b2')); + + describe('header option', () => { + it('should write an array of objects without headers', () => + expect(csv.writeToString(objectRows, { headers: false })).resolves.toEqual('a1,b1\na2,b2')); + + it('should write an array of objects with headers', () => + expect(csv.writeToString(objectRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should write an array of arrays without headers', async () => { + const rows = [ + ['a1', 'b1'], + ['a2', 'b2'], + ]; + await expect(csv.writeToString(rows, { headers: false })).resolves.toEqual('a1,b1\na2,b2'); + }); + + it('should write an array of arrays with headers', () => + expect(csv.writeToString(arrayRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should write an array of multi-dimensional arrays without headers', () => + expect(csv.writeToString(multiDimensionalRows, { headers: false })).resolves.toEqual('a1,b1\na2,b2')); + + it('should write an array of multi-dimensional arrays with headers', () => + expect(csv.writeToString(multiDimensionalRows, { headers: true })).resolves.toEqual( + 'a,b\na1,b1\na2,b2', + )); + }); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(csv.writeToString(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + 'a,b\r\na1,b1\r\na2,b2', + )); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\t1', b: 'b1' }, + { a: 'a\t2', b: 'b2' }, + ]; + await expect(csv.writeToString(rows, { headers: true, rowDelimiter: '\t' })).resolves.toEqual( + 'a,b\t"a\t1",b1\t"a\t2",b2', + ); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(csv.writeToString(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( + 'a,b\na1,b1\na2,b2\n', + )); + }); + + describe('.writeToBuffer', () => { + it('should write an array of arrays', () => + expect(csv.writeToBuffer(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should support transforming an array of arrays', () => + expect( + csv.writeToBuffer(arrayRows, { + headers: true, + transform(row: csv.FormatterRow): csv.FormatterRow { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(Buffer.from('A,B\nA1,B1\nA2,B2'))); + + it('should write an array of multi-dimensional arrays', () => + expect(csv.writeToBuffer(multiDimensionalRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + csv.writeToBuffer(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(Buffer.from('a,b\nA1,B1\nA2,B2'))); + + it('should write an array of objects', () => + expect( + csv.writeToBuffer(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap): csv.FormatterRow { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(Buffer.from('A,B\na1,b1\na2,b2'))); + + describe('header option', () => { + it('should write an array of objects without headers', () => + expect(csv.writeToBuffer(objectRows, { headers: false })).resolves.toEqual( + Buffer.from('a1,b1\na2,b2'), + )); + + it('should write an array of objects with headers', () => + expect(csv.writeToBuffer(objectRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + + it('should write an array of arrays without headers', async () => { + const rows = [ + ['a1', 'b1'], + ['a2', 'b2'], + ]; + await expect(csv.writeToBuffer(rows, { headers: false })).resolves.toEqual(Buffer.from('a1,b1\na2,b2')); + }); + + it('should write an array of arrays with headers', () => + expect(csv.writeToBuffer(arrayRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + + it('should write an array of multi-dimensional arrays without headers', () => + expect(csv.writeToBuffer(multiDimensionalRows, { headers: false })).resolves.toEqual( + Buffer.from('a1,b1\na2,b2'), + )); + + it('should write an array of multi-dimensional arrays with headers', () => + expect(csv.writeToBuffer(multiDimensionalRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + }); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(csv.writeToBuffer(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + Buffer.from('a,b\r\na1,b1\r\na2,b2'), + )); + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\t1', b: 'b1' }, + { a: 'a\t2', b: 'b2' }, + ]; + await expect(csv.writeToBuffer(rows, { headers: true, rowDelimiter: '\t' })).resolves.toEqual( + Buffer.from('a,b\t"a\t1",b1\t"a\t2",b2'), + ); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(csv.writeToBuffer(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2\n'), + )); + }); + + describe('.write', () => { + const writeToRecordingStream = (rows: csv.FormatterRow[], options = {}) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + csv.write(rows, options) + .on('error', rej) + .pipe(rs) + .on('finish', () => { + res(rs.data); + }); + }); + + it('should write an array of arrays', () => + expect(writeToRecordingStream(arrayRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of arrays', () => + expect( + writeToRecordingStream(arrayRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToRecordingStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + writeToRecordingStream(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of objects', () => + expect(writeToRecordingStream(objectRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of objects', () => + expect( + writeToRecordingStream(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\na1,b1', + '\r\na2,b2', + ])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\n1', b: 'b1' }, + { a: 'a\n2', b: 'b2' }, + ]; + await expect(writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' })).resolves.toEqual([ + 'a,b', + '\n"a\n1",b1', + '\n"a\n2",b2', + ]); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect( + writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true }), + ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); + }); + + describe('.writeToPath', () => { + const writeToPath = (rows: csv.FormatterRow[], options = {}) => + new Promise((res, rej) => { + const csvPath = path.resolve(__dirname, '__fixtures__', 'test_output.csv'); + csv.writeToPath(csvPath, rows, options) + .on('error', rej) + .on('finish', () => { + const content = fs.readFileSync(csvPath); + fs.unlinkSync(csvPath); + res(content); + }); + }); + + it('should write an array of arrays', () => + expect(writeToPath(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should write an array of objects', () => + expect(writeToPath(objectRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToPath(multiDimensionalRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + + it('should support transforming an array of arrays', () => + expect( + writeToPath(arrayRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(Buffer.from('A,B\nA1,B1\nA2,B2'))); + + it('should transforming an array of objects', () => + expect( + writeToPath(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(Buffer.from('A,B\na1,b1\na2,b2'))); + + it('should transforming an array of multi-dimensional array', () => + expect( + writeToPath(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(Buffer.from('a,b\nA1,B1\nA2,B2'))); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToPath(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + Buffer.from('a,b\r\na1,b1\r\na2,b2'), + )); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\r\n1', b: 'b1' }, + { a: 'a\r\n2', b: 'b2' }, + ]; + await expect(writeToPath(rows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + Buffer.from('a,b\r\n"a\r\n1",b1\r\n"a\r\n2",b2'), + ); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeToPath(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2\n'), + )); + }); + + describe('.write', () => { + const writeToRecordingStream = (rows: csv.FormatterRow[], options = {}) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + csv.write(rows, options) + .on('error', rej) + .pipe(rs) + .on('finish', () => { + res(rs.data); + }); + }); + + it('should write an array of arrays', () => + expect(writeToRecordingStream(arrayRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of arrays', () => + expect( + writeToRecordingStream(arrayRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToRecordingStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + writeToRecordingStream(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow) { + return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of objects', () => + expect(writeToRecordingStream(objectRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of objects', () => + expect( + writeToRecordingStream(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\na1,b1', + '\r\na2,b2', + ])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\n1', b: 'b1' }, + { a: 'a\n2', b: 'b2' }, + ]; + await expect(writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' })).resolves.toEqual([ + 'a,b', + '\n"a\n1",b1', + '\n"a\n2",b2', + ]); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect( + writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true }), + ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); + }); + + describe('.writeToStream', () => { + const writeToStream = (rows: csv.FormatterRow[], options: csv.FormatterOptionsArgs = {}) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + csv.writeToStream(rs, rows, options); + rs.on('error', rej).on('finish', () => { + res(rs.data); + }); + }); + + it('should write an array of arrays', () => + expect(writeToStream(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of objects', () => + expect(writeToStream(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of arrays', () => + expect( + writeToStream(arrayRows, { + headers: true, + transform(row: csv.FormatterRow): csv.FormatterRow { + return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should transforming an array of objects', () => + expect( + writeToStream(objectRows, { + headers: true, + transform(row: csv.FormatterRowMap): csv.FormatterRow { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + + it('should transforming an array of multi-dimensional array', () => + expect( + writeToStream(multiDimensionalRows, { + headers: true, + transform(row: csv.FormatterRow): csv.FormatterRow { + return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\na1,b1', + '\r\na2,b2', + ])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\r\n1', b: 'b1' }, + { a: 'a\r\n2', b: 'b2' }, + ]; + await expect(writeToStream(rows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\n"a\r\n1",b1', + '\r\n"a\r\n2",b2', + ]); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeToStream(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + '\n', + ])); + }); +}); diff --git a/test/formatter/FormatterOptions.test.ts b/__tests__/formatter/FormatterOptions.spec.ts similarity index 52% rename from test/formatter/FormatterOptions.test.ts rename to __tests__/formatter/FormatterOptions.spec.ts index d8afe80f..b131416c 100644 --- a/test/formatter/FormatterOptions.test.ts +++ b/__tests__/formatter/FormatterOptions.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { FormatterOptionsArgs } from '../../src'; import { FormatterOptions } from '../../src/formatter'; @@ -7,99 +6,91 @@ describe('FormatterOptions', () => { describe('#objectMode', () => { it('should have default objectMode', () => { - assert.strictEqual(createOptions().objectMode, true); + expect(createOptions().objectMode).toBe(true); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ objectMode: true }).objectMode, true); - assert.strictEqual(createOptions({ objectMode: false }).objectMode, false); + expect(createOptions({ objectMode: true }).objectMode).toBe(true); + expect(createOptions({ objectMode: false }).objectMode).toBe(false); }); }); describe('#delimiter', () => { it('should have default delimiter', () => { - assert.strictEqual(createOptions().delimiter, ','); + expect(createOptions().delimiter).toBe(','); }); it('should accept a custom delimiter', () => { - assert.strictEqual(createOptions({ delimiter: '\t' }).delimiter, '\t'); + expect(createOptions({ delimiter: '\t' }).delimiter).toBe('\t'); }); }); describe('#rowDelimiter', () => { it('should have default rowDelimiter', () => { - assert.strictEqual(createOptions().rowDelimiter, '\n'); + expect(createOptions().rowDelimiter).toBe('\n'); }); it('should accept a custom rowDelimiter', () => { - assert.strictEqual(createOptions({ rowDelimiter: '\r\n' }).rowDelimiter, '\r\n'); + expect(createOptions({ rowDelimiter: '\r\n' }).rowDelimiter).toBe('\r\n'); }); }); describe('#quote', () => { it('should set a default quote value', () => { - assert.strictEqual(createOptions().quote, '"'); + expect(createOptions().quote).toBe('"'); }); it('should accept an alternate quote', () => { - assert.strictEqual(createOptions({ quote: '$' }).quote, '$'); + expect(createOptions({ quote: '$' }).quote).toBe('$'); }); it('if the set to true the default quote should be used', () => { - assert.strictEqual(createOptions({ quote: true }).quote, '"'); + expect(createOptions({ quote: true }).quote).toBe('"'); }); it('if the set to false the quote should be empty', () => { - assert.strictEqual(createOptions({ quote: false }).quote, ''); + expect(createOptions({ quote: false }).quote).toBe(''); }); }); describe('#escape', () => { it('should set the escape character to the quote value if not specified', () => { - assert.strictEqual(createOptions().escape, '"'); + expect(createOptions().escape).toBe('"'); }); it('should set the escape character to the quote value if not specified', () => { - assert.strictEqual(createOptions({ quote: '$' }).escape, '$'); + expect(createOptions({ quote: '$' }).escape).toBe('$'); }); it('should accept an alternate escape', () => { - assert.strictEqual(createOptions({ escape: '%' }).escape, '%'); + expect(createOptions({ escape: '%' }).escape).toBe('%'); }); }); describe('#quoteColumns', () => { it('should set the quoteColumns to false', () => { - assert.strictEqual(createOptions().quoteColumns, false); + expect(createOptions().quoteColumns).toBe(false); }); it('should set the quoteColumns to true if specified', () => { - assert.strictEqual(createOptions({ quoteColumns: true }).quoteColumns, true); + expect(createOptions({ quoteColumns: true }).quoteColumns).toBe(true); }); it('should set the quoteColumns to an array if specified', () => { - assert.deepStrictEqual(createOptions({ quoteColumns: [true, true, true] }).quoteColumns, [ - true, - true, - true, - ]); + expect(createOptions({ quoteColumns: [true, true, true] }).quoteColumns).toEqual([true, true, true]); }); it('should set the quoteColumns to an object if specified', () => { - assert.deepStrictEqual(createOptions({ quoteColumns: { a: true, b: false } }).quoteColumns, { + expect(createOptions({ quoteColumns: { a: true, b: false } }).quoteColumns).toEqual({ a: true, b: false, }); }); it('should set quoteHeaders to quoteColumns if quoteHeaders is not specified and quoteColumns is', () => { - assert.deepStrictEqual(createOptions({ quoteColumns: true }).quoteHeaders, true); - assert.deepStrictEqual(createOptions({ quoteColumns: [true, true, true] }).quoteHeaders, [ - true, - true, - true, - ]); - assert.deepStrictEqual(createOptions({ quoteColumns: { a: true, b: false } }).quoteHeaders, { + expect(createOptions({ quoteColumns: true }).quoteHeaders).toBe(true); + expect(createOptions({ quoteColumns: [true, true, true] }).quoteHeaders).toEqual([true, true, true]); + expect(createOptions({ quoteColumns: { a: true, b: false } }).quoteHeaders).toEqual({ a: true, b: false, }); @@ -108,23 +99,19 @@ describe('FormatterOptions', () => { describe('#quoteHeaders', () => { it('should set the quoteHeaders to false', () => { - assert.strictEqual(createOptions().quoteHeaders, false); + expect(createOptions().quoteHeaders).toBe(false); }); it('should set the quoteHeaders to true if specified', () => { - assert.strictEqual(createOptions({ quoteHeaders: true }).quoteHeaders, true); + expect(createOptions({ quoteHeaders: true }).quoteHeaders).toBe(true); }); it('should set the quoteHeaders to an array if specified', () => { - assert.deepStrictEqual(createOptions({ quoteHeaders: [true, true, true] }).quoteHeaders, [ - true, - true, - true, - ]); + expect(createOptions({ quoteHeaders: [true, true, true] }).quoteHeaders).toEqual([true, true, true]); }); it('should set the quoteHeaders to an object if specified', () => { - assert.deepStrictEqual(createOptions({ quoteHeaders: { a: true, b: false } }).quoteHeaders, { + expect(createOptions({ quoteHeaders: { a: true, b: false } }).quoteHeaders).toEqual({ a: true, b: false, }); @@ -133,53 +120,53 @@ describe('FormatterOptions', () => { describe('#headers', () => { it('should have default headers', () => { - assert.strictEqual(createOptions().headers, null); + expect(createOptions().headers).toBeNull(); }); it('should accept an array of headers', () => { - assert.deepStrictEqual(createOptions({ headers: ['1', '2', '3'] }).headers, ['1', '2', '3']); + expect(createOptions({ headers: ['1', '2', '3'] }).headers).toEqual(['1', '2', '3']); }); it('should accept an boolean and set headers to null', () => { - assert.deepStrictEqual(createOptions({ headers: true }).headers, null); + expect(createOptions({ headers: true }).headers).toBeNull(); }); it('should set hasHeaders provided to true if headers is provided as an array', () => { - assert.deepStrictEqual(createOptions({ headers: ['1', '2', '3'] }).shouldWriteHeaders, true); + expect(createOptions({ headers: ['1', '2', '3'] }).shouldWriteHeaders).toBe(true); }); it('should set hasHeaders provided to false if headers is provided as a boolean', () => { - assert.deepStrictEqual(createOptions({ headers: true }).shouldWriteHeaders, true); + expect(createOptions({ headers: true }).shouldWriteHeaders).toBe(true); }); }); describe('#includeEndRowDelimiter', () => { it('should set includeEndRowDelimiter to false by default', () => { - assert.strictEqual(createOptions().includeEndRowDelimiter, false); + expect(createOptions().includeEndRowDelimiter).toBe(false); }); it('should set to true if the includeEndRowDelimiter is specified', () => { - assert.strictEqual(createOptions({ includeEndRowDelimiter: true }).includeEndRowDelimiter, true); + expect(createOptions({ includeEndRowDelimiter: true }).includeEndRowDelimiter).toBe(true); }); }); describe('#writeBOM', () => { it('should set writeBOM to false by default', () => { - assert.strictEqual(createOptions().writeBOM, false); + expect(createOptions().writeBOM).toBe(false); }); it('should set to true if the writeBOM is specified', () => { - assert.strictEqual(createOptions({ writeBOM: true }).writeBOM, true); + expect(createOptions({ writeBOM: true }).writeBOM).toBe(true); }); }); describe('#alwaysWriteHeaders', () => { it('should set alwaysWriteHeaders to false by default', () => { - assert.strictEqual(createOptions().alwaysWriteHeaders, false); + expect(createOptions().alwaysWriteHeaders).toBe(false); }); it('should set to provided value if the alwaysWriteHeaders is specified', () => { - assert.strictEqual(createOptions({ alwaysWriteHeaders: true }).alwaysWriteHeaders, true); + expect(createOptions({ alwaysWriteHeaders: true }).alwaysWriteHeaders).toBe(true); }); }); }); diff --git a/test/formatter/assets/.gitkeep b/__tests__/formatter/__fixtures__/.gitkeep similarity index 100% rename from test/formatter/assets/.gitkeep rename to __tests__/formatter/__fixtures__/.gitkeep diff --git a/test/formatter/formatter/FieldFormatter.test.ts b/__tests__/formatter/formatter/FieldFormatter.spec.ts similarity index 73% rename from test/formatter/formatter/FieldFormatter.test.ts rename to __tests__/formatter/formatter/FieldFormatter.spec.ts index a469260e..ff26c8a6 100644 --- a/test/formatter/formatter/FieldFormatter.test.ts +++ b/__tests__/formatter/formatter/FieldFormatter.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { FormatterOptionsArgs } from '../../../src'; import { FormatterOptions, FieldFormatter } from '../../../src/formatter'; @@ -11,94 +10,94 @@ describe('FieldFormatter', () => { describe('header columns', () => { it('should return the field not quoted if it contains no quotes', () => { const formatter = createFormatter(); - assert.strictEqual(formatter.format('header', 0, true), 'header'); + expect(formatter.format('header', 0, true)).toEqual('header'); }); it('should quote the field and escape quotes if it contains a quote character', () => { const formatter = createFormatter(); - assert.strictEqual(formatter.format('hea"d"er', 0, true), '"hea""d""er"'); + expect(formatter.format('hea"d"er', 0, true)).toEqual('"hea""d""er"'); }); it('should quote the field and if it contains a rowDelimiter', () => { const formatter = createFormatter({ rowDelimiter: '\r\n' }); - assert.strictEqual(formatter.format('hea\r\nder', 0, true), '"hea\r\nder"'); + expect(formatter.format('hea\r\nder', 0, true)).toEqual('"hea\r\nder"'); }); it('should quote the field if quoteHeaders is true', () => { const formatter = createFormatter({ quoteHeaders: true }); - assert.strictEqual(formatter.format('header', 0, true), '"header"'); + expect(formatter.format('header', 0, true)).toEqual('"header"'); }); it('should quote the header if quote headers is an array and the index of the header is true in the quoteHeaders array', () => { const formatter = createFormatter({ quoteHeaders: [true] }); - assert.strictEqual(formatter.format('header', 0, true), '"header"'); + expect(formatter.format('header', 0, true)).toEqual('"header"'); }); it('should not quote the header if quote headers is an array and the index of the header is false in the quoteHeaders array', () => { const formatter = createFormatter({ quoteHeaders: [false] }); - assert.strictEqual(formatter.format('header', 0, true), 'header'); + expect(formatter.format('header', 0, true)).toEqual('header'); }); it('should quote the header if quoteHeaders is an object and quoteHeaders object has true for the column name', () => { const formatter = createFormatter({ quoteHeaders: { header: true }, headers: ['header'] }); - assert.strictEqual(formatter.format('header', 0, true), '"header"'); + expect(formatter.format('header', 0, true)).toEqual('"header"'); }); it('should not quote the header if quoteHeaders is an object and quoteHeaders object has false for the column nam', () => { const formatter = createFormatter({ quoteHeaders: { header: false }, headers: ['header'] }); - assert.strictEqual(formatter.format('header', 0, true), 'header'); + expect(formatter.format('header', 0, true)).toEqual('header'); }); it('should not quote the header if quoteHeaders is an object and quoteHeaders object does not contain the header', () => { const formatter = createFormatter({ quoteHeaders: { header2: true }, headers: ['header'] }); - assert.strictEqual(formatter.format('header', 0, true), 'header'); + expect(formatter.format('header', 0, true)).toEqual('header'); }); }); describe('non-header columns', () => { it('should return the field not quoted if it contains no quotes', () => { const formatter = createFormatter(); - assert.strictEqual(formatter.format('col', 0, false), 'col'); + expect(formatter.format('col', 0, false)).toEqual('col'); }); it('should quote the field and escape quotes if it contains a quote character', () => { const formatter = createFormatter(); - assert.strictEqual(formatter.format('c"o"l', 0, false), '"c""o""l"'); + expect(formatter.format('c"o"l', 0, false)).toEqual('"c""o""l"'); }); it('should quote the field if it contains a rowDelimiter', () => { const formatter = createFormatter({ rowDelimiter: '\r\n' }); - assert.strictEqual(formatter.format('col\r\n', 0, false), '"col\r\n"'); + expect(formatter.format('col\r\n', 0, false)).toEqual('"col\r\n"'); }); it('should quote the field if quoteColumns is true', () => { const formatter = createFormatter({ quoteColumns: true }); - assert.strictEqual(formatter.format('col', 0, false), '"col"'); + expect(formatter.format('col', 0, false)).toEqual('"col"'); }); it('should quote the header if quote headers is an array and the index of the header is true in the quoteColumns array', () => { const formatter = createFormatter({ quoteColumns: [true] }); - assert.strictEqual(formatter.format('col', 0, false), '"col"'); + expect(formatter.format('col', 0, false)).toEqual('"col"'); }); it('should not quote the header if quote headers is an array and the index of the header is false in the quoteColumns array', () => { const formatter = createFormatter({ quoteColumns: [false] }); - assert.strictEqual(formatter.format('col', 0, false), 'col'); + expect(formatter.format('col', 0, false)).toEqual('col'); }); it('should quote the header if quoteColumns is an object and quoteColumns object has true for the column name', () => { const formatter = createFormatter({ quoteColumns: { header: true }, headers: ['header'] }); - assert.strictEqual(formatter.format('col', 0, false), '"col"'); + expect(formatter.format('col', 0, false)).toEqual('"col"'); }); it('should not quote the header if quoteColumns is an object and quoteColumns object has false for the column nam', () => { const formatter = createFormatter({ quoteColumns: { header: false }, headers: ['header'] }); - assert.strictEqual(formatter.format('col', 0, false), 'col'); + expect(formatter.format('col', 0, false)).toEqual('col'); }); it('should not quote the header if quoteColumns is an object and quoteColumns object does not contain the header', () => { const formatter = createFormatter({ quoteColumns: { header2: true }, headers: ['header'] }); - assert.strictEqual(formatter.format('col', 0, false), 'col'); + expect(formatter.format('col', 0, false)).toEqual('col'); }); }); }); diff --git a/test/formatter/formatter/RowFormatter.test.ts b/__tests__/formatter/formatter/RowFormatter.spec.ts similarity index 58% rename from test/formatter/formatter/RowFormatter.test.ts rename to __tests__/formatter/formatter/RowFormatter.spec.ts index aa3052cc..64b68864 100644 --- a/test/formatter/formatter/RowFormatter.test.ts +++ b/__tests__/formatter/formatter/RowFormatter.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { FormatterRow as Row, FormatterRowArray as RowArray, @@ -49,89 +48,78 @@ describe('RowFormatter', () => { setImmediate(() => cb(new Error('Expected Error'))); }; - it('should format an array', () => { + it('should format an array', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(headerRow, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b'])); + await expect(formatRow(headerRow, formatter)).resolves.toEqual(['a,b']); }); - it('should should append a new line if a second row is written', () => { + it('should should append a new line if a second row is written', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(headerRow, formatter) - .then(rows => assert.deepStrictEqual(rows, ['a,b'])) - .then(() => formatRow(columnsRow, formatter)) - .then(rows => assert.deepStrictEqual(rows, ['\na1,b1'])); + await expect(formatRow(headerRow, formatter)).resolves.toEqual(['a,b']); + await expect(formatRow(columnsRow, formatter)).resolves.toEqual(['\na1,b1']); }); - it('should support a sync transform', () => { + it('should support a sync transform', async () => { const formatter = createFormatter({ headers: true, transform: syncTransform }); - return formatRow(headerRow, formatter).then(rows => assert.deepStrictEqual(rows, ['A,B'])); + await expect(formatRow(headerRow, formatter)).resolves.toEqual(['A,B']); }); - it('should catch a sync transform thrown error', () => { + it('should catch a sync transform thrown error', async () => { const formatter = createFormatter({ headers: true, transform: syncError }); - return formatRow(headerRow, formatter).catch(err => assert.strictEqual(err.message, 'Expected Error')); + await expect(formatRow(headerRow, formatter)).rejects.toThrowError('Expected Error'); }); - it('should support an async transform', () => { + it('should support an async transform', async () => { const formatter = createFormatter({ headers: true, transform: asyncTransform }); - return formatRow(headerRow, formatter).then(rows => assert.deepStrictEqual(rows, ['A,B'])); + await expect(formatRow(headerRow, formatter)).resolves.toEqual(['A,B']); }); - it('should support an async transform with error', () => { + it('should support an async transform with error', async () => { const formatter = createFormatter({ headers: true, transform: asyncErrorTransform }); - return formatRow(headerRow, formatter).catch(err => assert.strictEqual(err.message, 'Expected Error')); + await expect(formatRow(headerRow, formatter)).rejects.toThrowError('Expected Error'); }); describe('headers option', () => { describe('with headers=false', () => { - it('should still write the first row', () => { + it('should still write the first row', async () => { const formatter = createFormatter({ headers: false }); - return formatRow(headerRow, formatter).then(rows => - assert.deepStrictEqual(rows, [headerRow.join(',')]), - ); + await expect(formatRow(headerRow, formatter)).resolves.toEqual([headerRow.join(',')]); }); }); describe('with headers=true', () => { - it('should only write the first row', () => { + it('should only write the first row', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(headerRow, formatter).then(rows => - assert.deepStrictEqual(rows, [headerRow.join(',')]), - ); + await expect(formatRow(headerRow, formatter)).resolves.toEqual([headerRow.join(',')]); }); }); describe('with headers provided', () => { - it('should only write the first row', () => { + it('should only write the first row', async () => { const formatter = createFormatter({ headers: headerRow }); - return formatRow(columnsRow, formatter).then(rows => - assert.deepStrictEqual(rows, [headerRow.join(','), `\n${columnsRow.join(',')}`]), - ); + await expect(formatRow(columnsRow, formatter)).resolves.toEqual([ + headerRow.join(','), + `\n${columnsRow.join(',')}`, + ]); }); - it('should append an additional column for new fields', () => { + it('should append an additional column for new fields', async () => { const formatter = createFormatter({ headers: ['A', 'B', 'no_field'] }); - return formatRow(columnsRow, formatter).then(rows => - assert.deepStrictEqual(rows, ['A,B,no_field', '\na1,b1,']), - ); + await expect(formatRow(columnsRow, formatter)).resolves.toEqual(['A,B,no_field', '\na1,b1,']); }); - it('should exclude columns that do not have a header', () => { + it('should exclude columns that do not have a header', async () => { const formatter = createFormatter({ headers: ['A'] }); - return formatRow(columnsRow, formatter).then(rows => - assert.deepStrictEqual(rows, ['A', '\na1']), - ); + await expect(formatRow(columnsRow, formatter)).resolves.toEqual(['A', '\na1']); }); }); }); describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => { + it('should support specifying an alternate row delimiter', async () => { const formatter = createFormatter({ headers: true, rowDelimiter: '\r\n' }); - return formatRow(headerRow, formatter) - .then(rows => assert.deepStrictEqual(rows, ['a,b'])) - .then(() => formatRow(columnsRow, formatter)) - .then(rows => assert.deepStrictEqual(rows, ['\r\na1,b1'])); + await expect(formatRow(headerRow, formatter)).resolves.toEqual(['a,b']); + await expect(formatRow(columnsRow, formatter)).resolves.toEqual(['\r\na1,b1']); }); }); }); @@ -154,75 +142,73 @@ describe('RowFormatter', () => { const asyncErrorTransform = (rowToTransform: RowHashArray, cb: RowTransformCallback) => setImmediate(() => cb(new Error('Expected Error'))); - it('should format a multi-dimensional array with headers true', () => { + it('should format a multi-dimensional array with headers true', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\na1,b1']); }); - it('should not include headers if headers is false', () => { + it('should not include headers if headers is false', async () => { const formatter = createFormatter({ headers: false }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a1,b1']); }); - it('should support a sync transform', () => { + it('should support a sync transform', async () => { const formatter = createFormatter({ headers: true, transform: syncTransform }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\nA1,B1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\nA1,B1']); }); - it('should catch a sync transform thrown error', () => { + it('should catch a sync transform thrown error', async () => { const formatter = createFormatter({ headers: true, transform: syncError }); - return formatRow(row, formatter).catch(err => assert.strictEqual(err.message, 'Expected Error')); + await expect(formatRow(row, formatter)).rejects.toThrowError('Expected Error'); }); - it('should support an async transform', () => { + it('should support an async transform', async () => { const formatter = createFormatter({ headers: true, transform: asyncTransform }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\nA1,B1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\nA1,B1']); }); - it('should support an async transform with error', () => { + it('should support an async transform with error', async () => { const formatter = createFormatter({ headers: true, transform: asyncErrorTransform }); - return formatRow(row, formatter).catch(err => assert.strictEqual(err.message, 'Expected Error')); + await expect(formatRow(row, formatter)).rejects.toThrowError('Expected Error'); }); describe('headers option', () => { describe('with headers=false', () => { - it('should still write the first row', () => { + it('should still write the first row', async () => { const formatter = createFormatter({ headers: false }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a1,b1']); }); }); describe('with headers=true', () => { - it('should only write the first row', () => { + it('should only write the first row', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\na1,b1']); }); }); describe('with headers provided', () => { - it('should write the headers and first row', () => { + it('should write the headers and first row', async () => { const formatter = createFormatter({ headers: ['A', 'B'] }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['A,B', '\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['A,B', '\na1,b1']); }); - it('should append an additional column for new fields', () => { + it('should append an additional column for new fields', async () => { const formatter = createFormatter({ headers: ['A', 'B', 'no_field'] }); - return formatRow(row, formatter).then(rows => - assert.deepStrictEqual(rows, ['A,B,no_field', '\na1,b1,']), - ); + await expect(formatRow(row, formatter)).resolves.toEqual(['A,B,no_field', '\na1,b1,']); }); - it('should exclude columns that do not have a header', () => { + it('should exclude columns that do not have a header', async () => { const formatter = createFormatter({ headers: ['A'] }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['A', '\na1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['A', '\na1']); }); }); }); describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => { + it('should support specifying an alternate row delimiter', async () => { const formatter = createFormatter({ headers: true, rowDelimiter: '\r\n' }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\r\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\r\na1,b1']); }); }); }); @@ -242,75 +228,73 @@ describe('RowFormatter', () => { const asyncErrorTransform = (rowToTransform: RowMap, cb: RowTransformCallback) => setImmediate(() => cb(new Error('Expected Error'))); - it('should return a headers row with when headers true', () => { + it('should return a headers row with when headers true', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\na1,b1']); }); - it('should not include headers if headers is false', () => { + it('should not include headers if headers is false', async () => { const formatter = createFormatter({ headers: false }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a1,b1']); }); - it('should support a sync transform', () => { + it('should support a sync transform', async () => { const formatter = createFormatter({ headers: true, transform: syncTransform }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\nA1,B1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\nA1,B1']); }); - it('should catch a sync transform thrown error', () => { + it('should catch a sync transform thrown error', async () => { const formatter = createFormatter({ headers: true, transform: syncError }); - return formatRow(row, formatter).catch(err => assert.strictEqual(err.message, 'Expected Error')); + await expect(formatRow(row, formatter)).rejects.toThrowError('Expected Error'); }); - it('should support an async transform', () => { + it('should support an async transform', async () => { const formatter = createFormatter({ headers: true, transform: asyncTransform }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\nA1,B1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\nA1,B1']); }); - it('should support an async transform with error', () => { + it('should support an async transform with error', async () => { const formatter = createFormatter({ headers: true, transform: asyncErrorTransform }); - return formatRow(row, formatter).catch(err => assert.strictEqual(err.message, 'Expected Error')); + await expect(formatRow(row, formatter)).rejects.toThrowError('Expected Error'); }); describe('headers option', () => { describe('with headers=false', () => { - it('should still write the first row', () => { + it('should still write the first row', async () => { const formatter = createFormatter({ headers: false }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a1,b1']); }); }); describe('with headers=true', () => { - it('should only write the first row', () => { + it('should only write the first row', async () => { const formatter = createFormatter({ headers: true }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\na1,b1']); }); }); describe('with headers provided', () => { - it('should the new headers and the row', () => { + it('should the new headers and the row', async () => { const formatter = createFormatter({ headers: ['a', 'b'] }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\na1,b1']); }); - it('should respect the order of the columns', () => { + it('should respect the order of the columns', async () => { const formatter = createFormatter({ headers: ['b', 'a'] }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['b,a', '\nb1,a1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['b,a', '\nb1,a1']); }); - it('should append an additional column for new fields', () => { + it('should append an additional column for new fields', async () => { const formatter = createFormatter({ headers: ['a', 'b', 'no_field'] }); - return formatRow(row, formatter).then(rows => - assert.deepStrictEqual(rows, ['a,b,no_field', '\na1,b1,']), - ); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b,no_field', '\na1,b1,']); }); }); }); describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => { + it('should support specifying an alternate row delimiter', async () => { const formatter = createFormatter({ headers: true, rowDelimiter: '\r\n' }); - return formatRow(row, formatter).then(rows => assert.deepStrictEqual(rows, ['a,b', '\r\na1,b1'])); + await expect(formatRow(row, formatter)).resolves.toEqual(['a,b', '\r\na1,b1']); }); }); }); @@ -318,38 +302,31 @@ describe('RowFormatter', () => { describe('#finish', () => { describe('alwaysWriteHeaders option', () => { - it('should return a headers row if no rows have been written', () => { + it('should return a headers row if no rows have been written', async () => { const headers = ['h1', 'h2']; const formatter = createFormatter({ headers, alwaysWriteHeaders: true }); - return finish(formatter).then(rows => assert.deepStrictEqual(rows, [headers.join(',')])); + await expect(finish(formatter)).resolves.toEqual([headers.join(',')]); }); - it('should not return a headers row if rows have been written', () => { + it('should not return a headers row if rows have been written', async () => { const headers = ['h1', 'h2']; const formatter = createFormatter({ headers, alwaysWriteHeaders: true }); - return formatRow(['c1', 'c2'], formatter) - .then(rows => { - assert.deepStrictEqual(rows, ['h1,h2', '\nc1,c2']); - return finish(formatter); - }) - .then(rows => assert.deepStrictEqual(rows, [])); + await expect(formatRow(['c1', 'c2'], formatter)).resolves.toEqual(['h1,h2', '\nc1,c2']); + await expect(finish(formatter)).resolves.toEqual([]); }); - it('should reject if headers are not specified', () => { + it('should reject if headers are not specified', async () => { const formatter = createFormatter({ alwaysWriteHeaders: true }); - return finish(formatter).catch(e => - assert.strictEqual( - e.message, - '`alwaysWriteHeaders` option is set to true but `headers` option not provided.', - ), + await expect(finish(formatter)).rejects.toThrowError( + '`alwaysWriteHeaders` option is set to true but `headers` option not provided.', ); }); }); describe('includeEndRowDelimiter option', () => { - it('should write the endRowDelimiter if ', () => { + it('should write the endRowDelimiter if ', async () => { const formatter = createFormatter({ includeEndRowDelimiter: true }); - return finish(formatter).then(rows => assert.deepStrictEqual(rows, ['\n'])); + await expect(finish(formatter)).resolves.toEqual(['\n']); }); }); }); @@ -357,10 +334,10 @@ describe('RowFormatter', () => { describe('#rowTransform', () => { it('should throw an error if the transform is set and is not a function', () => { const formatter = createFormatter(); - assert.throws(() => { + expect(() => { // @ts-ignore formatter.rowTransform = 'foo'; - }, /TypeError: The transform should be a function/); + }).toThrow('The transform should be a function'); }); }); }); diff --git a/test/issues/assets/issue102.csv b/__tests__/issues/__fixtures__/issue102.csv similarity index 100% rename from test/issues/assets/issue102.csv rename to __tests__/issues/__fixtures__/issue102.csv diff --git a/test/issues/assets/issue68-invalid.tsv b/__tests__/issues/__fixtures__/issue68-invalid.tsv similarity index 100% rename from test/issues/assets/issue68-invalid.tsv rename to __tests__/issues/__fixtures__/issue68-invalid.tsv diff --git a/test/issues/assets/issue68.tsv b/__tests__/issues/__fixtures__/issue68.tsv similarity index 100% rename from test/issues/assets/issue68.tsv rename to __tests__/issues/__fixtures__/issue68.tsv diff --git a/test/issues/assets/issue87.csv b/__tests__/issues/__fixtures__/issue87.csv similarity index 100% rename from test/issues/assets/issue87.csv rename to __tests__/issues/__fixtures__/issue87.csv diff --git a/test/issues/issue102.test.ts b/__tests__/issues/issue102.spec.ts similarity index 73% rename from test/issues/issue102.test.ts rename to __tests__/issues/issue102.spec.ts index a2434f1c..62c8870f 100644 --- a/test/issues/issue102.test.ts +++ b/__tests__/issues/issue102.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { resolve } from 'path'; import { parseFile } from '../../src'; @@ -16,16 +15,18 @@ describe('Issue #102 - https://github.com/C2FO/fast-csv/issues/102', () => { it('parse all rows ', next => { let receivedRows = 0; - parseFile(resolve(__dirname, 'assets', 'issue102.csv')) + parseFile(resolve(__dirname, '__fixtures__', 'issue102.csv')) .on('data-invalid', () => next(new Error('Should not have received data-invalid event'))) .on('data', r => { receivedRows += 1; - assert.deepStrictEqual(r, row); + if (receivedRows % 1000 === 0) { + expect(r).toEqual(row); + } }) .on('error', err => next(err)) .on('end', (rowCount: number) => { - assert.strictEqual(rowCount, 100000); - assert.strictEqual(receivedRows, rowCount); + expect(rowCount).toBe(100000); + expect(receivedRows).toBe(rowCount); next(); }); }); diff --git a/test/issues/issue111.test.ts b/__tests__/issues/issue111.spec.ts similarity index 87% rename from test/issues/issue111.test.ts rename to __tests__/issues/issue111.spec.ts index 85937a1c..57ab5316 100644 --- a/test/issues/issue111.test.ts +++ b/__tests__/issues/issue111.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptions, Parser } from '../../src/parser'; describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { @@ -8,7 +7,7 @@ describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { it('should parse a block of CSV text with a trailing delimiter', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com,\n'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(runParser(data, false, myParser), { + expect(runParser(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -20,7 +19,7 @@ describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { it('should parse a block of CSV text with a delimiter at file end', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com,'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(runParser(data, false, myParser), { + expect(runParser(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -32,7 +31,7 @@ describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { it('should parse a block of CSV text with two delimiters at file end', () => { const data = 'first_name,last_name,email_address,empty1,empty2\nFirst1,Last1,email1@email.com,,'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(runParser(data, false, myParser), { + expect(runParser(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty1', 'empty2'], @@ -44,7 +43,7 @@ describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { it('should parse a block of CSV text with a trailing delimiter followed by a space', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com, \n'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(runParser(data, false, myParser), { + expect(runParser(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -56,7 +55,7 @@ describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { it('should parse a block of Space Separated Value text with a trailing delimiter', () => { const data = 'first_name last_name email_address empty\nFirst1 Last1 email1@email.com \n'; const myParser = createParser({ delimiter: ' ' }); - assert.deepStrictEqual(runParser(data, false, myParser), { + expect(runParser(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -68,7 +67,7 @@ describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { it('should parse a block of Space Separated Values with two delimiters at file end', () => { const data = 'first_name last_name email_address empty empty2\nFirst1 Last1 email1@email.com \n'; const myParser = createParser({ delimiter: ' ' }); - assert.deepStrictEqual(runParser(data, false, myParser), { + expect(runParser(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty', 'empty2'], diff --git a/test/issues/issue131.test.ts b/__tests__/issues/issue131.spec.ts similarity index 79% rename from test/issues/issue131.test.ts rename to __tests__/issues/issue131.spec.ts index a5243ed9..3a556ebe 100644 --- a/test/issues/issue131.test.ts +++ b/__tests__/issues/issue131.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { EOL } from 'os'; import * as csv from '../../src'; @@ -13,8 +12,8 @@ describe('Issue #131 - https://github.com/C2FO/fast-csv/issues/131', () => { csv.parseString(csvWithBom, { headers: true }) .on('data', data => actual.push(data)) .on('end', (count: number) => { - assert.deepStrictEqual(actual[0].first_name, 'First1'); - assert.strictEqual(count, actual.length); + expect(actual[0].first_name).toBe('First1'); + expect(count).toBe(actual.length); next(); }); }); diff --git a/test/issues/issue150.test.ts b/__tests__/issues/issue150.spec.ts similarity index 89% rename from test/issues/issue150.test.ts rename to __tests__/issues/issue150.spec.ts index 4fd0cc04..db0ba99c 100644 --- a/test/issues/issue150.test.ts +++ b/__tests__/issues/issue150.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptions, Parser } from '../../src/parser'; describe('Issue #150 - https://github.com/C2FO/fast-csv/issues/150', () => { @@ -9,7 +8,7 @@ describe('Issue #150 - https://github.com/C2FO/fast-csv/issues/150', () => { const data = 'first_name,last_name,email_address\r'; const myParser = createParser({}); const parsedData = runParser(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address\r', rows: [], }); diff --git a/test/issues/issue158.test.ts b/__tests__/issues/issue158.spec.ts similarity index 88% rename from test/issues/issue158.test.ts rename to __tests__/issues/issue158.spec.ts index c70c1ed7..f794c22b 100644 --- a/test/issues/issue158.test.ts +++ b/__tests__/issues/issue158.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as csv from '../../src'; import RecordingStream from '../RecordingStream'; @@ -35,7 +34,7 @@ describe('Issue #158 - https://github.com/C2FO/fast-csv/issues/158', () => { .pipe(rs) .on('error', next) .on('finish', () => { - assert.deepStrictEqual(rs.data.join(''), 'id,name,calculatedValue\n1,a,2\n2,b,4\n3,c,6'); + expect(rs.data.join('')).toBe('id,name,calculatedValue\n1,a,2\n2,b,4\n3,c,6'); next(); }); }); diff --git a/test/issues/issue174.test.ts b/__tests__/issues/issue174.spec.ts similarity index 91% rename from test/issues/issue174.test.ts rename to __tests__/issues/issue174.spec.ts index 2e249095..c976a215 100644 --- a/test/issues/issue174.test.ts +++ b/__tests__/issues/issue174.spec.ts @@ -1,5 +1,4 @@ import { EOL } from 'os'; -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../src'; import { Parser, ParserOptions } from '../../src/parser'; @@ -12,7 +11,7 @@ describe('Issue #174 - https://github.com/C2FO/fast-csv/issues/174', () => { it('skip trailing whitespace after a quoted field', () => { const parser = createParser({ headers: true }); const parsedData = runParser(CSV_CONTENT, false, parser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [ ['f1', 'f2', 'f3'], diff --git a/test/issues/issue214.test.ts b/__tests__/issues/issue214.spec.ts similarity index 84% rename from test/issues/issue214.test.ts rename to __tests__/issues/issue214.spec.ts index 72730894..2c9cf50a 100644 --- a/test/issues/issue214.test.ts +++ b/__tests__/issues/issue214.spec.ts @@ -1,5 +1,4 @@ import { EOL } from 'os'; -import * as assert from 'assert'; import * as csv from '../../src'; describe('Issue #214 - https://github.com/C2FO/fast-csv/issues/214', () => { @@ -24,8 +23,8 @@ describe('Issue #214 - https://github.com/C2FO/fast-csv/issues/214', () => { .on('data', (r: csv.ParserRowMap) => rows.push(r)) .on('error', next) .on('end', (count: number) => { - assert.deepStrictEqual(rows, expectedRows); - assert.strictEqual(count, expectedRows.length); + expect(rows).toEqual(expectedRows); + expect(count).toBe(expectedRows.length); next(); }); }); @@ -36,8 +35,8 @@ describe('Issue #214 - https://github.com/C2FO/fast-csv/issues/214', () => { .addListener('data', (r: csv.ParserRowMap) => rows.push(r)) .on('error', next) .on('end', (count: number) => { - assert.deepStrictEqual(rows, expectedRows); - assert.strictEqual(count, expectedRows.length); + expect(rows).toEqual(expectedRows); + expect(count).toBe(expectedRows.length); next(); }); }); diff --git a/test/issues/issue223.test.ts b/__tests__/issues/issue223.spec.ts similarity index 91% rename from test/issues/issue223.test.ts rename to __tests__/issues/issue223.spec.ts index 29948a1b..68b7967e 100644 --- a/test/issues/issue223.test.ts +++ b/__tests__/issues/issue223.spec.ts @@ -1,5 +1,4 @@ import { EOL } from 'os'; -import * as assert from 'assert'; import { Parser, ParserOptions } from '../../src/parser'; describe('Issue #223 - https://github.com/C2FO/fast-csv/issues/223', () => { @@ -10,7 +9,7 @@ describe('Issue #223 - https://github.com/C2FO/fast-csv/issues/223', () => { const CSV_CONTENT = ['"ABC" ,"DEFG" ,12345,"HI"', '"JKLM" ,"NOP" ,67890,"QR" '].join(EOL); const parser = createParser(); const parsedData = runParser(CSV_CONTENT, false, parser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [ ['ABC', 'DEFG', '12345', 'HI'], diff --git a/test/issues/issue252.test.ts b/__tests__/issues/issue252.spec.ts similarity index 81% rename from test/issues/issue252.test.ts rename to __tests__/issues/issue252.spec.ts index 238c6281..0c797c41 100644 --- a/test/issues/issue252.test.ts +++ b/__tests__/issues/issue252.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as csv from '../../src'; import RecordingStream from '../RecordingStream'; @@ -16,7 +15,7 @@ describe('Issue #252 - https://github.com/C2FO/fast-csv/issues/252', () => { .pipe(rs) .on('error', next) .on('finish', () => { - assert.deepStrictEqual(rs.data.join(''), 'header1,header2,header3\na,b,c\nd,e,f'); + expect(rs.data.join('')).toBe('header1,header2,header3\na,b,c\nd,e,f'); next(); }); }); diff --git a/test/issues/issue68.test.ts b/__tests__/issues/issue68.spec.ts similarity index 60% rename from test/issues/issue68.test.ts rename to __tests__/issues/issue68.spec.ts index 046d923c..dbb6b0dc 100644 --- a/test/issues/issue68.test.ts +++ b/__tests__/issues/issue68.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as path from 'path'; import * as domain from 'domain'; import * as csv from '../../src'; @@ -11,13 +10,16 @@ describe('Issue #68 - https://github.com/C2FO/fast-csv/issues/68', () => { d.exit(); if (!called) { called = true; - assert.strictEqual(/^Parse Error/.test(err.message), true); + expect(err.message).toMatch(/^Parse Error/); next(); } }); d.run(() => csv - .parseFile(path.resolve(__dirname, './assets/issue68-invalid.tsv'), { headers: true, delimiter: '\t' }) + .parseFile(path.resolve(__dirname, '__fixtures__', 'issue68-invalid.tsv'), { + headers: true, + delimiter: '\t', + }) .on('data', () => null), ); }); @@ -29,7 +31,7 @@ describe('Issue #68 - https://github.com/C2FO/fast-csv/issues/68', () => { d.exit(); if (!called) { called = true; - assert.strictEqual(err.message, 'Data error'); + expect(err.message).toBe('Data error'); next(); } else { throw err; @@ -37,15 +39,15 @@ describe('Issue #68 - https://github.com/C2FO/fast-csv/issues/68', () => { }); d.run(() => { let count = 0; - csv.parseFile(path.resolve(__dirname, './assets/issue68.tsv'), { headers: true, delimiter: '\t' }).on( - 'data', - () => { - count += 1; - if (count % 1001 === 0) { - throw new Error('Data error'); - } - }, - ); + csv.parseFile(path.resolve(__dirname, '__fixtures__', 'issue68.tsv'), { + headers: true, + delimiter: '\t', + }).on('data', () => { + count += 1; + if (count % 1001 === 0) { + throw new Error('Data error'); + } + }); }); }); }); diff --git a/test/issues/issue77.test.ts b/__tests__/issues/issue77.spec.ts similarity index 65% rename from test/issues/issue77.test.ts rename to __tests__/issues/issue77.spec.ts index ba423c4b..a90e3089 100644 --- a/test/issues/issue77.test.ts +++ b/__tests__/issues/issue77.spec.ts @@ -1,19 +1,17 @@ -import * as assert from 'assert'; import * as fs from 'fs'; import * as path from 'path'; import * as csv from '../../src'; describe('Issue #77 - https://github.com/C2FO/fast-csv/issues/77', () => { it('should sort columns by order of headers defined when formatting a csv', next => { - const writable = fs.createWriteStream(path.resolve(__dirname, 'assets/test.csv'), { encoding: 'utf8' }); + const writable = fs.createWriteStream(path.resolve(__dirname, '__fixtures__/test.csv'), { encoding: 'utf8' }); const csvStream = csv.format({ headers: ['second', 'first'] }).on('error', next); writable.on('finish', () => { - assert.strictEqual( - fs.readFileSync(path.resolve(__dirname, 'assets/test.csv')).toString(), - 'second,first\n2,1', + expect(fs.readFileSync(path.resolve(__dirname, '__fixtures__', 'test.csv'))).toEqual( + Buffer.from('second,first\n2,1'), ); - fs.unlinkSync(path.resolve(__dirname, 'assets/test.csv')); + fs.unlinkSync(path.resolve(__dirname, '__fixtures__', 'test.csv')); next(); }); @@ -25,15 +23,14 @@ describe('Issue #77 - https://github.com/C2FO/fast-csv/issues/77', () => { }); it('should write headers even with no data when formatting a csv', next => { - const writable = fs.createWriteStream(path.resolve(__dirname, 'assets/test.csv'), { encoding: 'utf8' }); + const writable = fs.createWriteStream(path.resolve(__dirname, '__fixtures__/test.csv'), { encoding: 'utf8' }); const csvStream = csv.format({ headers: ['first', 'second'] }).on('error', next); writable.on('finish', () => { - assert.strictEqual( - fs.readFileSync(path.resolve(__dirname, 'assets/test.csv')).toString(), - 'first,second\n,', + expect(fs.readFileSync(path.resolve(__dirname, '__fixtures__/test.csv'))).toEqual( + Buffer.from('first,second\n,'), ); - fs.unlinkSync(path.resolve(__dirname, 'assets/test.csv')); + fs.unlinkSync(path.resolve(__dirname, '__fixtures__/test.csv')); next(); }); diff --git a/test/issues/issue87.test.ts b/__tests__/issues/issue87.spec.ts similarity index 87% rename from test/issues/issue87.test.ts rename to __tests__/issues/issue87.spec.ts index 236f423d..556fcea1 100644 --- a/test/issues/issue87.test.ts +++ b/__tests__/issues/issue87.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as fs from 'fs'; import * as path from 'path'; import { Transform, TransformCallback } from 'stream'; @@ -31,13 +30,13 @@ describe('Issue #87 - https://github.com/C2FO/fast-csv/issues/87', () => { it('should not emit end until data is flushed from source', next => { const myStream = new MyStream(); - fs.createReadStream(path.resolve(__dirname, './assets/issue87.csv')) + fs.createReadStream(path.resolve(__dirname, '__fixtures__', 'issue87.csv')) .pipe(csv.parse({ headers: true })) .on('error', next) .pipe(myStream) .on('error', next) .on('finish', () => { - assert.strictEqual(myStream.rowCount, 99); + expect(myStream.rowCount).toBe(99); next(); }); }); diff --git a/test/issues/issue93.test.ts b/__tests__/issues/issue93.spec.ts similarity index 91% rename from test/issues/issue93.test.ts rename to __tests__/issues/issue93.spec.ts index c1076a19..7f525431 100644 --- a/test/issues/issue93.test.ts +++ b/__tests__/issues/issue93.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as domain from 'domain'; import { EOL } from 'os'; import * as csv from '../../src'; @@ -15,7 +14,7 @@ describe('Issue #93 - https://github.com/C2FO/fast-csv/issues/93', () => { throw err; } called = true; - assert.strictEqual(err.message, 'End error'); + expect(err.message).toBe('End error'); next(); }); d.run(() => @@ -40,7 +39,7 @@ describe('Issue #93 - https://github.com/C2FO/fast-csv/issues/93', () => { throw err; } called = true; - assert.strictEqual(err.message, 'End error'); + expect(err.message).toBe('End error'); next(); }); d.run(() => diff --git a/test/issues/issue97.test.ts b/__tests__/issues/issue97.spec.ts similarity index 81% rename from test/issues/issue97.test.ts rename to __tests__/issues/issue97.spec.ts index dcce783e..0e287f60 100644 --- a/test/issues/issue97.test.ts +++ b/__tests__/issues/issue97.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as csv from '../../src'; import RecordingStream from '../RecordingStream'; @@ -14,7 +13,7 @@ describe('Issue #97 - https://github.com/C2FO/fast-csv/issues/97', () => { .pipe(rs) .on('error', next) .on('finish', () => { - assert.deepStrictEqual(rs.data.join(''), 'field1,field2\na1"a,b1"b\na2"a,b2"b'); + expect(rs.data.join('')).toBe('field1,field2\na1"a,b1"b\na2"a,b2"b'); next(); }); }); diff --git a/test/parser/CsvParsingStream.test.ts b/__tests__/parser/CsvParsingStream.spec.ts similarity index 56% rename from test/parser/CsvParsingStream.test.ts rename to __tests__/parser/CsvParsingStream.spec.ts index e8f68df7..fe4fbadd 100644 --- a/test/parser/CsvParsingStream.test.ts +++ b/__tests__/parser/CsvParsingStream.spec.ts @@ -1,21 +1,19 @@ -/* eslint-disable no-cond-assign,@typescript-eslint/camelcase */ -import * as assert from 'assert'; +/* eslint-disable no-cond-assign,@typescript-eslint/camelcase,@typescript-eslint/no-explicit-any */ import * as fs from 'fs'; import * as domain from 'domain'; -import * as sinon from 'sinon'; import partition from 'lodash.partition'; import * as csv from '../../src'; -import assets, { PathAndContent } from './assets'; +import assets, { PathAndContent } from './__fixtures__'; import { CsvParserStream } from '../../src/parser'; -import Done = Mocha.Done; +import DoneCallback = jest.DoneCallback; describe('CsvParserStream', () => { - const listenForError = (stream: CsvParserStream, message: string, next: Done) => { + const listenForError = (stream: CsvParserStream, message: string, next: DoneCallback) => { let called = false; stream .on('error', (err: Error) => { - assert.strictEqual(err.message, message); + expect(err.message).toBe(message); if (!called) { called = true; next(); @@ -74,18 +72,27 @@ describe('CsvParserStream', () => { parser.end(); }); + const expectParsed = ( + resultsPromise: Promise, + expectedRows: any[], + expectedInvalidRows: any[] = [], + ): Promise => { + return expect(resultsPromise).resolves.toEqual({ + count: expectedRows.length + expectedInvalidRows.length, + rows: expectedRows, + invalidRows: expectedInvalidRows, + }); + }; + it('should parse a csv without quotes or escapes', () => - parseContentAndCollect(assets.withHeaders, { headers: true }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - })); + expectParsed(parseContentAndCollect(assets.withHeaders, { headers: true }), assets.withHeaders.parsed)); it('should emit a readable event ', next => { const actual: csv.ParserRow[] = []; const parser = csv.parse({ headers: true }); const stream = parser.on('error', next).on('end', (count: number) => { - assert.deepStrictEqual(actual, assets.withHeaders.parsed); - assert.strictEqual(count, actual.length); + expect(actual).toEqual(assets.withHeaders.parsed); + expect(count).toBe(actual.length); next(); }); let index = 0; @@ -99,116 +106,95 @@ describe('CsvParserStream', () => { stream.end(); }); - it('should emit data as a buffer if objectMode is false', () => { + it('should emit data as a buffer if objectMode is false', async () => { const expected = assets.withHeaders.parsed.map(r => Buffer.from(JSON.stringify(r))); - return parseContentAndCollect(assets.withHeaders, { headers: true, objectMode: false }).then( - ({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, rows.length); - }, - ); + await expectParsed(parseContentAndCollect(assets.withHeaders, { headers: true, objectMode: false }), expected); }); it('should emit data as an object if objectMode is true', () => - parseContentAndCollect(assets.withHeaders, { headers: true, objectMode: true }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - })); + expectParsed( + parseContentAndCollect(assets.withHeaders, { headers: true, objectMode: true }), + assets.withHeaders.parsed, + )); it('should emit data as an object if objectMode is not specified', () => - parseContentAndCollect(assets.withHeaders, { headers: true }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - })); + expectParsed(parseContentAndCollect(assets.withHeaders, { headers: true }), assets.withHeaders.parsed)); it('should parse a csv with quotes', () => - parseContentAndCollect(assets.withHeadersAndQuotes, { headers: true }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeadersAndQuotes.parsed); - assert.strictEqual(count, rows.length); - })); + expectParsed( + parseContentAndCollect(assets.withHeadersAndQuotes, { headers: true }), + assets.withHeadersAndQuotes.parsed, + )); it('should parse a csv with without headers', () => - parseContentAndCollect(assets.noHeadersAndQuotes).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.noHeadersAndQuotes.parsed); - assert.strictEqual(count, rows.length); - })); + expectParsed(parseContentAndCollect(assets.noHeadersAndQuotes), assets.noHeadersAndQuotes.parsed)); it("should parse a csv with ' escapes", () => - parseContentAndCollect(assets.withHeadersAndAlternateQuote, { headers: true, quote: "'" }).then( - ({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeadersAndAlternateQuote.parsed); - assert.strictEqual(count, rows.length); - }, + expectParsed( + parseContentAndCollect(assets.withHeadersAndAlternateQuote, { headers: true, quote: "'" }), + assets.withHeadersAndAlternateQuote.parsed, )); describe('headers option', () => { - it('should allow specifying of headers', () => { + it('should allow specifying of headers', async () => { const expected = assets.noHeadersAndQuotes.parsed.map(r => ({ first_name: r[0], last_name: r[1], email_address: r[2], address: r[3], })); - return parseContentAndCollect(assets.noHeadersAndQuotes, { - headers: ['first_name', 'last_name', 'email_address', 'address'], - }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.noHeadersAndQuotes, { + headers: ['first_name', 'last_name', 'email_address', 'address'], + }), + expected, + ); }); - it('should allow transforming headers with a function', () => { + it('should allow transforming headers with a function', async () => { const expected = assets.withHeadersAndQuotes.parsed.map(r => ({ firstName: r.first_name, lastName: r.last_name, emailAddress: r.email_address, address: r.address, })); - const transform = sinon.stub().returns(['firstName', 'lastName', 'emailAddress', 'address']); - return parseContentAndCollect(assets.withHeadersAndQuotes, { - headers: transform, - }).then(({ count, rows }) => { - sinon.assert.calledOnce(transform); - sinon.assert.calledWith(transform, ['first_name', 'last_name', 'email_address', 'address']); - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, rows.length); - }); + const transform = jest.fn().mockReturnValue(['firstName', 'lastName', 'emailAddress', 'address']); + await expectParsed(parseContentAndCollect(assets.withHeadersAndQuotes, { headers: transform }), expected); + expect(transform).toBeCalledTimes(1); + expect(transform).toBeCalledWith(['first_name', 'last_name', 'email_address', 'address']); }); describe('renameHeaders option', () => { - it('should allow renaming headers', () => { + it('should allow renaming headers', async () => { const expected = assets.withHeadersAndQuotes.parsed.map(r => ({ firstName: r.first_name, lastName: r.last_name, emailAddress: r.email_address, address: r.address, })); - return parseContentAndCollect(assets.withHeadersAndQuotes, { - headers: ['firstName', 'lastName', 'emailAddress', 'address'], - renameHeaders: true, - }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeadersAndQuotes, { + headers: ['firstName', 'lastName', 'emailAddress', 'address'], + renameHeaders: true, + }), + expected, + ); }); - it('should ignore the renameHeaders option if transforming headers with a function', () => { + it('should ignore the renameHeaders option if transforming headers with a function', async () => { const expected = assets.withHeadersAndQuotes.parsed.map(r => ({ firstName: r.first_name, lastName: r.last_name, emailAddress: r.email_address, address: r.address, })); - const transform = sinon.stub().returns(['firstName', 'lastName', 'emailAddress', 'address']); - return parseContentAndCollect(assets.withHeadersAndQuotes, { - headers: transform, - renameHeaders: true, - }).then(({ count, rows }) => { - sinon.assert.calledOnce(transform); - sinon.assert.calledWith(transform, ['first_name', 'last_name', 'email_address', 'address']); - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, rows.length); - }); + const transform = jest.fn().mockReturnValue(['firstName', 'lastName', 'emailAddress', 'address']); + await expectParsed( + parseContentAndCollect(assets.withHeadersAndQuotes, { headers: transform, renameHeaders: true }), + expected, + ); + expect(transform).toBeCalledTimes(1); + expect(transform).toBeCalledWith(['first_name', 'last_name', 'email_address', 'address']); }); it('should propagate an error when trying to rename headers without providing new ones', next => { @@ -241,121 +227,99 @@ describe('CsvParserStream', () => { }); it('should discard extra columns that do not map to a header when discardUnmappedColumns is true', () => - parseContentAndCollect(assets.headerColumnMismatch, { headers: true, discardUnmappedColumns: true }).then( - ({ count, rows }) => { - assert.deepStrictEqual(rows, assets.headerColumnMismatch.parsed); - assert.strictEqual(count, rows.length); - }, + expectParsed( + parseContentAndCollect(assets.headerColumnMismatch, { headers: true, discardUnmappedColumns: true }), + assets.headerColumnMismatch.parsed, )); - it('should report missing columns that do not exist but have a header with strictColumnHandling option', () => { + it('should report missing columns that do not exist but have a header with strictColumnHandling option', async () => { const expectedRows = assets.withHeadersAndMissingColumns.parsed.filter(r => r.address !== null); const expectedInvalidRows = assets.withHeadersAndMissingColumns.parsed .filter(r => r.address === null) .map(r => Object.values(r).filter(v => !!v)); - return parseContentAndCollect(assets.withHeadersAndMissingColumns, { - headers: true, - strictColumnHandling: true, - }).then(({ count, rows, invalidRows }) => { - assert.deepStrictEqual(rows, expectedRows); - assert.deepStrictEqual(invalidRows, expectedInvalidRows); - assert.strictEqual(count, rows.length + invalidRows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeadersAndMissingColumns, { + headers: true, + strictColumnHandling: true, + }), + expectedRows, + expectedInvalidRows, + ); }); - it('should allow specifying of columns as a sparse array', () => { + it('should allow specifying of columns as a sparse array', async () => { const expected = assets.noHeadersAndQuotes.parsed.map(r => ({ first_name: r[0], email_address: r[2], })); - return parseContentAndCollect(assets.noHeadersAndQuotes, { - headers: ['first_name', undefined, 'email_address', undefined], - }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.noHeadersAndQuotes, { + headers: ['first_name', undefined, 'email_address', undefined], + }), + expected, + ); }); }); it('should parse data with an alternate encoding', () => - parseContentAndCollect(assets.alternateEncoding, { headers: true, encoding: 'utf16le' }).then( - ({ count, rows }) => { - assert.deepStrictEqual(rows, assets.alternateEncoding.parsed); - assert.strictEqual(count, rows.length); - }, + expectParsed( + parseContentAndCollect(assets.alternateEncoding, { headers: true, encoding: 'utf16le' }), + assets.alternateEncoding.parsed, )); it('should handle a trailing comma', () => - parseContentAndCollect(assets.trailingComma, { headers: true }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.trailingComma.parsed); - assert.strictEqual(count, rows.length); - })); + expectParsed(parseContentAndCollect(assets.trailingComma, { headers: true }), assets.trailingComma.parsed)); it('should skip valid, but empty rows when ignoreEmpty is true', () => - parseContentAndCollect(assets.emptyRows, { headers: true, ignoreEmpty: true }).then( - ({ count, rows, invalidRows }) => { - assert.strictEqual(count, 0); - assert.deepStrictEqual(rows, []); - assert.deepStrictEqual(invalidRows, []); - }, - )); + expectParsed(parseContentAndCollect(assets.emptyRows, { headers: true, ignoreEmpty: true }), [])); describe('alternate delimiters', () => { ['\t', '|', ';'].forEach(delimiter => { - it(`should support '${delimiter.replace(/\t/, '\\t')}' delimiters`, () => { + it(`should support '${delimiter.replace(/\t/, '\\t')}' delimiters`, async () => { const { path: assetPath, content } = assets.withHeadersAlternateDelimiter; - const data = { - path: assetPath, - content: content(delimiter), - }; - return parseContentAndCollect(data, { headers: true, delimiter }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeadersAlternateDelimiter.parsed); - assert.strictEqual(count, rows.length); - }); + const data = { path: assetPath, content: content(delimiter) }; + await expectParsed( + parseContentAndCollect(data, { headers: true, delimiter }), + assets.withHeadersAlternateDelimiter.parsed, + ); }); }); }); describe('maxRows option', () => { - it('should parse up to the specified number of maxRows', () => { + it('should parse up to the specified number of maxRows', async () => { const maxRows = 3; - return parseContentAndCollect(assets.withHeaders, { headers: true, maxRows }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed.slice(0, maxRows)); - assert.strictEqual(count, maxRows); - }); + await expectParsed( + parseContentAndCollect(assets.withHeaders, { headers: true, maxRows }), + assets.withHeaders.parsed.slice(0, maxRows), + ); }); - it('should parse all rows if maxRows === 0', () => { + it('should parse all rows if maxRows === 0', async () => { const maxRows = 0; - return parseContentAndCollect(assets.withHeaders, { headers: true, maxRows }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeaders, { headers: true, maxRows }), + assets.withHeaders.parsed, + ); }); }); describe('skipLines option', () => { - it('should skip up to the specified number of rows using the first non-skipped line as headers', () => { + it('should skip up to the specified number of rows using the first non-skipped line as headers', async () => { const skipLines = 2; - return parseContentAndCollect(assets.withHeadersSkippedLines, { - headers: true, - skipLines, - }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeadersSkippedLines.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeadersSkippedLines, { headers: true, skipLines }), + assets.withHeadersSkippedLines.parsed, + ); }); - it('should skip up to the specified number of rows not withoutHeaders', () => { + it('should skip up to the specified number of rows not withoutHeaders', async () => { const skipLines = 2; - return parseContentAndCollect(assets.skipLines, { skipLines }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.skipLines.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed(parseContentAndCollect(assets.skipLines, { skipLines }), assets.skipLines.parsed); }); describe('with transform', () => { - it('should not transform skipped rows', () => { + it('should not transform skipped rows', async () => { let transformedRows: csv.ParserRow[] = []; const transformer = (row: csv.ParserRow): csv.ParserRow => { const transformed = { @@ -370,18 +334,13 @@ describe('CsvParserStream', () => { const expected = assets.withHeadersSkippedLines.parsed.map(transformer); transformedRows = []; const parser = csv.parse({ headers: true, skipLines }).transform(transformer); - return parseContentAndCollectFromStream(assets.withHeadersSkippedLines, parser).then( - ({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.deepStrictEqual(transformedRows, expected); - assert.strictEqual(count, expected.length); - }, - ); + await expectParsed(parseContentAndCollectFromStream(assets.withHeadersSkippedLines, parser), expected); + expect(transformedRows).toEqual(expected); }); }); describe('with validate', () => { - it('should not validate skipped rows', () => { + it('should not validate skipped rows', async () => { let validatedRows: csv.ParserRow[] = []; const validator = (row: csv.ParserRow): boolean => { validatedRows.push(row); @@ -389,96 +348,83 @@ describe('CsvParserStream', () => { }; const skipLines = 2; const nonSkippedRows = assets.withHeadersSkippedLines.parsed; - const expected = nonSkippedRows.filter(validator); + const [expected, invalid] = partition(nonSkippedRows, validator); validatedRows = []; const parser = csv.parse({ headers: true, skipLines }).validate(validator); - return parseContentAndCollectFromStream(assets.withHeadersSkippedLines, parser).then( - ({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.deepStrictEqual(validatedRows, nonSkippedRows); - assert.strictEqual(count, nonSkippedRows.length); - }, + await expectParsed( + parseContentAndCollectFromStream(assets.withHeadersSkippedLines, parser), + expected, + invalid, ); + expect(validatedRows).toEqual(nonSkippedRows); }); }); - it('should parse all rows if maxRows === 0', () => { + it('should parse all rows if maxRows === 0', async () => { const skipLines = 0; - return parseContentAndCollect(assets.withHeaders, { headers: true, skipLines }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeaders, { headers: true, skipLines }), + assets.withHeaders.parsed, + ); }); }); describe('skipRows option', () => { describe('with headers', () => { - it('should skip up to the specified number of rows not including the header row in the count', () => { + it('should skip up to the specified number of rows not including the header row in the count', async () => { const skipRows = 3; - return parseContentAndCollect(assets.withHeaders, { - headers: true, - skipRows, - }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed.slice(skipRows)); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeaders, { headers: true, skipRows }), + assets.withHeaders.parsed.slice(skipRows), + ); }); - it('should skip up to the specified number of rows and allow renaming the headers', () => { + it('should skip up to the specified number of rows and allow renaming the headers', async () => { const skipRows = 3; - return parseContentAndCollect(assets.withHeaders, { - headers: ['h1', 'h2', 'h3'], - renameHeaders: true, - skipRows, - }).then(({ count, rows }) => { - assert.deepStrictEqual( - rows, - assets.withHeaders.parsed.slice(skipRows).map(r => { - return { - h1: r.first_name, - h2: r.last_name, - h3: r.email_address, - }; - }), - ); - assert.strictEqual(count, rows.length); + const expected = assets.withHeaders.parsed.slice(skipRows).map(r => { + return { + h1: r.first_name, + h2: r.last_name, + h3: r.email_address, + }; }); + await expectParsed( + parseContentAndCollect(assets.withHeaders, { + headers: ['h1', 'h2', 'h3'], + renameHeaders: true, + skipRows, + }), + expected, + ); }); }); describe('without headers', () => { - it('should skip up to the specified number of rows without headers', () => { + it('should skip up to the specified number of rows without headers', async () => { const skipRows = 3; - return parseContentAndCollect(assets.noHeadersAndQuotes, { skipRows }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.noHeadersAndQuotes.parsed.slice(skipRows)); - assert.strictEqual(count, rows.length); - }); + const expected = assets.noHeadersAndQuotes.parsed.slice(skipRows); + await expectParsed(parseContentAndCollect(assets.noHeadersAndQuotes, { skipRows }), expected); }); - it('should skip up to the specified number of rows without headers and allow specifying headers', () => { + it('should skip up to the specified number of rows without headers and allow specifying headers', async () => { const skipRows = 3; - return parseContentAndCollect(assets.noHeadersAndQuotes, { - headers: ['h1', 'h2', 'h3', 'h4'], - skipRows, - }).then(({ count, rows }) => { - assert.deepStrictEqual( - rows, - assets.noHeadersAndQuotes.parsed.slice(skipRows).map(r => { - return { - h1: r[0], - h2: r[1], - h3: r[2], - h4: r[3], - }; - }), - ); - assert.strictEqual(count, rows.length); + const expected = assets.noHeadersAndQuotes.parsed.slice(skipRows).map(r => { + return { + h1: r[0], + h2: r[1], + h3: r[2], + h4: r[3], + }; }); + await expectParsed( + parseContentAndCollect(assets.noHeadersAndQuotes, { headers: ['h1', 'h2', 'h3', 'h4'], skipRows }), + expected, + ); }); }); describe('with transform', () => { - it('should not transform skipped rows', () => { + it('should not transform skipped rows', async () => { let transformedRows: csv.ParserRow[] = []; const transformer = (row: csv.ParserRow): csv.ParserRow => { const transformed = { @@ -494,16 +440,13 @@ describe('CsvParserStream', () => { const expected = assets.withHeaders.parsed.slice(skipRows).map(transformer); transformedRows = []; const parser = csv.parse({ headers: true, skipRows }).transform(transformer); - return parseContentAndCollectFromStream(assets.withHeaders, parser).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.deepStrictEqual(transformedRows, expected); - assert.strictEqual(count, expected.length); - }); + await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected); + expect(transformedRows).toEqual(expected); }); }); describe('with validate', () => { - it('should not validate skipped rows', () => { + it('should not validate skipped rows', async () => { let validatedRows: csv.ParserRow[] = []; const validator = (row: csv.ParserRow): boolean => { validatedRows.push(row); @@ -511,23 +454,20 @@ describe('CsvParserStream', () => { }; const skipRows = 3; const nonSkippedRows = assets.withHeaders.parsed.slice(skipRows); - const expected = nonSkippedRows.filter(validator); + const [expected, invalid] = partition(nonSkippedRows, validator); validatedRows = []; const parser = csv.parse({ headers: true, skipRows }).validate(validator); - return parseContentAndCollectFromStream(assets.withHeaders, parser).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.deepStrictEqual(validatedRows, nonSkippedRows); - assert.strictEqual(count, nonSkippedRows.length); - }); + await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected, invalid); + expect(validatedRows).toEqual(nonSkippedRows); }); }); - it('should parse all rows if maxRows === 0', () => { + it('should parse all rows if maxRows === 0', async () => { const skipRows = 0; - return parseContentAndCollect(assets.withHeaders, { headers: true, skipRows }).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed( + parseContentAndCollect(assets.withHeaders, { headers: true, skipRows }), + assets.withHeaders.parsed, + ); }); }); @@ -544,28 +484,18 @@ describe('CsvParserStream', () => { cb(null, syncValidator(row)); }; - it('should allow validation of rows', () => { - const invalidValid = partition(assets.withHeaders.parsed, syncValidator); + it('should allow validation of rows', async () => { + const [valid, invalid] = partition(assets.withHeaders.parsed, syncValidator); const parser = csv.parse({ headers: true }).validate(syncValidator); - - return parseContentAndCollectFromStream(assets.withHeaders, parser).then(({ count, rows, invalidRows }) => { - assert.deepStrictEqual(invalidRows, invalidValid[1]); - assert.deepStrictEqual(rows, invalidValid[0]); - assert.strictEqual(count, invalidValid[0].length + invalidValid[1].length); - }); + await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), valid, invalid); }); - it('should allow async validation of rows', () => { + it('should allow async validation of rows', async () => { const validator = (row: csv.ParserRow): boolean => parseInt((row as csv.ParserRowMap).first_name.replace(/^First/, ''), 10) % 2 !== 0; - const invalidValid = partition(assets.withHeaders.parsed, validator); + const [valid, invalid] = partition(assets.withHeaders.parsed, validator); const parser = csv.parse({ headers: true }).validate(asyncValidator); - - return parseContentAndCollectFromStream(assets.withHeaders, parser).then(({ count, rows, invalidRows }) => { - assert.deepStrictEqual(invalidRows, invalidValid[1]); - assert.deepStrictEqual(rows, invalidValid[0]); - assert.strictEqual(count, invalidValid[0].length + invalidValid[1].length); - }); + await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), valid, invalid); }); it('should propagate errors from async validation', next => { @@ -617,10 +547,10 @@ describe('CsvParserStream', () => { }); it('should throw an error if validate is not called with a function', () => { - assert.throws(() => { - // @ts-ignore - csv.parse({ headers: true }).validate('hello'); - }, /TypeError: The validate should be a function/); + // @ts-ignore + expect(() => csv.parse({ headers: true }).validate('hello')).toThrowError( + 'The validate should be a function', + ); }); }); @@ -632,24 +562,18 @@ describe('CsvParserStream', () => { address: (row as csv.ParserRowMap).address, }); - it('should allow transforming of data', () => { + it('should allow transforming of data', async () => { const expected = assets.withHeaders.parsed.map(transformer); const parser = csv.parse({ headers: true }).transform(transformer); - return parseContentAndCollectFromStream(assets.withHeaders, parser).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, expected.length); - }); + await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected); }); - it('should async transformation of data', () => { + it('should async transformation of data', async () => { const expected = assets.withHeaders.parsed.map(transformer); const parser = csv .parse({ headers: true }) .transform((row, next) => setImmediate(() => next(null, transformer(row)))); - return parseContentAndCollectFromStream(assets.withHeaders, parser).then(({ count, rows }) => { - assert.deepStrictEqual(rows, expected); - assert.strictEqual(count, expected.length); - }); + await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected); }); it('should propogate errors when transformation of data', next => { @@ -699,10 +623,10 @@ describe('CsvParserStream', () => { }); it('should throw an error if a transform is not called with a function', () => { - assert.throws(() => { - // @ts-ignore - csv.parse({ headers: true }).transform('hello'); - }, /TypeError: The transform should be a function/); + // @ts-ignore + expect(() => csv.parse({ headers: true }).transform('hello')).toThrowError( + 'The transform should be a function', + ); }); }); @@ -717,20 +641,20 @@ describe('CsvParserStream', () => { .on('error', rej) .pipe(stream) .on('data', row => { - assert.ok(!paused); + expect(paused).toBe(false); rows.push(row); paused = true; stream.pause(); setTimeout(() => { - assert.ok(paused); + expect(paused).toBe(true); paused = false; stream.resume(); }, 100); }) .on('error', rej) .on('end', (count: number) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); + expect(rows).toEqual(assets.withHeaders.parsed); + expect(count).toBe(rows.length); res(); }); }); @@ -747,7 +671,7 @@ describe('CsvParserStream', () => { throw err; } called = true; - assert.strictEqual(err.message, 'End error'); + expect(err.message).toBe('End error'); next(); }); d.run(() => @@ -765,37 +689,26 @@ describe('CsvParserStream', () => { }); describe('.parseStream', () => { - it('should accept a stream', () => { + it('should accept a stream', async () => { assets.write(assets.withHeaders); const stream = csv.parseStream(fs.createReadStream(assets.withHeaders.path), { headers: true }); - return collectData(stream).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed(collectData(stream), assets.withHeaders.parsed); }); }); describe('.parseFile', () => { - it('parse a csv from the given path', () => { + it('parse a csv from the given path', async () => { assets.write(assets.withHeaders); const stream = csv.parseFile(assets.withHeaders.path, { headers: true }); - return collectData(stream).then(({ count, rows }) => { - assert.deepStrictEqual(rows, assets.withHeaders.parsed); - assert.strictEqual(count, rows.length); - }); + await expectParsed(collectData(stream), assets.withHeaders.parsed); }); }); describe('.parseString', () => { - it('should accept a csv string', next => { - const actual: csv.ParserRow[] = []; - csv.parseString(assets.withHeaders.content, { headers: true }) - .on('data', data => actual.push(data)) - .on('end', (count: number) => { - assert.deepStrictEqual(actual, assets.withHeaders.parsed); - assert.strictEqual(count, actual.length); - next(); - }); - }); + it('should accept a csv string', () => + expectParsed( + collectData(csv.parseString(assets.withHeaders.content, { headers: true })), + assets.withHeaders.parsed, + )); }); }); diff --git a/test/parser/ParserOptions.test.ts b/__tests__/parser/ParserOptions.spec.ts similarity index 53% rename from test/parser/ParserOptions.test.ts rename to __tests__/parser/ParserOptions.spec.ts index 59867354..e35a4432 100644 --- a/test/parser/ParserOptions.test.ts +++ b/__tests__/parser/ParserOptions.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../src'; import { ParserOptions } from '../../src/parser'; @@ -7,211 +6,211 @@ describe('ParserOptions', () => { describe('#objectMode', () => { it('should have default objectMode', () => { - assert.strictEqual(createOptions().objectMode, true); + expect(createOptions().objectMode).toBe(true); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ objectMode: true }).objectMode, true); - assert.strictEqual(createOptions({ objectMode: false }).objectMode, false); + expect(createOptions({ objectMode: true }).objectMode).toBe(true); + expect(createOptions({ objectMode: false }).objectMode).toBe(false); }); }); describe('#delimiter', () => { it('should have default delimiter', () => { - assert.strictEqual(createOptions().delimiter, ','); + expect(createOptions().delimiter).toBe(','); }); it('should accept a custom delimiter', () => { - assert.strictEqual(createOptions({ delimiter: '\t' }).delimiter, '\t'); + expect(createOptions({ delimiter: '\t' }).delimiter).toBe('\t'); }); it('should escape a custom delimiter', () => { - assert.strictEqual(createOptions({ delimiter: '\\' }).delimiter, '\\'); - assert.strictEqual(createOptions({ delimiter: '\\' }).escapedDelimiter, '\\\\'); + expect(createOptions({ delimiter: '\\' }).delimiter).toBe('\\'); + expect(createOptions({ delimiter: '\\' }).escapedDelimiter).toBe('\\\\'); }); }); describe('#strictColumnHandling', () => { it('should set default strictColumnHandling to false', () => { - assert.strictEqual(createOptions().strictColumnHandling, false); + expect(createOptions().strictColumnHandling).toBe(false); }); it('should accept a strictColumnHandling parameter', () => { - assert.strictEqual(createOptions({ strictColumnHandling: true }).strictColumnHandling, true); + expect(createOptions({ strictColumnHandling: true }).strictColumnHandling).toBe(true); }); }); describe('#quote', () => { it('should set a default quote value', () => { - assert.strictEqual(createOptions().quote, '"'); + expect(createOptions().quote).toBe('"'); }); it('should accept an alternate quote', () => { - assert.strictEqual(createOptions({ quote: '$' }).quote, '$'); + expect(createOptions({ quote: '$' }).quote).toBe('$'); }); }); describe('#escapeChar', () => { it('should set the escape character to the quote value if not specified', () => { - assert.strictEqual(createOptions().escapeChar, '"'); + expect(createOptions().escapeChar).toBe('"'); }); it('should set the escape character to the quote value if not specified', () => { - assert.strictEqual(createOptions({ quote: '$' }).escapeChar, '$'); + expect(createOptions({ quote: '$' }).escapeChar).toBe('$'); }); it('should accept an alternate escape', () => { - assert.strictEqual(createOptions({ escape: '%' }).escapeChar, '%'); + expect(createOptions({ escape: '%' }).escapeChar).toBe('%'); }); }); describe('#comment', () => { it('should set the comment null if not specified', () => { - assert.strictEqual(createOptions().comment, null); + expect(createOptions().comment).toBe(null); }); it('should accept a comment character', () => { - assert.strictEqual(createOptions({ comment: '#' }).comment, '#'); + expect(createOptions({ comment: '#' }).comment).toBe('#'); }); }); describe('#supportsComments', () => { it('should set supports comments to false by default', () => { - assert.strictEqual(createOptions().supportsComments, false); + expect(createOptions().supportsComments).toBe(false); }); it('should set to true if the comment character is specified', () => { - assert.strictEqual(createOptions({ comment: '#' }).supportsComments, true); + expect(createOptions({ comment: '#' }).supportsComments).toBe(true); }); }); describe('#trim', () => { it('should have default trim', () => { - assert.strictEqual(createOptions().trim, false); + expect(createOptions().trim).toBe(false); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ trim: true }).trim, true); - assert.strictEqual(createOptions({ trim: false }).trim, false); + expect(createOptions({ trim: true }).trim).toBe(true); + expect(createOptions({ trim: false }).trim).toBe(false); }); }); describe('#ltrim', () => { it('should have default ltrim', () => { - assert.strictEqual(createOptions().ltrim, false); + expect(createOptions().ltrim).toBe(false); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ ltrim: true }).ltrim, true); - assert.strictEqual(createOptions({ ltrim: false }).ltrim, false); + expect(createOptions({ ltrim: true }).ltrim).toBe(true); + expect(createOptions({ ltrim: false }).ltrim).toBe(false); }); }); describe('#rtrim', () => { it('should have default rtrim', () => { - assert.strictEqual(createOptions().rtrim, false); + expect(createOptions().rtrim).toBe(false); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ rtrim: true }).rtrim, true); - assert.strictEqual(createOptions({ rtrim: false }).rtrim, false); + expect(createOptions({ rtrim: true }).rtrim).toBe(true); + expect(createOptions({ rtrim: false }).rtrim).toBe(false); }); }); describe('#discardUnmappedColumns', () => { it('should have default discardUnmappedColumns', () => { - assert.strictEqual(createOptions().discardUnmappedColumns, false); + expect(createOptions().discardUnmappedColumns).toBe(false); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ discardUnmappedColumns: true }).discardUnmappedColumns, true); - assert.strictEqual(createOptions({ discardUnmappedColumns: false }).discardUnmappedColumns, false); + expect(createOptions({ discardUnmappedColumns: true }).discardUnmappedColumns).toBe(true); + expect(createOptions({ discardUnmappedColumns: false }).discardUnmappedColumns).toBe(false); }); }); describe('#strictColumnHandling', () => { it('should have default strictColumnHandling', () => { - assert.strictEqual(createOptions().strictColumnHandling, false); + expect(createOptions().strictColumnHandling).toBe(false); }); it('should accept a boolean objectMode', () => { - assert.strictEqual(createOptions({ strictColumnHandling: true }).strictColumnHandling, true); - assert.strictEqual(createOptions({ strictColumnHandling: false }).strictColumnHandling, false); + expect(createOptions({ strictColumnHandling: true }).strictColumnHandling).toBe(true); + expect(createOptions({ strictColumnHandling: false }).strictColumnHandling).toBe(false); }); }); describe('#headers', () => { it('should have default headers', () => { - assert.strictEqual(createOptions().headers, null); + expect(createOptions().headers).toBeNull(); }); it('should accept an array of headers', () => { - assert.deepStrictEqual(createOptions({ headers: ['1', '2', '3'] }).headers, ['1', '2', '3']); + expect(createOptions({ headers: ['1', '2', '3'] }).headers).toEqual(['1', '2', '3']); }); it('should accept a function', () => { const opts = createOptions({ headers: headers => headers.map(h => h?.toLowerCase()) }); // @ts-ignore - assert.deepStrictEqual(opts.headers(['A', 'B', 'C']), ['a', 'b', 'c']); + expect(opts.headers(['A', 'B', 'C'])).toEqual(['a', 'b', 'c']); }); it('should accept headers as a boolean', () => { - assert.deepStrictEqual(createOptions({ headers: true }).headers, true); + expect(createOptions({ headers: true }).headers).toBe(true); }); }); describe('#renameHeaders', () => { it('should have default renameHeaders', () => { - assert.strictEqual(createOptions().renameHeaders, false); + expect(createOptions().renameHeaders).toBe(false); }); it('should accept a boolean renameHeaders', () => { - assert.strictEqual(createOptions({ renameHeaders: true }).renameHeaders, true); - assert.strictEqual(createOptions({ renameHeaders: false }).renameHeaders, false); + expect(createOptions({ renameHeaders: true }).renameHeaders).toBe(true); + expect(createOptions({ renameHeaders: false }).renameHeaders).toBe(false); }); }); describe('#maxRows', () => { it('should default maxRows 0 and limitRows to false', () => { const opts = createOptions(); - assert.strictEqual(opts.maxRows, 0); - assert.strictEqual(opts.limitRows, false); + expect(opts.maxRows).toBe(0); + expect(opts.limitRows).toBe(false); }); it('should set maxRows to the provided option and limitRows to true if maxRows > 0', () => { const opts = createOptions({ maxRows: 1 }); - assert.strictEqual(opts.maxRows, 1); - assert.strictEqual(opts.limitRows, true); + expect(opts.maxRows).toBe(1); + expect(opts.limitRows).toBe(true); }); it('should set maxRows to the provided option and limitRows to true if maxRows === 0', () => { const opts = createOptions({ maxRows: 0 }); - assert.strictEqual(opts.maxRows, 0); - assert.strictEqual(opts.limitRows, false); + expect(opts.maxRows).toBe(0); + expect(opts.limitRows).toBe(false); }); }); describe('#skipLines', () => { it('should default skipLines to 0', () => { const opts = createOptions(); - assert.strictEqual(opts.skipLines, 0); + expect(opts.skipLines).toBe(0); }); it('should set skipLines to the user provided option', () => { const opts = createOptions({ skipLines: 10 }); - assert.strictEqual(opts.skipLines, 10); + expect(opts.skipLines).toBe(10); }); }); describe('#skipRows', () => { it('should default skipLines to 0', () => { const opts = createOptions(); - assert.strictEqual(opts.skipRows, 0); + expect(opts.skipRows).toBe(0); }); it('should set skipLines to the user provided option', () => { const opts = createOptions({ skipRows: 10 }); - assert.strictEqual(opts.skipRows, 10); + expect(opts.skipRows).toBe(10); }); }); }); diff --git a/test/parser/assets/alternateEncoding.ts b/__tests__/parser/__fixtures__/alternateEncoding.ts similarity index 100% rename from test/parser/assets/alternateEncoding.ts rename to __tests__/parser/__fixtures__/alternateEncoding.ts diff --git a/test/parser/assets/duplicateHeaders.ts b/__tests__/parser/__fixtures__/duplicateHeaders.ts similarity index 100% rename from test/parser/assets/duplicateHeaders.ts rename to __tests__/parser/__fixtures__/duplicateHeaders.ts diff --git a/test/parser/assets/emptyRows.ts b/__tests__/parser/__fixtures__/emptyRows.ts similarity index 100% rename from test/parser/assets/emptyRows.ts rename to __tests__/parser/__fixtures__/emptyRows.ts diff --git a/test/parser/assets/headerColumnMismatch.ts b/__tests__/parser/__fixtures__/headerColumnMismatch.ts similarity index 100% rename from test/parser/assets/headerColumnMismatch.ts rename to __tests__/parser/__fixtures__/headerColumnMismatch.ts diff --git a/test/parser/assets/index.ts b/__tests__/parser/__fixtures__/index.ts similarity index 95% rename from test/parser/assets/index.ts rename to __tests__/parser/__fixtures__/index.ts index 5333b1c1..9eec0c72 100644 --- a/test/parser/assets/index.ts +++ b/__tests__/parser/__fixtures__/index.ts @@ -14,6 +14,7 @@ import malformed from './malformed'; import trailingComma from './trailingComma'; import emptyRows from './emptyRows'; import duplicateHeaders from './duplicateHeaders'; +import RecordingStream from '../../RecordingStream'; export interface PathAndContent { path: string; @@ -33,6 +34,7 @@ const write = (opts: PathAndContent): void => { }; export default { + RecordingStream, write, alternateEncoding, duplicateHeaders, diff --git a/test/parser/assets/malformed.ts b/__tests__/parser/__fixtures__/malformed.ts similarity index 100% rename from test/parser/assets/malformed.ts rename to __tests__/parser/__fixtures__/malformed.ts diff --git a/test/parser/assets/noHeadersAndQuotes.ts b/__tests__/parser/__fixtures__/noHeadersAndQuotes.ts similarity index 100% rename from test/parser/assets/noHeadersAndQuotes.ts rename to __tests__/parser/__fixtures__/noHeadersAndQuotes.ts diff --git a/test/parser/assets/skipLines.ts b/__tests__/parser/__fixtures__/skipLines.ts similarity index 100% rename from test/parser/assets/skipLines.ts rename to __tests__/parser/__fixtures__/skipLines.ts diff --git a/test/parser/assets/trailingComma.ts b/__tests__/parser/__fixtures__/trailingComma.ts similarity index 100% rename from test/parser/assets/trailingComma.ts rename to __tests__/parser/__fixtures__/trailingComma.ts diff --git a/test/parser/assets/withHeaders.ts b/__tests__/parser/__fixtures__/withHeaders.ts similarity index 100% rename from test/parser/assets/withHeaders.ts rename to __tests__/parser/__fixtures__/withHeaders.ts diff --git a/test/parser/assets/withHeadersAlternateDelimiter.ts b/__tests__/parser/__fixtures__/withHeadersAlternateDelimiter.ts similarity index 100% rename from test/parser/assets/withHeadersAlternateDelimiter.ts rename to __tests__/parser/__fixtures__/withHeadersAlternateDelimiter.ts diff --git a/test/parser/assets/withHeadersAndAlternateQuote.ts b/__tests__/parser/__fixtures__/withHeadersAndAlternateQuote.ts similarity index 100% rename from test/parser/assets/withHeadersAndAlternateQuote.ts rename to __tests__/parser/__fixtures__/withHeadersAndAlternateQuote.ts diff --git a/test/parser/assets/withHeadersAndMissingColumns.ts b/__tests__/parser/__fixtures__/withHeadersAndMissingColumns.ts similarity index 100% rename from test/parser/assets/withHeadersAndMissingColumns.ts rename to __tests__/parser/__fixtures__/withHeadersAndMissingColumns.ts diff --git a/test/parser/assets/withHeadersAndQuotes.ts b/__tests__/parser/__fixtures__/withHeadersAndQuotes.ts similarity index 100% rename from test/parser/assets/withHeadersAndQuotes.ts rename to __tests__/parser/__fixtures__/withHeadersAndQuotes.ts diff --git a/test/parser/assets/withHeadersSkippedLines.ts b/__tests__/parser/__fixtures__/withHeadersSkippedLines.ts similarity index 100% rename from test/parser/assets/withHeadersSkippedLines.ts rename to __tests__/parser/__fixtures__/withHeadersSkippedLines.ts diff --git a/test/parser/parser/Parser.test.ts b/__tests__/parser/parser/Parser.spec.ts similarity index 85% rename from test/parser/parser/Parser.test.ts rename to __tests__/parser/parser/Parser.spec.ts index 524cec76..896e46a8 100644 --- a/test/parser/parser/Parser.test.ts +++ b/__tests__/parser/parser/Parser.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../../src'; import { ParserOptions, Parser } from '../../../src/parser'; @@ -10,7 +9,7 @@ describe('Parser', () => { it('should parse a block of CSV text that starts with a BOM', () => { const data = '\ufefffirst_name,last_name,email_address'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [['first_name', 'last_name', 'email_address']], }); @@ -21,7 +20,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -33,7 +32,7 @@ describe('Parser', () => { it('should ignore empty rows if ignoreEmpty is true', () => { const data = 'first_name,last_name,email_address\nFirst1,Last1,email1@email.com\n,,'; const myParser = createParser({ delimiter: ',', ignoreEmpty: true }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -45,7 +44,7 @@ describe('Parser', () => { it('should not ignore empty rows if ignoreEmpty is false', () => { const data = 'first_name,last_name,email_address\nFirst1,Last1,email1@email.com\n,,'; const myParser = createParser({ delimiter: ',', ignoreEmpty: false }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -58,7 +57,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com,\n'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -70,7 +69,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter and no new line', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com,'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -82,7 +81,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter followed by a space', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com, \n'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -94,7 +93,7 @@ describe('Parser', () => { it('should parse a block of Space Separated Value text with a trailing delimiter', () => { const data = 'first_name last_name email_address empty\nFirst1 Last1 email1@email.com \n'; const myParser = createParser({ delimiter: ' ' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -106,7 +105,7 @@ describe('Parser', () => { it('should return the rest of the line if there is more data', () => { const data = 'first_name,last_name,email_address\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: 'First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -116,11 +115,11 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual(parse(`${parsedData.line}\nFirst2,Last2,email2@email.com`, false, myParser), { + expect(parse(`${parsedData.line}\nFirst2,Last2,email2@email.com`, false, myParser)).toEqual({ line: '', rows: [ ['First1', 'Last1', 'email1@email.com'], @@ -133,7 +132,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address', rows: [], }); @@ -143,7 +142,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address,'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address,', rows: [], }); @@ -153,7 +152,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address, '; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address, ', rows: [], }); @@ -163,7 +162,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\n'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [['first_name', 'last_name', 'email_address']], }); @@ -174,7 +173,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\n"First,1","Last,1","email1@email.com"'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -186,7 +185,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com,\n'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -198,7 +197,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter followed by a space', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com, \n'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -210,7 +209,7 @@ describe('Parser', () => { it('should parse a block of Space Separated Value text with a trailing delimiter', () => { const data = 'first_name last_name email_address empty\nFirst1 Last1 email1@email.com \n'; const myParser = createParser({ delimiter: ' ' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -222,7 +221,7 @@ describe('Parser', () => { it('should parse a block of CSV text with escaped escaped char', () => { const data = 'first_name,last_name,email_address\n"First,""1""","Last,""1""","email1@email.com"'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -234,7 +233,7 @@ describe('Parser', () => { it('should parse a block of CSV text with alternate escape char', () => { const data = 'first_name,last_name,email_address\n"First,\\"1\\"","Last,\\"1\\"","email1@email.com"'; const myParser = createParser({ delimiter: ',', escape: '\\' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -246,7 +245,7 @@ describe('Parser', () => { it('should return the rest of the line if a complete value is not found', () => { const data = 'first_name,last_name,email_address\n"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -256,40 +255,39 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\n"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual( + expect( parse(`${parsedData.line}"\n"First,""2""","Last,""2""","email2@email.com"`, false, myParser), - { - line: '', - rows: [ - ['First,"1"', 'Last,"1"', 'email1@email.com'], - ['First,"2"', 'Last,"2"', 'email2@email.com'], - ], - }, - ); + ).toEqual({ + line: '', + rows: [ + ['First,"1"', 'Last,"1"', 'email1@email.com'], + ['First,"2"', 'Last,"2"', 'email2@email.com'], + ], + }); }); it('should throw an error if there is not more data and there is an invalid escape sequence', () => { const data = 'first_name,last_name,email_address\n"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.throws(() => { + expect(() => { myParser.parse(`${parsedData.line}\n"First,"",2""","Last""2""","email2@email.com"`, false); - }, /Parse Error: expected: ',' OR new line got: 'F'. at 'First,"",2/); + }).toThrowError(/Parse Error: expected: ',' OR new line got: 'F'. at 'First,"",2/); }); it('should handle empty values properly', () => { const data = '"","",""\n,Last4,email4@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [ ['', '', ''], @@ -302,7 +300,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address"'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address"', rows: [], }); @@ -312,7 +310,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address",'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address",', rows: [], }); @@ -322,7 +320,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address"\n'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [['first_name', 'last_name', 'email_address']], }); @@ -333,7 +331,7 @@ describe('Parser', () => { it('should ignore escaping if quote is null', () => { const data = 'first_name,last_name,email_address\n"First1","Last1","email1@email.com"'; const myParser = createParser({ delimiter: ',', quote: null }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -349,7 +347,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\rFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -361,7 +359,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter', () => { const data = 'first_name,last_name,email_address,empty\rFirst1,Last1,email1@email.com,\r'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -373,7 +371,7 @@ describe('Parser', () => { it('should parse a block of CSV text with a trailing delimiter followed by a space', () => { const data = 'first_name,last_name,email_address,empty\nFirst1,Last1,email1@email.com, \r'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -385,7 +383,7 @@ describe('Parser', () => { it('should parse a block of Space Separated Value text with a trailing delimiter', () => { const data = 'first_name last_name email_address empty\rFirst1 Last1 email1@email.com \r'; const myParser = createParser({ delimiter: ' ' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address', 'empty'], @@ -397,7 +395,7 @@ describe('Parser', () => { it('should return the rest of the line if there is more data', () => { const data = 'first_name,last_name,email_address\rFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: 'First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -407,11 +405,11 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\rFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual(parse(`${parsedData.line}\rFirst2,Last2,email2@email.com`, false, myParser), { + expect(parse(`${parsedData.line}\rFirst2,Last2,email2@email.com`, false, myParser)).toEqual({ line: '', rows: [ ['First1', 'Last1', 'email1@email.com'], @@ -424,7 +422,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address', rows: [], }); @@ -434,7 +432,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address,'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address,', rows: [], }); @@ -444,7 +442,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\r'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address\r', rows: [], }); @@ -455,7 +453,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\r"First,1","Last,1","email1@email.com"'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -467,7 +465,7 @@ describe('Parser', () => { it('should parse a block of CSV text with escaped escaped char', () => { const data = 'first_name,last_name,email_address\r"First,""1""","Last,""1""","email1@email.com"'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -479,7 +477,7 @@ describe('Parser', () => { it('should parse a block of CSV text with alternate escape char', () => { const data = 'first_name,last_name,email_address\r"First,\\"1\\"","Last,\\"1\\"","email1@email.com"'; const myParser = createParser({ delimiter: ',', escape: '\\' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -491,7 +489,7 @@ describe('Parser', () => { it('should return the rest of the line if a complete value is not found', () => { const data = 'first_name,last_name,email_address\r"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -501,40 +499,39 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\r"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual( + expect( parse(`${parsedData.line}"\r"First,""2""","Last,""2""","email2@email.com"`, false, myParser), - { - line: '', - rows: [ - ['First,"1"', 'Last,"1"', 'email1@email.com'], - ['First,"2"', 'Last,"2"', 'email2@email.com'], - ], - }, - ); + ).toEqual({ + line: '', + rows: [ + ['First,"1"', 'Last,"1"', 'email1@email.com'], + ['First,"2"', 'Last,"2"', 'email2@email.com'], + ], + }); }); it('should throw an error if there is not more data and there is an invalid escape sequence', () => { const data = 'first_name,last_name,email_address\r"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.throws(() => { + expect(() => { myParser.parse(`${parsedData.line}\r"First,"",2""","Last""2""","email2@email.com"`, false); - }, /Parse Error: expected: ',' OR new line got: 'F'. at 'First,"",2/); + }).toThrowError(/Parse Error: expected: ',' OR new line got: 'F'. at 'First,"",2/); }); it('should handle empty values properly', () => { const data = '"","",""\r,Last4,email4@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [ ['', '', ''], @@ -547,7 +544,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address"'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address"', rows: [], }); @@ -557,7 +554,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address",'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address",', rows: [], }); @@ -567,7 +564,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address"\r'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address"\r', rows: [], }); @@ -578,7 +575,7 @@ describe('Parser', () => { it('should ignore escaping if quote is null', () => { const data = 'first_name,last_name,email_address\r"First1","Last1","email1@email.com"'; const myParser = createParser({ delimiter: ',', quote: null }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -594,7 +591,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\r\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -606,7 +603,7 @@ describe('Parser', () => { it('should return the rest of the line if there is more data', () => { const data = 'first_name,last_name,email_address\r\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: 'First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -616,11 +613,11 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\r\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual(parse(`${parsedData.line}\r\nFirst2,Last2,email2@email.com`, false, myParser), { + expect(parse(`${parsedData.line}\r\nFirst2,Last2,email2@email.com`, false, myParser)).toEqual({ line: '', rows: [ ['First1', 'Last1', 'email1@email.com'], @@ -633,7 +630,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address', rows: [], }); @@ -643,7 +640,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\r'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address\r', rows: [], }); @@ -653,7 +650,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address,'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: 'first_name,last_name,email_address,', rows: [], }); @@ -663,7 +660,7 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\r\n'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [['first_name', 'last_name', 'email_address']], }); @@ -674,7 +671,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\r\n"First,1","Last,1","email1@email.com"'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -686,7 +683,7 @@ describe('Parser', () => { it('should parse a block of CSV text with escaped escaped char', () => { const data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","email1@email.com"'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -698,7 +695,7 @@ describe('Parser', () => { it('should parse a block of CSV text with alternate escape char', () => { const data = 'first_name,last_name,email_address\r\n"First,\\"1\\"","Last,\\"1\\"","email1@email.com"'; const myParser = createParser({ delimiter: ',', escape: '\\' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -710,7 +707,7 @@ describe('Parser', () => { it('should return the rest of the line if a complete value is not found', () => { const data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -720,40 +717,39 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual( + expect( parse(`${parsedData.line}"\r\n"First,""2""","Last,""2""","email2@email.com"`, false, myParser), - { - line: '', - rows: [ - ['First,"1"', 'Last,"1"', 'email1@email.com'], - ['First,"2"', 'Last,"2"', 'email2@email.com'], - ], - }, - ); + ).toEqual({ + line: '', + rows: [ + ['First,"1"', 'Last,"1"', 'email1@email.com'], + ['First,"2"', 'Last,"2"', 'email2@email.com'], + ], + }); }); it('should throw an error if there is not more data and there is an invalid escape sequence', () => { const data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","email1@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"First,""1""","Last,""1""","email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); - assert.throws(() => { + expect(() => { myParser.parse(`${parsedData.line}\r\n"First,"",2""","Last""2""","email2@email.com"`, false); - }, /Parse Error: expected: ',' OR new line got: 'F'. at 'First,"",2/); + }).toThrowError(/Parse Error: expected: ',' OR new line got: 'F'. at 'First,"",2/); }); it('should handle empty values properly', () => { const data = '"","",""\r\n,Last4,email4@email.com'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [ ['', '', ''], @@ -766,7 +762,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address"'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address"', rows: [], }); @@ -776,7 +772,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address",'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '"first_name","last_name","email_address",', rows: [], }); @@ -786,7 +782,7 @@ describe('Parser', () => { const data = '"first_name","last_name","email_address"\r\n'; const myParser = createParser({ delimiter: ',' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [['first_name', 'last_name', 'email_address']], }); @@ -797,7 +793,7 @@ describe('Parser', () => { it('should ignore escaping if quote is null', () => { const data = 'first_name,last_name,email_address\r\n"First1","Last1","email1@email.com"'; const myParser = createParser({ delimiter: ',', quote: null }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -812,7 +808,7 @@ describe('Parser', () => { it('should parse a block of CSV text', () => { const data = 'first_name,last_name,email_address\n#The first row of data\nFirst1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',', comment: '#' }); - assert.deepStrictEqual(parse(data, false, myParser), { + expect(parse(data, false, myParser)).toEqual({ line: '', rows: [ ['first_name', 'last_name', 'email_address'], @@ -824,7 +820,7 @@ describe('Parser', () => { it('should return the rest of the line if there is more data', () => { const data = 'first_name,last_name,email_address\n#First1,Last1,email1@email.com'; const myParser = createParser({ delimiter: ',', comment: '#' }); - assert.deepStrictEqual(parse(data, true, myParser), { + expect(parse(data, true, myParser)).toEqual({ line: '#First1,Last1,email1@email.com', rows: [['first_name', 'last_name', 'email_address']], }); @@ -834,31 +830,30 @@ describe('Parser', () => { const data = 'first_name,last_name,email_address\n#This is a comment'; const myParser = createParser({ delimiter: ',', comment: '#' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '#This is a comment', rows: [['first_name', 'last_name', 'email_address']], }); - assert.deepStrictEqual( + expect( parse( `${parsedData.line}\nFirst1,Last1,email1@email.com\nFirst2,Last2,email2@email.com`, false, myParser, ), - { - line: '', - rows: [ - ['First1', 'Last1', 'email1@email.com'], - ['First2', 'Last2', 'email2@email.com'], - ], - }, - ); + ).toEqual({ + line: '', + rows: [ + ['First1', 'Last1', 'email1@email.com'], + ['First2', 'Last2', 'email2@email.com'], + ], + }); }); it('should not parse a row if a new line is not found and there is more data', () => { const data = '#first_name,last_name,email_address'; const myParser = createParser({ delimiter: ',', comment: '#' }); const parsedData = parse(data, true, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '#first_name,last_name,email_address', rows: [], }); @@ -868,7 +863,7 @@ describe('Parser', () => { const data = 'f#irst_name,last_name,email_address'; const myParser = createParser({ delimiter: ',', comment: '#' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [['f#irst_name', 'last_name', 'email_address']], }); @@ -878,7 +873,7 @@ describe('Parser', () => { const data = '"#first_name",last_name,email_address'; const myParser = createParser({ delimiter: ',', comment: '#' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [['#first_name', 'last_name', 'email_address']], }); @@ -888,7 +883,7 @@ describe('Parser', () => { const data = '#Comment1\n#Comment2'; const myParser = createParser({ delimiter: ',', comment: '#' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [], }); @@ -898,7 +893,7 @@ describe('Parser', () => { const data = '#Comment1\n#Comment2\n'; const myParser = createParser({ delimiter: ',', comment: '#' }); const parsedData = parse(data, false, myParser); - assert.deepStrictEqual(parsedData, { + expect(parsedData).toEqual({ line: '', rows: [], }); diff --git a/test/parser/parser/RowParser.test.ts b/__tests__/parser/parser/RowParser.spec.ts similarity index 68% rename from test/parser/parser/RowParser.test.ts rename to __tests__/parser/parser/RowParser.spec.ts index 49da09e1..8d7c0df9 100644 --- a/test/parser/parser/RowParser.test.ts +++ b/__tests__/parser/parser/RowParser.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../../src'; import { ParserOptions, Scanner, RowParser } from '../../../src/parser'; @@ -15,65 +14,65 @@ describe('RowParser', () => { it('should not parse a row that does not have a row delimiter', () => { const line = 'first_name,last_name,email_address'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, line); - assert.strictEqual(row, null); + expect(scanner.line).toBe(line); + expect(row).toBeNull(); }); it('should parse and empty row', () => { const line = ',,\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['', '', '']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['', '', '']); }); it('should parse and empty row with quotes with trailing delimiter', () => { const line = '"","","","",\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['', '', '', '', '']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['', '', '', '', '']); }); it('should parse and empty row with quotes without trailing delimiter', () => { const line = '"","","",""\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['', '', '', '']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['', '', '', '']); }); it('should parse a row that does have a LF', () => { const line = 'first_name,last_name,email_address\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); it('should parse a row that has a LF in a quoted column', () => { const line = '"first\nname",last_name,email_address\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first\nname', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first\nname', 'last_name', 'email_address']); }); it('should parse a row that has a CR in a quoted column', () => { const line = '"first\rname",last_name,email_address\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first\rname', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first\rname', 'last_name', 'email_address']); }); it('should parse a row that has a CRLF in a quoted column', () => { const line = '"first\r\nname",last_name,email_address\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first\r\nname', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first\r\nname', 'last_name', 'email_address']); }); it('should parse a row with a "\\t" delimiter with fields that have spaces', () => { const line = '058B \t09/09/2003\tGL\tARONCA\t58 \t0191006\t1H7\t1 \t \t \tA751 \tAERONCA058B\n'; const { scanner, row } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, [ + expect(scanner.line).toBe(''); + expect(row).toEqual([ '058B ', '09/09/2003', 'GL', @@ -92,22 +91,22 @@ describe('RowParser', () => { it('should parse a row that does have a CR/LF', () => { const line = 'first_name,last_name,email_address\r\n'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); it('should not parse a row that does have a CR but no LF', () => { const line = 'first_name,last_name,email_address\r'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, line); - assert.deepStrictEqual(row, null); + expect(scanner.line).toBe(line); + expect(row).toBeNull(); }); it('should not parse a row that does have a CR but no LF but is followed by more data', () => { const line = 'first_name,last_name,email_address\rFirst1'; const { scanner, row } = parse(line, true); - assert.strictEqual(scanner.line, 'First1'); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe('First1'); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); }); @@ -115,29 +114,29 @@ describe('RowParser', () => { it('should parse a row that does not have a row delimiter', () => { const line = 'first_name,last_name,email_address'; const { scanner, row } = parse(line, false); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); it('should parse a row that does have a LF', () => { const line = 'first_name,last_name,email_address\n'; const { scanner, row } = parse(line, false); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); it('should parse a row that does have a CR/LF', () => { const line = 'first_name,last_name,email_address\r\n'; const { scanner, row } = parse(line, false); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); it('should parse a row that does have a CR but no LF', () => { const line = 'first_name,last_name,email_address\r'; const { scanner, row } = parse(line, false); - assert.strictEqual(scanner.line, ''); - assert.deepStrictEqual(row, ['first_name', 'last_name', 'email_address']); + expect(scanner.line).toBe(''); + expect(row).toEqual(['first_name', 'last_name', 'email_address']); }); }); }); diff --git a/test/parser/parser/Scanner.test.ts b/__tests__/parser/parser/Scanner.spec.ts similarity index 58% rename from test/parser/parser/Scanner.test.ts rename to __tests__/parser/parser/Scanner.spec.ts index b5a1db80..11ffde9c 100644 --- a/test/parser/parser/Scanner.test.ts +++ b/__tests__/parser/parser/Scanner.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../../src'; import { ParserOptions, Scanner, Token, MaybeToken } from '../../../src/parser'; @@ -12,72 +11,70 @@ describe('Scanner', () => { cursor, }); - const assertToken = (token: MaybeToken): token is Token => { - if (token === null) { - assert.fail('Expected non-null token'); - } + const expectNonNullToken = (token: MaybeToken): token is Token => { + expect(token).not.toBeNull(); return true; }; - const assertTokenContent = (token: MaybeToken, content: string): void => { - if (assertToken(token)) { - assert.strictEqual(token.token, content); + const expectTokenContent = (token: MaybeToken, content: string): void => { + if (expectNonNullToken(token)) { + expect(token.token).toBe(content); } }; describe('#hasMoreCharacters', () => { it('should return true if the cursor is not past the end of the line', () => { - assert.strictEqual(getScanner('hello', true).hasMoreCharacters, true); + expect(getScanner('hello', true).hasMoreCharacters).toBe(true); }); it('should return true if the cursor is not past the end of the line', () => { - assert.strictEqual(getScanner('hello', true, 5).hasMoreCharacters, false); + expect(getScanner('hello', true, 5).hasMoreCharacters).toBe(false); }); }); describe('#nextNonSpaceToken', () => { it('should get non space token in the line', () => { - assertTokenContent(getScanner(' h', true, 0).nextNonSpaceToken, 'h'); + expectTokenContent(getScanner(' h', true, 0).nextNonSpaceToken, 'h'); }); it('should get the LF in the line', () => { - assertTokenContent(getScanner(' \n', true, 0).nextNonSpaceToken, '\n'); + expectTokenContent(getScanner(' \n', true, 0).nextNonSpaceToken, '\n'); }); it('should get the CR in the line', () => { - assertTokenContent(getScanner(' \r', true, 0).nextNonSpaceToken, '\r'); + expectTokenContent(getScanner(' \r', true, 0).nextNonSpaceToken, '\r'); }); it('should get the CRLF in the line', () => { - assertTokenContent(getScanner(' \r\n', true, 0).nextNonSpaceToken, '\r\n'); + expectTokenContent(getScanner(' \r\n', true, 0).nextNonSpaceToken, '\r\n'); }); it('should return null if there is nothing but white space', () => { - assert.strictEqual(getScanner(' \t', true, 0).nextNonSpaceToken, null); + expect(getScanner(' \t', true, 0).nextNonSpaceToken).toBeNull(); }); it('should return a token the delimiter is a space token', () => { - assertTokenContent(getScanner(' \t', true, 0, { delimiter: '\t' }).nextNonSpaceToken, '\t'); + expectTokenContent(getScanner(' \t', true, 0, { delimiter: '\t' }).nextNonSpaceToken, '\t'); }); }); describe('#nextCharacterToken', () => { it('should get the next character in the line', () => { - assertTokenContent(getScanner('h', true, 0).nextCharacterToken, 'h'); + expectTokenContent(getScanner('h', true, 0).nextCharacterToken, 'h'); }); it('should get the next character in the line if it it whitespace', () => { - assertTokenContent(getScanner(' h', true, 0).nextCharacterToken, ' '); + expectTokenContent(getScanner(' h', true, 0).nextCharacterToken, ' '); }); it('should return null if the cursor is at the end of the line', () => { - assert.strictEqual(getScanner('hello', true, 5).nextCharacterToken, null); + expect(getScanner('hello', true, 5).nextCharacterToken).toBe(null); }); }); describe('#line from cursor', () => { it('should return the line from the current cursor', () => { - assert.strictEqual(getScanner('hello', true, 2).lineFromCursor, 'llo'); + expect(getScanner('hello', true, 2).lineFromCursor).toBe('llo'); }); }); @@ -85,19 +82,19 @@ describe('Scanner', () => { it('should advance past the next LF', () => { const scanner = getScanner('hel\nlo', true, 2); scanner.advancePastLine(); - assert.strictEqual(scanner.lineFromCursor, 'lo'); + expect(scanner.lineFromCursor).toBe('lo'); }); it('should advance past the next CR', () => { const scanner = getScanner('hel\rlo', true, 2); scanner.advancePastLine(); - assert.strictEqual(scanner.lineFromCursor, 'lo'); + expect(scanner.lineFromCursor).toBe('lo'); }); it('should advance past the next CRLF', () => { const scanner = getScanner('hel\r\nlo', true, 2); scanner.advancePastLine(); - assert.strictEqual(scanner.lineFromCursor, 'lo'); + expect(scanner.lineFromCursor).toBe('lo'); }); }); @@ -105,25 +102,25 @@ describe('Scanner', () => { it('should advance past the next LF', () => { const scanner = getScanner('hel\nlo', true, 2); scanner.advancePastLine(); - assert.strictEqual(scanner.lineFromCursor, 'lo'); + expect(scanner.lineFromCursor).toBe('lo'); }); it('should advance past the next CR', () => { const scanner = getScanner('hel\rlo', true, 2); scanner.advancePastLine(); - assert.strictEqual(scanner.lineFromCursor, 'lo'); + expect(scanner.lineFromCursor).toBe('lo'); }); it('should advance past the next CRLF', () => { const scanner = getScanner('hel\r\nlo', true, 2); scanner.advancePastLine(); - assert.strictEqual(scanner.lineFromCursor, 'lo'); + expect(scanner.lineFromCursor).toBe('lo'); }); }); describe('#advanceTo', () => { it('should set the cursor to the supplied value', () => { - assert.strictEqual(getScanner('hello', true, 0).advanceTo(2).cursor, 2); + expect(getScanner('hello', true, 0).advanceTo(2).cursor).toBe(2); }); }); @@ -131,8 +128,8 @@ describe('Scanner', () => { it('should set the cursor to the supplied value', () => { const scanner = getScanner('hello', true, 0); const token = scanner.nextCharacterToken; - if (assertToken(token)) { - assert.strictEqual(scanner.advanceToToken(token).cursor, token.startCursor); + if (expectNonNullToken(token)) { + expect(scanner.advanceToToken(token).cursor).toBe(token.startCursor); } }); }); @@ -141,8 +138,8 @@ describe('Scanner', () => { it('should set the cursor to the supplied value', () => { const scanner = getScanner('hello', true, 0); const token = scanner.nextCharacterToken; - if (assertToken(token)) { - assert.strictEqual(scanner.advancePastToken(token).cursor, token.endCursor + 1); + if (expectNonNullToken(token)) { + expect(scanner.advancePastToken(token).cursor).toBe(token.endCursor + 1); } }); }); @@ -150,9 +147,9 @@ describe('Scanner', () => { describe('#truncateToCursor', () => { it('should set the cursor to the supplied value', () => { const scanner = getScanner('hello', true, 2).truncateToCursor(); - assert.strictEqual(scanner.line, 'llo'); - assert.strictEqual(scanner.lineLength, 3); - assert.strictEqual(scanner.cursor, 0); + expect(scanner.line).toBe('llo'); + expect(scanner.lineLength).toBe(3); + expect(scanner.cursor).toBe(0); }); }); }); @@ -162,67 +159,67 @@ describe('Token', () => { describe('.isTokenRowDelimiter', () => { it('should return true if the token is a row delimiter', () => { - assert.strictEqual(Token.isTokenRowDelimiter(createToken('\n')), true); - assert.strictEqual(Token.isTokenRowDelimiter(createToken('\r')), true); - assert.strictEqual(Token.isTokenRowDelimiter(createToken('\r\n')), true); + expect(Token.isTokenRowDelimiter(createToken('\n'))).toBe(true); + expect(Token.isTokenRowDelimiter(createToken('\r'))).toBe(true); + expect(Token.isTokenRowDelimiter(createToken('\r\n'))).toBe(true); }); it('should return false if the token is not a row delimiter', () => { - assert.strictEqual(Token.isTokenRowDelimiter(createToken('\\n')), false); - assert.strictEqual(Token.isTokenRowDelimiter(createToken('\\r')), false); + expect(Token.isTokenRowDelimiter(createToken('\\n'))).toBe(false); + expect(Token.isTokenRowDelimiter(createToken('\\r'))).toBe(false); }); }); describe('#isTokenCarriageReturn', () => { it('should return true if the token is a CR delimiter', () => { - assert.strictEqual(Token.isTokenCarriageReturn(createToken('\r'), createOptions()), true); + expect(Token.isTokenCarriageReturn(createToken('\r'), createOptions())).toBe(true); }); it('should return false if the token is not a CR delimiter', () => { - assert.strictEqual(Token.isTokenCarriageReturn(createToken('\n'), createOptions()), false); - assert.strictEqual(Token.isTokenCarriageReturn(createToken('\r\n'), createOptions()), false); + expect(Token.isTokenCarriageReturn(createToken('\n'), createOptions())).toBe(false); + expect(Token.isTokenCarriageReturn(createToken('\r\n'), createOptions())).toBe(false); }); }); describe('#isTokenComment', () => { it('should return true if the token is a comment character', () => { - assert.strictEqual(Token.isTokenComment(createToken('#'), createOptions({ comment: '#' })), true); + expect(Token.isTokenComment(createToken('#'), createOptions({ comment: '#' }))).toBe(true); }); it('should return false if the token is not a comment character', () => { - assert.strictEqual(Token.isTokenComment(createToken('+'), createOptions({ comment: '#' })), false); + expect(Token.isTokenComment(createToken('+'), createOptions({ comment: '#' }))).toBe(false); }); it('should return false if the token is not a comments are not supported', () => { - assert.strictEqual(Token.isTokenComment(createToken('#'), createOptions()), false); + expect(Token.isTokenComment(createToken('#'), createOptions())).toBe(false); }); }); describe('#isTokenEscapeCharacter', () => { it('should return true if the token is an escape character', () => { - assert.strictEqual(Token.isTokenEscapeCharacter(createToken('\\'), createOptions({ escape: '\\' })), true); + expect(Token.isTokenEscapeCharacter(createToken('\\'), createOptions({ escape: '\\' }))).toBe(true); }); it('should return false if the token is not a escape character', () => { - assert.strictEqual(Token.isTokenEscapeCharacter(createToken('"'), createOptions({ escape: '\\' })), false); + expect(Token.isTokenEscapeCharacter(createToken('"'), createOptions({ escape: '\\' }))).toBe(false); }); }); describe('#isTokenQuote', () => { it('should return true if the token is an quote character', () => { - assert.strictEqual(Token.isTokenEscapeCharacter(createToken('$'), createOptions({ quote: '$' })), true); + expect(Token.isTokenEscapeCharacter(createToken('$'), createOptions({ quote: '$' }))).toBe(true); }); it('should return false if the token is not a quote character', () => { - assert.strictEqual(Token.isTokenEscapeCharacter(createToken('"'), createOptions({ quote: '$' })), false); + expect(Token.isTokenEscapeCharacter(createToken('"'), createOptions({ quote: '$' }))).toBe(false); }); }); describe('#isTokenDelimiter', () => { it('should return true if the token is an delimiter character', () => { - assert.strictEqual(Token.isTokenDelimiter(createToken('\t'), createOptions({ delimiter: '\t' })), true); + expect(Token.isTokenDelimiter(createToken('\t'), createOptions({ delimiter: '\t' }))).toBe(true); }); it('should return false if the token is not a delimiter character', () => { - assert.strictEqual(Token.isTokenDelimiter(createToken(','), createOptions({ delimiter: '\t' })), false); + expect(Token.isTokenDelimiter(createToken(','), createOptions({ delimiter: '\t' }))).toBe(false); }); }); }); diff --git a/test/parser/parser/column/ColumnParser.test.ts b/__tests__/parser/parser/column/ColumnParser.spec.ts similarity index 88% rename from test/parser/parser/column/ColumnParser.test.ts rename to __tests__/parser/parser/column/ColumnParser.spec.ts index 3553b32e..d09ed87f 100644 --- a/test/parser/parser/column/ColumnParser.test.ts +++ b/__tests__/parser/parser/column/ColumnParser.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import * as sinon from 'sinon'; import { ParserOptions, Scanner, ColumnParser } from '../../../../src/parser'; @@ -16,7 +15,7 @@ describe('ColumnParser', () => { .once() .withArgs(scanner) .returns(expectedResult); - assert.deepStrictEqual(lineParser.parse(scanner), expectedResult); + expect(lineParser.parse(scanner)).toEqual(expectedResult); mock.verify(); }); }); @@ -32,7 +31,7 @@ describe('ColumnParser', () => { .once() .withArgs(scanner) .returns(expectedResult); - assert.deepStrictEqual(lineParser.parse(scanner), expectedResult); + expect(lineParser.parse(scanner)).toEqual(expectedResult); mock.verify(); }); }); diff --git a/test/parser/parser/column/NonQuotedColumnParser.test.ts b/__tests__/parser/parser/column/NonQuotedColumnParser.spec.ts similarity index 69% rename from test/parser/parser/column/NonQuotedColumnParser.test.ts rename to __tests__/parser/parser/column/NonQuotedColumnParser.spec.ts index 19f0d6fd..30dad12f 100644 --- a/test/parser/parser/column/NonQuotedColumnParser.test.ts +++ b/__tests__/parser/parser/column/NonQuotedColumnParser.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../../../src'; import { ParserOptions, Scanner, NonQuotedColumnParser } from '../../../../src/parser'; @@ -17,64 +16,64 @@ describe('NonQuotedColumnParser', () => { const parserOptions = new ParserOptions({}); const lineParser = new NonQuotedColumnParser(parserOptions); const scanner = new Scanner({ line, parserOptions, hasMoreData: true }); - assert.strictEqual(lineParser.parse(scanner), null); + expect(lineParser.parse(scanner)).toBeNull(); }); it('should parse a column up to a column delimiter', () => { const line = 'hello,world'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ',world'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(',world'); }); it('should parse a column when not followed by any characters', () => { const line = 'hello'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a column up to a LF', () => { const line = 'hello\nworld'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\nworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\nworld'); }); it('should parse a column up to a CR', () => { const line = 'hello\rworld'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\rworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\rworld'); }); it('should parse a column up to a CRLF', () => { const line = 'hello\r\nworld'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\nworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r\nworld'); }); describe('trim options', () => { it('should trim the item', () => { const line = ' hello '; const { scanner, col } = parse(line, true, { trim: true }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should ltrim the item', () => { const line = ' hello '; const { scanner, col } = parse(line, true, { ltrim: true }); - assert.strictEqual(col, 'hello '); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello '); + expect(scanner.lineFromCursor).toBe(''); }); it('should rtrim the item', () => { const line = ' hello '; const { scanner, col } = parse(line, true, { rtrim: true }); - assert.strictEqual(col, ' hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe(' hello'); + expect(scanner.lineFromCursor).toBe(''); }); }); }); @@ -85,72 +84,72 @@ describe('NonQuotedColumnParser', () => { const parserOptions = new ParserOptions({ delimiter: '\t' }); const lineParser = new NonQuotedColumnParser(parserOptions); const scanner = new Scanner({ line, parserOptions, hasMoreData: true }); - assert.strictEqual(lineParser.parse(scanner), null); - assert.strictEqual(scanner, scanner); + expect(lineParser.parse(scanner)).toBeNull(); + expect(scanner).toBe(scanner); }); it('should parse a column when not followed by any characters', () => { const line = 'hello'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a column up to the column delimiter', () => { const line = 'hello\tworld'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\tworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\tworld'); }); it('should include all white space up to a column delimiter', () => { const line = ' \t '; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, ' '); - assert.strictEqual(scanner.lineFromCursor, '\t '); + expect(col).toBe(' '); + expect(scanner.lineFromCursor).toBe('\t '); }); it('should parse a column up to a LF', () => { const line = 'hello\nworld'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\nworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\nworld'); }); it('should parse a column up to a CR', () => { const line = 'hello\rworld'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\rworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\rworld'); }); it('should parse a column up to a CRLF', () => { const line = 'hello\r\nworld'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\nworld'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r\nworld'); }); describe('trim options', () => { it('should trim white space from both ends when trim is true', () => { const line = ' hello \t'; const { scanner, col } = parse(line, true, { delimiter: '\t', trim: true }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\t'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\t'); }); it('should trim white space from the left when ltrim is true', () => { const line = ' hello \t'; const { scanner, col } = parse(line, true, { delimiter: '\t', ltrim: true }); - assert.strictEqual(col, 'hello '); - assert.strictEqual(scanner.lineFromCursor, '\t'); + expect(col).toBe('hello '); + expect(scanner.lineFromCursor).toBe('\t'); }); it('should trim white space from the right when rtrim is true', () => { const line = ' hello \t'; const { scanner, col } = parse(line, true, { delimiter: '\t', ltrim: true }); - assert.strictEqual(col, 'hello '); - assert.strictEqual(scanner.lineFromCursor, '\t'); + expect(col).toBe('hello '); + expect(scanner.lineFromCursor).toBe('\t'); }); }); }); diff --git a/test/parser/parser/column/QuotedColumnParser.test.ts b/__tests__/parser/parser/column/QuotedColumnParser.spec.ts similarity index 67% rename from test/parser/parser/column/QuotedColumnParser.test.ts rename to __tests__/parser/parser/column/QuotedColumnParser.spec.ts index 6fdc206d..b51278d4 100644 --- a/test/parser/parser/column/QuotedColumnParser.test.ts +++ b/__tests__/parser/parser/column/QuotedColumnParser.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs } from '../../../../src'; import { ParserOptions, QuotedColumnParser, Scanner } from '../../../../src/parser'; @@ -17,169 +16,175 @@ describe('QuotedColumnParser', () => { const parserOptions = new ParserOptions({}); const lineParser = new QuotedColumnParser(parserOptions); const scanner = new Scanner({ line, parserOptions, hasMoreData: true }); - assert.strictEqual(lineParser.parse(scanner), null); - assert.strictEqual(scanner, scanner); + expect(lineParser.parse(scanner)).toBe(null); + expect(scanner).toBe(scanner); }); it('should parse a quoted col when not followed by any characters', () => { const line = '"hello"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should not parse a quoted col when not followed by any characters', () => { const line = '"hello,'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, null); - assert.strictEqual(scanner.lineFromCursor, '"hello,'); + expect(col).toBe(null); + expect(scanner.lineFromCursor).toBe('"hello,'); }); it('should parse a quoted col up to a column delimiter', () => { const line = '"hello","world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted col up to a column delimiter with a LF in the column', () => { const line = '"hel\nlo","world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hel\nlo'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hel\nlo'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted col up to a column delimiter with a CR in the column', () => { const line = '"hel\rlo","world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hel\rlo'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hel\rlo'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted col up to a column delimiter with a CRLF in the column', () => { const line = '"hel\r\nlo","world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hel\r\nlo'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hel\r\nlo'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted col up to a LF', () => { const line = '"hello"\n"world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\n"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\n"world"'); }); it('should parse a quoted col up to a CR', () => { const line = '"hello"\r"world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r"world"'); }); it('should parse a quoted col up to a CR', () => { const line = '"hello"\r\n"world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\n"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r\n"world"'); }); it('should parse a quoted column with escaped quotes when not followed by any characters', () => { const line = '"hell""o"""'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted column with escaped quotes when followed by a delimiter', () => { const line = '"hell""o""","world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted column with escaped quotes when followed by a LF', () => { const line = '"hell""o"""\n"world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\n"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\n"world"'); }); it('should parse a quoted column with escaped quotes when followed by a CR', () => { const line = '"hell""o"""\r"world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\r"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\r"world"'); }); it('should parse a quoted column with escaped quotes when followed by a CRLF', () => { const line = '"hell""o"""\r\n"world"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\r\n"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\r\n"world"'); }); it('should skip white space after a quote up to the column delimiter', () => { const line = '"Hello" ,"World"'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, ',"World"'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe(',"World"'); }); it('should skip white space after a quote up to a LF', () => { const line = '"Hello" \n'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\n'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\n'); }); it('should skip white space after a quote up to a CR', () => { const line = '"Hello" \r'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\r'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\r'); }); it('should skip white space after a quote up to a CRLF', () => { const line = '"Hello" \r\n'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\n'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\r\n'); }); it('should skip white space after a quote if has more data is false and there is no new line', () => { const line = '"Hello" '; const { scanner, col } = parse(line, false); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should include all quoted white space up to a column delimiter', () => { const line = '" "," "'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, ' '); - assert.strictEqual(scanner.lineFromCursor, '," "'); + expect(col).toBe(' '); + expect(scanner.lineFromCursor).toBe('," "'); }); it('should throw an error if a column contains a closing quote that is not followed by a row or column delimiter', () => { const line = '"hello\n"First'; - assert.throws(() => parse(line, true), /Parse Error: expected: ',' OR new line got: 'F'. at 'First/); - assert.throws(() => parse(line, false), /Parse Error: expected: ',' OR new line got: 'F'. at 'First/); + expect(() => parse(line, true)).toThrowError( + /Parse Error: expected: ',' OR new line got: 'F'. at 'First/, + ); + expect(() => parse(line, false)).toThrowError( + /Parse Error: expected: ',' OR new line got: 'F'. at 'First/, + ); }); describe('hasMoreData is true', () => { it('should not parse a column without a closing quote', () => { const line = '"hell""o'; const { scanner, col } = parse(line, true); - assert.strictEqual(col, null); - assert.strictEqual(scanner.lineFromCursor, line); + expect(col).toBe(null); + expect(scanner.lineFromCursor).toBe(line); }); }); describe('hasMoreData is false', () => { it('should not parse a column without a closing quote', () => { const line = '"hell""o'; - assert.throws(() => parse(line, false), /Parse Error: missing closing: '"' in line: at '"hell""o'/); + expect(() => parse(line, false)).toThrowError( + /Parse Error: missing closing: '"' in line: at '"hell""o'/, + ); }); }); }); @@ -190,130 +195,128 @@ describe('QuotedColumnParser', () => { const parserOptions = new ParserOptions({ delimiter: '\t' }); const lineParser = new QuotedColumnParser(parserOptions); const scanner = new Scanner({ line, parserOptions, hasMoreData: true }); - assert.strictEqual(lineParser.parse(scanner), null); - assert.strictEqual(scanner, scanner); + expect(lineParser.parse(scanner)).toBe(null); + expect(scanner).toBe(scanner); }); it('should parse a quoted col when not followed by any characters', () => { const line = '"hello"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted col up to a column delimiter', () => { const line = '"hello"\t"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\t"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\t"world"'); }); it('should parse a quoted col up to a LF', () => { const line = '"hello"\n"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\n"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\n"world"'); }); it('should parse a quoted col up to a CR', () => { const line = '"hello"\r"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r"world"'); }); it('should parse a quoted col up to a CR', () => { const line = '"hello"\r\n"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\n"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r\n"world"'); }); it('should parse a quoted column with escaped quotes when not followed by any characters', () => { const line = '"hell""o"""'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted column with escaped quotes when followed by a delimiter', () => { const line = '"hell""o"""\t"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\t"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\t"world"'); }); it('should parse a quoted column with escaped quotes when followed by a LF', () => { const line = '"hell""o"""\n"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\n"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\n"world"'); }); it('should parse a quoted column with escaped quotes when followed by a CR', () => { const line = '"hell""o"""\r"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\r"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\r"world"'); }); it('should parse a quoted column with escaped quotes when followed by a CRLF', () => { const line = '"hell""o"""\r\n"world"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\r\n"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\r\n"world"'); }); it('should skip white space after a quote up to the column delimiter', () => { const line = '"Hello" \t"World"'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\t"World"'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\t"World"'); }); it('should skip white space after a quote up to a LF', () => { const line = '"Hello" \n'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\n'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\n'); }); it('should skip white space after a quote up to a CR', () => { const line = '"Hello" \r'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\r'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\r'); }); it('should skip white space after a quote up to a CRLF', () => { const line = '"Hello" \r\n'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\n'); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe('\r\n'); }); it('should skip white space after a quote if has more data is false and there is no new line', () => { const line = '"Hello" '; const { scanner, col } = parse(line, false, { delimiter: '\t' }); - assert.strictEqual(col, 'Hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('Hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should include all quoted white space up to a column delimiter', () => { const line = '" "\t" "'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, ' '); - assert.strictEqual(scanner.lineFromCursor, '\t" "'); + expect(col).toBe(' '); + expect(scanner.lineFromCursor).toBe('\t" "'); }); it('should throw an error if a column contains a closing quote that is not followed by a row or column delimiter', () => { const line = '"hello\n"First'; - assert.throws( - () => parse(line, true, { delimiter: '\t' }), + expect(() => parse(line, true, { delimiter: '\t' })).toThrowError( /Parse Error: expected: '\t' OR new line got: 'F'. at 'First/, ); - assert.throws( - () => parse(line, false, { delimiter: '\t' }), + expect(() => parse(line, false, { delimiter: '\t' })).toThrowError( /Parse Error: expected: '\t' OR new line got: 'F'. at 'First/, ); }); @@ -322,16 +325,15 @@ describe('QuotedColumnParser', () => { it('should not parse a column without a closing quote', () => { const line = '"hell""o'; const { scanner, col } = parse(line, true, { delimiter: '\t' }); - assert.strictEqual(col, null); - assert.strictEqual(scanner.lineFromCursor, line); + expect(col).toBe(null); + expect(scanner.lineFromCursor).toBe(line); }); }); describe('hasMoreData is false', () => { it('should not parse a column without a closing quote', () => { const line = '"hell""o'; - assert.throws( - () => parse(line, false, { delimiter: '\t' }), + expect(() => parse(line, false, { delimiter: '\t' })).toThrowError( /Parse Error: missing closing: '"' in line: at '"hell""o'/, ); }); @@ -344,88 +346,86 @@ describe('QuotedColumnParser', () => { const parserOptions = new ParserOptions({ quote: '$' }); const lineParser = new QuotedColumnParser(parserOptions); const scanner = new Scanner({ line, parserOptions, hasMoreData: true }); - assert.strictEqual(lineParser.parse(scanner), null); - assert.strictEqual(scanner, scanner); + expect(lineParser.parse(scanner)).toBe(null); + expect(scanner).toBe(scanner); }); it('should parse a quoted col when not followed by any characters', () => { const line = '$hello$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted col up to a column delimiter', () => { const line = '$hello$,$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ',$world$'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(',$world$'); }); it('should parse a quoted col up to a LF', () => { const line = '$hello$\n$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\n$world$'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\n$world$'); }); it('should parse a quoted col up to a CR', () => { const line = '$hello$\r$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r$world$'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r$world$'); }); it('should parse a quoted col up to a CR', () => { const line = '$hello$\r\n$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\n$world$'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r\n$world$'); }); it('should parse a quoted column with escaped quotes when not followed by any characters', () => { const line = '$hell$$o$$$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hell$o$'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hell$o$'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted column with escaped quotes when followed by a delimiter', () => { const line = '$hell$$o$$$,$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hell$o$'); - assert.strictEqual(scanner.lineFromCursor, ',$world$'); + expect(col).toBe('hell$o$'); + expect(scanner.lineFromCursor).toBe(',$world$'); }); it('should parse a quoted column with escaped quotes when followed by a LF', () => { const line = '$hell$$o$$$\n$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hell$o$'); - assert.strictEqual(scanner.lineFromCursor, '\n$world$'); + expect(col).toBe('hell$o$'); + expect(scanner.lineFromCursor).toBe('\n$world$'); }); it('should parse a quoted column with escaped quotes when followed by a CR', () => { const line = '$hell$$o$$$\r$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hell$o$'); - assert.strictEqual(scanner.lineFromCursor, '\r$world$'); + expect(col).toBe('hell$o$'); + expect(scanner.lineFromCursor).toBe('\r$world$'); }); it('should parse a quoted column with escaped quotes when followed by a CRLF', () => { const line = '$hell$$o$$$\r\n$world$'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, 'hell$o$'); - assert.strictEqual(scanner.lineFromCursor, '\r\n$world$'); + expect(col).toBe('hell$o$'); + expect(scanner.lineFromCursor).toBe('\r\n$world$'); }); it('should throw an error if a column contains a closing quote that is not followed by a row or column delimiter', () => { const line = '$hello\n$First'; - assert.throws( - () => parse(line, true, { quote: '$' }), + expect(() => parse(line, true, { quote: '$' })).toThrowError( /Parse Error: expected: ',' OR new line got: 'F'. at 'First/, ); - assert.throws( - () => parse(line, false, { quote: '$' }), + expect(() => parse(line, false, { quote: '$' })).toThrowError( /Parse Error: expected: ',' OR new line got: 'F'. at 'First/, ); }); @@ -434,16 +434,15 @@ describe('QuotedColumnParser', () => { it('should not parse a column without a closing quote', () => { const line = '$hell$$o'; const { scanner, col } = parse(line, true, { quote: '$' }); - assert.strictEqual(col, null); - assert.strictEqual(scanner.lineFromCursor, line); + expect(col).toBe(null); + expect(scanner.lineFromCursor).toBe(line); }); }); describe('hasMoreData is false', () => { it('should not parse a column without a closing quote', () => { const line = '$hell$$o'; - assert.throws( - () => parse(line, false, { quote: '$' }), + expect(() => parse(line, false, { quote: '$' })).toThrowError( /Parse Error: missing closing: '\$' in line: at '\$hell\$\$o'/, ); }); @@ -456,95 +455,93 @@ describe('QuotedColumnParser', () => { const parserOptions = new ParserOptions({ escape: '$' }); const lineParser = new QuotedColumnParser(parserOptions); const scanner = new Scanner({ line, parserOptions, hasMoreData: true }); - assert.strictEqual(lineParser.parse(scanner), null); - assert.strictEqual(scanner, scanner); + expect(lineParser.parse(scanner)).toBe(null); + expect(scanner).toBe(scanner); }); it('should parse a quoted col when not followed by any characters', () => { const line = '"hello"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted col up to a column delimiter', () => { const line = '"hello","world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse an escape not followed by a quote', () => { const line = '"hell$o","world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hell$o'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hell$o'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted col up to a LF', () => { const line = '"hello"\n"world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\n"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\n"world"'); }); it('should parse a quoted col up to a CR', () => { const line = '"hello"\r"world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r"world"'); }); it('should parse a quoted col up to a CR', () => { const line = '"hello"\r\n"world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, '\r\n"world"'); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe('\r\n"world"'); }); it('should parse a quoted column with escaped quotes when not followed by any characters', () => { const line = '"hell$"o$""'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe(''); }); it('should parse a quoted column with escaped quotes when followed by a delimiter', () => { const line = '"hell$"o$"","world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, ',"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe(',"world"'); }); it('should parse a quoted column with escaped quotes when followed by a LF', () => { const line = '"hell$"o$""\n"world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\n"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\n"world"'); }); it('should parse a quoted column with escaped quotes when followed by a CR', () => { const line = '"hell$"o$""\r"world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\r"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\r"world"'); }); it('should parse a quoted column with escaped quotes when followed by a CRLF', () => { const line = '"hell$"o$""\r\n"world"'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, 'hell"o"'); - assert.strictEqual(scanner.lineFromCursor, '\r\n"world"'); + expect(col).toBe('hell"o"'); + expect(scanner.lineFromCursor).toBe('\r\n"world"'); }); it('should throw an error if a column contains a closing quote that is not followed by a row or column delimiter', () => { const line = '"hello\n"First'; - assert.throws( - () => parse(line, true, { escape: '$' }), + expect(() => parse(line, true, { escape: '$' })).toThrowError( /Parse Error: expected: ',' OR new line got: 'F'. at 'First/, ); - assert.throws( - () => parse(line, false, { escape: '$' }), + expect(() => parse(line, false, { escape: '$' })).toThrowError( /Parse Error: expected: ',' OR new line got: 'F'. at 'First/, ); }); @@ -553,16 +550,15 @@ describe('QuotedColumnParser', () => { it('should not parse a column without a closing quote', () => { const line = '"hell$"o'; const { scanner, col } = parse(line, true, { escape: '$' }); - assert.strictEqual(col, null); - assert.strictEqual(scanner.lineFromCursor, line); + expect(col).toBe(null); + expect(scanner.lineFromCursor).toBe(line); }); }); describe('hasMoreData is false', () => { it('should not parse a column without a closing quote', () => { const line = '"hell$"o'; - assert.throws( - () => parse(line, false, { escape: '$' }), + expect(() => parse(line, false, { escape: '$' })).toThrowError( /Parse Error: missing closing: '"' in line: at '"hell\$"o'/, ); }); @@ -573,22 +569,22 @@ describe('QuotedColumnParser', () => { it('should trim the item', () => { const line = '" hello "'; const { scanner, col } = parse(line, true, { trim: true }); - assert.strictEqual(col, 'hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello'); + expect(scanner.lineFromCursor).toBe(''); }); it('should ltrim the item', () => { const line = '" hello "'; const { scanner, col } = parse(line, true, { ltrim: true }); - assert.strictEqual(col, 'hello '); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe('hello '); + expect(scanner.lineFromCursor).toBe(''); }); it('should rtrim the item', () => { const line = '" hello "'; const { scanner, col } = parse(line, true, { rtrim: true }); - assert.strictEqual(col, ' hello'); - assert.strictEqual(scanner.lineFromCursor, ''); + expect(col).toBe(' hello'); + expect(scanner.lineFromCursor).toBe(''); }); }); }); diff --git a/test/parser/transforms/HeaderTransformer.test.ts b/__tests__/parser/transforms/HeaderTransformer.spec.ts similarity index 50% rename from test/parser/transforms/HeaderTransformer.test.ts rename to __tests__/parser/transforms/HeaderTransformer.spec.ts index 15f517a1..5f980d94 100644 --- a/test/parser/transforms/HeaderTransformer.test.ts +++ b/__tests__/parser/transforms/HeaderTransformer.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserOptionsArgs, ParserRowArray as RowArray } from '../../../src'; import { ParserOptions, RowValidationResult, HeaderTransformer } from '../../../src/parser'; @@ -19,181 +18,148 @@ describe('HeaderTransformer', () => { }); describe('#transform', () => { - it('should return a valid row', () => { + it('should return a valid row', async () => { const row = ['a', 'b']; const transformer = createHeaderTransformer({ headers: false }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { row, isValid: true }); - }); + await expect(transform(row, transformer)).resolves.toEqual({ row, isValid: true }); }); - it('should return a null row that is still valid if headers is true', () => { + it('should return a null row that is still valid if headers is true', async () => { const row = ['a', 'b']; const transformer = createHeaderTransformer({ headers: true }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { row: null, isValid: true }); - }); + await expect(transform(row, transformer)).resolves.toEqual({ row: null, isValid: true }); }); - it('should return a row with mapped headers if headers is an array', () => { + it('should return a row with mapped headers if headers is an array', async () => { const row = ['a', 'b']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'] }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { row: { header1: 'a', header2: 'b' }, isValid: true }); + await expect(transform(row, transformer)).resolves.toEqual({ + row: { header1: 'a', header2: 'b' }, + isValid: true, }); }); - it('should skip columns with an undefined header', () => { + it('should skip columns with an undefined header', async () => { const row = ['a', 'b', 'c']; const transformer = createHeaderTransformer({ headers: ['header1', undefined, 'header2'] }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { row: { header1: 'a', header2: 'c' }, isValid: true }); + await expect(transform(row, transformer)).resolves.toEqual({ + row: { header1: 'a', header2: 'c' }, + isValid: true, }); }); - it('should skip the first row if renameHeaders is true and headers is an array', () => { + it('should skip the first row if renameHeaders is true and headers is an array', async () => { const row1 = ['origHeader1', 'origHeader2']; const row2 = ['a', 'b']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'], renameHeaders: true }); - return transform(row1, transformer) - .then(results => { - assert.deepStrictEqual(results, { row: null, isValid: true }); - return transform(row2, transformer); - }) - .then(results => { - assert.deepStrictEqual(results, { row: { header1: 'a', header2: 'b' }, isValid: true }); - }); + await expect(transform(row1, transformer)).resolves.toEqual({ row: null, isValid: true }); + await expect(transform(row2, transformer)).resolves.toEqual({ + row: { header1: 'a', header2: 'b' }, + isValid: true, + }); }); - it('should skip the first row if headers is function and properly map the headers to the row', () => { + it('should skip the first row if headers is function and properly map the headers to the row', async () => { const row1 = ['origHeader1', 'origHeader2']; const row2 = ['a', 'b']; const transformer = createHeaderTransformer({ headers: headers => headers.map(h => h?.toUpperCase()), }); - return transform(row1, transformer) - .then(results => { - assert.deepStrictEqual(results, { row: null, isValid: true }); - return transform(row2, transformer); - }) - .then(results => { - assert.deepStrictEqual(results, { row: { ORIGHEADER1: 'a', ORIGHEADER2: 'b' }, isValid: true }); - }); + await expect(transform(row1, transformer)).resolves.toEqual({ row: null, isValid: true }); + await expect(transform(row2, transformer)).resolves.toEqual({ + row: { ORIGHEADER1: 'a', ORIGHEADER2: 'b' }, + isValid: true, + }); }); - it('should throw an error if headers is true and the first row is not unique', () => { + it('should throw an error if headers is true and the first row is not unique', async () => { const row1 = ['origHeader1', 'origHeader1', 'origHeader2']; const transformer = createHeaderTransformer({ headers: true }); - return transform(row1, transformer).then( - () => assert.fail('should have failed'), - err => assert.strictEqual(err.message, 'Duplicate headers found ["origHeader1"]'), - ); + await expect(transform(row1, transformer)).rejects.toThrowError('Duplicate headers found ["origHeader1"]'); }); it('should throw an error if headers is an array and is not unique', () => { const headers = ['origHeader1', 'origHeader1', 'origHeader2']; - assert.throws(() => createHeaderTransformer({ headers }), /Duplicate headers found \["origHeader1"]/); + expect(() => createHeaderTransformer({ headers })).toThrowError('Duplicate headers found ["origHeader1"]'); }); - it('should throw an error if headers is a transform and returns non-unique values', () => { + it('should throw an error if headers is a transform and returns non-unique values', async () => { const row = ['h1', 'h2', 'h3']; const transformer = createHeaderTransformer({ headers: () => ['h1', 'h1', 'h3'] }); - return transform(row, transformer).catch(err => - assert.strictEqual(err.message, 'Duplicate headers found ["h1"]'), - ); + await expect(transform(row, transformer)).rejects.toThrowError('Duplicate headers found ["h1"]'); }); - it('should throw an error if headers is not defined and renameHeaders is true', () => { + it('should throw an error if headers is not defined and renameHeaders is true', async () => { const row1 = ['origHeader1', 'origHeader2']; const transformer = createHeaderTransformer({ renameHeaders: true }); - return transform(row1, transformer).then( - () => assert.fail('should have failed'), - err => - assert.strictEqual(err.message, 'Error renaming headers: new headers must be provided in an array'), + await expect(transform(row1, transformer)).rejects.toThrowError( + 'Error renaming headers: new headers must be provided in an array', ); }); - it('should throw an error if the row length is > than the headers length as strictColumnHandling is not defined', () => { + it('should throw an error if the row length is > than the headers length as strictColumnHandling is not defined', async () => { const row = ['a', 'b', 'c']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'] }); - return transform(row, transformer).then( - () => assert.fail('should have failed'), - err => - assert.strictEqual( - err.message, - 'Unexpected Error: column header mismatch expected: 2 columns got: 3', - ), + await expect(transform(row, transformer)).rejects.toThrowError( + 'Unexpected Error: column header mismatch expected: 2 columns got: 3', ); }); - it('should throw an error if the row length is > than the headers length as strictColumnHandling is false', () => { + it('should throw an error if the row length is > than the headers length as strictColumnHandling is false', async () => { const row = ['a', 'b', 'c']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'], strictColumnHandling: false, }); - return transform(row, transformer).then( - () => assert.fail('should have failed'), - err => - assert.strictEqual( - err.message, - 'Unexpected Error: column header mismatch expected: 2 columns got: 3', - ), + await expect(transform(row, transformer)).rejects.toThrowError( + 'Unexpected Error: column header mismatch expected: 2 columns got: 3', ); }); - it('should mark the row as invalid if the row length is > than the headers length as strictColumnHandling is true', () => { + it('should mark the row as invalid if the row length is > than the headers length as strictColumnHandling is true', async () => { const row = ['a', 'b', 'c']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'], strictColumnHandling: true, }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { - row, - isValid: false, - reason: 'Column header mismatch expected: 2 columns got: 3', - }); + await expect(transform(row, transformer)).resolves.toEqual({ + row, + isValid: false, + reason: 'Column header mismatch expected: 2 columns got: 3', }); }); - it('should return a mapped row if row length is < than the headers length as strictColumnHandling is not defined', () => { + it('should return a mapped row if row length is < than the headers length as strictColumnHandling is not defined', async () => { const row = ['a']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'] }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { - row: { header1: 'a', header2: '' }, - isValid: true, - }); + await expect(transform(row, transformer)).resolves.toEqual({ + row: { header1: 'a', header2: '' }, + isValid: true, }); }); - it('should return a mapped row if row length is < than the headers length as strictColumnHandling is not false', () => { + it('should return a mapped row if row length is < than the headers length as strictColumnHandling is not false', async () => { const row = ['a']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'], strictColumnHandling: false, }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { - row: { header1: 'a', header2: '' }, - isValid: true, - }); + await expect(transform(row, transformer)).resolves.toEqual({ + row: { header1: 'a', header2: '' }, + isValid: true, }); }); - it('should mark the row as invalid if the row length is < than the headers length as strictColumnHandling is true', () => { + it('should mark the row as invalid if the row length is < than the headers length as strictColumnHandling is true', async () => { const row = ['a']; const transformer = createHeaderTransformer({ headers: ['header1', 'header2'], strictColumnHandling: true, }); - return transform(row, transformer).then(results => { - assert.deepStrictEqual(results, { - row, - isValid: false, - reason: 'Column header mismatch expected: 2 columns got: 1', - }); + await expect(transform(row, transformer)).resolves.toEqual({ + row, + isValid: false, + reason: 'Column header mismatch expected: 2 columns got: 1', }); }); }); diff --git a/test/parser/transforms/RowTransformerValidator.test.ts b/__tests__/parser/transforms/RowTransformerValidator.spec.ts similarity index 66% rename from test/parser/transforms/RowTransformerValidator.test.ts rename to __tests__/parser/transforms/RowTransformerValidator.spec.ts index e52a4a7b..2e648529 100644 --- a/test/parser/transforms/RowTransformerValidator.test.ts +++ b/__tests__/parser/transforms/RowTransformerValidator.spec.ts @@ -1,4 +1,3 @@ -import * as assert from 'assert'; import { ParserRow as Row, ParserRowArray as RowArray } from '../../../src'; import { RowValidationResult, RowTransformerValidator } from '../../../src/parser'; @@ -19,55 +18,52 @@ describe('RowTransformerValidator', () => { }); describe('#transformAndValidate', () => { - it('should return a valid row if validator and transform are not defined', () => { + it('should return a valid row if validator and transform are not defined', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row, isValid: true }); - }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ row, isValid: true }); }); describe('#rowTransform', () => { it('should throw an error if the transform is not a function', () => { const transformer = createRowTransformerValidator(); - assert.throws(() => { + expect(() => { // @ts-ignore transformer.rowTransform = 'foo'; - }, /TypeError: The transform should be a function/); + }).toThrowError('The transform should be a function'); }); - it('should transform a row synchronously', () => { + it('should transform a row synchronously', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowTransform = (r: Row) => (r as RowArray).map(col => col.toUpperCase()); - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row: ['A', 'B'], isValid: true }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ + row: ['A', 'B'], + isValid: true, }); }); - it('should transform a row synchronously', () => { + it('should transform a row synchronously', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowTransform = (r: Row) => (r as RowArray).map(col => col.toUpperCase()); - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row: ['A', 'B'], isValid: true }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ + row: ['A', 'B'], + isValid: true, }); }); - it('should resolve with an error if the transform throws an error', () => { + it('should resolve with an error if the transform throws an error', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); // eslint-disable-next-line @typescript-eslint/no-unused-vars transformer.rowTransform = (r: Row) => { throw new Error('Expected error'); }; - return transformAndValidate(row, transformer).then( - () => assert.fail('should have failed'), - err => assert.strictEqual(err.message, 'Expected error'), - ); + await expect(transformAndValidate(row, transformer)).rejects.toThrowError('Expected error'); }); - it('should transform a row asynchronously', () => { + it('should transform a row asynchronously', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowTransform = (r: Row, cb) => { @@ -78,12 +74,13 @@ describe('RowTransformerValidator', () => { ); }); }; - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row: ['A', 'B'], isValid: true }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ + row: ['A', 'B'], + isValid: true, }); }); - it('should resolve with an error if an error is provided to the callback', () => { + it('should resolve with an error if an error is provided to the callback', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowTransform = (r: Row, cb) => { @@ -91,33 +88,32 @@ describe('RowTransformerValidator', () => { cb(new Error('Expected error')); }); }; - return transformAndValidate(row, transformer).then( - () => assert.fail('should have failed'), - err => assert.strictEqual(err.message, 'Expected error'), - ); + await expect(transformAndValidate(row, transformer)).rejects.toThrowError('Expected error'); }); }); describe('#rowValidator', () => { it('should throw an error if the validator is not a function', () => { const transformer = createRowTransformerValidator(); - assert.throws(() => { + expect(() => { // @ts-ignore transformer.rowValidator = 'foo'; - }, /TypeError: The validate should be a function/); + }).toThrowError('The validate should be a function'); }); - it('should validate a row synchronously', () => { + it('should validate a row synchronously', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); // eslint-disable-next-line @typescript-eslint/no-unused-vars transformer.rowValidator = (r: Row) => false; - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row, isValid: false, reason: undefined }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ + row, + isValid: false, + reason: undefined, }); }); - it('should validate a row asynchronously', () => { + it('should validate a row asynchronously', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowValidator = (r: Row, cb) => { @@ -125,12 +121,14 @@ describe('RowTransformerValidator', () => { cb(null, false); }); }; - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row, isValid: false, reason: undefined }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ + row, + isValid: false, + reason: undefined, }); }); - it('should validate a row asynchronously with a reason', () => { + it('should validate a row asynchronously with a reason', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowValidator = (r: Row, cb) => { @@ -138,25 +136,24 @@ describe('RowTransformerValidator', () => { cb(null, false, 'just because'); }); }; - return transformAndValidate(row, transformer).then(results => { - assert.deepStrictEqual(results, { row, isValid: false, reason: 'just because' }); + await expect(transformAndValidate(row, transformer)).resolves.toEqual({ + row, + isValid: false, + reason: 'just because', }); }); - it('should resolve with an error if the validate throws an error', () => { + it('should resolve with an error if the validate throws an error', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); // eslint-disable-next-line @typescript-eslint/no-unused-vars transformer.rowValidator = (r: Row) => { throw new Error('Expected error'); }; - return transformAndValidate(row, transformer).then( - () => assert.fail('should have failed'), - err => assert.strictEqual(err.message, 'Expected error'), - ); + await expect(transformAndValidate(row, transformer)).rejects.toThrowError('Expected error'); }); - it('should resolve with an error if an error is provided to the callback', () => { + it('should resolve with an error if an error is provided to the callback', async () => { const row = ['a', 'b']; const transformer = createRowTransformerValidator(); transformer.rowValidator = (r: Row, cb) => { @@ -164,10 +161,7 @@ describe('RowTransformerValidator', () => { cb(new Error('Expected error')); }); }; - return transformAndValidate(row, transformer).then( - () => assert.fail('should have failed'), - err => assert.strictEqual(err.message, 'Expected error'), - ); + await expect(transformAndValidate(row, transformer)).rejects.toThrowError('Expected error'); }); }); }); diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..f865a7b8 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,11 @@ +// jest.config.js +module.exports = { + // [...] + // Replace `ts-jest` with the preset you want to use + // from the above list + preset: 'ts-jest', + collectCoverageFrom: [ + "src/**/*.ts" + ], + testMatch: [ "**/__tests__/**/*.spec.ts"], +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d7fd30dc..9155f394 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,57 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/core": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.7.tgz", + "integrity": "sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.7", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.7", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz", + "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz", + "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==", + "dev": true + } + } + }, "@babel/generator": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", @@ -45,6 +96,12 @@ "@babel/types": "^7.7.4" } }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, "@babel/helper-split-export-declaration": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", @@ -54,6 +111,17 @@ "@babel/types": "^7.7.4" } }, + "@babel/helpers": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", + "dev": true, + "requires": { + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, "@babel/highlight": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", @@ -71,6 +139,15 @@ "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==", "dev": true }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/template": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", @@ -130,12 +207,282 @@ "to-fast-properties": "^2.0.0" } }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "@istanbuljs/nyc-config-typescript": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-0.1.3.tgz", "integrity": "sha512-EzRFg92bRSD1W/zeuNkeGwph0nkWf+pP2l/lYW4/5hav7RjKKBN5kV1Ix7Tvi0CMu3pC4Wi/U7rNisiJMR3ORg==", "dev": true }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, "@sinonjs/commons": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", @@ -180,12 +527,87 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", + "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", + "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", "dev": true }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.24.tgz", + "integrity": "sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ==", + "dev": true, + "requires": { + "jest-diff": "^24.3.0" + } + }, "@types/json-schema": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", @@ -288,12 +710,6 @@ "@types/lodash": "*" } }, - "@types/mocha": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", - "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", - "dev": true - }, "@types/node": { "version": "12.12.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", @@ -311,6 +727,27 @@ "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", "dev": true }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.11.0.tgz", @@ -370,18 +807,48 @@ } } }, + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "dev": true + }, "acorn": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + } + } + }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -394,12 +861,6 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, "ansi-escapes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", @@ -424,6 +885,16 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, "append-transform": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", @@ -454,6 +925,30 @@ "sprintf-js": "~1.0.2" } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", @@ -490,6 +985,12 @@ } } }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, "array.prototype.flat": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.2.tgz", @@ -516,18 +1017,36 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -540,23 +1059,142 @@ "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", "dev": true }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", "dev": true, "requires": { - "tweetnacl": "^0.14.3" - } - }, - "brace-expansion": { - "version": "1.1.11", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, @@ -565,18 +1203,99 @@ "concat-map": "0.0.1" } }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", "dev": true }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, "caching-transform": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", @@ -627,6 +1346,15 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -667,6 +1395,29 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -693,12 +1444,28 @@ "wrap-ansi": "^2.0.0" } }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -736,6 +1503,12 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -763,6 +1536,12 @@ "safe-buffer": "~5.1.1" } }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -875,6 +1654,21 @@ } } }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -884,6 +1678,30 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -899,6 +1717,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -923,18 +1747,71 @@ "object-keys": "^1.0.12" } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -944,6 +1821,15 @@ "esutils": "^2.0.2" } }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1019,6 +1905,34 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, "eslint": { "version": "6.7.2", "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz", @@ -1333,6 +2247,12 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "exec-sh": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", + "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", + "dev": true + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -1348,12 +2268,103 @@ "strip-eof": "^1.0.0" } }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -1365,6 +2376,71 @@ "tmp": "^0.0.33" } }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -1395,6 +2471,15 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, "figures": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", @@ -1413,6 +2498,36 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -1444,15 +2559,6 @@ "locate-path": "^3.0.0" } }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -1481,6 +2587,12 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -1520,550 +2632,1918 @@ "mime-types": "^2.1.12" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handlebars": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", - "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", - "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "is-stream": "^1.0.1" + "map-cache": "^0.2.2" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "husky": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz", - "integrity": "sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ==", + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", "dev": true, + "optional": true, "requires": { - "chalk": "^2.4.2", - "ci-info": "^2.0.0", - "cosmiconfig": "^5.2.1", - "execa": "^1.0.0", - "get-stdin": "^7.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", - "please-upgrade-node": "^3.2.0", - "read-pkg": "^5.2.0", - "run-node": "^1.0.0", - "slash": "^3.0.0" + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" }, "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "abbrev": { + "version": "1.1.1", + "bundled": true, "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } + "optional": true }, - "locate-path": { - "version": "5.0.0", + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "handlebars": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "dev": true, + "requires": { + "is-stream": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "husky": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz", + "integrity": "sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "ci-info": "^2.0.0", + "cosmiconfig": "^5.2.1", + "execa": "^1.0.0", + "get-stdin": "^7.0.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "read-pkg": "^5.2.0", + "run-node": "^1.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", + "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } } + } + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, - "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" + "is-buffer": "^1.1.5" } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "find-up": "^4.0.0" + "is-buffer": "^1.1.5" } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "is-buffer": "^1.1.5" } - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true } } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "has-symbols": "^1.0.1" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "append-transform": "^1.0.0" } }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } }, - "inquirer": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", - "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==", + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", "dev": true, "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" + "handlebars": "^4.1.2" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + } }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", "dev": true }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", "dev": true, "requires": { - "has": "^1.0.1" + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0" + } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", "dev": true }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } }, - "istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", "dev": true, "requires": { - "append-transform": "^1.0.0" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" } }, - "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", "dev": true, "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" }, "dependencies": { "semver": { @@ -2074,65 +4554,96 @@ } } }, - "istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" }, "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, - "istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", "dev": true, "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true } } }, - "istanbul-reports": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", - "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "requires": { - "handlebars": "^4.1.2" + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "js-tokens": { @@ -2157,6 +4668,48 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2193,6 +4746,23 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2211,6 +4781,18 @@ "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -2226,6 +4808,18 @@ "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", "dev": true }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -2316,12 +4910,24 @@ "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, "lodash.partition": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.partition/-/lodash.partition-4.6.0.tgz", "integrity": "sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", @@ -2339,21 +4945,21 @@ "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, "lolex": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", "dev": true }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -2388,6 +4994,15 @@ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -2397,6 +5012,21 @@ "p-defer": "^1.0.0" } }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, "mem": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", @@ -2433,6 +5063,33 @@ } } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, "mime-db": { "version": "1.42.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", @@ -2469,147 +5126,36 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", - "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.0", - "yargs-parser": "13.1.1", - "yargs-unparser": "1.6.0" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "is-plain-object": "^2.0.4" } } } }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -2622,6 +5168,32 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2659,22 +5231,29 @@ "path-to-regexp": "^1.7.0" } }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", "dev": true, "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" } }, "normalize-package-data": { @@ -2689,6 +5268,15 @@ "validate-npm-package-license": "^3.0.1" } }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -2704,6 +5292,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, "nyc": { "version": "14.1.1", "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", @@ -2743,6 +5337,43 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "object-inspect": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", @@ -2755,6 +5386,15 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", @@ -2810,6 +5450,15 @@ "es-abstract": "^1.5.1" } }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, "object.values": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", @@ -2907,6 +5556,15 @@ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -2937,6 +5595,12 @@ "p-limit": "^2.0.0" } }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -2973,6 +5637,18 @@ "error-ex": "^1.2.0" } }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -3035,6 +5711,15 @@ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -3098,6 +5783,18 @@ "semver-compare": "^1.0.0" } }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -3119,12 +5816,42 @@ "fast-diff": "^1.1.2" } }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "prompts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", + "integrity": "sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.3" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -3159,6 +5886,12 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", + "dev": true + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -3225,6 +5958,25 @@ } } }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, "regexpp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", @@ -3240,6 +5992,24 @@ "es6-error": "^4.0.1" } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -3268,6 +6038,34 @@ "uuid": "^3.3.2" } }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3289,12 +6087,35 @@ "path-parse": "^1.0.6" } }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -3305,6 +6126,12 @@ "signal-exit": "^3.0.2" } }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -3314,6 +6141,12 @@ "glob": "^7.1.3" } }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -3344,12 +6177,52 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", @@ -3368,6 +6241,29 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -3383,6 +6279,12 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -3415,6 +6317,12 @@ } } }, + "sisteransi": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", + "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3432,12 +6340,153 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, "source-map-support": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", @@ -3456,6 +6505,12 @@ } } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "spawn-wrap": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", @@ -3502,6 +6557,15 @@ "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", "dev": true }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3525,6 +6589,49 @@ "tweetnacl": "~0.14.0" } }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -3576,21 +6683,12 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -3715,6 +6813,12 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -3730,12 +6834,66 @@ "os-tmpdir": "~1.0.2" } }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -3754,6 +6912,50 @@ } } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "ts-jest": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.2.0.tgz", + "integrity": "sha512-Yc+HLyldlIC9iIK8xEN7tV960Or56N49MDP7hubCZUeI7EbIOTsas6rXCMB4kQjLACJ7eDOF4xWEO5qumpKsag==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "mkdirp": "0.x", + "resolve": "1.x", + "semver": "^5.5", + "yargs-parser": "10.x" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, "ts-node": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.4.tgz", @@ -3852,6 +7054,58 @@ } } }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -3861,6 +7115,28 @@ "punycode": "^2.1.0" } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -3894,6 +7170,56 @@ "extsprintf": "^1.2.0" } }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -3909,15 +7235,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -3997,6 +7314,21 @@ "signal-exit": "^3.0.2" } }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -4066,101 +7398,6 @@ "decamelize": "^1.2.0" } }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 71bd2360..b0558dfe 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,14 @@ "types": "./build/src/index.d.ts", "scripts": { "prepare": "npm run build", - "build": "tsc", - "mocha": "nyc mocha", - "test": "npm run lint && npm run mocha", - "lint": "eslint --ext=.js,.ts src/ test/ examples/", - "lint-fix": "eslint --fix --ext=.js,.ts src/ test/ examples/", + "build": "npm run clean && tsc", + "clean": "rm -rf ./build", + "jest": "jest --coverage", + "test": "npm run lint && npm run jest", + "lint": "eslint --ext=.js,.ts src/ __tests__/ examples/", + "lint-fix": "eslint --fix --ext=.js,.ts src/ __tests__/ examples/", "benchmark": "node ./benchmark", - "coverage": "nyc report --reporter=text-lcov | coveralls" + "coverage": "jest --coverage --coverageReporters=text-lcov | coveralls" }, "files": [ "build/src/**" @@ -34,7 +35,9 @@ "license": "MIT", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^0.1.3", + "@types/jest": "^24.0.24", "@types/lodash.escaperegexp": "^4.1.6", + "@types/lodash.groupby": "^4.6.6", "@types/lodash.isboolean": "^3.0.6", "@types/lodash.isequal": "^4.5.5", "@types/lodash.isfunction": "^3.0.6", @@ -43,8 +46,6 @@ "@types/lodash.isundefined": "^3.0.6", "@types/lodash.partition": "^4.6.6", "@types/lodash.uniq": "^4.5.6", - "@types/lodash.groupby": "^4.6.6", - "@types/mocha": "^5.2.7", "@types/sinon": "^7.5.1", "@typescript-eslint/eslint-plugin": "^2.11.0", "@typescript-eslint/parser": "^2.11.0", @@ -55,12 +56,13 @@ "eslint-plugin-import": "^2.19.1", "eslint-plugin-prettier": "^3.1.1", "husky": "^3.1.0", + "jest": "^24.9.0", "lodash.partition": "^4.6.0", - "mocha": "^6.2.2", "nyc": "^14.1.1", "prettier": "^1.19.1", "sinon": "^7.5.0", "source-map-support": "^0.5.16", + "ts-jest": "^24.2.0", "ts-node": "^8.5.4", "typescript": "^3.7.3" }, diff --git a/test/formatter/CsvFormatterStream.test.ts b/test/formatter/CsvFormatterStream.test.ts deleted file mode 100644 index 79c1f4c8..00000000 --- a/test/formatter/CsvFormatterStream.test.ts +++ /dev/null @@ -1,923 +0,0 @@ -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as csv from '../../src'; -import { FormatterOptions, CsvFormatterStream } from '../../src/formatter'; -import RecordingStream from '../RecordingStream'; - -describe('CsvFormatterStream', () => { - const objectRows = [ - { a: 'a1', b: 'b1' }, - { a: 'a2', b: 'b2' }, - ]; - - const arrayRows = [ - ['a', 'b'], - ['a1', 'b1'], - ['a2', 'b2'], - ]; - - const multiDimensionalRows = [ - [ - ['a', 'a1'], - ['b', 'b1'], - ], - [ - ['a', 'a2'], - ['b', 'b2'], - ], - ]; - - const pipeToRecordingStream = (formatter: CsvFormatterStream, rows: csv.FormatterRow[]) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - formatter - .on('error', e => rej(e)) - .pipe(rs) - .on('finish', () => { - res(rs.data); - }); - rows.forEach(row => formatter.write(row)); - formatter.end(); - }); - - const formatRows = (rows: csv.FormatterRow[], options: csv.FormatterOptionsArgs = {}) => - pipeToRecordingStream(csv.format(options), rows); - - it('should write an array of arrays', () => - formatRows(arrayRows, { headers: true }).then(written => - assert.deepStrictEqual(written, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should write an array of objects', () => - formatRows(objectRows, { headers: true }).then(written => - assert.deepStrictEqual(written, ['a,b', '\na1,b1', '\na2,b2']), - )); - - describe('transform option', () => { - it('should support transforming an array of arrays', () => - formatRows(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }).then(written => assert.deepStrictEqual(written, ['A,B', '\nA1,B1', '\nA2,B2']))); - - it('should support transforming an array of multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]); - }, - }).then(written => { - assert.deepStrictEqual(written, ['a,b', '\nA1,B1', '\nA2,B2']); - })); - - it('should support transforming an array of objects', () => - formatRows(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { A: row.a, B: row.b }; - }, - }).then(written => assert.deepStrictEqual(written, ['A,B', '\na1,b1', '\na2,b2']))); - }); - describe('#transform', () => { - it('should support transforming an array of arrays', () => { - const formatter = new CsvFormatterStream( - new FormatterOptions({ headers: true }), - ).transform((row: csv.FormatterRow) => (row as csv.FormatterRowArray).map(entry => entry.toUpperCase())); - return pipeToRecordingStream(formatter, arrayRows).then(written => - assert.deepStrictEqual(written, ['A,B', '\nA1,B1', '\nA2,B2']), - ); - }); - - it('should support transforming an array of multi-dimensional arrays', () => { - const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( - (row: csv.FormatterRow): csv.FormatterRow => - (row as csv.FormatterRowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]), - ); - return pipeToRecordingStream(formatter, multiDimensionalRows).then(written => - assert.deepStrictEqual(written, ['a,b', '\nA1,B1', '\nA2,B2']), - ); - }); - - it('should support transforming an array of objects', () => { - const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( - (row: csv.FormatterRow): csv.FormatterRow => ({ - A: (row as csv.FormatterRowMap).a, - B: (row as csv.FormatterRowMap).b, - }), - ); - return pipeToRecordingStream(formatter, objectRows).then(written => - assert.deepStrictEqual(written, ['A,B', '\na1,b1', '\na2,b2']), - ); - }); - - it('should error if the transform fails', () => { - const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - (row: csv.FormatterRow): csv.FormatterRow => { - throw new Error('Expected error'); - }, - ); - return pipeToRecordingStream(formatter, objectRows).then( - () => assert.fail('Should have failed'), - err => { - assert.strictEqual(err.message, 'Expected error'); - }, - ); - }); - }); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - formatRows(objectRows, { - headers: true, - rowDelimiter: '\r\n', - }).then(written => assert.deepStrictEqual(written, ['a,b', '\r\na1,b1', '\r\na2,b2']))); - - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\n1', b: 'b1' }, - { a: 'a\n2', b: 'b2' }, - ]; - return formatRows(rows, { headers: true, rowDelimiter: '\n' }).then(written => - assert.deepStrictEqual(written, ['a,b', '\n"a\n1",b1', '\n"a\n2",b2']), - ); - }); - }); - - describe('quoteColumns option', () => { - describe('quote all columns and headers if quoteColumns is true and quoteHeaders is false', () => { - it('should work with objects', () => - formatRows(objectRows, { headers: true, quoteColumns: true }).then(written => - assert.deepStrictEqual(written, ['"a","b"', '\n"a1","b1"', '\n"a2","b2"']), - )); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteColumns: true }).then(written => - assert.deepStrictEqual(written, ['"a","b"', '\n"a1","b1"', '\n"a2","b2"']), - )); - - it('should work with multi-dimenional arrays', () => - formatRows(multiDimensionalRows, { headers: true, quoteColumns: true }).then(written => - assert.deepStrictEqual(written, ['"a","b"', '\n"a1","b1"', '\n"a2","b2"']), - )); - }); - - describe('quote headers if quoteHeaders is true and not columns is quoteColumns is undefined', () => { - it('should work with objects', () => - formatRows(objectRows, { headers: true, quoteHeaders: true }).then(written => - assert.deepStrictEqual(written, ['"a","b"', '\na1,b1', '\na2,b2']), - )); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteHeaders: true }).then(written => - assert.deepStrictEqual(written, ['"a","b"', '\na1,b1', '\na2,b2']), - )); - - it('should work with multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { headers: true, quoteHeaders: true }).then(written => - assert.deepStrictEqual(written, ['"a","b"', '\na1,b1', '\na2,b2']), - )); - }); - - describe('quote columns if quoteColumns is true and not quote headers if quoteHeaders is false', () => { - it('should work with objects', () => - formatRows(objectRows, { headers: true, quoteHeaders: false, quoteColumns: true }).then(written => - assert.deepStrictEqual(written, ['a,b', '\n"a1","b1"', '\n"a2","b2"']), - )); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteHeaders: false, quoteColumns: true }).then(written => - assert.deepStrictEqual(written, ['a,b', '\n"a1","b1"', '\n"a2","b2"']), - )); - - it('should work with multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { - headers: true, - quoteHeaders: false, - quoteColumns: true, - }).then(written => assert.deepStrictEqual(written, ['a,b', '\n"a1","b1"', '\n"a2","b2"']))); - }); - - describe('if quoteColumns object it should only quote the specified column and header', () => { - it('should work with objects', () => - formatRows(objectRows, { headers: true, quoteColumns: { a: true } }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\n"a1",b1', '\n"a2",b2']), - )); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteColumns: { a: true } }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\n"a1",b1', '\n"a2",b2']), - )); - - it('should work with multi dimensional arrays', () => - formatRows(multiDimensionalRows, { headers: true, quoteColumns: { a: true } }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\n"a1",b1', '\n"a2",b2']), - )); - }); - - describe('if quoteColumns object and quoteHeaders is false it should only quote the specified column and not the header', () => { - it('should work with objects', () => - formatRows(multiDimensionalRows, { - headers: true, - quoteHeaders: false, - quoteColumns: { a: true }, - }).then(written => assert.deepStrictEqual(written, ['a,b', '\n"a1",b1', '\n"a2",b2']))); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteHeaders: false, quoteColumns: { a: true } }).then(written => - assert.deepStrictEqual(written, ['a,b', '\n"a1",b1', '\n"a2",b2']), - )); - - it('should work with multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { - headers: true, - quoteHeaders: false, - quoteColumns: { a: true }, - }).then(written => assert.deepStrictEqual(written, ['a,b', '\n"a1",b1', '\n"a2",b2']))); - }); - - describe('if quoteColumns is an array it should only quote the specified column index', () => { - it('should work with objects', () => - formatRows(objectRows, { headers: true, quoteColumns: [true] }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\n"a1",b1', '\n"a2",b2']), - )); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteColumns: [true] }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\n"a1",b1', '\n"a2",b2']), - )); - - it('should work with multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { headers: true, quoteColumns: [true] }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\n"a1",b1', '\n"a2",b2']), - )); - }); - - describe('if quoteColumns is false and quoteHeaders is an object it should only quote the specified header and not the column', () => { - it('should work with object', () => - formatRows(objectRows, { - headers: true, - quoteHeaders: { a: true }, - quoteColumns: false, - }).then(written => assert.deepStrictEqual(written, ['"a",b', '\na1,b1', '\na2,b2']))); - - it('should work with arrays', () => - formatRows(arrayRows, { headers: true, quoteHeaders: { a: true }, quoteColumns: false }).then(written => - assert.deepStrictEqual(written, ['"a",b', '\na1,b1', '\na2,b2']), - )); - - it('should work with multi-dimenional arrays', () => - formatRows(multiDimensionalRows, { - headers: true, - quoteHeaders: { a: true }, - quoteColumns: false, - }).then(written => assert.deepStrictEqual(written, ['"a",b', '\na1,b1', '\na2,b2']))); - }); - - describe('if quoteColumns is an object and quoteHeaders is an object it should only quote the specified header and column', () => { - it('should work with objects', () => - formatRows(objectRows, { - headers: true, - quoteHeaders: { b: true }, - quoteColumns: { a: true }, - }).then(written => assert.deepStrictEqual(written, ['a,"b"', '\n"a1",b1', '\n"a2",b2']))); - - it('should work with arrays', () => - formatRows(arrayRows, { - headers: true, - quoteHeaders: { b: true }, - quoteColumns: { a: true }, - }).then(written => assert.deepStrictEqual(written, ['a,"b"', '\n"a1",b1', '\n"a2",b2']))); - - it('should work with multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { - headers: true, - quoteHeaders: { b: true }, - quoteColumns: { a: true }, - }).then(written => assert.deepStrictEqual(written, ['a,"b"', '\n"a1",b1', '\n"a2",b2']))); - }); - - describe('if quoteHeaders is an array and quoteColumns is an false it should only quote the specified header and not the column', () => { - it('should work with objects', () => - formatRows(objectRows, { - headers: true, - quoteHeaders: [false, true], - quoteColumns: false, - }).then(written => assert.deepStrictEqual(written, ['a,"b"', '\na1,b1', '\na2,b2']))); - - it('should work with arrays', () => - formatRows(arrayRows, { - headers: true, - quoteHeaders: [false, true], - quoteColumns: false, - }).then(written => assert.deepStrictEqual(written, ['a,"b"', '\na1,b1', '\na2,b2']))); - - it('should work with arrays of multi-dimensional arrays', () => - formatRows(multiDimensionalRows, { - headers: true, - quoteHeaders: [false, true], - quoteColumns: false, - }).then(written => assert.deepStrictEqual(written, ['a,"b"', '\na1,b1', '\na2,b2']))); - }); - }); - - describe('header option', () => { - it('should write an array of objects without headers', () => - formatRows(objectRows, { headers: false }).then(formatted => - assert.deepStrictEqual(formatted, ['a1,b1', '\na2,b2']), - )); - - it('should write an array of objects with headers', () => - formatRows(objectRows, { headers: true }).then(formatted => - assert.deepStrictEqual(formatted, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should write an array of arrays without headers', () => { - const rows = [ - ['a1', 'b1'], - ['a2', 'b2'], - ]; - return formatRows(rows, { headers: false }).then(formatted => - assert.deepStrictEqual(formatted, ['a1,b1', '\na2,b2']), - ); - }); - - it('should write an array of arrays with headers', () => - formatRows(arrayRows, { headers: true }).then(parsedCsv => - assert.deepStrictEqual(parsedCsv, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should write an array of multi-dimensional arrays without headers', () => - formatRows(multiDimensionalRows, { headers: false }).then(parsedCsv => - assert.deepStrictEqual(parsedCsv, ['a1,b1', '\na2,b2']), - )); - - it('should write an array of multi-dimensional arrays with headers', () => - formatRows(multiDimensionalRows, { headers: true }).then(parsedCsv => - assert.deepStrictEqual(parsedCsv, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should not write anything if headers are provided but no rows are provided', () => - formatRows([], { headers: true }).then(parsedCsv => assert.deepStrictEqual(parsedCsv, []))); - - describe('alwaysWriteHeaders option', () => { - it('should write the headers if rows are not provided', () => { - const headers = ['h1', 'h2']; - return formatRows([], { headers, alwaysWriteHeaders: true }).then(parsedCsv => - assert.deepStrictEqual(parsedCsv, [headers.join(',')]), - ); - }); - - it('should write the headers ones if rows are provided', () => { - const headers = ['h1', 'h2']; - return formatRows(arrayRows, { headers, alwaysWriteHeaders: true }).then(parsedCsv => - assert.deepStrictEqual(parsedCsv, [headers.join(','), '\na,b', '\na1,b1', '\na2,b2']), - ); - }); - - it('should fail if no headers are provided', () => { - return formatRows(arrayRows, { alwaysWriteHeaders: true }).catch(e => - assert.strictEqual( - e.message, - '`alwaysWriteHeaders` option is set to true but `headers` option not provided.', - ), - ); - }); - - it('should write the headers and an endRowDelimiter if includeEndRowDelimiter is true', () => { - const headers = ['h1', 'h2']; - return formatRows([], { - headers, - includeEndRowDelimiter: true, - alwaysWriteHeaders: true, - }).then(parsedCsv => assert.deepStrictEqual(parsedCsv, [headers.join(','), '\n'])); - }); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - formatRows(objectRows, { headers: true, includeEndRowDelimiter: true }).then(written => - assert.deepStrictEqual(written, ['a,b', '\na1,b1', '\na2,b2', '\n']), - )); - - it('should write a BOM character if writeBOM is true', () => - formatRows(objectRows, { headers: true, writeBOM: true }).then(written => - assert.deepStrictEqual(written, ['\ufeff', 'a,b', '\na1,b1', '\na2,b2']), - )); - - describe('.writeToString', () => { - it('should write an array of arrays', () => - csv - .writeToString(arrayRows, { headers: true }) - .then(formatted => assert.strictEqual(formatted, 'a,b\na1,b1\na2,b2'))); - - it('should support transforming an array of arrays', () => - csv - .writeToString(arrayRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }) - .then(formatted => assert.strictEqual(formatted, 'A,B\nA1,B1\nA2,B2'))); - - it('should write an array of multi-dimensional arrays', () => - csv - .writeToString(multiDimensionalRows, { headers: true }) - .then(formatted => assert.strictEqual(formatted, 'a,b\na1,b1\na2,b2'))); - - it('should support transforming an array of multi-dimensional arrays', () => - csv - .writeToString(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }) - .then(formatted => assert.strictEqual(formatted, 'a,b\nA1,B1\nA2,B2'))); - - it('should write an array of objects', () => - csv - .writeToString(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }) - .then(formatted => assert.strictEqual(formatted, 'A,B\na1,b1\na2,b2'))); - - describe('header option', () => { - it('should write an array of objects without headers', () => - csv - .writeToString(objectRows, { headers: false }) - .then(formatted => assert.strictEqual(formatted, 'a1,b1\na2,b2'))); - - it('should write an array of objects with headers', () => - csv - .writeToString(objectRows, { headers: true }) - .then(formatted => assert.strictEqual(formatted, 'a,b\na1,b1\na2,b2'))); - - it('should write an array of arrays without headers', () => { - const rows = [ - ['a1', 'b1'], - ['a2', 'b2'], - ]; - return csv - .writeToString(rows, { headers: false }) - .then(formatted => assert.strictEqual(formatted, 'a1,b1\na2,b2')); - }); - - it('should write an array of arrays with headers', () => - csv - .writeToString(arrayRows, { headers: true }) - .then(parsedCsv => assert.strictEqual(parsedCsv, 'a,b\na1,b1\na2,b2'))); - - it('should write an array of multi-dimensional arrays without headers', () => - csv - .writeToString(multiDimensionalRows, { headers: false }) - .then(parsedCsv => assert.strictEqual(parsedCsv, 'a1,b1\na2,b2'))); - - it('should write an array of multi-dimensional arrays with headers', () => - csv - .writeToString(multiDimensionalRows, { headers: true }) - .then(parsedCsv => assert.strictEqual(parsedCsv, 'a,b\na1,b1\na2,b2'))); - }); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - csv - .writeToString(objectRows, { headers: true, rowDelimiter: '\r\n' }) - .then(parsedCsv => assert.strictEqual(parsedCsv, 'a,b\r\na1,b1\r\na2,b2'))); - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\t1', b: 'b1' }, - { a: 'a\t2', b: 'b2' }, - ]; - return csv - .writeToString(rows, { headers: true, rowDelimiter: '\t' }) - .then(parsedCsv => assert.strictEqual(parsedCsv, 'a,b\t"a\t1",b1\t"a\t2",b2')); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - csv - .writeToString(objectRows, { headers: true, includeEndRowDelimiter: true }) - .then(parsedCsv => assert.strictEqual(parsedCsv, 'a,b\na1,b1\na2,b2\n'))); - }); - - describe('.writeToBuffer', () => { - it('should write an array of arrays', () => - csv - .writeToBuffer(arrayRows, { headers: true }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('a,b\na1,b1\na2,b2')))); - - it('should support transforming an array of arrays', () => - csv - .writeToBuffer(arrayRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('A,B\nA1,B1\nA2,B2')))); - - it('should write an array of multi-dimensional arrays', () => - csv - .writeToBuffer(multiDimensionalRows, { headers: true }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('a,b\na1,b1\na2,b2')))); - - it('should support transforming an array of multi-dimensional arrays', () => - csv - .writeToBuffer(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('a,b\nA1,B1\nA2,B2')))); - - it('should write an array of objects', () => - csv - .writeToBuffer(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap): csv.FormatterRow { - return { - A: row.a, - B: row.b, - }; - }, - }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('A,B\na1,b1\na2,b2')))); - - describe('header option', () => { - it('should write an array of objects without headers', () => - csv - .writeToBuffer(objectRows, { headers: false }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('a1,b1\na2,b2')))); - - it('should write an array of objects with headers', () => - csv - .writeToBuffer(objectRows, { headers: true }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('a,b\na1,b1\na2,b2')))); - - it('should write an array of arrays without headers', () => { - const rows = [ - ['a1', 'b1'], - ['a2', 'b2'], - ]; - return csv - .writeToBuffer(rows, { headers: false }) - .then(formatted => assert.deepStrictEqual(formatted, Buffer.from('a1,b1\na2,b2'))); - }); - - it('should write an array of arrays with headers', () => - csv - .writeToBuffer(arrayRows, { headers: true }) - .then(parsedCsv => assert.deepStrictEqual(parsedCsv, Buffer.from('a,b\na1,b1\na2,b2')))); - - it('should write an array of multi-dimensional arrays without headers', () => - csv - .writeToBuffer(multiDimensionalRows, { headers: false }) - .then(parsedCsv => assert.deepStrictEqual(parsedCsv, Buffer.from('a1,b1\na2,b2')))); - - it('should write an array of multi-dimensional arrays with headers', () => - csv - .writeToBuffer(multiDimensionalRows, { headers: true }) - .then(parsedCsv => assert.deepStrictEqual(parsedCsv, Buffer.from('a,b\na1,b1\na2,b2')))); - }); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - csv - .writeToBuffer(objectRows, { headers: true, rowDelimiter: '\r\n' }) - .then(parsedCsv => assert.deepStrictEqual(parsedCsv, Buffer.from('a,b\r\na1,b1\r\na2,b2')))); - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\t1', b: 'b1' }, - { a: 'a\t2', b: 'b2' }, - ]; - return csv - .writeToBuffer(rows, { headers: true, rowDelimiter: '\t' }) - .then(parsedCsv => assert.deepStrictEqual(parsedCsv, Buffer.from('a,b\t"a\t1",b1\t"a\t2",b2'))); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - csv - .writeToBuffer(objectRows, { headers: true, includeEndRowDelimiter: true }) - .then(parsedCsv => assert.deepStrictEqual(parsedCsv, Buffer.from('a,b\na1,b1\na2,b2\n')))); - }); - - describe('.write', () => { - const writeToRecordingStream = (rows: csv.FormatterRow[], options = {}) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - csv.write(rows, options) - .on('error', rej) - .pipe(rs) - .on('finish', () => { - res(rs.data); - }); - }); - - it('should write an array of arrays', () => - writeToRecordingStream(arrayRows, { headers: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of arrays', () => - writeToRecordingStream(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }).then(data => assert.deepStrictEqual(data, ['A,B', '\nA1,B1', '\nA2,B2']))); - - it('should write an array of multi-dimensional arrays', () => - writeToRecordingStream(multiDimensionalRows, { headers: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of multi-dimensional arrays', () => - writeToRecordingStream(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }).then(data => assert.deepStrictEqual(data, ['a,b', '\nA1,B1', '\nA2,B2']))); - - it('should write an array of objects', () => - writeToRecordingStream(objectRows, { headers: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of objects', () => - writeToRecordingStream(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }).then(data => assert.deepStrictEqual(data, ['A,B', '\na1,b1', '\na2,b2']))); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' }).then(data => - assert.deepStrictEqual(data, ['a,b', '\r\na1,b1', '\r\na2,b2']), - )); - - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\n1', b: 'b1' }, - { a: 'a\n2', b: 'b2' }, - ]; - return writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' }).then(data => - assert.deepStrictEqual(data, ['a,b', '\n"a\n1",b1', '\n"a\n2",b2']), - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2', '\n']), - )); - }); - - describe('.writeToPath', () => { - const writeToPath = (rows: csv.FormatterRow[], options = {}) => - new Promise((res, rej) => { - const csvPath = path.resolve(__dirname, 'assets/test_output.csv'); - csv.writeToPath(csvPath, rows, options) - .on('error', rej) - .on('finish', () => { - const content = fs.readFileSync(csvPath); - fs.unlinkSync(csvPath); - res(content); - }); - }); - - it('should write an array of arrays', () => - writeToPath(arrayRows, { headers: true }).then(content => - assert.deepStrictEqual(content, Buffer.from('a,b\na1,b1\na2,b2')), - )); - - it('should write an array of objects', () => - writeToPath(objectRows, { headers: true }).then(content => - assert.deepStrictEqual(content, Buffer.from('a,b\na1,b1\na2,b2')), - )); - - it('should write an array of multi-dimensional arrays', () => - writeToPath(multiDimensionalRows, { headers: true }).then(content => - assert.deepStrictEqual(content, Buffer.from('a,b\na1,b1\na2,b2')), - )); - - it('should support transforming an array of arrays', () => - writeToPath(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }).then(content => assert.deepStrictEqual(content, Buffer.from('A,B\nA1,B1\nA2,B2')))); - - it('should transforming an array of objects', () => - writeToPath(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }).then(content => assert.deepStrictEqual(content, Buffer.from('A,B\na1,b1\na2,b2')))); - - it('should transforming an array of multi-dimensional array', () => - writeToPath(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }).then(content => assert.deepStrictEqual(content, Buffer.from('a,b\nA1,B1\nA2,B2')))); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - writeToPath(objectRows, { headers: true, rowDelimiter: '\r\n' }).then(content => - assert.deepStrictEqual(content, Buffer.from('a,b\r\na1,b1\r\na2,b2')), - )); - - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\r\n1', b: 'b1' }, - { a: 'a\r\n2', b: 'b2' }, - ]; - return writeToPath(rows, { headers: true, rowDelimiter: '\r\n' }).then(content => - assert.deepStrictEqual(content, Buffer.from('a,b\r\n"a\r\n1",b1\r\n"a\r\n2",b2')), - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - writeToPath(objectRows, { headers: true, includeEndRowDelimiter: true }).then(content => - assert.deepStrictEqual(content, Buffer.from('a,b\na1,b1\na2,b2\n')), - )); - }); - - describe('.write', () => { - const writeToRecordingStream = (rows: csv.FormatterRow[], options = {}) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - csv.write(rows, options) - .on('error', rej) - .pipe(rs) - .on('finish', () => { - res(rs.data); - }); - }); - - it('should write an array of arrays', () => - writeToRecordingStream(arrayRows, { headers: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of arrays', () => - writeToRecordingStream(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }).then(data => assert.deepStrictEqual(data, ['A,B', '\nA1,B1', '\nA2,B2']))); - - it('should write an array of multi-dimensional arrays', () => - writeToRecordingStream(multiDimensionalRows, { headers: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of multi-dimensional arrays', () => - writeToRecordingStream(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }).then(data => assert.deepStrictEqual(data, ['a,b', '\nA1,B1', '\nA2,B2']))); - - it('should write an array of objects', () => - writeToRecordingStream(objectRows, { headers: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of objects', () => - writeToRecordingStream(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }).then(data => assert.deepStrictEqual(data, ['A,B', '\na1,b1', '\na2,b2']))); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' }).then(data => - assert.deepStrictEqual(data, ['a,b', '\r\na1,b1', '\r\na2,b2']), - )); - - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\n1', b: 'b1' }, - { a: 'a\n2', b: 'b2' }, - ]; - return writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' }).then(data => - assert.deepStrictEqual(data, ['a,b', '\n"a\n1",b1', '\n"a\n2",b2']), - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true }).then(data => - assert.deepStrictEqual(data, ['a,b', '\na1,b1', '\na2,b2', '\n']), - )); - }); - - describe('.writeToStream', () => { - const writeToStream = (rows: csv.FormatterRow[], options: csv.FormatterOptionsArgs = {}) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - csv.writeToStream(rs, rows, options); - rs.on('error', rej).on('finish', () => { - res(rs.data); - }); - }); - - it('should write an array of arrays', () => - writeToStream(arrayRows, { headers: true }).then(content => - assert.deepStrictEqual(content, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should write an array of objects', () => - writeToStream(objectRows, { headers: true }).then(content => - assert.deepStrictEqual(content, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should write an array of multi-dimensional arrays', () => - writeToStream(multiDimensionalRows, { headers: true }).then(content => - assert.deepStrictEqual(content, ['a,b', '\na1,b1', '\na2,b2']), - )); - - it('should support transforming an array of arrays', () => - writeToStream(arrayRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }).then(content => assert.deepStrictEqual(content, ['A,B', '\nA1,B1', '\nA2,B2']))); - - it('should transforming an array of objects', () => - writeToStream(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap): csv.FormatterRow { - return { - A: row.a, - B: row.b, - }; - }, - }).then(content => assert.deepStrictEqual(content, ['A,B', '\na1,b1', '\na2,b2']))); - - it('should transforming an array of multi-dimensional array', () => - writeToStream(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }).then(content => assert.deepStrictEqual(content, ['a,b', '\nA1,B1', '\nA2,B2']))); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - writeToStream(objectRows, { headers: true, rowDelimiter: '\r\n' }).then(content => - assert.deepStrictEqual(content, ['a,b', '\r\na1,b1', '\r\na2,b2']), - )); - - it('should escape values that contain the alternate row delimiter', () => { - const rows = [ - { a: 'a\r\n1', b: 'b1' }, - { a: 'a\r\n2', b: 'b2' }, - ]; - return writeToStream(rows, { headers: true, rowDelimiter: '\r\n' }).then(content => - assert.deepStrictEqual(content, ['a,b', '\r\n"a\r\n1",b1', '\r\n"a\r\n2",b2']), - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - writeToStream(objectRows, { headers: true, includeEndRowDelimiter: true }).then(content => - assert.deepStrictEqual(content, ['a,b', '\na1,b1', '\na2,b2', '\n']), - )); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index ac8f6922..e7bfd658 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,6 +22,6 @@ ], "include": [ "src/**/*.ts", - "test/**/*.ts" + "__tests__/**/*.ts" ] } \ No newline at end of file From 99d8e8d5edd4896b78de4931bfbe65c588296798 Mon Sep 17 00:00:00 2001 From: doug-martin Date: Sat, 21 Dec 2019 18:14:09 -0600 Subject: [PATCH 2/8] Updating version --- History.md | 4 ++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index ceee9fdc..4207e5c7 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +# v4.0.0 + +* Migrated from mocha to jest + # v3.7.0 * [ADDED] Ability to Transform Header [#287](https://github.com/C2FO/fast-csv/issues/287) diff --git a/package-lock.json b/package-lock.json index 9155f394..aeb39af1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "fast-csv", - "version": "3.7.0", + "version": "4.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b0558dfe..1b91565f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fast-csv", - "version": "3.7.0", + "version": "4.0.0", "description": "CSV parser and writer", "main": "./build/src/index.js", "types": "./build/src/index.d.ts", From 5c9f055daf5efa1a7f76dca84ab29d2a949d2b4f Mon Sep 17 00:00:00 2001 From: doug-martin Date: Mon, 23 Dec 2019 17:58:34 -0600 Subject: [PATCH 3/8] Moved to lerna * Moved to `lerna`. * Split `parse` and `format` packages * Added running examples and checking output as part of the tests * Updated docs --- .eslintrc.js | 5 +- .github/ISSUE_TEMPLATE/bug_report.md | 5 + .github/ISSUE_TEMPLATE/feature_request.md | 5 + .gitignore | 4 +- .travis.yml | 5 + History.md | 4 + README.md | 50 +- .../formatter/CsvFormatterStream.spec.ts | 906 -- __tests__/parser/__fixtures__/index.ts | 53 - .../benchmark}/.eslintrc.js | 0 .../benchmark}/assets/100000.nonquoted.csv | 0 .../benchmark}/assets/100000.quoted.csv | 0 .../benchmark}/assets/20000.nonquoted.csv | 0 .../benchmark}/assets/20000.quoted.csv | 0 .../benchmark}/assets/50000.nonquoted.csv | 0 .../benchmark}/assets/50000.quoted.csv | 0 .../benchmark}/createData.js | 28 +- {benchmark => examples/benchmark}/index.js | 4 +- examples/benchmark/package.json | 11 + examples/example-runner/bin/run-examples | 81 + examples/example-runner/package.json | 14 + examples/{ => fast-csv-js}/.eslintrc.js | 0 examples/fast-csv-js/README.md | 144 + .../fast-csv-js/examples/assets/parse.csv | 6 + .../examples}/assets/snake_case_users.csv | 0 .../fast-csv-js/examples/format.example.js | 18 + .../{ => fast-csv-js/examples}/models/user.js | 0 .../fast-csv-js/examples/parse.example.js | 17 + ...arse_and_format_transform_async.example.js | 14 +- examples/fast-csv-js/package-lock.json | 568 ++ examples/fast-csv-js/package.json | 13 + examples/formatting-js/.eslintrc.js | 8 + .../formatting-js/README.md | 411 +- .../examples}/append.example.js | 11 +- .../examples}/delimiter_option.example.js | 7 +- .../examples}/escape_option.example.js | 7 +- .../examples}/format.example.js | 7 +- .../examples}/hash_array.example.js | 9 +- ...aders_auto_discovery_hash_array.example.js | 9 +- .../headers_auto_discovery_object.example.js | 9 +- .../headers_provided_array.example.js | 9 +- .../headers_provided_hash_array.example.js | 9 +- .../headers_provided_object.example.js | 9 +- ...s_provided_object_remove_column.example.js | 9 +- .../examples}/quote_all_columns.example.js | 9 +- .../examples}/quote_all_headers.example.js | 9 +- .../examples}/quote_columns_array.example.js | 9 +- .../quote_columns_not_headers.example.js | 9 +- .../examples}/quote_columns_object.example.js | 9 +- .../examples}/quote_headers_array.example.js | 9 +- .../examples}/quote_headers_object.example.js | 9 +- .../examples/quote_option.example.js} | 7 +- .../quote_some_columns_and_headers.example.js | 9 +- .../examples}/row_delimiter_option.example.js | 5 +- .../formatting-js/examples/tmp}/.gitkeep | 0 .../examples}/transform.example.js | 9 +- .../examples}/transform_async.example.js | 9 +- .../examples}/transform_option.example.js | 9 +- .../examples}/write.example.js | 7 +- .../examples}/write_to_buffer.example.js | 7 +- .../examples/write_to_path.example.js | 22 + .../examples}/write_to_stream.example.js | 7 +- .../examples}/write_to_string.example.js | 7 +- .../write_to_string_no_headers.example.js | 6 +- .../write_to_string_transform.example.js | 7 +- examples/formatting-js/package.json | 13 + examples/formatting/write_to_path.example.js | 11 - examples/parsing-js/.eslintrc.js | 8 + .../parsing-js/README.md | 336 +- .../parsing-js/assets/snake_case_users.csv | 10 + .../examples}/alternate_delimiter.example.js | 7 +- .../examples}/custom_headers.example.js | 7 +- .../examples}/first_row_as_headers.example.js | 7 +- .../examples}/ignore_empty_rows.example.js | 7 +- .../examples}/manual_write.example.js | 6 +- .../examples}/max_rows.example.js | 10 +- .../examples}/parse_string.example.js | 9 +- examples/parsing-js/examples/pipe.example.js | 22 + .../examples}/rename_headers.example.js | 7 +- .../examples}/skip_lines.example.js | 9 +- .../examples}/skip_rows.example.js | 9 +- .../examples}/skipping_columns.example.js | 7 +- .../examples}/transform.example.js | 8 +- .../examples}/transform_async.example.js | 8 +- .../examples}/transform_headers.example.js | 7 +- .../examples}/validate.example.js | 8 +- .../examples}/validate_async.example.js | 8 +- .../examples}/validate_with_reason.example.js | 8 +- examples/parsing-js/package-lock.json | 568 ++ examples/parsing-js/package.json | 15 + examples/parsing/pipe.example.js | 9 - jest.config.js | 8 +- lerna.json | 7 + package-lock.json | 8943 ++++++++++++----- package.json | 66 +- packages/fast-csv/.eslintrc.js | 5 + packages/fast-csv/README.md | 31 + packages/fast-csv/__tests__/fast-csv.spec.ts | 10 + packages/fast-csv/package.json | 44 + {src => packages/fast-csv/src}/index.ts | 23 +- packages/fast-csv/tsconfig.build.json | 11 + packages/fast-csv/tsconfig.json | 4 + packages/format/.eslintrc.js | 5 + packages/format/README.md | 252 + .../__tests__/CsvFormatterStream.spec.ts | 347 + .../__tests__}/FormatterOptions.spec.ts | 4 +- .../format/__tests__/__fixtures__/.gitkeep | 0 .../__fixtures__}/RecordingStream.ts | 2 +- .../format/__tests__/__fixtures__/index.ts | 22 + packages/format/__tests__/format.spec.ts | 538 + .../formatter/FieldFormatter.spec.ts | 4 +- .../__tests__}/formatter/RowFormatter.spec.ts | 11 +- .../__tests__/issues/__fixtures__/.gitkeep | 0 .../format/__tests__}/issues/issue158.spec.ts | 2 +- .../format/__tests__}/issues/issue252.spec.ts | 2 +- .../format/__tests__}/issues/issue77.spec.ts | 0 .../format/__tests__}/issues/issue97.spec.ts | 6 +- packages/format/package-lock.json | 84 + packages/format/package.json | 51 + .../format/src}/CsvFormatterStream.ts | 4 +- .../format/src}/FormatterOptions.ts | 0 .../format/src}/formatter/FieldFormatter.ts | 2 +- .../format/src}/formatter/RowFormatter.ts | 4 +- packages/format/src/formatter/index.ts | 2 + .../format/src}/index.ts | 7 +- .../format/src}/types.ts | 0 packages/format/tsconfig.build.json | 7 + packages/format/tsconfig.json | 4 + packages/parse/.eslintrc.js | 5 + packages/parse/README.md | 184 + .../parse/__tests__}/CsvParsingStream.spec.ts | 435 +- .../parse/__tests__}/ParserOptions.spec.ts | 4 +- .../__tests__/__fixtures__/RecordingStream.ts | 14 + .../__fixtures__/alternateEncoding.ts | 2 +- .../__fixtures__/duplicateHeaders.ts | 2 +- .../__tests__}/__fixtures__/emptyRows.ts | 2 +- .../__fixtures__/headerColumnMismatch.ts | 2 +- .../parse/__tests__/__fixtures__/helpers.ts | 55 + .../parse/__tests__/__fixtures__/index.ts | 32 + .../__tests__}/__fixtures__/malformed.ts | 2 +- .../__fixtures__/noHeadersAndQuotes.ts | 2 +- .../__tests__}/__fixtures__/skipLines.ts | 2 +- .../__tests__}/__fixtures__/trailingComma.ts | 2 +- .../__tests__}/__fixtures__/withHeaders.ts | 2 +- .../withHeadersAlternateDelimiter.ts | 2 +- .../withHeadersAndAlternateQuote.ts | 2 +- .../withHeadersAndMissingColumns.ts | 2 +- .../__fixtures__/withHeadersAndQuotes.ts | 2 +- .../withHeadersAndSkippedLines.ts | 2 +- .../issues/__fixtures__/issue102.csv | 0 .../issues/__fixtures__/issue68-invalid.tsv | 0 .../issues/__fixtures__/issue68.tsv | 0 .../issues/__fixtures__/issue87.csv | 0 .../parse/__tests__}/issues/issue102.spec.ts | 0 .../parse/__tests__}/issues/issue111.spec.ts | 3 +- .../parse/__tests__}/issues/issue131.spec.ts | 2 +- .../parse/__tests__}/issues/issue150.spec.ts | 3 +- .../parse/__tests__}/issues/issue174.spec.ts | 3 +- .../parse/__tests__}/issues/issue214.spec.ts | 8 +- .../parse/__tests__}/issues/issue223.spec.ts | 3 +- .../parse/__tests__}/issues/issue68.spec.ts | 0 .../parse/__tests__}/issues/issue87.spec.ts | 2 +- .../parse/__tests__}/issues/issue93.spec.ts | 0 packages/parse/__tests__/parse.spec.ts | 30 + .../parse/__tests__}/parser/Parser.spec.ts | 5 +- .../parse/__tests__}/parser/RowParser.spec.ts | 5 +- .../parse/__tests__}/parser/Scanner.spec.ts | 5 +- .../parser/column/ColumnParser.spec.ts | 4 +- .../column/NonQuotedColumnParser.spec.ts | 6 +- .../parser/column/QuotedColumnParser.spec.ts | 6 +- .../transforms/HeaderTransformer.spec.ts | 5 +- .../RowTransformerValidator.spec.ts | 4 +- packages/parse/package-lock.json | 260 + packages/parse/package.json | 58 + .../parse/src}/CsvParserStream.ts | 2 +- .../parse/src}/ParserOptions.ts | 0 {src/parser => packages/parse/src}/index.ts | 8 +- .../parse/src}/parser/Parser.ts | 4 +- .../parse/src}/parser/RowParser.ts | 2 +- .../parse/src}/parser/Scanner.ts | 0 .../parse/src}/parser/Token.ts | 0 .../src}/parser/column/ColumnFormatter.ts | 2 +- .../parse/src}/parser/column/ColumnParser.ts | 6 +- .../parser/column/NonQuotedColumnParser.ts | 4 +- .../src}/parser/column/QuotedColumnParser.ts | 4 +- packages/parse/src/parser/column/index.ts | 4 + .../parse/src}/parser/index.ts | 4 +- .../src}/transforms/HeaderTransformer.ts | 2 +- .../transforms/RowTransformerValidator.ts | 2 +- packages/parse/src/transforms/index.ts | 2 + {src/parser => packages/parse/src}/types.ts | 0 packages/parse/tsconfig.build.json | 11 + packages/parse/tsconfig.json | 4 + src/formatter/formatter/index.ts | 2 - src/parser/parser/column/index.ts | 4 - src/parser/transforms/index.ts | 2 - tsconfig.build.json | 24 + tsconfig.json | 36 +- 198 files changed, 11205 insertions(+), 4372 deletions(-) delete mode 100644 __tests__/formatter/CsvFormatterStream.spec.ts delete mode 100644 __tests__/parser/__fixtures__/index.ts rename {benchmark => examples/benchmark}/.eslintrc.js (100%) rename {benchmark => examples/benchmark}/assets/100000.nonquoted.csv (100%) rename {benchmark => examples/benchmark}/assets/100000.quoted.csv (100%) rename {benchmark => examples/benchmark}/assets/20000.nonquoted.csv (100%) rename {benchmark => examples/benchmark}/assets/20000.quoted.csv (100%) rename {benchmark => examples/benchmark}/assets/50000.nonquoted.csv (100%) rename {benchmark => examples/benchmark}/assets/50000.quoted.csv (100%) rename {benchmark => examples/benchmark}/createData.js (60%) rename {benchmark => examples/benchmark}/index.js (96%) create mode 100644 examples/benchmark/package.json create mode 100755 examples/example-runner/bin/run-examples create mode 100644 examples/example-runner/package.json rename examples/{ => fast-csv-js}/.eslintrc.js (100%) create mode 100644 examples/fast-csv-js/README.md create mode 100644 examples/fast-csv-js/examples/assets/parse.csv rename examples/{ => fast-csv-js/examples}/assets/snake_case_users.csv (100%) create mode 100644 examples/fast-csv-js/examples/format.example.js rename examples/{ => fast-csv-js/examples}/models/user.js (100%) create mode 100644 examples/fast-csv-js/examples/parse.example.js rename examples/{ => fast-csv-js/examples}/parse_and_format_transform_async.example.js (61%) create mode 100644 examples/fast-csv-js/package-lock.json create mode 100644 examples/fast-csv-js/package.json create mode 100644 examples/formatting-js/.eslintrc.js rename docs/formatting.md => examples/formatting-js/README.md (59%) rename examples/{formatting => formatting-js/examples}/append.example.js (92%) rename examples/{formatting => formatting-js/examples}/delimiter_option.example.js (69%) rename examples/{formatting => formatting-js/examples}/escape_option.example.js (67%) rename examples/{formatting => formatting-js/examples}/format.example.js (66%) rename examples/{formatting => formatting-js/examples}/hash_array.example.js (74%) rename examples/{formatting => formatting-js/examples}/headers_auto_discovery_hash_array.example.js (74%) rename examples/{formatting => formatting-js/examples}/headers_auto_discovery_object.example.js (71%) rename examples/{formatting => formatting-js/examples}/headers_provided_array.example.js (67%) rename examples/{formatting => formatting-js/examples}/headers_provided_hash_array.example.js (73%) rename examples/{formatting => formatting-js/examples}/headers_provided_object.example.js (72%) rename examples/{formatting => formatting-js/examples}/headers_provided_object_remove_column.example.js (77%) rename examples/{formatting => formatting-js/examples}/quote_all_columns.example.js (69%) rename examples/{formatting => formatting-js/examples}/quote_all_headers.example.js (71%) rename examples/{formatting => formatting-js/examples}/quote_columns_array.example.js (72%) rename examples/{formatting => formatting-js/examples}/quote_columns_not_headers.example.js (73%) rename examples/{formatting => formatting-js/examples}/quote_columns_object.example.js (71%) rename examples/{formatting => formatting-js/examples}/quote_headers_array.example.js (73%) rename examples/{formatting => formatting-js/examples}/quote_headers_object.example.js (72%) rename examples/{formatting/quote_option.examples.js => formatting-js/examples/quote_option.example.js} (69%) rename examples/{formatting => formatting-js/examples}/quote_some_columns_and_headers.example.js (73%) rename examples/{formatting => formatting-js/examples}/row_delimiter_option.example.js (70%) rename {__tests__/formatter/__fixtures__ => examples/formatting-js/examples/tmp}/.gitkeep (100%) rename examples/{formatting => formatting-js/examples}/transform.example.js (76%) rename examples/{formatting => formatting-js/examples}/transform_async.example.js (78%) rename examples/{formatting => formatting-js/examples}/transform_option.example.js (76%) rename examples/{formatting => formatting-js/examples}/write.example.js (58%) rename examples/{formatting => formatting-js/examples}/write_to_buffer.example.js (64%) create mode 100644 examples/formatting-js/examples/write_to_path.example.js rename examples/{formatting => formatting-js/examples}/write_to_stream.example.js (58%) rename examples/{formatting => formatting-js/examples}/write_to_string.example.js (62%) rename examples/{formatting => formatting-js/examples}/write_to_string_no_headers.example.js (80%) rename examples/{ => formatting-js/examples}/write_to_string_transform.example.js (78%) create mode 100644 examples/formatting-js/package.json delete mode 100644 examples/formatting/write_to_path.example.js create mode 100644 examples/parsing-js/.eslintrc.js rename docs/parsing.md => examples/parsing-js/README.md (56%) create mode 100644 examples/parsing-js/assets/snake_case_users.csv rename examples/{parsing => parsing-js/examples}/alternate_delimiter.example.js (76%) rename examples/{parsing => parsing-js/examples}/custom_headers.example.js (74%) rename examples/{parsing => parsing-js/examples}/first_row_as_headers.example.js (74%) rename examples/{parsing => parsing-js/examples}/ignore_empty_rows.example.js (77%) rename examples/{parsing => parsing-js/examples}/manual_write.example.js (72%) rename examples/{parsing => parsing-js/examples}/max_rows.example.js (65%) rename examples/{parsing => parsing-js/examples}/parse_string.example.js (60%) create mode 100644 examples/parsing-js/examples/pipe.example.js rename examples/{parsing => parsing-js/examples}/rename_headers.example.js (76%) rename examples/{parsing => parsing-js/examples}/skip_lines.example.js (67%) rename examples/{parsing => parsing-js/examples}/skip_rows.example.js (65%) rename examples/{parsing => parsing-js/examples}/skipping_columns.example.js (75%) rename examples/{parsing => parsing-js/examples}/transform.example.js (67%) rename examples/{parsing => parsing-js/examples}/transform_async.example.js (71%) rename examples/{parsing => parsing-js/examples}/transform_headers.example.js (73%) rename examples/{parsing => parsing-js/examples}/validate.example.js (70%) rename examples/{parsing => parsing-js/examples}/validate_async.example.js (71%) rename examples/{parsing => parsing-js/examples}/validate_with_reason.example.js (74%) create mode 100644 examples/parsing-js/package-lock.json create mode 100644 examples/parsing-js/package.json delete mode 100644 examples/parsing/pipe.example.js create mode 100644 lerna.json create mode 100644 packages/fast-csv/.eslintrc.js create mode 100644 packages/fast-csv/README.md create mode 100644 packages/fast-csv/__tests__/fast-csv.spec.ts create mode 100644 packages/fast-csv/package.json rename {src => packages/fast-csv/src}/index.ts (61%) create mode 100644 packages/fast-csv/tsconfig.build.json create mode 100644 packages/fast-csv/tsconfig.json create mode 100644 packages/format/.eslintrc.js create mode 100644 packages/format/README.md create mode 100644 packages/format/__tests__/CsvFormatterStream.spec.ts rename {__tests__/formatter => packages/format/__tests__}/FormatterOptions.spec.ts (98%) rename examples/parsing/ignore_empty.example.js => packages/format/__tests__/__fixtures__/.gitkeep (100%) rename {__tests__ => packages/format/__tests__/__fixtures__}/RecordingStream.ts (82%) create mode 100644 packages/format/__tests__/__fixtures__/index.ts create mode 100644 packages/format/__tests__/format.spec.ts rename {__tests__/formatter => packages/format/__tests__}/formatter/FieldFormatter.spec.ts (97%) rename {__tests__/formatter => packages/format/__tests__}/formatter/RowFormatter.spec.ts (98%) create mode 100644 packages/format/__tests__/issues/__fixtures__/.gitkeep rename {__tests__ => packages/format/__tests__}/issues/issue158.spec.ts (95%) rename {__tests__ => packages/format/__tests__}/issues/issue252.spec.ts (92%) rename {__tests__ => packages/format/__tests__}/issues/issue77.spec.ts (100%) rename {__tests__ => packages/format/__tests__}/issues/issue97.spec.ts (78%) create mode 100644 packages/format/package-lock.json create mode 100644 packages/format/package.json rename {src/formatter => packages/format/src}/CsvFormatterStream.ts (94%) rename {src/formatter => packages/format/src}/FormatterOptions.ts (100%) rename {src/formatter => packages/format/src}/formatter/FieldFormatter.ts (98%) rename {src/formatter => packages/format/src}/formatter/RowFormatter.ts (98%) create mode 100644 packages/format/src/formatter/index.ts rename {src/formatter => packages/format/src}/index.ts (91%) rename {src/formatter => packages/format/src}/types.ts (100%) create mode 100644 packages/format/tsconfig.build.json create mode 100644 packages/format/tsconfig.json create mode 100644 packages/parse/.eslintrc.js create mode 100644 packages/parse/README.md rename {__tests__/parser => packages/parse/__tests__}/CsvParsingStream.spec.ts (53%) rename {__tests__/parser => packages/parse/__tests__}/ParserOptions.spec.ts (98%) create mode 100644 packages/parse/__tests__/__fixtures__/RecordingStream.ts rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/alternateEncoding.ts (96%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/duplicateHeaders.ts (89%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/emptyRows.ts (96%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/headerColumnMismatch.ts (93%) create mode 100644 packages/parse/__tests__/__fixtures__/helpers.ts create mode 100644 packages/parse/__tests__/__fixtures__/index.ts rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/malformed.ts (93%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/noHeadersAndQuotes.ts (97%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/skipLines.ts (97%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/trailingComma.ts (98%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/withHeaders.ts (98%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/withHeadersAlternateDelimiter.ts (97%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/withHeadersAndAlternateQuote.ts (98%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/withHeadersAndMissingColumns.ts (95%) rename {__tests__/parser => packages/parse/__tests__}/__fixtures__/withHeadersAndQuotes.ts (98%) rename __tests__/parser/__fixtures__/withHeadersSkippedLines.ts => packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts (97%) rename {__tests__ => packages/parse/__tests__}/issues/__fixtures__/issue102.csv (100%) rename {__tests__ => packages/parse/__tests__}/issues/__fixtures__/issue68-invalid.tsv (100%) rename {__tests__ => packages/parse/__tests__}/issues/__fixtures__/issue68.tsv (100%) rename {__tests__ => packages/parse/__tests__}/issues/__fixtures__/issue87.csv (100%) rename {__tests__ => packages/parse/__tests__}/issues/issue102.spec.ts (100%) rename {__tests__ => packages/parse/__tests__}/issues/issue111.spec.ts (97%) rename {__tests__ => packages/parse/__tests__}/issues/issue131.spec.ts (93%) rename {__tests__ => packages/parse/__tests__}/issues/issue150.spec.ts (87%) rename {__tests__ => packages/parse/__tests__}/issues/issue174.spec.ts (89%) rename {__tests__ => packages/parse/__tests__}/issues/issue214.spec.ts (86%) rename {__tests__ => packages/parse/__tests__}/issues/issue223.spec.ts (88%) rename {__tests__ => packages/parse/__tests__}/issues/issue68.spec.ts (100%) rename {__tests__ => packages/parse/__tests__}/issues/issue87.spec.ts (93%) rename {__tests__ => packages/parse/__tests__}/issues/issue93.spec.ts (100%) create mode 100644 packages/parse/__tests__/parse.spec.ts rename {__tests__/parser => packages/parse/__tests__}/parser/Parser.spec.ts (99%) rename {__tests__/parser => packages/parse/__tests__}/parser/RowParser.spec.ts (97%) rename {__tests__/parser => packages/parse/__tests__}/parser/Scanner.spec.ts (98%) rename {__tests__/parser => packages/parse/__tests__}/parser/column/ColumnParser.spec.ts (91%) rename {__tests__/parser => packages/parse/__tests__}/parser/column/NonQuotedColumnParser.spec.ts (96%) rename {__tests__/parser => packages/parse/__tests__}/parser/column/QuotedColumnParser.spec.ts (99%) rename {__tests__/parser => packages/parse/__tests__}/transforms/HeaderTransformer.spec.ts (97%) rename {__tests__/parser => packages/parse/__tests__}/transforms/RowTransformerValidator.spec.ts (97%) create mode 100644 packages/parse/package-lock.json create mode 100644 packages/parse/package.json rename {src/parser => packages/parse/src}/CsvParserStream.ts (99%) rename {src/parser => packages/parse/src}/ParserOptions.ts (100%) rename {src/parser => packages/parse/src}/index.ts (81%) rename {src/parser => packages/parse/src}/parser/Parser.ts (97%) rename {src/parser => packages/parse/src}/parser/RowParser.ts (98%) rename {src/parser => packages/parse/src}/parser/Scanner.ts (100%) rename {src/parser => packages/parse/src}/parser/Token.ts (100%) rename {src/parser => packages/parse/src}/parser/column/ColumnFormatter.ts (93%) rename {src/parser => packages/parse/src}/parser/column/ColumnParser.ts (86%) rename {src/parser => packages/parse/src}/parser/column/NonQuotedColumnParser.ts (92%) rename {src/parser => packages/parse/src}/parser/column/QuotedColumnParser.ts (98%) create mode 100644 packages/parse/src/parser/column/index.ts rename {src/parser => packages/parse/src}/parser/index.ts (62%) rename {src/parser => packages/parse/src}/transforms/HeaderTransformer.ts (99%) rename {src/parser => packages/parse/src}/transforms/RowTransformerValidator.ts (98%) create mode 100644 packages/parse/src/transforms/index.ts rename {src/parser => packages/parse/src}/types.ts (100%) create mode 100644 packages/parse/tsconfig.build.json create mode 100644 packages/parse/tsconfig.json delete mode 100644 src/formatter/formatter/index.ts delete mode 100644 src/parser/parser/column/index.ts delete mode 100644 src/parser/transforms/index.ts create mode 100644 tsconfig.build.json diff --git a/.eslintrc.js b/.eslintrc.js index 6b32f758..e6665952 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { parser: "@typescript-eslint/parser", parserOptions: { - project: "./tsconfig.json" + project: "./tsconfig.build.json" }, plugins: ["@typescript-eslint", "prettier"], extends: [ @@ -16,6 +16,7 @@ module.exports = { node: true, jest: true, }, + ignorePatterns: ["**/build", "**/node_modules"], settings:{ "import/extensions": [ ".ts" @@ -51,6 +52,8 @@ module.exports = { 4, { "SwitchCase": 1 } ], + "import/prefer-default-export": 0, + "import/no-default-export": ["error"], "no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"], "object-curly-spacing": ["error", "always"], "no-underscore-dangle": 0, diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2e093eda..3b83032c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,6 +10,11 @@ assignees: doug-martin, dustinsmith1024 **Describe the bug** A clear and concise description of what the bug is. +**Parsing or Formatting?** + + - [ ] Formatting + - [ ] Parsing + **To Reproduce** Steps to reproduce the behavior: 1. Example file contents if applicable diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 5051d951..4a01a61e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,6 +7,11 @@ assignees: doug-martin, dustinsmith1024 --- +**Parsing or Formatting?** + + - [ ] Formatting + - [ ] Parsing + **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] diff --git a/.gitignore b/.gitignore index f3d42d69..780a0a50 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ node_modules benchmark/results .nyc_output build -**/tmp -coverage \ No newline at end of file +coverage +**/tmp/*.csv \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index ddc392f2..451de0fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,9 @@ node_js: - "10" - "8" +script: + - npm run bootstrap + - npm run build + - npm run test + after_success: npm run coverage \ No newline at end of file diff --git a/History.md b/History.md index 4207e5c7..18afa570 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,10 @@ # v4.0.0 * Migrated from mocha to jest +* Moved to `lerna`. + * Split `parse` and `format` packages +* Added running examples and checking output as part of the tests +* Updated docs # v3.7.0 diff --git a/README.md b/README.md index b646bb97..3ea08289 100644 --- a/README.md +++ b/README.md @@ -11,50 +11,25 @@ Fast-csv is library for parsing and formatting csvs or any other delimited value `npm install -S fast-csv` -## Usage +## Packages -To use `fast-csv` in `javascript` you can require the module/ +There are three packages published from this repo. -```js -const csv = require('fast-csv'); -``` - -To import with typescript - -```typescript -import * as csv from 'fast-csv'; -``` +* [`fast-csv`](./packages/fast-csv) - Exposes both formatting and parsing methods in a single package +* [`@fast-csv/parse`](./packages/parse) - Parsing package, use this if you only need to parse files. +* [`@fast-csv/format`](./packages/format) - Formatting package, use this if you only need to format files. ## Documentation -* [Parsing Docs](./docs/parsing.md) -* [Formatting Docs](./docs/formatting.md) - -### Quick Examples - -**parsing** - -To read a csv with headers create a read stream and pipe it to parser. +* [`fast-csv` Docs](./packages/fast-csv/README.md) +* [Parsing Docs](./packages/parse/README.md) +* [Formatting Docs](./packages/format/README.md) -```javascript -fs.createReadStream('path/to/my.csv') - .pipe(csv.parse({ headers: true })) - .on('data', row => console.log(row)) -``` +### Examples -For more in depth parsing examples and docs check out the [parsing docs](./docs/parsing.md) - -**formatting** - -To format a csv you can write rows to a formatter. - -```javascript -someStream - .pipe(csv.format({ headers: true }) - .pipe(process.stdout); -``` - -For more in depth formatting examples and docs check out the [formatting docs](./docs/formatting.md) +* [`fast-csv` Examples](./examples/fast-csv-js/README.md) +* [`@fast-csv/format` Examples](./examples/formatting-js/README.md) +* [`@fast-csv/parse` Examples](./examples/parsing-js/README.md) ### Migrating from older versions @@ -70,3 +45,4 @@ MIT * Twitter: [http://twitter.com/c2fo](http://twitter.com/c2fo) - 877.465.4045 + diff --git a/__tests__/formatter/CsvFormatterStream.spec.ts b/__tests__/formatter/CsvFormatterStream.spec.ts deleted file mode 100644 index f7017a5b..00000000 --- a/__tests__/formatter/CsvFormatterStream.spec.ts +++ /dev/null @@ -1,906 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import * as csv from '../../src'; -import { FormatterOptions, CsvFormatterStream } from '../../src/formatter'; -import RecordingStream from '../RecordingStream'; - -describe('CsvFormatterStream', () => { - const objectRows = [ - { a: 'a1', b: 'b1' }, - { a: 'a2', b: 'b2' }, - ]; - - const arrayRows = [ - ['a', 'b'], - ['a1', 'b1'], - ['a2', 'b2'], - ]; - - const multiDimensionalRows = [ - [ - ['a', 'a1'], - ['b', 'b1'], - ], - [ - ['a', 'a2'], - ['b', 'b2'], - ], - ]; - - const pipeToRecordingStream = (formatter: CsvFormatterStream, rows: csv.FormatterRow[]) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - formatter - .on('error', e => rej(e)) - .pipe(rs) - .on('finish', () => { - res(rs.data); - }); - rows.forEach(row => formatter.write(row)); - formatter.end(); - }); - - const formatRows = (rows: csv.FormatterRow[], options: csv.FormatterOptionsArgs = {}) => - pipeToRecordingStream(csv.format(options), rows); - - it('should write an array of arrays', () => - expect(formatRows(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); - - it('should write an array of objects', () => - expect(formatRows(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); - - describe('transform option', () => { - it('should support transforming an array of arrays', () => - expect( - formatRows(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); - - it('should support transforming an array of multi-dimensional arrays', () => - expect( - formatRows(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]); - }, - }), - ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); - - it('should support transforming an array of objects', () => - expect( - formatRows(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { A: row.a, B: row.b }; - }, - }), - ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); - }); - describe('#transform', () => { - it('should support transforming an array of arrays', async () => { - const formatter = new CsvFormatterStream( - new FormatterOptions({ headers: true }), - ).transform((row: csv.FormatterRow) => (row as csv.FormatterRowArray).map(entry => entry.toUpperCase())); - await expect(pipeToRecordingStream(formatter, arrayRows)).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2']); - }); - - it('should support transforming an array of multi-dimensional arrays', async () => { - const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( - (row: csv.FormatterRow): csv.FormatterRow => - (row as csv.FormatterRowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]), - ); - await expect(pipeToRecordingStream(formatter, multiDimensionalRows)).resolves.toEqual([ - 'a,b', - '\nA1,B1', - '\nA2,B2', - ]); - }); - - it('should support transforming an array of objects', async () => { - const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( - (row: csv.FormatterRow): csv.FormatterRow => ({ - A: (row as csv.FormatterRowMap).a, - B: (row as csv.FormatterRowMap).b, - }), - ); - await expect(pipeToRecordingStream(formatter, objectRows)).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2']); - }); - - it('should error if the transform fails', async () => { - const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( - (): csv.FormatterRow => { - throw new Error('Expected error'); - }, - ); - await expect(pipeToRecordingStream(formatter, objectRows)).rejects.toThrowError('Expected error'); - }); - }); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect( - formatRows(objectRows, { - headers: true, - rowDelimiter: '\r\n', - }), - ).resolves.toEqual(['a,b', '\r\na1,b1', '\r\na2,b2'])); - - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\n1', b: 'b1' }, - { a: 'a\n2', b: 'b2' }, - ]; - await expect( - formatRows(rows, { - headers: true, - rowDelimiter: '\n', - }), - ).resolves.toEqual(['a,b', '\n"a\n1",b1', '\n"a\n2",b2']); - }); - }); - - describe('quoteColumns option', () => { - describe('quote all columns and headers if quoteColumns is true and quoteHeaders is false', () => { - const opts = { - headers: true, - quoteColumns: true, - }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['"a","b"', '\n"a1","b1"', '\n"a2","b2"'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a","b"', '\n"a1","b1"', '\n"a2","b2"'])); - - it('should work with multi-dimenional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual([ - '"a","b"', - '\n"a1","b1"', - '\n"a2","b2"', - ])); - }); - - describe('quote headers if quoteHeaders is true and not columns is quoteColumns is undefined', () => { - const opts = { headers: true, quoteHeaders: true }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); - - it('should work with multi-dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); - }); - - describe('quote columns if quoteColumns is true and not quote headers if quoteHeaders is false', () => { - const opts = { headers: true, quoteHeaders: false, quoteColumns: true }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); - - it('should work with multi-dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); - }); - - describe('if quoteColumns object it should only quote the specified column and header', () => { - const opts = { headers: true, quoteColumns: { a: true } }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with multi dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); - }); - - describe('if quoteColumns object and quoteHeaders is false it should only quote the specified column and not the header', () => { - const opts = { - headers: true, - quoteHeaders: false, - quoteColumns: { a: true }, - }; - it('should work with objects', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with multi-dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); - }); - - describe('if quoteColumns is an array it should only quote the specified column index', () => { - const opts = { headers: true, quoteColumns: [true] }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with multi-dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); - }); - - describe('if quoteColumns is false and quoteHeaders is an object it should only quote the specified header and not the column', () => { - const opts = { - headers: true, - quoteHeaders: { a: true }, - quoteColumns: false, - }; - it('should work with object', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); - - it('should work with multi-dimenional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); - }); - - describe('if quoteColumns is an object and quoteHeaders is an object it should only quote the specified header and column', () => { - const opts = { - headers: true, - quoteHeaders: { b: true }, - quoteColumns: { a: true }, - }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); - - it('should work with multi-dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); - }); - - describe('if quoteHeaders is an array and quoteColumns is an false it should only quote the specified header and not the column', () => { - const opts = { - headers: true, - quoteHeaders: [false, true], - quoteColumns: false, - }; - it('should work with objects', () => - expect(formatRows(objectRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); - - it('should work with arrays', () => - expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); - - it('should work with arrays of multi-dimensional arrays', () => - expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); - }); - }); - - describe('header option', () => { - it('should write an array of objects without headers', () => - expect(formatRows(objectRows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2'])); - - it('should write an array of objects with headers', () => - expect(formatRows(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); - - it('should write an array of arrays without headers', async () => { - const rows = [ - ['a1', 'b1'], - ['a2', 'b2'], - ]; - await expect(formatRows(rows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2']); - }); - - it('should write an array of arrays with headers', () => - expect(formatRows(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); - - it('should write an array of multi-dimensional arrays without headers', () => - expect(formatRows(multiDimensionalRows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2'])); - - it('should write an array of multi-dimensional arrays with headers', () => - expect(formatRows(multiDimensionalRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should not write anything if headers are provided but no rows are provided', () => - expect(formatRows([], { headers: true })).resolves.toEqual([])); - - describe('alwaysWriteHeaders option', () => { - it('should write the headers if rows are not provided', async () => { - const headers = ['h1', 'h2']; - await expect( - formatRows([], { - headers, - alwaysWriteHeaders: true, - }), - ).resolves.toEqual([headers.join(',')]); - }); - - it('should write the headers ones if rows are provided', async () => { - const headers = ['h1', 'h2']; - await expect( - formatRows(arrayRows, { - headers, - alwaysWriteHeaders: true, - }), - ).resolves.toEqual([headers.join(','), '\na,b', '\na1,b1', '\na2,b2']); - }); - - it('should fail if no headers are provided', async () => { - await expect(formatRows([], { alwaysWriteHeaders: true })).rejects.toThrowError( - '`alwaysWriteHeaders` option is set to true but `headers` option not provided.', - ); - }); - - it('should write the headers and an endRowDelimiter if includeEndRowDelimiter is true', async () => { - const headers = ['h1', 'h2']; - await expect( - formatRows([], { - headers, - includeEndRowDelimiter: true, - alwaysWriteHeaders: true, - }), - ).resolves.toEqual([headers.join(','), '\n']); - }); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect( - formatRows(objectRows, { - headers: true, - includeEndRowDelimiter: true, - }), - ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); - - it('should write a BOM character if writeBOM is true', () => - expect( - formatRows(objectRows, { - headers: true, - writeBOM: true, - }), - ).resolves.toEqual(['\ufeff', 'a,b', '\na1,b1', '\na2,b2'])); - - describe('.writeToString', () => { - it('should write an array of arrays', () => - expect(csv.writeToString(arrayRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); - - it('should support transforming an array of arrays', () => - expect( - csv.writeToString(arrayRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual('A,B\nA1,B1\nA2,B2')); - - it('should write an array of multi-dimensional arrays', () => - expect(csv.writeToString(multiDimensionalRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); - - it('should support transforming an array of multi-dimensional arrays', () => - expect( - csv.writeToString(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }), - ).resolves.toEqual('a,b\nA1,B1\nA2,B2')); - - it('should write an array of objects', () => - expect( - csv.writeToString(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }), - ).resolves.toEqual('A,B\na1,b1\na2,b2')); - - describe('header option', () => { - it('should write an array of objects without headers', () => - expect(csv.writeToString(objectRows, { headers: false })).resolves.toEqual('a1,b1\na2,b2')); - - it('should write an array of objects with headers', () => - expect(csv.writeToString(objectRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); - - it('should write an array of arrays without headers', async () => { - const rows = [ - ['a1', 'b1'], - ['a2', 'b2'], - ]; - await expect(csv.writeToString(rows, { headers: false })).resolves.toEqual('a1,b1\na2,b2'); - }); - - it('should write an array of arrays with headers', () => - expect(csv.writeToString(arrayRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); - - it('should write an array of multi-dimensional arrays without headers', () => - expect(csv.writeToString(multiDimensionalRows, { headers: false })).resolves.toEqual('a1,b1\na2,b2')); - - it('should write an array of multi-dimensional arrays with headers', () => - expect(csv.writeToString(multiDimensionalRows, { headers: true })).resolves.toEqual( - 'a,b\na1,b1\na2,b2', - )); - }); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect(csv.writeToString(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( - 'a,b\r\na1,b1\r\na2,b2', - )); - - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\t1', b: 'b1' }, - { a: 'a\t2', b: 'b2' }, - ]; - await expect(csv.writeToString(rows, { headers: true, rowDelimiter: '\t' })).resolves.toEqual( - 'a,b\t"a\t1",b1\t"a\t2",b2', - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect(csv.writeToString(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( - 'a,b\na1,b1\na2,b2\n', - )); - }); - - describe('.writeToBuffer', () => { - it('should write an array of arrays', () => - expect(csv.writeToBuffer(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); - - it('should support transforming an array of arrays', () => - expect( - csv.writeToBuffer(arrayRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual(Buffer.from('A,B\nA1,B1\nA2,B2'))); - - it('should write an array of multi-dimensional arrays', () => - expect(csv.writeToBuffer(multiDimensionalRows, { headers: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2'), - )); - - it('should support transforming an array of multi-dimensional arrays', () => - expect( - csv.writeToBuffer(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }), - ).resolves.toEqual(Buffer.from('a,b\nA1,B1\nA2,B2'))); - - it('should write an array of objects', () => - expect( - csv.writeToBuffer(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap): csv.FormatterRow { - return { - A: row.a, - B: row.b, - }; - }, - }), - ).resolves.toEqual(Buffer.from('A,B\na1,b1\na2,b2'))); - - describe('header option', () => { - it('should write an array of objects without headers', () => - expect(csv.writeToBuffer(objectRows, { headers: false })).resolves.toEqual( - Buffer.from('a1,b1\na2,b2'), - )); - - it('should write an array of objects with headers', () => - expect(csv.writeToBuffer(objectRows, { headers: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2'), - )); - - it('should write an array of arrays without headers', async () => { - const rows = [ - ['a1', 'b1'], - ['a2', 'b2'], - ]; - await expect(csv.writeToBuffer(rows, { headers: false })).resolves.toEqual(Buffer.from('a1,b1\na2,b2')); - }); - - it('should write an array of arrays with headers', () => - expect(csv.writeToBuffer(arrayRows, { headers: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2'), - )); - - it('should write an array of multi-dimensional arrays without headers', () => - expect(csv.writeToBuffer(multiDimensionalRows, { headers: false })).resolves.toEqual( - Buffer.from('a1,b1\na2,b2'), - )); - - it('should write an array of multi-dimensional arrays with headers', () => - expect(csv.writeToBuffer(multiDimensionalRows, { headers: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2'), - )); - }); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect(csv.writeToBuffer(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( - Buffer.from('a,b\r\na1,b1\r\na2,b2'), - )); - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\t1', b: 'b1' }, - { a: 'a\t2', b: 'b2' }, - ]; - await expect(csv.writeToBuffer(rows, { headers: true, rowDelimiter: '\t' })).resolves.toEqual( - Buffer.from('a,b\t"a\t1",b1\t"a\t2",b2'), - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect(csv.writeToBuffer(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2\n'), - )); - }); - - describe('.write', () => { - const writeToRecordingStream = (rows: csv.FormatterRow[], options = {}) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - csv.write(rows, options) - .on('error', rej) - .pipe(rs) - .on('finish', () => { - res(rs.data); - }); - }); - - it('should write an array of arrays', () => - expect(writeToRecordingStream(arrayRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of arrays', () => - expect( - writeToRecordingStream(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); - - it('should write an array of multi-dimensional arrays', () => - expect(writeToRecordingStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of multi-dimensional arrays', () => - expect( - writeToRecordingStream(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }), - ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); - - it('should write an array of objects', () => - expect(writeToRecordingStream(objectRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of objects', () => - expect( - writeToRecordingStream(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }), - ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect(writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ - 'a,b', - '\r\na1,b1', - '\r\na2,b2', - ])); - - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\n1', b: 'b1' }, - { a: 'a\n2', b: 'b2' }, - ]; - await expect(writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' })).resolves.toEqual([ - 'a,b', - '\n"a\n1",b1', - '\n"a\n2",b2', - ]); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect( - writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true }), - ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); - }); - - describe('.writeToPath', () => { - const writeToPath = (rows: csv.FormatterRow[], options = {}) => - new Promise((res, rej) => { - const csvPath = path.resolve(__dirname, '__fixtures__', 'test_output.csv'); - csv.writeToPath(csvPath, rows, options) - .on('error', rej) - .on('finish', () => { - const content = fs.readFileSync(csvPath); - fs.unlinkSync(csvPath); - res(content); - }); - }); - - it('should write an array of arrays', () => - expect(writeToPath(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); - - it('should write an array of objects', () => - expect(writeToPath(objectRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); - - it('should write an array of multi-dimensional arrays', () => - expect(writeToPath(multiDimensionalRows, { headers: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2'), - )); - - it('should support transforming an array of arrays', () => - expect( - writeToPath(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual(Buffer.from('A,B\nA1,B1\nA2,B2'))); - - it('should transforming an array of objects', () => - expect( - writeToPath(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }), - ).resolves.toEqual(Buffer.from('A,B\na1,b1\na2,b2'))); - - it('should transforming an array of multi-dimensional array', () => - expect( - writeToPath(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }), - ).resolves.toEqual(Buffer.from('a,b\nA1,B1\nA2,B2'))); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect(writeToPath(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( - Buffer.from('a,b\r\na1,b1\r\na2,b2'), - )); - - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\r\n1', b: 'b1' }, - { a: 'a\r\n2', b: 'b2' }, - ]; - await expect(writeToPath(rows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( - Buffer.from('a,b\r\n"a\r\n1",b1\r\n"a\r\n2",b2'), - ); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect(writeToPath(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( - Buffer.from('a,b\na1,b1\na2,b2\n'), - )); - }); - - describe('.write', () => { - const writeToRecordingStream = (rows: csv.FormatterRow[], options = {}) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - csv.write(rows, options) - .on('error', rej) - .pipe(rs) - .on('finish', () => { - res(rs.data); - }); - }); - - it('should write an array of arrays', () => - expect(writeToRecordingStream(arrayRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of arrays', () => - expect( - writeToRecordingStream(arrayRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); - - it('should write an array of multi-dimensional arrays', () => - expect(writeToRecordingStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of multi-dimensional arrays', () => - expect( - writeToRecordingStream(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow) { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }), - ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); - - it('should write an array of objects', () => - expect(writeToRecordingStream(objectRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of objects', () => - expect( - writeToRecordingStream(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap) { - return { - A: row.a, - B: row.b, - }; - }, - }), - ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect(writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ - 'a,b', - '\r\na1,b1', - '\r\na2,b2', - ])); - - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\n1', b: 'b1' }, - { a: 'a\n2', b: 'b2' }, - ]; - await expect(writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' })).resolves.toEqual([ - 'a,b', - '\n"a\n1",b1', - '\n"a\n2",b2', - ]); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect( - writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true }), - ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); - }); - - describe('.writeToStream', () => { - const writeToStream = (rows: csv.FormatterRow[], options: csv.FormatterOptionsArgs = {}) => - new Promise((res, rej) => { - const rs = new RecordingStream(); - csv.writeToStream(rs, rows, options); - rs.on('error', rej).on('finish', () => { - res(rs.data); - }); - }); - - it('should write an array of arrays', () => - expect(writeToStream(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); - - it('should write an array of objects', () => - expect(writeToStream(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); - - it('should write an array of multi-dimensional arrays', () => - expect(writeToStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - ])); - - it('should support transforming an array of arrays', () => - expect( - writeToStream(arrayRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowArray).map(entry => entry.toUpperCase()); - }, - }), - ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); - - it('should transforming an array of objects', () => - expect( - writeToStream(objectRows, { - headers: true, - transform(row: csv.FormatterRowMap): csv.FormatterRow { - return { - A: row.a, - B: row.b, - }; - }, - }), - ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); - - it('should transforming an array of multi-dimensional array', () => - expect( - writeToStream(multiDimensionalRows, { - headers: true, - transform(row: csv.FormatterRow): csv.FormatterRow { - return (row as csv.FormatterRowHashArray).map(col => [col[0], col[1].toUpperCase()]); - }, - }), - ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); - - describe('rowDelimiter option', () => { - it('should support specifying an alternate row delimiter', () => - expect(writeToStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ - 'a,b', - '\r\na1,b1', - '\r\na2,b2', - ])); - - it('should escape values that contain the alternate row delimiter', async () => { - const rows = [ - { a: 'a\r\n1', b: 'b1' }, - { a: 'a\r\n2', b: 'b2' }, - ]; - await expect(writeToStream(rows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ - 'a,b', - '\r\n"a\r\n1",b1', - '\r\n"a\r\n2",b2', - ]); - }); - }); - - it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => - expect(writeToStream(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual([ - 'a,b', - '\na1,b1', - '\na2,b2', - '\n', - ])); - }); -}); diff --git a/__tests__/parser/__fixtures__/index.ts b/__tests__/parser/__fixtures__/index.ts deleted file mode 100644 index 9eec0c72..00000000 --- a/__tests__/parser/__fixtures__/index.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { existsSync, mkdirSync, writeFileSync } from 'fs'; -import * as path from 'path'; -import alternateEncoding from './alternateEncoding'; -import noHeadersAndQuotes from './noHeadersAndQuotes'; -import skipLines from './skipLines'; -import withHeaders from './withHeaders'; -import withHeadersAndQuotes from './withHeadersAndQuotes'; -import withHeadersAndAlternateQuote from './withHeadersAndAlternateQuote'; -import withHeadersAndMissingColumns from './withHeadersAndMissingColumns'; -import withHeadersAlternateDelimiter from './withHeadersAlternateDelimiter'; -import withHeadersSkippedLines from './withHeadersSkippedLines'; -import headerColumnMismatch from './headerColumnMismatch'; -import malformed from './malformed'; -import trailingComma from './trailingComma'; -import emptyRows from './emptyRows'; -import duplicateHeaders from './duplicateHeaders'; -import RecordingStream from '../../RecordingStream'; - -export interface PathAndContent { - path: string; - content: string | Buffer; -} - -const mkDirIfNotExists = (filePath: string): void => { - const dir = path.dirname(filePath); - if (!existsSync(dir)) { - mkdirSync(dir); - } -}; - -const write = (opts: PathAndContent): void => { - mkDirIfNotExists(opts.path); - writeFileSync(opts.path, opts.content); -}; - -export default { - RecordingStream, - write, - alternateEncoding, - duplicateHeaders, - skipLines, - withHeaders, - withHeadersAndQuotes, - withHeadersAndAlternateQuote, - withHeadersAndMissingColumns, - withHeadersAlternateDelimiter, - withHeadersSkippedLines, - noHeadersAndQuotes, - headerColumnMismatch, - malformed, - trailingComma, - emptyRows, -}; diff --git a/benchmark/.eslintrc.js b/examples/benchmark/.eslintrc.js similarity index 100% rename from benchmark/.eslintrc.js rename to examples/benchmark/.eslintrc.js diff --git a/benchmark/assets/100000.nonquoted.csv b/examples/benchmark/assets/100000.nonquoted.csv similarity index 100% rename from benchmark/assets/100000.nonquoted.csv rename to examples/benchmark/assets/100000.nonquoted.csv diff --git a/benchmark/assets/100000.quoted.csv b/examples/benchmark/assets/100000.quoted.csv similarity index 100% rename from benchmark/assets/100000.quoted.csv rename to examples/benchmark/assets/100000.quoted.csv diff --git a/benchmark/assets/20000.nonquoted.csv b/examples/benchmark/assets/20000.nonquoted.csv similarity index 100% rename from benchmark/assets/20000.nonquoted.csv rename to examples/benchmark/assets/20000.nonquoted.csv diff --git a/benchmark/assets/20000.quoted.csv b/examples/benchmark/assets/20000.quoted.csv similarity index 100% rename from benchmark/assets/20000.quoted.csv rename to examples/benchmark/assets/20000.quoted.csv diff --git a/benchmark/assets/50000.nonquoted.csv b/examples/benchmark/assets/50000.nonquoted.csv similarity index 100% rename from benchmark/assets/50000.nonquoted.csv rename to examples/benchmark/assets/50000.nonquoted.csv diff --git a/benchmark/assets/50000.quoted.csv b/examples/benchmark/assets/50000.quoted.csv similarity index 100% rename from benchmark/assets/50000.quoted.csv rename to examples/benchmark/assets/50000.quoted.csv diff --git a/benchmark/createData.js b/examples/benchmark/createData.js similarity index 60% rename from benchmark/createData.js rename to examples/benchmark/createData.js index 0dc09a50..1b7c4fcd 100644 --- a/benchmark/createData.js +++ b/examples/benchmark/createData.js @@ -1,29 +1,27 @@ const path = require('path'); -const fastCsv = require('..'); +const fastCsv = require('fast-csv'); -const headers = [ - [ 'first_name', 'last_name', 'email_address', 'address' ], -]; +const headers = [['first_name', 'last_name', 'email_address', 'address']]; const nonQuotedLines = [ - [ 'First1', 'Last1', 'email1@email.com', '1 Street St State ST 88888' ], - [ 'First1', 'Last1', 'email1@email.com', '' ], - [ 'First1', 'Last1', '', '' ], - [ 'First1', '', '', '' ], - [ '', '', '', '' ], + ['First1', 'Last1', 'email1@email.com', '1 Street St State ST 88888'], + ['First1', 'Last1', 'email1@email.com', ''], + ['First1', 'Last1', '', ''], + ['First1', '', '', ''], + ['', '', '', ''], ]; const quotedLines = [ - [ "First'1", '"Last1"', '"email1@email.com"', '1 Street St, State ST, 88888' ], - [ "First'1", '"Last1"', '"email1@email.com"', '""' ], - [ "First'1", '"Last1"', '""', '""' ], - [ "First'1", '""', '""', '""' ], - [ '""', '""', '""', '""' ], + ["First'1", '"Last1"', '"email1@email.com"', '1 Street St, State ST, 88888'], + ["First'1", '"Last1"', '"email1@email.com"', '""'], + ["First'1", '"Last1"', '""', '""'], + ["First'1", '""', '""', '""'], + ['""', '""', '""', '""'], ]; const writeCsv = (count, lineOptions, filename) => { console.log(`Writing ${filename}...`); - const rows = [ ...headers ]; + const rows = [...headers]; const lineOptionLength = lineOptions.length; for (let i = 0; i < count; i += 1) { rows.push(lineOptions[i % lineOptionLength]); diff --git a/benchmark/index.js b/examples/benchmark/index.js similarity index 96% rename from benchmark/index.js rename to examples/benchmark/index.js index b721147f..125fd6bd 100644 --- a/benchmark/index.js +++ b/examples/benchmark/index.js @@ -1,6 +1,6 @@ const path = require('path'); const fs = require('fs'); -const fastCsv = require('..'); +const fastCsv = require('fast-csv'); function camelize(str) { return str.replace(/_(.)/g, (a, b) => b.toUpperCase()); @@ -10,7 +10,7 @@ const promisfyStream = (stream, expectedRows) => { let count = 0; return new Promise((res, rej) => { stream - .on('data', row => { + .on('data', () => { count += 1; }) .on('end', () => { diff --git a/examples/benchmark/package.json b/examples/benchmark/package.json new file mode 100644 index 00000000..04eb1b97 --- /dev/null +++ b/examples/benchmark/package.json @@ -0,0 +1,11 @@ +{ + "name": "fast-csv-benchmarks", + "private": true, + "description": "fast-csv examples", + "dependencies": { + "fast-csv": "^4.0.0" + }, + "scripts": { + "benchmarks": "node ./index.js" + } +} diff --git a/examples/example-runner/bin/run-examples b/examples/example-runner/bin/run-examples new file mode 100755 index 00000000..d68e2912 --- /dev/null +++ b/examples/example-runner/bin/run-examples @@ -0,0 +1,81 @@ +#!/usr/bin/env node + +const { EOL } = require('os'); +const fs = require('fs'); +const cp = require('child_process'); +const path = require('path'); +const globby = require('globby'); +const diffDefault = require('jest-diff'); + +const exampleNameArg = process.argv[2]; + +const OUTPUT_REGEXP = new RegExp(`\\/\\/ Output: *${EOL}`); + +const getExampleFiles = async () => { + const files = await globby(path.resolve(process.cwd(), 'examples', '**', '*.example.js'), { stats: true }); + return files.reduce((map, f) => ({ ...map, ...{ [f.name.replace('.example.js', '')]: f.path } }), {}); +}; + +const printExamples = examples => console.log(`Available Examples:\n\t${Object.keys(examples).join('\n\t')}`); + +const getExpectedOutput = examplePath => { + const contents = fs.readFileSync(examplePath).toString(); + const outputCommentMatch = contents.match(OUTPUT_REGEXP); + if (!outputCommentMatch) { + return null; + } + const startIndex = outputCommentMatch.index + outputCommentMatch[0].length; + return contents + .slice(startIndex) + .split(EOL) + .map(l => { + return l.replace(/\/\/ /, ''); + }) + .join(EOL); +}; + +const checkOutput = (exampleName, examples, exampleActualOutput) => { + const expected = getExpectedOutput(examples[exampleName]); + if (!expected) { + throw new Error(`Example '${exampleName}' did not define expected output!`); + } + if (expected.trim() !== exampleActualOutput.trim()) { + throw new Error(`Example ${exampleName} failed!\n\n${diffDefault(expected, exampleActualOutput)}`); + } else { + console.log(`Example ${exampleName} Output:\n\n${exampleActualOutput}\n\n`); + } +}; + +const runExample = (exampleName, examples) => { + if (!examples[exampleName]) { + return Promise.reject(new Error(`unable to find example: ${exampleName}`)); + } + return new Promise((res, rej) => { + cp.exec(`node ${examples[exampleName]}`, (error, stdout) => { + if (error) { + return rej(error); + } + + return res(stdout); + }); + }); +}; + +(async () => { + const examples = await getExampleFiles(); + if (!exampleNameArg) { + return printExamples(examples); + } + if (exampleNameArg === 'all') { + return Object.keys(examples).reduce(async (prev, exampleName) => { + await prev; + const output = await runExample(exampleName, examples); + checkOutput(exampleName, examples, output); + }, Promise.resolve()); + } + const output = await runExample(exampleNameArg, examples); + return checkOutput(exampleNameArg, examples, output); +})().catch(err => { + console.error(err.stack); + process.exit(1); +}); diff --git a/examples/example-runner/package.json b/examples/example-runner/package.json new file mode 100644 index 00000000..c0ffe38a --- /dev/null +++ b/examples/example-runner/package.json @@ -0,0 +1,14 @@ +{ + "name": "example-runner", + "version": "4.0.0", + "private": true, + "description": "Runs examples and checks output", + "bin": { + "run-all-examples": "./bin/run-examples", + "run-examples": "./bin/run-examples" + }, + "dependencies": { + "globby": "^10.0.1", + "jest-diff": "^24.9.0" + } +} diff --git a/examples/.eslintrc.js b/examples/fast-csv-js/.eslintrc.js similarity index 100% rename from examples/.eslintrc.js rename to examples/fast-csv-js/.eslintrc.js diff --git a/examples/fast-csv-js/README.md b/examples/fast-csv-js/README.md new file mode 100644 index 00000000..60217ff5 --- /dev/null +++ b/examples/fast-csv-js/README.md @@ -0,0 +1,144 @@ +`fast-csv` examples. + +## Usage + +To run all examples + +```sh +npm run all-examples +``` + +To see a list of all available examples + +```sh +npm run example +``` + +To run a sepcific example + +```sh +npm run example -- {example_name} +``` + +## Examples + +* [Format](#format) +* [Parse](#parse) +* [Parse And Format](#parse-and-format) + + +### Format + +[`examples/format.example.js`](./examples/format.example.js) +```sh +npm run example -- format +``` +```javascript +const csv = require('fast-csv'); + +const csvStream = csv.format({ headers: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'row1-col1', header2: 'row1-col2' }); +csvStream.write({ header1: 'row2-col1', header2: 'row2-col2' }); +csvStream.write({ header1: 'row3-col1', header2: 'row3-col2' }); +csvStream.write({ header1: 'row4-col1', header2: 'row4-col2' }); +csvStream.end(); +``` + +Expected output + +``` +header1,header2 +row1-col1,row1-col2 +row2-col1,row2-col2 +row3-col1,row3-col2 +row4-col1,row4-col2 +``` +--- + + +### Parse + +[`examples/parse.example.js`](./examples/parse.example.js) +```sh +npm run example -- parse +``` +```javascript +const fs = require('fs'); +const path = require('path'); +const csv = require('fast-csv'); + +fs.createReadStream(path.resolve(__dirname, 'assets', 'parse.csv')) + .pipe(csv.parse({ headers: true })) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +``` + +Expected output + +``` +{ header1: 'row1-col1', header2: 'row1-col2' } +{ header1: 'row2-col1', header2: 'row2-col2' } +{ header1: 'row3-col1', header2: 'row3-col2' } +{ header1: 'row4-col1', header2: 'row4-col2' } +{ header1: 'row5-col1', header2: 'row5-col2' } +Parsed 5 rows +``` +--- + + +### Parse And Format + +[`examples/parse_and_format_transform_async.example.js`](./examples/parse_and_format_transform_async.example.js) +```sh +npm run example -- parse_and_format_transform_async +``` +```javascript +const fs = require('fs'); +const path = require('path'); +const csv = require('fast-csv'); +const User = require('./models/user'); + +fs.createReadStream(path.resolve(__dirname, 'assets', 'snake_case_users.csv')) + .pipe(csv.parse({ headers: true })) + // pipe the parsed input into a csv formatter + .pipe(csv.format({ headers: true })) + // Using the transform function from the formatting stream + .transform((row, next) => { + User.findById(row.id, (err, user) => { + if (err) { + return next(err); + } + return next(null, { + id: row.id, + firstName: row.first_name, + lastName: row.last_name, + address: row.address, + // properties from user + isVerified: user.isVerified, + hasLoggedIn: user.hasLoggedIn, + age: user.age, + }); + }); + }) + .pipe(process.stdout) + .on('end', process.exit); +``` + +Expected output + +``` +id,firstName,lastName,address,isVerified,hasLoggedIn,age +1,Bob,Yukon,1111 State St. Yukon AK,false,false,11 +2,Sally,Yukon,1111 State St. Yukon AK,true,false,12 +3,Bobby,Yukon,1111 State St. Yukon AK,false,false,13 +4,Jane,Yukon,1111 State St. Yukon AK,true,true,14 +5,Dick,Yukon,1111 State St. Yukon AK,false,false,15 +6,John,Doe,1112 State St. Yukon AK,true,false,16 +7,Jane,Doe,1113 State St. Yukon AK,false,false,17 +8,Billy,Doe,1112 State St. Yukon AK,true,true,18 +9,Edith,Doe,1112 State St. Yukon AK,false,false,19 +``` \ No newline at end of file diff --git a/examples/fast-csv-js/examples/assets/parse.csv b/examples/fast-csv-js/examples/assets/parse.csv new file mode 100644 index 00000000..667fa402 --- /dev/null +++ b/examples/fast-csv-js/examples/assets/parse.csv @@ -0,0 +1,6 @@ +header1,header2 +row1-col1,row1-col2 +row2-col1,row2-col2 +row3-col1,row3-col2 +row4-col1,row4-col2 +row5-col1,row5-col2 \ No newline at end of file diff --git a/examples/assets/snake_case_users.csv b/examples/fast-csv-js/examples/assets/snake_case_users.csv similarity index 100% rename from examples/assets/snake_case_users.csv rename to examples/fast-csv-js/examples/assets/snake_case_users.csv diff --git a/examples/fast-csv-js/examples/format.example.js b/examples/fast-csv-js/examples/format.example.js new file mode 100644 index 00000000..8d237fa5 --- /dev/null +++ b/examples/fast-csv-js/examples/format.example.js @@ -0,0 +1,18 @@ +const csv = require('fast-csv'); + +const csvStream = csv.format({ headers: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'row1-col1', header2: 'row1-col2' }); +csvStream.write({ header1: 'row2-col1', header2: 'row2-col2' }); +csvStream.write({ header1: 'row3-col1', header2: 'row3-col2' }); +csvStream.write({ header1: 'row4-col1', header2: 'row4-col2' }); +csvStream.end(); + +// Output: +// header1,header2 +// row1-col1,row1-col2 +// row2-col1,row2-col2 +// row3-col1,row3-col2 +// row4-col1,row4-col2 diff --git a/examples/models/user.js b/examples/fast-csv-js/examples/models/user.js similarity index 100% rename from examples/models/user.js rename to examples/fast-csv-js/examples/models/user.js diff --git a/examples/fast-csv-js/examples/parse.example.js b/examples/fast-csv-js/examples/parse.example.js new file mode 100644 index 00000000..00ef543c --- /dev/null +++ b/examples/fast-csv-js/examples/parse.example.js @@ -0,0 +1,17 @@ +const fs = require('fs'); +const path = require('path'); +const csv = require('fast-csv'); + +fs.createReadStream(path.resolve(__dirname, 'assets', 'parse.csv')) + .pipe(csv.parse({ headers: true })) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); + +// Output: +// { header1: 'row1-col1', header2: 'row1-col2' } +// { header1: 'row2-col1', header2: 'row2-col2' } +// { header1: 'row3-col1', header2: 'row3-col2' } +// { header1: 'row4-col1', header2: 'row4-col2' } +// { header1: 'row5-col1', header2: 'row5-col2' } +// Parsed 5 rows diff --git a/examples/parse_and_format_transform_async.example.js b/examples/fast-csv-js/examples/parse_and_format_transform_async.example.js similarity index 61% rename from examples/parse_and_format_transform_async.example.js rename to examples/fast-csv-js/examples/parse_and_format_transform_async.example.js index 88b14886..bfed065c 100644 --- a/examples/parse_and_format_transform_async.example.js +++ b/examples/fast-csv-js/examples/parse_and_format_transform_async.example.js @@ -1,6 +1,6 @@ const fs = require('fs'); const path = require('path'); -const csv = require('../'); +const csv = require('fast-csv'); const User = require('./models/user'); fs.createReadStream(path.resolve(__dirname, 'assets', 'snake_case_users.csv')) @@ -27,3 +27,15 @@ fs.createReadStream(path.resolve(__dirname, 'assets', 'snake_case_users.csv')) }) .pipe(process.stdout) .on('end', process.exit); + +// Output: +// id,firstName,lastName,address,isVerified,hasLoggedIn,age +// 1,Bob,Yukon,1111 State St. Yukon AK,false,false,11 +// 2,Sally,Yukon,1111 State St. Yukon AK,true,false,12 +// 3,Bobby,Yukon,1111 State St. Yukon AK,false,false,13 +// 4,Jane,Yukon,1111 State St. Yukon AK,true,true,14 +// 5,Dick,Yukon,1111 State St. Yukon AK,false,false,15 +// 6,John,Doe,1112 State St. Yukon AK,true,false,16 +// 7,Jane,Doe,1113 State St. Yukon AK,false,false,17 +// 8,Billy,Doe,1112 State St. Yukon AK,true,true,18 +// 9,Edith,Doe,1112 State St. Yukon AK,false,false,19 diff --git a/examples/fast-csv-js/package-lock.json b/examples/fast-csv-js/package-lock.json new file mode 100644 index 00000000..89b1d2b2 --- /dev/null +++ b/examples/fast-csv-js/package-lock.json @@ -0,0 +1,568 @@ +{ + "name": "@fast-csv/parse-js-examples", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@fast-csv/parse": { + "version": "4.0.0", + "requires": { + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + }, + "dependencies": { + "@sinonjs/commons": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + }, + "lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" + }, + "nise": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } + } + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, + "@types/node": { + "version": "12.12.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", + "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" + }, + "@types/yargs": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "fast-glob": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", + "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2" + } + }, + "fastq": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", + "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", + "requires": { + "reusify": "^1.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" + }, + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} diff --git a/examples/fast-csv-js/package.json b/examples/fast-csv-js/package.json new file mode 100644 index 00000000..bad94932 --- /dev/null +++ b/examples/fast-csv-js/package.json @@ -0,0 +1,13 @@ +{ + "name": "fast-csv-js-examples", + "private": true, + "description": "fast-csv examples", + "dependencies": { + "example-runner": "^4.0.0", + "fast-csv": "^4.0.0" + }, + "scripts": { + "all-examples": "run-examples all", + "example": "run-examples" + } +} diff --git a/examples/formatting-js/.eslintrc.js b/examples/formatting-js/.eslintrc.js new file mode 100644 index 00000000..6571794b --- /dev/null +++ b/examples/formatting-js/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + parserOptions: { + project: null, + }, + rules: { + 'no-console': 0, + }, +}; diff --git a/docs/formatting.md b/examples/formatting-js/README.md similarity index 59% rename from docs/formatting.md rename to examples/formatting-js/README.md index c4901fe8..2832a8d3 100644 --- a/docs/formatting.md +++ b/examples/formatting-js/README.md @@ -1,262 +1,56 @@ -# Formatting - -* [Options](#parsing-options) -* [Valid Rows Types](#valid-row-types) -* [Formatting Methods](#formatting-methods) - * [`csv.format`](#csv-format) - * [`csv.write`](#csv-write) - * [`csv.writeToStream`](#csv-write-to-stream) - * [`csv.writeToBuffer`](#csv-write-to-buffer) - * [`csv.writeToString`](#csv-write-to-string) - * [`csv.writeToPath`](#csv-write-to-path) -* [Examples](#examples) - * [Alternate `delimiter`](#examples-alternate-delimiter) - * [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) - * [Appending To A CSV](#examples-appending) - - -## Options - -* `delimiter: {string} = ','`: Specify an alternate field delimiter such as `;` or `\t`. - * **NOTE** When specifying an alternate `delimiter` you may only pass in a single character delimiter -* `rowDelimiter: {string} = '\n'`: Specify an alternate row delimiter (i.e `\r\n`) -* `quote: {string|boolean} = '"'`: - * If provided as a string it will be used to quote fields that contain a delimiter. - * `"first,name",last name` - * If `quote` is set to `true` the default quote will be used. - * **NOTE** This is the same as not providing the option - * If `quote` false then quoting will be disabled - * **CAUTION** If your field could contain a delimiter then you may end up with extra columns -* `escape: {string} = '"'`: The character to use when escaping a value that is `quoted` and contains a `quote` character that is not the end of the field. - * `i.e`: `First,"Name"' => '"First,""Name"""` -* `includeEndRowDelimiter: {boolean} = false`: Set to `true` to include a row delimiter at the end of the csv. -* `writeBOM: {boolean} = false`: Set to true if you want the first character written to the stream to be a utf-8 BOM character. -* `headers: {null|boolean|string[]} = null`: - * If true then the headers will be auto detected from the first row. - * 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 -* `alwaysWriteHeaders: {boolean} = false`: Set to true if you always want headers written, even if no rows are written. - * **NOTE** This will throw an error if headers are not specified as an array. -* `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) - * If it is an array then each item in the array that is true will have the column at the corresponding index quoted (unless `quoteHeaders` is specified) - * **NOTE** if `quoteHeaders` is not specified this option will apply to both columns and headers. -* `quoteHeaders: {boolean|boolean[]|{[string]: boolean} = quoteColumns` - * Defaults to the `quoteColumns` option. - * If `true` then all headers will be quoted. - * If it is an object then each key that has a true value will be quoted (see example below) - * If it is an array then each item in the array that is true will have the header at the corresponding index quoted (see example below) -* `transform: {(row) => Row | (row, cb) => void} = null`: A function that accepts a row and returns a transformed one to be written, or your function can accept an optional callback to do async transformations. - - -## Valid Row Types - -When creating a CSV `fast-csv` supports a few row formats. - -**`{[string]: any}`** - -You can pass in object to any formatter function if your CSV requires headers the keys of the first object will be used as the header names. +`@fast-csv/format` formatting examples. -```javascript -{ - a: "a1", - b: "b1", - c: "c1", -} - -//Generated CSV -//a,b,c -//a1,b1,c1 -``` - -**`string[]`** - -You can also pass in your rows as arrays. If your CSV requires headers the first row passed in will be the headers used. - -```javascript -[ - ["a", "b", "c"], - ["a1", "b1", "c1"] -] -//Generated CSV -//a,b,c -//a1,b1,c1 -``` - -**`[string, any][]`** - -This is the least commonly used format but can be useful if you have requirements to generate a CSV with headers with the same column name (Crazy we know but we have seen it). - -```javascript -[ - [ - ["a", "a1"], - ["a", "a2"], - ["b", "b1"], - ["b", "b2"], - ["c", "c1"], - ["c", "c2"] - ] -] - -//Generated CSV -//a,a,b,b,c,c -//a1,a2,b1,b2,c1,c2 -``` - - -## Formatting Methods - - -**`csv.format(options): CsvFormatterStream`** - -This is the main entry point for formatting CSVs. It is used by all other helper methods. - -```javascript -const stream = csv.format(); -stream.pipe(process.stdout); - -stream.write([ 'a', 'b' ]); -stream.write([ 'a1', 'b1' ]); -stream.write([ 'a2', 'b2' ]); -stream.end(); -``` - -Expected output - -``` -a,b -a1,b1 -a2,b2 -``` - - -**`write(rows[, options]): CsvFormatterStream`** - -Create a formatter, writes the rows and returns the `CsvFormatterStream`. - -```javascript -const rows = [ - [ 'a', 'b' ], - [ 'a1', 'b1' ], - [ 'a2', 'b2' ], -]; -csv.write(rows).pipe(process.stdout); -``` - -Expected output - -``` -a,b -a1,b1 -a2,b2 -``` - - -**`writeToStream(stream, rows[, options])`** +## Usage -Write an array of values to a `WritableStream`, and returns the original stream - -```javascript -const rows = [ - [ 'a', 'b' ], - [ 'a1', 'b1' ], - [ 'a2', 'b2' ], -]; -csv.writeToStream(process.stdout, rows); +To run all examples +```sh +npm run all-examples ``` -Expected output +To see a list of all available examples +```sh +npm run example ``` -a,b -a1,b1 -a2,b2 -``` - - -**`writeToPath(path, rows[, options])`** -Write an array of values to the specified path - -```javascript -const rows = [ - [ 'a', 'b' ], - [ 'a1', 'b1' ], - [ 'a2', 'b2' ], -]; -csv.writeToPath(path.resolve(__dirname, 'tmp.csv'), rows) - .on('error', err => console.error(err)) - .on('finish', () => console.log('Done writing.')); +To run a sepcific example +```sh +npm run example -- {example_name} ``` -Expected file content - -``` -a,b -a1,b1 -a2,b2 -``` - - -**`writeToString(arr[, options]): Promise`** - -Formats the rows and returns a `Promise` that will resolve with the CSV content as a `string`. - -```javascript -const rows = [ - [ 'a', 'b' ], - [ 'a1', 'b1' ], - [ 'a2', 'b2' ], -]; -csv.writeToString(rows).then(data => console.log(data)); -``` - - -**`writeToBuffer(arr[, options]): Promise`** - -Formats the rows and returns a `Promise` that will resolve with the CSV content as a `Buffer`. - -```javascript -const rows = [ - [ 'a', 'b' ], - [ 'a1', 'b1' ], - [ 'a2', 'b2' ], -]; -csv.writeToBuffer(rows).then(data => console.log(data.toString())); -``` - - - ## Examples +* [Alternate `delimiter`](#examples-alternate-delimiter) +* [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) +* [Appending To A CSV](#examples-appending) + ### Alternate `delimiter` You can change the default delimiter `,` by specifying the `delimiter` option -[`examples/formatting/delimiter_option.example.js`](../examples/formatting/delimiter_option.example.js) +[`examples/delimiter_option.example.js`](./examples/delimiter_option.example.js) + +```sh +npm run example -- delimiter_option +``` + ```javascript const stream = csv.format({ delimiter: '\t' }); stream.pipe(process.stdout); @@ -275,12 +69,17 @@ a1\tb1 a2\tb2 ``` +--- ### Alternate `rowDelimiter` You can change the default row delimiter `\n` by specifying the `rowDelimiter` option. -[`examples/formatting/row_delimiter_option.example.js`](../examples/formatting/row_delimiter_option.example.js) +[`examples/row_delimiter_option.example.js`](./examples/row_delimiter_option.example.js) + +```sh +npm run example -- row_delimiter_option +``` ```javascript const stream = csv.format({ rowDelimiter: '\r\n' }); @@ -300,12 +99,17 @@ a1,b1 a2,b2 ``` +--- ### Alternate `quote` You change change the default quote `"` option by specifying the `quote` option. -[`examples/formatting/quote_option.example.js`](../examples/formatting/quote_option.example.js) +[`examples/quote_option.example.js`](./examples/quote_option.example.js) + +```sh +npm run example -- quote_option +``` ```javascript const stream = csv.format({ quote: "'" }); @@ -326,12 +130,17 @@ Expected output 'a2,a2','b2,b2' ``` +--- ### Alternate `escape` You change change the default escape `"` option by specifying the `escpae` option. -[`examples/formatting/escape_option.example.js`](../examples/formatting/escape_option.example.js) +[`examples/escape_option.example.js`](./examples/escape_option.example.js) + +```sh +npm run example -- escape_option +``` ```javascript const stream = csv.format({ escape: "'" }); @@ -352,6 +161,7 @@ Expected output "'"a2'"","'"b2'"" ``` +--- ### Headers @@ -363,10 +173,15 @@ Expected output **NOTE** When working is one-dimensional array rows (e.g. `[ 'a', 'b', 'c' ]`) this is a no-op. -[`examples/formatting/headers_auto_discovery_object.example.js`](../examples/formatting/headers_auto_discovery_object.example.js) + +[`examples/headers_auto_discovery_object.example.js`](./examples/headers_auto_discovery_object.example.js) In this example the headers are auto-discovered from the objects passed in. +```sh +npm run example -- headers_auto_discovery_object +``` + ```js const csvStream = csv.format({ headers: true}); @@ -391,10 +206,15 @@ value4a,value4b ``` -[`examples/formatting/headers_auto_discovery_hash_array.example.js`](../examples/formatting/headers_auto_discovery_hash_array.example.js) + +[`examples/headers_auto_discovery_hash_array.example.js`](./examples/headers_auto_discovery_hash_array.example.js) In this example the headers are auto-discovered from the hash arrays passed in. +```sh +npm run example -- headers_auto_discovery_hash_array +``` + ```js const csvStream = csv.format({ headers: true }); @@ -429,10 +249,15 @@ You can also provide a set of `headers` by providing an array. This allows you t **NOTE** When working with objects the header names should match keys. The headers option allows you to specify column order. -[`examples/formatting/headers_provided_array.example.js`](../examples/formatting/headers_provided_array.example.js) + +[`examples/headers_provided_array.example.js`](./examples/headers_provided_array.example.js) In this example a custom set of headers is provided for rows that are arrays. +```sh +npm run example -- headers_provided_array +``` + ```js const csvStream = csv.format({ headers: [ 'header1', 'header2' ] }); @@ -457,10 +282,15 @@ value4a,value4b ``` -[`examples/formatting/headers_provided_hash_array.example.js`](../examples/formatting/headers_provided_hash_array.example.js) + +[`examples/headers_provided_hash_array.example.js`](./examples/headers_provided_hash_array.example.js) In this example the headers are overridden with a custom set of headers +```sh +npm run example -- headers_provided_hash_array +``` + ```js const csvStream = csv.format({ headers: [ 'header1', 'header2' ] }); @@ -485,10 +315,14 @@ value4a,value4b ``` -[`examples/formatting/headers_provided_object.example.js`](../examples/formatting/headers_provided_object.example.js) +[`examples/headers_provided_object.example.js`](./examples/headers_provided_object.example.js) In this example the columns are reordered. +```sh +npm run example -- headers_provided_object +``` + ```js const csvStream = csv.format({ headers: [ 'header2', 'header1' ] }); @@ -514,10 +348,14 @@ value4b,value4a ``` -[`examples/formatting/headers_provided_object_remove_column.example.js`](../examples/formatting/headers_provided_object_remove_column.example.js) +[`examples/headers_provided_object_remove_column.example.js`](./examples/headers_provided_object_remove_column.example.js) In this example the one of the columns is removed. +```sh +npm run example -- headers_provided_object_remove_column +``` + ```js const csvStream = csv.format({ headers: [ 'header2' ] }); @@ -541,6 +379,7 @@ value3b value4b ``` +--- ### `quoteColumns` @@ -548,7 +387,11 @@ Sometimes you may need to quote columns is certain ways in order to meet certain Setting `quoteColumns` to true will by default quote all columns and headers. -[`examples/formatting/quote_all_columns.example.js`](../examples/formatting/quote_all_columns.example.js) +[`examples/quote_all_columns.example.js`](./examples/quote_all_columns.example.js) + +```sh +npm run example -- quote_all_columns +``` ```javascript const csvStream = csv.format({ headers: true, quoteColumns: true }); @@ -576,7 +419,11 @@ Expected output Setting `quoteColumns` to a `boolean[]` will quote the columns thats are set to true at each index in the array. -[`examples/formatting/quote_all_columns_array.example.js`](../examples/formatting/quote_all_columns_array.example.js) +[`examples/quote_all_columns_array.example.js`](./examples/quote_all_columns_array.example.js) + +```sh +npm run example -- quote_all_columns_array +``` ```javascript const csvStream = csv.format({ headers: [ 'header1', 'header2' ], quoteColumns: [ false, true ] }); @@ -604,7 +451,11 @@ value1a,"value2a" Setting `quoteColumns` to a `{[string]: boolean}` will quote the columns that are in the object with a value of true -[`examples/formatting/quote_all_columns_object.example.js`](../examples/formatting/quote_all_object.example.js) +[`examples/quote_columns_object.example.js`](./examples/quote_columns_object.example.js) + +```sh +npm run example -- quote_columns_object +``` ```javascript const csvStream = csv.format({ headers: true, quoteColumns: { header2: true } }); @@ -632,7 +483,11 @@ value1a,"value2a" If you need to quote columns and not headers you can set `quoteHeaders` to `null` or using the set it to a different configuration. -[`examples/formatting/quote_all_columns_not_headers.example.js`](../examples/formatting/quote_all_columns_not_headers.example.js) +[`examples/quote_columns_not_headers.example.js`](./examples/quote_columns_not_headers.example.js) + +```sh +npm run example -- quote_columns_not_headers +``` ```javascript const csvStream = csv.format({ headers: true, quoteColumns: { header2: true }, quoteHeaders: false }); @@ -659,12 +514,18 @@ value1a,"value2a" value1a,"value2a" ``` +--- ### `quoteHeaders` The `quoteHeaders` option uses the same types as `quoteColumns`. -[`examples/formatting/quote_all_headers.example.js`](../examples/formatting/quote_all_object.example.js) +[`examples/quote_all_headers.example.js`](./examples/quote_all_headers.example.js) + +```sh +npm run example -- quote_all_headers +``` + ```javascript const csvStream = csv.format({ headers: true, quoteHeaders: true }); @@ -689,7 +550,12 @@ value1a,value2a value1a,value2a ``` -[`examples/formatting/quote_headers_array.example.js`](../examples/formatting/quote_headers_array.example.js) +[`examples/quote_headers_array.example.js`](./examples/quote_headers_array.example.js) + +```sh +npm run example -- quote_headers_array +``` + ```javascript const csvStream = csv.format({ headers: [ 'header1', 'header2' ], quoteHeaders: [ false, true ] }); @@ -713,7 +579,12 @@ value1a,value2a value1a,value2a ``` -[`examples/formatting/quote_headers_object.example.js`](../examples/formatting/quote_headers_object.example.js) +[`examples/quote_headers_object.example.js`](./examples/quote_headers_object.example.js) + +```sh +npm run example -- quote_headers_object +``` + ```javascript const csvStream = csv.format({ headers: true, quoteHeaders: { header2: true } }); @@ -737,12 +608,17 @@ value1a,value2a value1a,value2a ``` +--- ### Transforming Rows You can transform rows by using the `.transform` method. -[`examples/formatting/transform.example.js`](../examples/formatting/transform.example.js) +[`examples/transform.example.js`](./examples/transform.example.js) + +```sh +npm run example -- transform +``` ```javascript const csvStream = csv @@ -775,7 +651,11 @@ VALUE1A,VALUE2A You can also specify your transform method as an option. -[`examples/formatting/transform_option.example.js`](../examples/formatting/transform_option.example.js) +[`examples/transform_option.example.js`](./examples/transform_option.example.js) + +```sh +npm run example -- transform_option +``` ```javascript const transform = row => ({ @@ -808,7 +688,11 @@ VALUE1A,VALUE2A Transform can also be async by accepting a callback. -[`examples/formatting/transform_async.example.js`](../examples/formatting/transform_async.example.js) +[`examples/transform_async.example.js`](./examples/transform_async.example.js) + +```sh +npm run example -- transform_async +``` ```javascript const csvStream = csv @@ -841,10 +725,15 @@ VALUE1A,VALUE2A VALUE1A,VALUE2A ``` +--- ### Appending To A CSV -[`examples/formatting/append.example.js`](../examples/formatting/append.example.js) +[`examples/append.example.js`](./examples/append.example.js) + +```sh +npm run example -- append +``` In this example a new csv is created then appended to. diff --git a/examples/formatting/append.example.js b/examples/formatting-js/examples/append.example.js similarity index 92% rename from examples/formatting/append.example.js rename to examples/formatting-js/examples/append.example.js index ac6c9c07..1aacea84 100644 --- a/examples/formatting/append.example.js +++ b/examples/formatting-js/examples/append.example.js @@ -1,6 +1,6 @@ const path = require('path'); const fs = require('fs'); -const csv = require('../..'); +const csv = require('@fast-csv/format'); const write = (filestream, rows, options) => { return new Promise((res, rej) => { @@ -59,3 +59,12 @@ createCsv(csvFilePath, [ console.error(err.stack); process.exit(1); }); + +// Output: +// a,b,c +// a1,b1,c1 +// a2,b2,c2 +// a3,b3,c3 +// a4,b4,c4 +// a5,b5,c5 +// a6,b6,c6 diff --git a/examples/formatting/delimiter_option.example.js b/examples/formatting-js/examples/delimiter_option.example.js similarity index 69% rename from examples/formatting/delimiter_option.example.js rename to examples/formatting-js/examples/delimiter_option.example.js index 785cd94c..69bcec87 100644 --- a/examples/formatting/delimiter_option.example.js +++ b/examples/formatting-js/examples/delimiter_option.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const stream = csv.format({ delimiter: '\t' }); stream.pipe(process.stdout); @@ -7,3 +7,8 @@ stream.write(['a', 'b']); stream.write(['a1', 'b1']); stream.write(['a2', 'b2']); stream.end(); + +// Output: +// a b +// a1 b1 +// a2 b2 diff --git a/examples/formatting/escape_option.example.js b/examples/formatting-js/examples/escape_option.example.js similarity index 67% rename from examples/formatting/escape_option.example.js rename to examples/formatting-js/examples/escape_option.example.js index a98668b3..3c5f7ab2 100644 --- a/examples/formatting/escape_option.example.js +++ b/examples/formatting-js/examples/escape_option.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const stream = csv.format({ escape: "'" }); stream.pipe(process.stdout); @@ -8,3 +8,8 @@ stream.write(['"a"', '"b"']); stream.write(['"a1"', '"b1"']); stream.write(['"a2"', '"b2"']); stream.end(); + +// Output: +// "'"a'"","'"b'"" +// "'"a1'"","'"b1'"" +// "'"a2'"","'"b2'"" diff --git a/examples/formatting/format.example.js b/examples/formatting-js/examples/format.example.js similarity index 66% rename from examples/formatting/format.example.js rename to examples/formatting-js/examples/format.example.js index 2621e4c5..14a99020 100644 --- a/examples/formatting/format.example.js +++ b/examples/formatting-js/examples/format.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const stream = csv.format(); stream.pipe(process.stdout); @@ -7,3 +7,8 @@ stream.write(['a', 'b']); stream.write(['a1', 'b1']); stream.write(['a2', 'b2']); stream.end(); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting/hash_array.example.js b/examples/formatting-js/examples/hash_array.example.js similarity index 74% rename from examples/formatting/hash_array.example.js rename to examples/formatting-js/examples/hash_array.example.js index 52fadf71..e5ed69b6 100644 --- a/examples/formatting/hash_array.example.js +++ b/examples/formatting-js/examples/hash_array.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true }); @@ -21,3 +21,10 @@ csvStream.write([ ['header2', 'value2d'], ]); csvStream.end(); + +// Output: +// header,header2 +// value1a,value2a +// value1b,value2b +// value1c,value2c +// value1d,value2d diff --git a/examples/formatting/headers_auto_discovery_hash_array.example.js b/examples/formatting-js/examples/headers_auto_discovery_hash_array.example.js similarity index 74% rename from examples/formatting/headers_auto_discovery_hash_array.example.js rename to examples/formatting-js/examples/headers_auto_discovery_hash_array.example.js index ef379f49..976c0125 100644 --- a/examples/formatting/headers_auto_discovery_hash_array.example.js +++ b/examples/formatting-js/examples/headers_auto_discovery_hash_array.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true }); @@ -21,3 +21,10 @@ csvStream.write([ ['header2', 'value4b'], ]); csvStream.end(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting/headers_auto_discovery_object.example.js b/examples/formatting-js/examples/headers_auto_discovery_object.example.js similarity index 71% rename from examples/formatting/headers_auto_discovery_object.example.js rename to examples/formatting-js/examples/headers_auto_discovery_object.example.js index a36b2c5c..4c089aa8 100644 --- a/examples/formatting/headers_auto_discovery_object.example.js +++ b/examples/formatting-js/examples/headers_auto_discovery_object.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value2a', header2: 'value2b' }); csvStream.write({ header1: 'value3a', header2: 'value3b' }); csvStream.write({ header1: 'value4a', header2: 'value4b' }); csvStream.end(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting/headers_provided_array.example.js b/examples/formatting-js/examples/headers_provided_array.example.js similarity index 67% rename from examples/formatting/headers_provided_array.example.js rename to examples/formatting-js/examples/headers_provided_array.example.js index 2ace4720..06c1af7f 100644 --- a/examples/formatting/headers_provided_array.example.js +++ b/examples/formatting-js/examples/headers_provided_array.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: ['header1', 'header2'] }); @@ -9,3 +9,10 @@ csvStream.write(['value2a', 'value2b']); csvStream.write(['value3a', 'value3b']); csvStream.write(['value4a', 'value4b']); csvStream.end(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting/headers_provided_hash_array.example.js b/examples/formatting-js/examples/headers_provided_hash_array.example.js similarity index 73% rename from examples/formatting/headers_provided_hash_array.example.js rename to examples/formatting-js/examples/headers_provided_hash_array.example.js index 9dbea6e3..f397168e 100644 --- a/examples/formatting/headers_provided_hash_array.example.js +++ b/examples/formatting-js/examples/headers_provided_hash_array.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: ['header1', 'header2'] }); @@ -21,3 +21,10 @@ csvStream.write([ ['h2', 'value4b'], ]); csvStream.end(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting/headers_provided_object.example.js b/examples/formatting-js/examples/headers_provided_object.example.js similarity index 72% rename from examples/formatting/headers_provided_object.example.js rename to examples/formatting-js/examples/headers_provided_object.example.js index a304ecdc..8c5728e0 100644 --- a/examples/formatting/headers_provided_object.example.js +++ b/examples/formatting-js/examples/headers_provided_object.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: ['header2', 'header1'] }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value2a', header2: 'value2b' }); csvStream.write({ header1: 'value3a', header2: 'value3b' }); csvStream.write({ header1: 'value4a', header2: 'value4b' }); csvStream.end(); + +// Output: +// header2,header1 +// value1b,value1a +// value2b,value2a +// value3b,value3a +// value4b,value4a diff --git a/examples/formatting/headers_provided_object_remove_column.example.js b/examples/formatting-js/examples/headers_provided_object_remove_column.example.js similarity index 77% rename from examples/formatting/headers_provided_object_remove_column.example.js rename to examples/formatting-js/examples/headers_provided_object_remove_column.example.js index 85f6f9a5..5ad7958d 100644 --- a/examples/formatting/headers_provided_object_remove_column.example.js +++ b/examples/formatting-js/examples/headers_provided_object_remove_column.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: ['header2'] }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value2a', header2: 'value2b' }); csvStream.write({ header1: 'value3a', header2: 'value3b' }); csvStream.write({ header1: 'value4a', header2: 'value4b' }); csvStream.end(); + +// Output: +// header2 +// value1b +// value2b +// value3b +// value4b diff --git a/examples/formatting/quote_all_columns.example.js b/examples/formatting-js/examples/quote_all_columns.example.js similarity index 69% rename from examples/formatting/quote_all_columns.example.js rename to examples/formatting-js/examples/quote_all_columns.example.js index 3b3438e7..48fbf0f0 100644 --- a/examples/formatting/quote_all_columns.example.js +++ b/examples/formatting-js/examples/quote_all_columns.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true, quoteColumns: true }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// "header1","header2" +// "value1a","value2a" +// "value1a","value2a" +// "value1a","value2a" +// "value1a","value2a" diff --git a/examples/formatting/quote_all_headers.example.js b/examples/formatting-js/examples/quote_all_headers.example.js similarity index 71% rename from examples/formatting/quote_all_headers.example.js rename to examples/formatting-js/examples/quote_all_headers.example.js index ae7151b0..7d1aed4f 100644 --- a/examples/formatting/quote_all_headers.example.js +++ b/examples/formatting-js/examples/quote_all_headers.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true, quoteHeaders: true }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// "header1","header2" +// value1a,value2a +// value1a,value2a +// value1a,value2a +// value1a,value2a diff --git a/examples/formatting/quote_columns_array.example.js b/examples/formatting-js/examples/quote_columns_array.example.js similarity index 72% rename from examples/formatting/quote_columns_array.example.js rename to examples/formatting-js/examples/quote_columns_array.example.js index 470fe8fa..d5fc69b6 100644 --- a/examples/formatting/quote_columns_array.example.js +++ b/examples/formatting-js/examples/quote_columns_array.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: ['header1', 'header2'], quoteColumns: [false, true] }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,"header2" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" diff --git a/examples/formatting/quote_columns_not_headers.example.js b/examples/formatting-js/examples/quote_columns_not_headers.example.js similarity index 73% rename from examples/formatting/quote_columns_not_headers.example.js rename to examples/formatting-js/examples/quote_columns_not_headers.example.js index 5c24fe39..b4fa6bbb 100644 --- a/examples/formatting/quote_columns_not_headers.example.js +++ b/examples/formatting-js/examples/quote_columns_not_headers.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true, quoteColumns: { header2: true }, quoteHeaders: false }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,header2 +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" diff --git a/examples/formatting/quote_columns_object.example.js b/examples/formatting-js/examples/quote_columns_object.example.js similarity index 71% rename from examples/formatting/quote_columns_object.example.js rename to examples/formatting-js/examples/quote_columns_object.example.js index d02019bb..3964a87f 100644 --- a/examples/formatting/quote_columns_object.example.js +++ b/examples/formatting-js/examples/quote_columns_object.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true, quoteColumns: { header2: true } }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,"header2" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" diff --git a/examples/formatting/quote_headers_array.example.js b/examples/formatting-js/examples/quote_headers_array.example.js similarity index 73% rename from examples/formatting/quote_headers_array.example.js rename to examples/formatting-js/examples/quote_headers_array.example.js index e0bd56a7..78118c8b 100644 --- a/examples/formatting/quote_headers_array.example.js +++ b/examples/formatting-js/examples/quote_headers_array.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: ['header1', 'header2'], quoteHeaders: [false, true] }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,"header2" +// value1a,value2a +// value1a,value2a +// value1a,value2a +// value1a,value2a diff --git a/examples/formatting/quote_headers_object.example.js b/examples/formatting-js/examples/quote_headers_object.example.js similarity index 72% rename from examples/formatting/quote_headers_object.example.js rename to examples/formatting-js/examples/quote_headers_object.example.js index 5b2acc82..434c0900 100644 --- a/examples/formatting/quote_headers_object.example.js +++ b/examples/formatting-js/examples/quote_headers_object.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true, quoteHeaders: { header2: true } }); @@ -9,3 +9,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,"header2" +// value1a,value2a +// value1a,value2a +// value1a,value2a +// value1a,value2a diff --git a/examples/formatting/quote_option.examples.js b/examples/formatting-js/examples/quote_option.example.js similarity index 69% rename from examples/formatting/quote_option.examples.js rename to examples/formatting-js/examples/quote_option.example.js index 79a6919d..3711a0d8 100644 --- a/examples/formatting/quote_option.examples.js +++ b/examples/formatting-js/examples/quote_option.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const stream = csv.format({ quote: "'" }); stream.pipe(process.stdout); @@ -8,3 +8,8 @@ stream.write(['a,a', 'b,b']); stream.write(['a1,a1', 'b1,b1']); stream.write(['a2,a2', 'b2,b2']); stream.end(); + +// Output: +// 'a,a','b,b' +// 'a1,a1','b1,b1' +// 'a2,a2','b2,b2' diff --git a/examples/formatting/quote_some_columns_and_headers.example.js b/examples/formatting-js/examples/quote_some_columns_and_headers.example.js similarity index 73% rename from examples/formatting/quote_some_columns_and_headers.example.js rename to examples/formatting-js/examples/quote_some_columns_and_headers.example.js index 48de5766..e5161bb8 100644 --- a/examples/formatting/quote_some_columns_and_headers.example.js +++ b/examples/formatting-js/examples/quote_some_columns_and_headers.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true, @@ -13,3 +13,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,"header2" +// "value1a",value2a +// "value1a",value2a +// "value1a",value2a +// "value1a",value2a diff --git a/examples/formatting/row_delimiter_option.example.js b/examples/formatting-js/examples/row_delimiter_option.example.js similarity index 70% rename from examples/formatting/row_delimiter_option.example.js rename to examples/formatting-js/examples/row_delimiter_option.example.js index a4333d17..43177b50 100644 --- a/examples/formatting/row_delimiter_option.example.js +++ b/examples/formatting-js/examples/row_delimiter_option.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const stream = csv.format({ rowDelimiter: '||' }); stream.pipe(process.stdout); @@ -7,3 +7,6 @@ stream.write(['a', 'b']); stream.write(['a1', 'b1']); stream.write(['a2', 'b2']); stream.end(); + +// Output: +// a,b||a1,b1||a2,b2 diff --git a/__tests__/formatter/__fixtures__/.gitkeep b/examples/formatting-js/examples/tmp/.gitkeep similarity index 100% rename from __tests__/formatter/__fixtures__/.gitkeep rename to examples/formatting-js/examples/tmp/.gitkeep diff --git a/examples/formatting/transform.example.js b/examples/formatting-js/examples/transform.example.js similarity index 76% rename from examples/formatting/transform.example.js rename to examples/formatting-js/examples/transform.example.js index 10974525..54bce78e 100644 --- a/examples/formatting/transform.example.js +++ b/examples/formatting-js/examples/transform.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true }).transform(row => ({ header1: row.header1.toUpperCase(), @@ -12,3 +12,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,header2 +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A diff --git a/examples/formatting/transform_async.example.js b/examples/formatting-js/examples/transform_async.example.js similarity index 78% rename from examples/formatting/transform_async.example.js rename to examples/formatting-js/examples/transform_async.example.js index 619ca0d7..97e80732 100644 --- a/examples/formatting/transform_async.example.js +++ b/examples/formatting-js/examples/transform_async.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const csvStream = csv.format({ headers: true }).transform((row, cb) => { setImmediate(() => @@ -16,3 +16,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,header2 +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A diff --git a/examples/formatting/transform_option.example.js b/examples/formatting-js/examples/transform_option.example.js similarity index 76% rename from examples/formatting/transform_option.example.js rename to examples/formatting-js/examples/transform_option.example.js index 6814b04d..50e0f927 100644 --- a/examples/formatting/transform_option.example.js +++ b/examples/formatting-js/examples/transform_option.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const transform = row => ({ header1: row.header1.toUpperCase(), @@ -14,3 +14,10 @@ csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.write({ header1: 'value1a', header2: 'value2a' }); csvStream.end(); + +// Output: +// header1,header2 +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A diff --git a/examples/formatting/write.example.js b/examples/formatting-js/examples/write.example.js similarity index 58% rename from examples/formatting/write.example.js rename to examples/formatting-js/examples/write.example.js index 000dd3b1..aed7b1df 100644 --- a/examples/formatting/write.example.js +++ b/examples/formatting-js/examples/write.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const rows = [ ['a', 'b'], @@ -6,3 +6,8 @@ const rows = [ ['a2', 'b2'], ]; csv.write(rows).pipe(process.stdout); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting/write_to_buffer.example.js b/examples/formatting-js/examples/write_to_buffer.example.js similarity index 64% rename from examples/formatting/write_to_buffer.example.js rename to examples/formatting-js/examples/write_to_buffer.example.js index a92d9845..5709e5bc 100644 --- a/examples/formatting/write_to_buffer.example.js +++ b/examples/formatting-js/examples/write_to_buffer.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const rows = [ ['a', 'b'], @@ -6,3 +6,8 @@ const rows = [ ['a2', 'b2'], ]; csv.writeToBuffer(rows).then(data => console.log(data.toString())); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-js/examples/write_to_path.example.js b/examples/formatting-js/examples/write_to_path.example.js new file mode 100644 index 00000000..77e19bff --- /dev/null +++ b/examples/formatting-js/examples/write_to_path.example.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const path = require('path'); +const csv = require('@fast-csv/format'); + +const rows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; +const filePath = path.resolve(__dirname, 'tmp', 'tmp.csv'); +csv.writeToPath(filePath, rows) + .on('error', err => console.error(err)) + .on('finish', () => { + console.log('File Contents:'); + console.log(fs.readFileSync(filePath).toString()); + }); + +// Output: +// File Contents: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting/write_to_stream.example.js b/examples/formatting-js/examples/write_to_stream.example.js similarity index 58% rename from examples/formatting/write_to_stream.example.js rename to examples/formatting-js/examples/write_to_stream.example.js index 0a49969b..52f5c59a 100644 --- a/examples/formatting/write_to_stream.example.js +++ b/examples/formatting-js/examples/write_to_stream.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const rows = [ ['a', 'b'], @@ -6,3 +6,8 @@ const rows = [ ['a2', 'b2'], ]; csv.writeToStream(process.stdout, rows); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting/write_to_string.example.js b/examples/formatting-js/examples/write_to_string.example.js similarity index 62% rename from examples/formatting/write_to_string.example.js rename to examples/formatting-js/examples/write_to_string.example.js index 4b6e4b99..fccc875f 100644 --- a/examples/formatting/write_to_string.example.js +++ b/examples/formatting-js/examples/write_to_string.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const rows = [ ['a', 'b'], @@ -6,3 +6,8 @@ const rows = [ ['a2', 'b2'], ]; csv.writeToString(rows).then(data => console.log(data)); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting/write_to_string_no_headers.example.js b/examples/formatting-js/examples/write_to_string_no_headers.example.js similarity index 80% rename from examples/formatting/write_to_string_no_headers.example.js rename to examples/formatting-js/examples/write_to_string_no_headers.example.js index aabe22e3..beb62e55 100644 --- a/examples/formatting/write_to_string_no_headers.example.js +++ b/examples/formatting-js/examples/write_to_string_no_headers.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/format'); const data = [ { a: 'a1', b: 'b1' }, @@ -13,3 +13,7 @@ csv.writeToString(data, { headers: false }) console.error(err.stack); process.exit(1); }); + +// Output: +// a1,b1 +// a2,b2 diff --git a/examples/write_to_string_transform.example.js b/examples/formatting-js/examples/write_to_string_transform.example.js similarity index 78% rename from examples/write_to_string_transform.example.js rename to examples/formatting-js/examples/write_to_string_transform.example.js index e788d076..cbfb998b 100644 --- a/examples/write_to_string_transform.example.js +++ b/examples/formatting-js/examples/write_to_string_transform.example.js @@ -1,4 +1,4 @@ -const csv = require('../'); +const csv = require('@fast-csv/format'); const data = [ { a: 'a1', b: 'b1' }, @@ -13,3 +13,8 @@ const transform = row => ({ csv.writeToString(data, { headers: true, transform }) .then(formattedCsv => console.log(formattedCsv)) .catch(err => console.error(err.stack)); + +// Output: +// A,B +// a1,b1 +// a2,b2 diff --git a/examples/formatting-js/package.json b/examples/formatting-js/package.json new file mode 100644 index 00000000..215bcc7c --- /dev/null +++ b/examples/formatting-js/package.json @@ -0,0 +1,13 @@ +{ + "name": "@fast-csv/format-js-examples", + "private": true, + "description": "fast-csv formatting examples", + "dependencies": { + "example-runner": "^4.0.0", + "@fast-csv/format": "^4.0.0" + }, + "scripts": { + "all-examples": "run-examples all", + "example": "run-examples" + } +} diff --git a/examples/formatting/write_to_path.example.js b/examples/formatting/write_to_path.example.js deleted file mode 100644 index e41af126..00000000 --- a/examples/formatting/write_to_path.example.js +++ /dev/null @@ -1,11 +0,0 @@ -const path = require('path'); -const csv = require('../../'); - -const rows = [ - ['a', 'b'], - ['a1', 'b1'], - ['a2', 'b2'], -]; -csv.writeToPath(path.resolve(__dirname, 'tmp.csv'), rows) - .on('error', err => console.error(err)) - .on('finish', () => console.log('Done writing.')); diff --git a/examples/parsing-js/.eslintrc.js b/examples/parsing-js/.eslintrc.js new file mode 100644 index 00000000..6571794b --- /dev/null +++ b/examples/parsing-js/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + parserOptions: { + project: null, + }, + rules: { + 'no-console': 0, + }, +}; diff --git a/docs/parsing.md b/examples/parsing-js/README.md similarity index 56% rename from docs/parsing.md rename to examples/parsing-js/README.md index 87d09df9..fbb308ec 100644 --- a/docs/parsing.md +++ b/examples/parsing-js/README.md @@ -1,189 +1,48 @@ -# Parsing - -* [Options](#parsing-options) -* [Events](#parsing-events) -* [Parsing Methods](#parsing-methods) - * [`csv.parse`](#csv-parse) - * [`csv.parseStream`](#csv-parse-stream) - * [`csv.parseFile`](#csv-parse-path) - * [`csv.parseString`](#csv-parse-string) -* [Examples](#examples) - * [Manual Write](#csv-parse-manual-write) - * [Alternate Delimiters](#csv-parse-alternate-delimiters) - * [First Row As Headers](#csv-parse-first-row-as-headers) - * [Custom Headers](#csv-parse-custom-headers) - * [Renaming Headers](#csv-parse-renaming-headers) - * [Transforming Headers](#csv-parse-transforming-headers) - * [Skipping Columns](#csv-parse-skipping-columns) - * [Ignoring Empty Rows](#csv-parse-ignoring-empty-rows) - * [Transforming Rows](#csv-parse-transforming) - * [Validating Rows](#csv-parse-validation) - * [Max Rows](#max-rows) - * [Skip Rows](#skip-rows) - * [Skip Lines](#skip-lines) - - -## Options - -* `objectMode: {boolean} = true`: Ensure that `data` events have an object emitted rather than the stringified version set to false to have a stringified buffer. -* `delimiter: {string} = ','`: If your data uses an alternate delimiter such as `;` or `\t`. - * **NOTE** When specifying an alternate `delimiter` you may only pass in a single character delimiter -* `quote: {string} = '"'`: The character to use to quote fields that contain a delimiter. If you set to `null` then all quoting will be ignored. - * `"first,name",last name` -* `escape: {string} = '"'`: The character to used tp escape quotes inside of a quoted field. - * `i.e`: `First,"Name"' => '"First,""Name"""` -* `headers: {boolean|string[]|(string[]) => string[])} = false`: - * If you want the first row to be treated as headers then set to `true` - * If there is not a headers row and you want to provide one then set to a `string[]` - * If you wish to discard the first row and use your own headers set to a `string[]` and set the `renameHeaders` option to `true` - * If you wish to transform the headers you can provide a transform function. - * **NOTE** This will always rename the headers - * **NOTE** If headers either parsed, provided or transformed are NOT unique, then an error will be emitted and the stream will stop parsing. -* `renameHeaders: {boolean} = false`: If you want the first line of the file to be removed and replaced by the one provided in the `headers` option. - * **NOTE** This option should only be used if the `headers` option is a `string[]` - * **NOTE** If the `headers` option is a function then this option is always set to true. -* `ignoreEmpty: {boolean} = false`: If you wish to ignore empty rows. - * **NOTE** this will discard columns that are all white space or delimiters. -* `comment: {string} = null`: If your CSV contains comments you can use this option to ignore lines that begin with the specified character (e.g. `#`). -* `discardUnmappedColumns: {boolean} = false`: If you want to discard columns that do not map to a header. - * **NOTE** this is only valid in the case that there are headers and the number of fields parsed is greater than the number of header fields. -* `strictColumnHandling: {boolean} = false`: If you want to consider empty lines/lines with too few fields as invalid and emit a `data-invalid` event - * **NOTE** This option is only considered when `headers` are present. -* `trim: {boolean} = false`: Set to `true` to trim all fields -* `rtrim: {boolean} = false`: Set to `true` to right trim all fields. -* `ltrim: {boolean} = false`: Set to `true` to left trim all fields. -* `encoding: {string} = 'utf8'`: Passed to [StringDecoder](https://nodejs.org/api/string_decoder.html#string_decoder_new_stringdecoder_encoding) when decoding incoming buffers. Change if incoming content is not 'utf8' encoded. -* `maxRows: {number} = 0`: If number is `> 0` the specified number of rows will be parsed.(e.g. `100` would return the first 100 rows of data). -* `skipRows: {number} = 0`: If number is `> 0` the specified number of **parsed** rows will be skipped. -* `skipLines: {number} = 0`: If number is `> 0` the specified number of lines will be skipped. - - -## Events - -* `data`: Emitted when a record is parsed. - * If headers are present then all rows will be an object. - * If headers are not present then all rows will be an array. - * **NOTE** if `objectMode` is set to false then all rows will be a buffer with a JSON row. -* `data-invalid`: Emitted if there was invalid row encounted; - * Emitted when a `validate` function is provided and an invalid row is encountered. - * Emitted when `strictColumnHandling` is `true` and a row with a different number of fields than headers is encountered. - - -## Methods - - -**`csv.parse([options]): CsvParserStream`** - -Creates a Csv Parsing Stream that can be piped or written to. - -This is the main entrypoint and is used by all the other parsing helpers. +`@fast-csv/parse` parsing examples. -```javascript +## Usage -//creates a stream you can pipe -const stream = csv.parse() +To run all examples -stream - .on('error', error => console.error(error)) - .on('data', row => console.log(row)) - .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +```sh +npm run all-examples ``` -To pipe to the stream from a file you can do the following. - -```javascript -const csv = require('fast-csv'); +To see a list of all available examples -fs.createReadStream('my.csv') - .pipe(csv.parse()) - .on('error', error => console.error(error)) - .on('data', row => console.log(`ROW=${JSON.stringify(row)}`)) - .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +```sh +npm run example ``` -```javascript -const csv = require('fast-csv'); - -const fileStream = fs.createReadStream("my.csv"); -const parser = csv.parse(); +To run a sepcific example -fileStream - .pipe(parser) - .on('error', error => console.error(error)) - .on('readable', () => { - for (let row = parser.read(); row; row = parser.read()) { - console.log(`ROW=${JSON.stringify(row)}`); - } - }) - .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`)); -``` - - -**`csv.parseStream(readableStream[, options]): CsvParserStream`** - -Accepts a readable stream and pipes it to a `CsvParserStream`. - -```javascript -const stream = fs.createReadStream('./path/to/my.csv'); - -csv - .parseStream(stream) - .on('error', error => console.error(error)) - .on('data', row => console.log(row)) - .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); - +```sh +npm run example -- {example_name} ``` - -**`csv.parseFile(path[, options]): CsvParserStream`** - -Parses a file from the specified path and returns the `CsvParserStream`. - -```javascript -const csv = require('fast-csv'); - -csv - .parseFile('./path/to/my.csv') - .on('error', error => console.error(error)) - .on('data', row => console.log(row)) - .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); -``` - - -**`csv.parseString(string[, options]): CsvParserStream`** - -This method parses a string and returns the `CsvParserStream`. - -```javascript -const { EOL } = require('os'); -const csv = require('fast-csv'); - -const CSV_STRING = [ - 'a,b', - 'a1,b1', - 'a2,b2', -].join(EOL); - -csv - .parseString(CSV_STRING, { headers: true }) - .on('error', error => console.error(error)) - .on('data', row => console.log(row)) - .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); -``` - - ## Examples -All of the examples below can be found in [examples/parsing](../examples/parsing) directory. - - - - - +* [Manual Write](#manual-write) +* [Alternate Delimiters](#alternate-delimiters) +* [First Row As Headers](#first-row-as-headers) +* [Custom Headers](#custom-headers) +* [Renaming Headers](#renaming-headers) +* [Transforming Headers](#transforming-headers) +* [Skipping Columns](#skipping-columns) +* [Ignoring Empty Rows](#ignoring-empty-rows) +* [Transforming Rows](#transforming) +* [Validating Rows](#validation) +* [Max Rows](#max-rows) +* [Skip Rows](#skip-rows) +* [Skip Lines](#skip-lines) + + ### Manual Write -[`examples/parsing/manual_write.example.js`](../examples/parsing/manual_write.examples.js) - +[`examples/manual_write.example.js`](./examples/manual_write.example.js) +```sh +npm run example -- manual_write +``` ```javascript const csv = require('fast-csv'); @@ -204,14 +63,16 @@ Expected output { header1: 'col1', header2: 'col2' } Parsed 1 rows ``` - - +--- + ### Alternate Delimiter You can provide a `delimiter` option to change the delimiter from a `,` character. -[`examples/parsing/alternate_delimiter.example.js`](../examples/parsing/alternate_delimiter.examples.js) - +[`examples/alternate_delimiter.example.js`](./examples/alternate_delimiter.example.js) +```sh +npm run example -- alternate_delimiter +``` ```javascript const CSV_STRING = [ 'a1\tb1', @@ -235,16 +96,18 @@ Expected output [ 'a2', 'b2' ] Parsed 2 rows ``` - - +--- + ### First Row As Headers If you expect the first line your CSV to be headers you may pass in a `headers` option. Setting the `headers` option to `true` will cause change each row to an object rather than an array. -[`examples/parsing/first_row_as_headers.example.js`](../examples/parsing/first_row_as_headers.example.js) - +[`examples/first_row_as_headers.example.js`](./examples/first_row_as_headers.example.js) +```sh +npm run example -- first_row_as_headers +``` ```javascript const { EOL } = require('os'); @@ -270,16 +133,18 @@ Expected output { a: 'a2', b: 'b2' } Parsed 2 rows ``` - - +--- + ### Custom Headers You may alternatively pass an array of header names. **NOTE** The order of the headers array will should match the order of fields in the CSV, otherwise the data columns will not match. -[`examples/parsing/custom_headers.example.js`](../examples/parsing/custom_headers.example.js) - +[`examples/custom_headers.example.js`](./examples/custom_headers.example.js) +```sh +npm run example -- custom_headers +``` ```javascript const { EOL } = require('os'); @@ -306,14 +171,16 @@ Expected output { a: 'a2', b: 'b2' } Parsed 2 rows ``` - - +--- + ### Renaming Headers If the CSV contains a header row but you want to provide custom headers you can pass an array of headers, and set `renameHeaders` to true. -[`examples/parsing/rename_headers.example.js`](../examples/parsing/rename_headers.example.js) - +[`examples/rename_headers.example.js`](./examples/rename_headers.example.js) +```sh +npm run example -- rename_headers +``` ```javascript const { EOL } = require('os'); @@ -341,14 +208,16 @@ Expected output { a: 'a2', b: 'b2' } Parsed 2 rows ``` - - +--- + ### Transforming Headers If the CSV contains a header row but you want transform the headers you can provide a function to the `headers` option. -[`examples/parsing/rename_headers.example.js`](../examples/parsing/rename_headers.example.js) - +[`examples/transform_headers.example.js`](./examples/transform_headers.example.js) +```sh +npm run example -- transform_headers +``` ```javascript const { EOL } = require('os'); @@ -374,14 +243,16 @@ Expected output { HEADER1: 'a2', HEADER2: 'b2' } Parsed 2 rows ``` - - +--- + ### Skipping Columns To omit some of the data columns you may not need, pass a sparse array as `headers`. -[`examples/parsing/skipping_columns.example.js`](../examples/parsing/skipping_columns.example.js) - +[`examples/skipping_columns.example.js`](./examples/skipping_columns.example.js) +```sh +npm run example -- skipping_columns +``` ```javascript const CSV_STRING = [ 'a1,b1,c1', @@ -406,16 +277,18 @@ Expected output { a: 'a2', c: 'c2' } Parsed 2 rows ``` - - +--- + ### Ignoring Empty Rows If your data includes empty rows, the sort Excel might include at the end of the file for instance, you can ignore these by including the `ignoreEmpty` option. Any rows consisting of nothing but empty strings and/or commas will be skipped, without emitting a 'data', 'data-invalid', or 'error' event. -[`examples/parsing/ignore_empty_rows.example.js`](../examples/parsing/ignore_empty_rows.example.js) - +[`examples/ignore_empty_rows.example.js`](./examples/ignore_empty_rows.example.js) +```sh +npm run example -- ignore_empty_rows +``` ```javascript const CSV_STRING = [ 'a1,b1', @@ -443,14 +316,16 @@ Expected output [ 'a2', 'b2' ] Parsed 2 rows ``` - - +--- + ### Transforming You can transform data by providing a transform function. What is returned from the transform function will be provided to validate and emitted as a row. -[`examples/parsing/transform.example.js`](../examples/parsing/transform.example.js) - +[`examples/transform.example.js`](./examples/transform.example.js) +```sh +npm run example -- transform +``` ```javascript const CSV_STRING = [ 'firstName,lastName', @@ -485,8 +360,10 @@ Parsed 3 rows `fast-csv` also supports async transformation with a callback. -[`examples/parsing/transform_async.example.js`](../examples/parsing/transform_async.example.js) - +[`examples/transform_async.example.js`](./examples/transform_async.example.js) +```sh +npm run example -- transform_async +``` ```javascript const CSV_STRING = [ 'firstName,lastName', @@ -521,13 +398,16 @@ Expected output Parsed 3 rows ``` - +--- + ### Validation You can validate each row in the CSV by providing a validate handler. If a row is invalid then a `data-invalid` event will be emitted with the row and the index. -[`examples/parsing/validate.example.js`](../examples/parsing/validate.example.js) - +[`examples/validate.example.js`](./examples/validate.example.js) +```sh +npm run example -- validate +``` ```javascript const CSV_STRING = [ 'firstName,lastName', @@ -559,7 +439,10 @@ Parsed 2 rows `fast-csv` also supports async validation, with a callback. -[`examples/parsing/validate_async.example.js`](../examples/parsing/validate_async.example.js) +[`examples/validate_async.example.js`](./examples/validate_async.example.js) +```sh +npm run example -- validate_async +``` ```javascript const CSV_STRING = [ 'firstName,lastName', @@ -584,15 +467,18 @@ stream.end(); Expected output ``` -Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] +Invalid [row={"firstName":"bob","lastName":"yukon"}] Valid [row={"firstName":"sally","lastName":"yukon"}] Valid [row={"firstName":"timmy","lastName":"yukon"}] -Parsed 2 rows +Parsed 3 rows ``` Sometimes you may wish to provide a reason that the row was invalid, you can use the callback to provide additional info. -[`examples/parsing/validate_with_reason.example.js`](../examples/parsing/validate_with_reason.example.js) +[`examples/validate_with_reason.example.js`](./examples/validate_with_reason.example.js) +```sh +npm run example -- validate_with_reason +``` ```javascript const CSV_STRING = [ 'firstName,lastName', @@ -628,12 +514,16 @@ Valid [row={"firstName":"sally","lastName":"yukon"}] Valid [row={"firstName":"timmy","lastName":"yukon"}] Parsed 2 rows ``` - +--- -[`examples/parsing/max_rows.example.example.js`](../examples/parsing/max_rows.example.js) +### Max Rows In the following example there are 10 rows, but only 5 will be parsed because of the `maxRows` option. +[`examples/max_rows.example.example.js`](./examples/max_rows.example.js) +```sh +npm run example -- max_rows +``` ```javascript const rows = [ 'header1,header2\n', @@ -669,14 +559,18 @@ Expected output { header1: 'col5', header2: 'col5' } Parsed 5 rows ``` - +--- -[`examples/parsing/skip_rows.example.example.js`](../examples/parsing/skip_rows.example.js) +### Skip Rows In the following example the first 2 rows are skipped. **NOTE** Notice how the header row is not skipped, only the row. +[`examples/skip_rows.example.example.js`](./examples/skip_rows.example.js) +```sh +npm run example -- skip_rows +``` ```javascript const rows = [ 'header1,header2\n', @@ -707,14 +601,18 @@ Expected output { header1: 'col6', header2: 'col6' } Parsed 4 rows ``` - +--- -[`examples/parsing/skip_lines.example.example.js`](../examples/parsing/skip_lines.example.js) +### Skip Lines In the following example the first 2 lines are skipped. **NOTE** Notice how the headers come from the third line because the first two are skipped. +[`examples/skip_lines.example.example.js`](./examples/skip_lines.example.js) +```sh +npm run example -- skip_lines +``` ```javascript const csv = require('../../'); @@ -748,5 +646,3 @@ Expected output Parsed 4 rows ``` - - diff --git a/examples/parsing-js/assets/snake_case_users.csv b/examples/parsing-js/assets/snake_case_users.csv new file mode 100644 index 00000000..68d197a2 --- /dev/null +++ b/examples/parsing-js/assets/snake_case_users.csv @@ -0,0 +1,10 @@ +id,first_name,last_name,address +1,Bob,Yukon,1111 State St. Yukon AK +2,Sally,Yukon,1111 State St. Yukon AK +3,Bobby,Yukon,1111 State St. Yukon AK +4,Jane,Yukon,1111 State St. Yukon AK +5,Dick,Yukon,1111 State St. Yukon AK +6,John,Doe,1112 State St. Yukon AK +7,Jane,Doe,1113 State St. Yukon AK +8,Billy,Doe,1112 State St. Yukon AK +9,Edith,Doe,1112 State St. Yukon AK \ No newline at end of file diff --git a/examples/parsing/alternate_delimiter.example.js b/examples/parsing-js/examples/alternate_delimiter.example.js similarity index 76% rename from examples/parsing/alternate_delimiter.example.js rename to examples/parsing-js/examples/alternate_delimiter.example.js index 797fa66e..2b8bf16b 100644 --- a/examples/parsing/alternate_delimiter.example.js +++ b/examples/parsing-js/examples/alternate_delimiter.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['a1\tb1', 'a2\tb2'].join(EOL); @@ -11,3 +11,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// [ 'a1', 'b1' ] +// [ 'a2', 'b2' ] +// Parsed 2 rows diff --git a/examples/parsing/custom_headers.example.js b/examples/parsing-js/examples/custom_headers.example.js similarity index 74% rename from examples/parsing/custom_headers.example.js rename to examples/parsing-js/examples/custom_headers.example.js index 86c9ced4..bb1cf2e4 100644 --- a/examples/parsing/custom_headers.example.js +++ b/examples/parsing-js/examples/custom_headers.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['a1,b1', 'a2,b2'].join(EOL); @@ -11,3 +11,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing/first_row_as_headers.example.js b/examples/parsing-js/examples/first_row_as_headers.example.js similarity index 74% rename from examples/parsing/first_row_as_headers.example.js rename to examples/parsing-js/examples/first_row_as_headers.example.js index dc3a6f77..7d102e6c 100644 --- a/examples/parsing/first_row_as_headers.example.js +++ b/examples/parsing-js/examples/first_row_as_headers.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL); @@ -11,3 +11,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing/ignore_empty_rows.example.js b/examples/parsing-js/examples/ignore_empty_rows.example.js similarity index 77% rename from examples/parsing/ignore_empty_rows.example.js rename to examples/parsing-js/examples/ignore_empty_rows.example.js index b211a756..a19cdd48 100644 --- a/examples/parsing/ignore_empty_rows.example.js +++ b/examples/parsing-js/examples/ignore_empty_rows.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['a1,b1', ',', 'a2,b2', ' ,\t', ''].join(EOL); @@ -11,3 +11,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// [ 'a1', 'b1' ] +// [ 'a2', 'b2' ] +// Parsed 2 rows diff --git a/examples/parsing/manual_write.example.js b/examples/parsing-js/examples/manual_write.example.js similarity index 72% rename from examples/parsing/manual_write.example.js rename to examples/parsing-js/examples/manual_write.example.js index 9dd0a7e9..827ec5a7 100644 --- a/examples/parsing/manual_write.example.js +++ b/examples/parsing-js/examples/manual_write.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const stream = csv .parse({ headers: true }) @@ -9,3 +9,7 @@ const stream = csv stream.write('header1,header2\n'); stream.write('col1,col2'); stream.end(); + +// Output: +// { header1: 'col1', header2: 'col2' } +// Parsed 1 rows diff --git a/examples/parsing/max_rows.example.js b/examples/parsing-js/examples/max_rows.example.js similarity index 65% rename from examples/parsing/max_rows.example.js rename to examples/parsing-js/examples/max_rows.example.js index 261f92bf..4dc2f4c5 100644 --- a/examples/parsing/max_rows.example.js +++ b/examples/parsing-js/examples/max_rows.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const rows = [ 'header1,header2\n', @@ -22,3 +22,11 @@ const stream = csv rows.forEach(row => stream.write(row)); stream.end(); + +// Output: +// { header1: 'col1', header2: 'col1' } +// { header1: 'col2', header2: 'col2' } +// { header1: 'col3', header2: 'col3' } +// { header1: 'col4', header2: 'col4' } +// { header1: 'col5', header2: 'col5' } +// Parsed 5 rows diff --git a/examples/parsing/parse_string.example.js b/examples/parsing-js/examples/parse_string.example.js similarity index 60% rename from examples/parsing/parse_string.example.js rename to examples/parsing-js/examples/parse_string.example.js index 888a2abd..e481abfc 100644 --- a/examples/parsing/parse_string.example.js +++ b/examples/parsing-js/examples/parse_string.example.js @@ -1,9 +1,14 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL); -csv.fromString(CSV_STRING, { headers: true }) +csv.parseString(CSV_STRING, { headers: true }) .on('error', error => console.error(error)) .on('data', row => console.log(row)) .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing-js/examples/pipe.example.js b/examples/parsing-js/examples/pipe.example.js new file mode 100644 index 00000000..a88a9346 --- /dev/null +++ b/examples/parsing-js/examples/pipe.example.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const path = require('path'); +const csv = require('@fast-csv/parse'); + +fs.createReadStream(path.resolve(__dirname, '..', 'assets', 'snake_case_users.csv')) + .pipe(csv.parse()) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); + +// Output: +// [ 'id', 'first_name', 'last_name', 'address' ] +// [ '1', 'Bob', 'Yukon', '1111 State St. Yukon AK' ] +// [ '2', 'Sally', 'Yukon', '1111 State St. Yukon AK' ] +// [ '3', 'Bobby', 'Yukon', '1111 State St. Yukon AK' ] +// [ '4', 'Jane', 'Yukon', '1111 State St. Yukon AK' ] +// [ '5', 'Dick', 'Yukon', '1111 State St. Yukon AK' ] +// [ '6', 'John', 'Doe', '1112 State St. Yukon AK' ] +// [ '7', 'Jane', 'Doe', '1113 State St. Yukon AK' ] +// [ '8', 'Billy', 'Doe', '1112 State St. Yukon AK' ] +// [ '9', 'Edith', 'Doe', '1112 State St. Yukon AK' ] +// Parsed 10 rows diff --git a/examples/parsing/rename_headers.example.js b/examples/parsing-js/examples/rename_headers.example.js similarity index 76% rename from examples/parsing/rename_headers.example.js rename to examples/parsing-js/examples/rename_headers.example.js index 4de30741..ea7c961c 100644 --- a/examples/parsing/rename_headers.example.js +++ b/examples/parsing-js/examples/rename_headers.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL); @@ -11,3 +11,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing/skip_lines.example.js b/examples/parsing-js/examples/skip_lines.example.js similarity index 67% rename from examples/parsing/skip_lines.example.js rename to examples/parsing-js/examples/skip_lines.example.js index d43eae1d..0b2a9288 100644 --- a/examples/parsing/skip_lines.example.js +++ b/examples/parsing-js/examples/skip_lines.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const rows = [ 'skip1_header1,skip1_header2\n', @@ -18,3 +18,10 @@ const stream = csv rows.forEach(row => stream.write(row)); stream.end(); + +// Output: +// { header1: 'col1', header2: 'col1' } +// { header1: 'col2', header2: 'col2' } +// { header1: 'col3', header2: 'col3' } +// { header1: 'col4', header2: 'col4' } +// Parsed 4 rows diff --git a/examples/parsing/skip_rows.example.js b/examples/parsing-js/examples/skip_rows.example.js similarity index 65% rename from examples/parsing/skip_rows.example.js rename to examples/parsing-js/examples/skip_rows.example.js index 69a8e6af..cc5519b9 100644 --- a/examples/parsing/skip_rows.example.js +++ b/examples/parsing-js/examples/skip_rows.example.js @@ -1,4 +1,4 @@ -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const rows = [ 'header1,header2\n', @@ -18,3 +18,10 @@ const stream = csv rows.forEach(row => stream.write(row)); stream.end(); + +// Output: +// { header1: 'col3', header2: 'col3' } +// { header1: 'col4', header2: 'col4' } +// { header1: 'col5', header2: 'col5' } +// { header1: 'col6', header2: 'col6' } +// Parsed 4 rows diff --git a/examples/parsing/skipping_columns.example.js b/examples/parsing-js/examples/skipping_columns.example.js similarity index 75% rename from examples/parsing/skipping_columns.example.js rename to examples/parsing-js/examples/skipping_columns.example.js index 5b1d4bbf..b887a0bf 100644 --- a/examples/parsing/skipping_columns.example.js +++ b/examples/parsing-js/examples/skipping_columns.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['a1,b1,c1', 'a2,b2,c2'].join(EOL); @@ -11,3 +11,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// { a: 'a1', c: 'c1' } +// { a: 'a2', c: 'c2' } +// Parsed 2 rows diff --git a/examples/parsing/transform.example.js b/examples/parsing-js/examples/transform.example.js similarity index 67% rename from examples/parsing/transform.example.js rename to examples/parsing-js/examples/transform.example.js index 3f9b2d98..f730b1ec 100644 --- a/examples/parsing/transform.example.js +++ b/examples/parsing-js/examples/transform.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); @@ -16,3 +16,9 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"} +// {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"} +// {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"} +// Parsed 3 rows diff --git a/examples/parsing/transform_async.example.js b/examples/parsing-js/examples/transform_async.example.js similarity index 71% rename from examples/parsing/transform_async.example.js rename to examples/parsing-js/examples/transform_async.example.js index 69a4be11..3a5e3608 100644 --- a/examples/parsing/transform_async.example.js +++ b/examples/parsing-js/examples/transform_async.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); @@ -20,3 +20,9 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"} +// {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"} +// {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"} +// Parsed 3 rows diff --git a/examples/parsing/transform_headers.example.js b/examples/parsing-js/examples/transform_headers.example.js similarity index 73% rename from examples/parsing/transform_headers.example.js rename to examples/parsing-js/examples/transform_headers.example.js index 35a39e31..6da0fb79 100644 --- a/examples/parsing/transform_headers.example.js +++ b/examples/parsing-js/examples/transform_headers.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL); @@ -13,3 +13,8 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// { HEADER1: 'a1', HEADER2: 'b1' } +// { HEADER1: 'a2', HEADER2: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing/validate.example.js b/examples/parsing-js/examples/validate.example.js similarity index 70% rename from examples/parsing/validate.example.js rename to examples/parsing-js/examples/validate.example.js index 36a09c15..eb3c2ee7 100644 --- a/examples/parsing/validate.example.js +++ b/examples/parsing-js/examples/validate.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); @@ -15,3 +15,9 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] +// Valid [row={"firstName":"sally","lastName":"yukon"}] +// Valid [row={"firstName":"timmy","lastName":"yukon"}] +// Parsed 3 rows diff --git a/examples/parsing/validate_async.example.js b/examples/parsing-js/examples/validate_async.example.js similarity index 71% rename from examples/parsing/validate_async.example.js rename to examples/parsing-js/examples/validate_async.example.js index 35f24c9b..0dc5ca31 100644 --- a/examples/parsing/validate_async.example.js +++ b/examples/parsing-js/examples/validate_async.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); @@ -15,3 +15,9 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// Invalid [row={"firstName":"bob","lastName":"yukon"}] +// Valid [row={"firstName":"sally","lastName":"yukon"}] +// Valid [row={"firstName":"timmy","lastName":"yukon"}] +// Parsed 3 rows diff --git a/examples/parsing/validate_with_reason.example.js b/examples/parsing-js/examples/validate_with_reason.example.js similarity index 74% rename from examples/parsing/validate_with_reason.example.js rename to examples/parsing-js/examples/validate_with_reason.example.js index 5137d00c..8de680f6 100644 --- a/examples/parsing/validate_with_reason.example.js +++ b/examples/parsing-js/examples/validate_with_reason.example.js @@ -1,5 +1,5 @@ const { EOL } = require('os'); -const csv = require('../../'); +const csv = require('@fast-csv/parse'); const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); @@ -21,3 +21,9 @@ const stream = csv stream.write(CSV_STRING); stream.end(); + +// Output: +// Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] [reason=Name is bob] +// Valid [row={"firstName":"sally","lastName":"yukon"}] +// Valid [row={"firstName":"timmy","lastName":"yukon"}] +// Parsed 3 rows diff --git a/examples/parsing-js/package-lock.json b/examples/parsing-js/package-lock.json new file mode 100644 index 00000000..89b1d2b2 --- /dev/null +++ b/examples/parsing-js/package-lock.json @@ -0,0 +1,568 @@ +{ + "name": "@fast-csv/parse-js-examples", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@fast-csv/parse": { + "version": "4.0.0", + "requires": { + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + }, + "dependencies": { + "@sinonjs/commons": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + }, + "lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" + }, + "nise": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } + } + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, + "@types/node": { + "version": "12.12.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", + "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" + }, + "@types/yargs": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "fast-glob": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", + "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2" + } + }, + "fastq": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", + "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", + "requires": { + "reusify": "^1.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" + }, + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} diff --git a/examples/parsing-js/package.json b/examples/parsing-js/package.json new file mode 100644 index 00000000..169e6438 --- /dev/null +++ b/examples/parsing-js/package.json @@ -0,0 +1,15 @@ +{ + "name": "@fast-csv/parse-js-examples", + "private": true, + "description": "fast-csv parsing examples", + "scripts": { + "all-examples": "run-examples all", + "example": "run-examples" + }, + "dependencies": { + "example-runner": "^4.0.0", + "@fast-csv/parse": "^4.0.0", + "globby": "^10.0.1", + "jest-diff": "^24.9.0" + } +} diff --git a/examples/parsing/pipe.example.js b/examples/parsing/pipe.example.js deleted file mode 100644 index 7db49774..00000000 --- a/examples/parsing/pipe.example.js +++ /dev/null @@ -1,9 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const csv = require('../../'); - -fs.createReadStream(path.resolve(__dirname, '..', 'assets', 'snake_case_users.csv')) - .pipe(csv.parse()) - .on('error', error => console.error(error)) - .on('data', row => console.log(row)) - .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); diff --git a/jest.config.js b/jest.config.js index f865a7b8..4134212e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,8 +4,6 @@ module.exports = { // Replace `ts-jest` with the preset you want to use // from the above list preset: 'ts-jest', - collectCoverageFrom: [ - "src/**/*.ts" - ], - testMatch: [ "**/__tests__/**/*.spec.ts"], -}; \ No newline at end of file + collectCoverageFrom: ['packages/**/*.ts', '!**/__tests__/**', '!**/build/**', '!**/node_modules/**'], + testMatch: ['**/__tests__/**/*.spec.ts'], +}; diff --git a/lerna.json b/lerna.json new file mode 100644 index 00000000..36e5e91a --- /dev/null +++ b/lerna.json @@ -0,0 +1,7 @@ +{ + "packages": [ + "packages/*", + "examples/*" + ], + "version": "4.0.0" +} diff --git a/package-lock.json b/package-lock.json index aeb39af1..7c7ccf70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -225,11 +225,149 @@ } } }, - "@istanbuljs/nyc-config-typescript": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-0.1.3.tgz", - "integrity": "sha512-EzRFg92bRSD1W/zeuNkeGwph0nkWf+pP2l/lYW4/5hav7RjKKBN5kV1Ix7Tvi0CMu3pC4Wi/U7rNisiJMR3ORg==", - "dev": true + "@evocateur/libnpmaccess": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz", + "integrity": "sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "aproba": "^2.0.0", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.0.0", + "npm-package-arg": "^6.1.0" + }, + "dependencies": { + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + } + } + }, + "@evocateur/libnpmpublish": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz", + "integrity": "sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "aproba": "^2.0.0", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.0.0", + "lodash.clonedeep": "^4.5.0", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "semver": "^5.5.1", + "ssri": "^6.0.1" + }, + "dependencies": { + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + } + } + }, + "@evocateur/npm-registry-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz", + "integrity": "sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@evocateur/pacote": { + "version": "9.6.5", + "resolved": "https://registry.npmjs.org/@evocateur/pacote/-/pacote-9.6.5.tgz", + "integrity": "sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w==", + "dev": true, + "requires": { + "@evocateur/npm-registry-fetch": "^4.0.0", + "bluebird": "^3.5.3", + "cacache": "^12.0.3", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.5.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.4.4", + "npm-pick-manifest": "^3.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.3", + "safe-buffer": "^5.2.0", + "semver": "^5.7.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } }, "@jest/console": { "version": "24.9.0", @@ -476,1938 +614,2277 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^1.1.1", "@types/yargs": "^13.0.0" } }, - "@sinonjs/commons": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", - "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "@lerna/add": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@lerna/add/-/add-3.19.0.tgz", + "integrity": "sha512-qzhxPyoczvvT1W0wwCK9I0iJ4B9WR+HzYsusmRuzM3mEhWjowhbuvKEl5BjGYuXc9AvEErM/S0Fm5K0RcuS39Q==", "dev": true, "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" + "@evocateur/pacote": "^9.6.3", + "@lerna/bootstrap": "3.18.5", + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.18.4", + "@lerna/npm-conf": "3.16.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "npm-package-arg": "^6.1.0", + "p-map": "^2.1.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" + "@lerna/bootstrap": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.18.5.tgz", + "integrity": "sha512-9vD/BfCz8YSF2Dx7sHaMVo6Cy33WjLEmoN1yrHgNkHjm7ykWbLHG5wru0f4Y4pvwa0s5Hf76rvT8aJWzGHk9IQ==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.18.4", + "@lerna/has-npm-version": "3.16.5", + "@lerna/npm-install": "3.16.5", + "@lerna/package-graph": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/rimraf-dir": "3.16.5", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/symlink-binary": "3.17.0", + "@lerna/symlink-dependencies": "3.17.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "get-port": "^4.2.0", + "multimatch": "^3.0.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0", + "p-waterfall": "^1.0.0", + "read-package-tree": "^5.1.6", + "semver": "^6.2.0" }, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@types/babel__core": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", - "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "@lerna/changed": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-3.18.5.tgz", + "integrity": "sha512-IXS7VZ5VDQUfCsgK56WYxd42luMBxL456cNUf1yBgQ1cy1U2FPVMitIdLN4AcP7bJizdPWeG8yDptf47jN/xVw==", "dev": true, "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@lerna/collect-updates": "3.18.0", + "@lerna/command": "3.18.5", + "@lerna/listable": "3.18.5", + "@lerna/output": "3.13.0" } }, - "@types/babel__generator": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", - "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "@lerna/check-working-tree": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz", + "integrity": "sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@lerna/collect-uncommitted": "3.16.5", + "@lerna/describe-ref": "3.16.5", + "@lerna/validation-error": "3.13.0" } }, - "@types/babel__template": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", - "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "@lerna/child-process": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-3.16.5.tgz", + "integrity": "sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg==", "dev": true, "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "chalk": "^2.3.1", + "execa": "^1.0.0", + "strong-log-transformer": "^2.0.0" } }, - "@types/babel__traverse": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", - "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", + "@lerna/clean": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-3.18.5.tgz", + "integrity": "sha512-tHxOj9frTIhB/H2gtgMU3xpIc4IJEhXcUlReko6RJt8TTiDZGPDudCcgjg6i7n15v9jXMOc1y4F+y5/1089bfA==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.18.4", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/rimraf-dir": "3.16.5", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0", + "p-waterfall": "^1.0.0" } }, - "@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "@lerna/cli": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-3.18.5.tgz", + "integrity": "sha512-erkbxkj9jfc89vVs/jBLY/fM0I80oLmJkFUV3Q3wk9J3miYhP14zgVEBsPZY68IZlEjT6T3Xlq2xO1AVaatHsA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*" + "@lerna/global-options": "3.13.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2", + "yargs": "^14.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "14.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.2.tgz", + "integrity": "sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.0" + } + }, + "yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, - "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "@lerna/collect-uncommitted": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz", + "integrity": "sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" + "@lerna/child-process": "3.16.5", + "chalk": "^2.3.1", + "figgy-pudding": "^3.5.1", + "npmlog": "^4.1.2" } }, - "@types/jest": { - "version": "24.0.24", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.24.tgz", - "integrity": "sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ==", + "@lerna/collect-updates": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-3.18.0.tgz", + "integrity": "sha512-LJMKgWsE/var1RSvpKDIxS8eJ7POADEc0HM3FQiTpEczhP6aZfv9x3wlDjaHpZm9MxJyQilqxZcasRANmRcNgw==", "dev": true, "requires": { - "jest-diff": "^24.3.0" + "@lerna/child-process": "3.16.5", + "@lerna/describe-ref": "3.16.5", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } } }, - "@types/json-schema": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", - "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==", - "dev": true + "@lerna/command": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/command/-/command-3.18.5.tgz", + "integrity": "sha512-36EnqR59yaTU4HrR1C9XDFti2jRx0BgpIUBeWn129LZZB8kAB3ov1/dJNa1KcNRKp91DncoKHLY99FZ6zTNpMQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/package-graph": "3.18.5", + "@lerna/project": "3.18.0", + "@lerna/validation-error": "3.13.0", + "@lerna/write-log-file": "3.13.0", + "clone-deep": "^4.0.1", + "dedent": "^0.7.0", + "execa": "^1.0.0", + "is-ci": "^2.0.0", + "npmlog": "^4.1.2" + } }, - "@types/lodash": { - "version": "4.14.132", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.132.tgz", - "integrity": "sha512-RNUU1rrh85NgUJcjOOr96YXr+RHwInGbaQCZmlitqOaCKXffj8bh+Zxwuq5rjDy5OgzFldDVoqk4pyLEDiwxIw==", - "dev": true + "@lerna/conventional-commits": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-3.18.5.tgz", + "integrity": "sha512-qcvXIEJ3qSgalxXnQ7Yxp5H9Ta5TVyai6vEor6AAEHc20WiO7UIdbLDCxBtiiHMdGdpH85dTYlsoYUwsCJu3HQ==", + "dev": true, + "requires": { + "@lerna/validation-error": "3.13.0", + "conventional-changelog-angular": "^5.0.3", + "conventional-changelog-core": "^3.1.6", + "conventional-recommended-bump": "^5.0.0", + "fs-extra": "^8.1.0", + "get-stream": "^4.0.0", + "lodash.template": "^4.5.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "pify": "^4.0.1", + "semver": "^6.2.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } }, - "@types/lodash.escaperegexp": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/lodash.escaperegexp/-/lodash.escaperegexp-4.1.6.tgz", - "integrity": "sha512-uENiqxLlqh6RzeE1cC6Z2gHqakToN9vKlTVCFkSVjAfeMeh2fY0916tHwJHeeKs28qB/hGYvKuampGYH5QDVCw==", + "@lerna/create": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-3.18.5.tgz", + "integrity": "sha512-cHpjocbpKmLopCuZFI7cKEM3E/QY8y+yC7VtZ4FQRSaLU8D8i2xXtXmYaP1GOlVNavji0iwoXjuNpnRMInIr2g==", "dev": true, "requires": { - "@types/lodash": "*" + "@evocateur/pacote": "^9.6.3", + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/npm-conf": "3.16.0", + "@lerna/validation-error": "3.13.0", + "camelcase": "^5.0.0", + "dedent": "^0.7.0", + "fs-extra": "^8.1.0", + "globby": "^9.2.0", + "init-package-json": "^1.10.3", + "npm-package-arg": "^6.1.0", + "p-reduce": "^1.0.0", + "pify": "^4.0.1", + "semver": "^6.2.0", + "slash": "^2.0.0", + "validate-npm-package-license": "^3.0.3", + "validate-npm-package-name": "^3.0.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } } }, - "@types/lodash.groupby": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.groupby/-/lodash.groupby-4.6.6.tgz", - "integrity": "sha512-kwg3T7Ia63KtDNoQQR8hKrLHCAgrH4I44l5uEMuA6JCbj7DiSccaV4tNV1vbjtAOpX990SolVthJCmBVtRVRgw==", + "@lerna/create-symlink": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-3.16.2.tgz", + "integrity": "sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw==", "dev": true, "requires": { - "@types/lodash": "*" + "@zkochan/cmd-shim": "^3.1.0", + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2" } }, - "@types/lodash.isboolean": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isboolean/-/lodash.isboolean-3.0.6.tgz", - "integrity": "sha512-9ommZgIE6GlZW/GuSRIOSJP3X0FkOD2qqt8xBNqUVb/t4L62WiIGCPgIKK2PNfZem7bEZulM0djX9f8IG2Qg3Q==", + "@lerna/describe-ref": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-3.16.5.tgz", + "integrity": "sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw==", "dev": true, "requires": { - "@types/lodash": "*" + "@lerna/child-process": "3.16.5", + "npmlog": "^4.1.2" } }, - "@types/lodash.isequal": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.5.tgz", - "integrity": "sha512-4IKbinG7MGP131wRfceK6W4E/Qt3qssEFLF30LnJbjYiSfHGGRU/Io8YxXrZX109ir+iDETC8hw8QsDijukUVg==", + "@lerna/diff": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-3.18.5.tgz", + "integrity": "sha512-u90lGs+B8DRA9Z/2xX4YaS3h9X6GbypmGV6ITzx9+1Ga12UWGTVlKaCXBgONMBjzJDzAQOK8qPTwLA57SeBLgA==", "dev": true, "requires": { - "@types/lodash": "*" + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/validation-error": "3.13.0", + "npmlog": "^4.1.2" } }, - "@types/lodash.isfunction": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isfunction/-/lodash.isfunction-3.0.6.tgz", - "integrity": "sha512-olhgKmBgzHnA5pxsOI6YHunzTBMSyBw1XjxIKFio8W+XhYiELGTt05FStE0suV0GWtlIMdn7V8M/UbYbSVdGYw==", + "@lerna/exec": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-3.18.5.tgz", + "integrity": "sha512-Q1nz95MeAxctS9bF+aG8FkjixzqEjRpg6ujtnDW84J42GgxedkPtNcJ2o/MBqLd/mxAlr+fW3UZ6CPC/zgoyCg==", "dev": true, "requires": { - "@types/lodash": "*" + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.18.4", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "p-map": "^2.1.0" } }, - "@types/lodash.isnil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isnil/-/lodash.isnil-4.0.6.tgz", - "integrity": "sha512-K+9ZVqwWUFKxijX7rPGnrubfTtCQ5VwW0xgPCL5iLBBLg5sUFFXdPG3QxkpGNJil8mgttRqNLSWNweEsUrBXTg==", + "@lerna/filter-options": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-3.18.4.tgz", + "integrity": "sha512-4giVQD6tauRwweO/322LP2gfVDOVrt/xN4khkXyfkJDfcsZziFXq+668otD9KSLL8Ps+To4Fah3XbK0MoNuEvA==", "dev": true, "requires": { - "@types/lodash": "*" + "@lerna/collect-updates": "3.18.0", + "@lerna/filter-packages": "3.18.0", + "dedent": "^0.7.0", + "figgy-pudding": "^3.5.1", + "npmlog": "^4.1.2" } }, - "@types/lodash.isstring": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isstring/-/lodash.isstring-4.0.6.tgz", - "integrity": "sha512-uUGvF9G1G7jQ5H42Y38GA9rZmUoY8wI/OMSwnW0BZA+Ra0uxzpuQf4CixXl3yG3TvF6LjuduMyt1WvKl+je8QA==", + "@lerna/filter-packages": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-3.18.0.tgz", + "integrity": "sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ==", "dev": true, "requires": { - "@types/lodash": "*" + "@lerna/validation-error": "3.13.0", + "multimatch": "^3.0.0", + "npmlog": "^4.1.2" } }, - "@types/lodash.isundefined": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isundefined/-/lodash.isundefined-3.0.6.tgz", - "integrity": "sha512-gXRrZ9MahWtxusjjUAbWaxUA4vU/NxXfI9kkfsjXYnBA0YjXVtl71toGBZ0X4+L023XS8NlO3BokLXFFuLtG/Q==", + "@lerna/get-npm-exec-opts": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz", + "integrity": "sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==", "dev": true, "requires": { - "@types/lodash": "*" + "npmlog": "^4.1.2" } }, - "@types/lodash.partition": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.partition/-/lodash.partition-4.6.6.tgz", - "integrity": "sha512-s8ZNNFWhBgTKI4uNxVrTs3Aa7UQoi7Fesw55bfpBBMCLda+uSuwDyuax8ka9aBy8Ccsjp2SiS034DkSZa+CzVA==", + "@lerna/get-packed": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-3.16.0.tgz", + "integrity": "sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw==", "dev": true, "requires": { - "@types/lodash": "*" + "fs-extra": "^8.1.0", + "ssri": "^6.0.1", + "tar": "^4.4.8" } }, - "@types/lodash.uniq": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.6.tgz", - "integrity": "sha512-XHNMXBtiwsWZstZMyxOYjr0e8YYWv0RgPlzIHblTuwBBiWo2MzWVaTBihtBpslb5BglgAWIeBv69qt1+RTRW1A==", + "@lerna/github-client": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-3.16.5.tgz", + "integrity": "sha512-rHQdn8Dv/CJrO3VouOP66zAcJzrHsm+wFuZ4uGAai2At2NkgKH+tpNhQy2H1PSC0Ezj9LxvdaHYrUzULqVK5Hw==", "dev": true, "requires": { - "@types/lodash": "*" + "@lerna/child-process": "3.16.5", + "@octokit/plugin-enterprise-rest": "^3.6.1", + "@octokit/rest": "^16.28.4", + "git-url-parse": "^11.1.2", + "npmlog": "^4.1.2" } }, - "@types/node": { - "version": "12.12.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", - "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" + "@lerna/gitlab-client": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz", + "integrity": "sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==", + "dev": true, + "requires": { + "node-fetch": "^2.5.0", + "npmlog": "^4.1.2", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } }, - "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "@lerna/global-options": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-3.13.0.tgz", + "integrity": "sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==", "dev": true }, - "@types/sinon": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", - "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", - "dev": true + "@lerna/has-npm-version": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz", + "integrity": "sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } }, - "@types/stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", - "dev": true + "@lerna/import": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/import/-/import-3.18.5.tgz", + "integrity": "sha512-PH0WVLEgp+ORyNKbGGwUcrueW89K3Iuk/DDCz8mFyG2IG09l/jOF0vzckEyGyz6PO5CMcz4TI1al/qnp3FrahQ==", + "dev": true, + "requires": { + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/validation-error": "3.13.0", + "dedent": "^0.7.0", + "fs-extra": "^8.1.0", + "p-map-series": "^1.0.0" + } }, - "@types/yargs": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", - "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "@lerna/init": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/init/-/init-3.18.5.tgz", + "integrity": "sha512-oCwipWrha98EcJAHm8AGd2YFFLNI7AW9AWi0/LbClj1+XY9ah+uifXIgYGfTk63LbgophDd8936ZEpHMxBsbAg==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "@lerna/child-process": "3.16.5", + "@lerna/command": "3.18.5", + "fs-extra": "^8.1.0", + "p-map": "^2.1.0", + "write-json-file": "^3.2.0" } }, - "@types/yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", - "dev": true + "@lerna/link": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/link/-/link-3.18.5.tgz", + "integrity": "sha512-xTN3vktJpkT7Nqc3QkZRtHO4bT5NvuLMtKNIBDkks0HpGxC9PRyyqwOoCoh1yOGbrWIuDezhfMg3Qow+6I69IQ==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/package-graph": "3.18.5", + "@lerna/symlink-dependencies": "3.17.0", + "p-map": "^2.1.0", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } }, - "@typescript-eslint/eslint-plugin": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.11.0.tgz", - "integrity": "sha512-G2HHA1vpMN0EEbUuWubiCCfd0R3a30BB+UdvnFkxwZIxYEGOrWEXDv8tBFO9f44CWc47Xv9lLM3VSn4ORLI2bA==", + "@lerna/list": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/list/-/list-3.18.5.tgz", + "integrity": "sha512-qIeomm28C2OCM8TMjEe/chTnQf6XLN54wPVQ6kZy+axMYxANFNt/uhs6GZEmhem7GEVawzkyHSz5ZJPsfH3IFg==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "2.11.0", - "eslint-utils": "^1.4.3", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "tsutils": "^3.17.1" + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.18.4", + "@lerna/listable": "3.18.5", + "@lerna/output": "3.13.0" } }, - "@typescript-eslint/experimental-utils": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.11.0.tgz", - "integrity": "sha512-YxcA/y0ZJaCc/fB/MClhcDxHI0nOBB7v2/WxBju2cOTanX7jO9ttQq6Fy4yW9UaY5bPd9xL3cun3lDVqk67sPQ==", + "@lerna/listable": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-3.18.5.tgz", + "integrity": "sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg==", "dev": true, "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.11.0", - "eslint-scope": "^5.0.0" + "@lerna/query-graph": "3.18.5", + "chalk": "^2.3.1", + "columnify": "^1.5.4" } }, - "@typescript-eslint/parser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.11.0.tgz", - "integrity": "sha512-DyGXeqhb3moMioEFZIHIp7oXBBh7dEfPTzGrlyP0Mi9ScCra4SWEGs3kPd18mG7Sy9Wy8z88zmrw5tSGL6r/6A==", + "@lerna/log-packed": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-3.16.0.tgz", + "integrity": "sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==", "dev": true, "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.11.0", - "@typescript-eslint/typescript-estree": "2.11.0", - "eslint-visitor-keys": "^1.1.0" + "byte-size": "^5.0.1", + "columnify": "^1.5.4", + "has-unicode": "^2.0.1", + "npmlog": "^4.1.2" } }, - "@typescript-eslint/typescript-estree": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.11.0.tgz", - "integrity": "sha512-HGY4+d4MagO6cKMcKfIKaTMxcAv7dEVnji2Zi+vi5VV8uWAM631KjAB5GxFcexMYrwKT0EekRiiGK1/Sd7VFGA==", + "@lerna/npm-conf": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-3.16.0.tgz", + "integrity": "sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==", "dev": true, "requires": { - "debug": "^4.1.1", - "eslint-visitor-keys": "^1.1.0", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash.unescape": "4.0.1", - "semver": "^6.3.0", - "tsutils": "^3.17.1" + "config-chain": "^1.1.11", + "pify": "^4.0.1" }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true } } }, - "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", - "dev": true - }, - "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", - "dev": true - }, - "acorn-globals": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", - "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "@lerna/npm-dist-tag": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz", + "integrity": "sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ==", "dev": true, "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", - "dev": true - } + "@evocateur/npm-registry-fetch": "^4.0.0", + "@lerna/otplease": "3.18.5", + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2" } }, - "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", - "dev": true - }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "dev": true - }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "@lerna/npm-install": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-3.16.5.tgz", + "integrity": "sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@lerna/child-process": "3.16.5", + "@lerna/get-npm-exec-opts": "3.13.0", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "signal-exit": "^3.0.2", + "write-pkg": "^3.1.0" } }, - "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "@lerna/npm-publish": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-3.18.5.tgz", + "integrity": "sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "@evocateur/libnpmpublish": "^1.2.2", + "@lerna/otplease": "3.18.5", + "@lerna/run-lifecycle": "3.16.2", + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "pify": "^4.0.1", + "read-package-json": "^2.0.13" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "@lerna/npm-run-script": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz", + "integrity": "sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "@lerna/child-process": "3.16.5", + "@lerna/get-npm-exec-opts": "3.13.0", + "npmlog": "^4.1.2" } }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "@lerna/otplease": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-3.18.5.tgz", + "integrity": "sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "@lerna/prompt": "3.18.5", + "figgy-pudding": "^3.5.1" } }, - "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "@lerna/output": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/output/-/output-3.13.0.tgz", + "integrity": "sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==", "dev": true, "requires": { - "default-require-extensions": "^2.0.0" + "npmlog": "^4.1.2" } }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arg": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.2.tgz", - "integrity": "sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "@lerna/pack-directory": { + "version": "3.16.4", + "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-3.16.4.tgz", + "integrity": "sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "@lerna/get-packed": "3.16.0", + "@lerna/package": "3.16.0", + "@lerna/run-lifecycle": "3.16.2", + "figgy-pudding": "^3.5.1", + "npm-packlist": "^1.4.4", + "npmlog": "^4.1.2", + "tar": "^4.4.10", + "temp-write": "^3.4.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, - "array-includes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.0.tgz", - "integrity": "sha512-ONOEQoKrvXPKk7Su92Co0YMqYO32FfqJTzkKU9u2UpIXyYZIzLSvpdg4AwvSw4mSUW0czu6inK+zby6Oj6gDjQ==", + "@lerna/package": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/package/-/package-3.16.0.tgz", + "integrity": "sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.0" + "load-json-file": "^5.3.0", + "npm-package-arg": "^6.1.0", + "write-pkg": "^3.1.0" }, "dependencies": { - "es-abstract": { - "version": "1.17.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.0.tgz", - "integrity": "sha512-7t0Ywrgy60w0u1bL1Zc9f6yj0re25yaEA6o+bQOxv6AmzKGWmRkHCXA9i+FtfnxL50mMxV1P3oLC+4vHLwfLPA==", + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", "dev": true, "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true } } }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.2.tgz", - "integrity": "sha512-VXjh7lAL4KXKF2hY4FnEW9eRW6IhdvFW1sN/JwLbmECbCgACCnBHNyP3lFiYuttr0jxRN9Bsc5+G27dMseSWqQ==", + "@lerna/package-graph": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-3.18.5.tgz", + "integrity": "sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.15.0", - "function-bind": "^1.1.1" + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/validation-error": "3.13.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "@lerna/prerelease-id-from-version": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz", + "integrity": "sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", - "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", - "dev": true - }, - "babel-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", - "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "@lerna/project": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@lerna/project/-/project-3.18.0.tgz", + "integrity": "sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA==", "dev": true, "requires": { - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/babel__core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", - "babel-preset-jest": "^24.9.0", - "chalk": "^2.4.2", - "slash": "^2.0.0" + "@lerna/package": "3.16.0", + "@lerna/validation-error": "3.13.0", + "cosmiconfig": "^5.1.0", + "dedent": "^0.7.0", + "dot-prop": "^4.2.0", + "glob-parent": "^5.0.0", + "globby": "^9.2.0", + "load-json-file": "^5.3.0", + "npmlog": "^4.1.2", + "p-map": "^2.1.0", + "resolve-from": "^4.0.0", + "write-json-file": "^3.2.0" }, "dependencies": { + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true } } }, - "babel-plugin-istanbul": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", - "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "find-up": "^3.0.0", - "istanbul-lib-instrument": "^3.3.0", - "test-exclude": "^5.2.3" - } - }, - "babel-plugin-jest-hoist": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", - "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", - "dev": true, - "requires": { - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", - "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", - "dev": true, - "requires": { - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "babel-plugin-jest-hoist": "^24.9.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "@lerna/prompt": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-3.18.5.tgz", + "integrity": "sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ==", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "inquirer": "^6.2.0", + "npmlog": "^4.1.2" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "restore-cursor": "^2.0.0" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "escape-string-regexp": "^1.0.5" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" } } } }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "@lerna/publish": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-3.18.5.tgz", + "integrity": "sha512-ifYqLX6mvw95T8vYRlhT68UC7Al0flQvnf5uF9lDgdrgR5Bs+BTwzk3D+0ctdqMtfooekrV6pqfW0R3gtwRffQ==", + "dev": true, + "requires": { + "@evocateur/libnpmaccess": "^3.1.2", + "@evocateur/npm-registry-fetch": "^4.0.0", + "@evocateur/pacote": "^9.6.3", + "@lerna/check-working-tree": "3.16.5", + "@lerna/child-process": "3.16.5", + "@lerna/collect-updates": "3.18.0", + "@lerna/command": "3.18.5", + "@lerna/describe-ref": "3.16.5", + "@lerna/log-packed": "3.16.0", + "@lerna/npm-conf": "3.16.0", + "@lerna/npm-dist-tag": "3.18.5", + "@lerna/npm-publish": "3.18.5", + "@lerna/otplease": "3.18.5", + "@lerna/output": "3.13.0", + "@lerna/pack-directory": "3.16.4", + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/prompt": "3.18.5", + "@lerna/pulse-till-done": "3.13.0", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "@lerna/version": "3.18.5", + "figgy-pudding": "^3.5.1", + "fs-extra": "^8.1.0", + "npm-package-arg": "^6.1.0", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-pipe": "^1.2.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@lerna/pulse-till-done": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz", + "integrity": "sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "npmlog": "^4.1.2" } }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "@lerna/query-graph": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-3.18.5.tgz", + "integrity": "sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA==", "dev": true, - "optional": true, "requires": { - "file-uri-to-path": "1.0.0" + "@lerna/package-graph": "3.18.5", + "figgy-pudding": "^3.5.1" } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "@lerna/resolve-symlink": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz", + "integrity": "sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "fs-extra": "^8.1.0", + "npmlog": "^4.1.2", + "read-cmd-shim": "^1.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "@lerna/rimraf-dir": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz", + "integrity": "sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "@lerna/child-process": "3.16.5", + "npmlog": "^4.1.2", + "path-exists": "^3.0.0", + "rimraf": "^2.6.2" } }, - "browser-process-hrtime": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", - "dev": true + "@lerna/run": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.18.5.tgz", + "integrity": "sha512-1S0dZccNJO8+gT5ztYE4rHTEnbXVwThHOfDnlVt2KDxl9cbnBALk3xprGLW7lSzJsxegS849hxrAPUh0UorMgw==", + "dev": true, + "requires": { + "@lerna/command": "3.18.5", + "@lerna/filter-options": "3.18.4", + "@lerna/npm-run-script": "3.16.5", + "@lerna/output": "3.13.0", + "@lerna/run-topologically": "3.18.5", + "@lerna/timer": "3.13.0", + "@lerna/validation-error": "3.13.0", + "p-map": "^2.1.0" + } }, - "browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "@lerna/run-lifecycle": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz", + "integrity": "sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==", "dev": true, "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } + "@lerna/npm-conf": "3.16.0", + "figgy-pudding": "^3.5.1", + "npm-lifecycle": "^3.1.2", + "npmlog": "^4.1.2" } }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "@lerna/run-topologically": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-3.18.5.tgz", + "integrity": "sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg==", "dev": true, "requires": { - "fast-json-stable-stringify": "2.x" + "@lerna/query-graph": "3.18.5", + "figgy-pudding": "^3.5.1", + "p-queue": "^4.0.0" } }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "@lerna/symlink-binary": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz", + "integrity": "sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==", "dev": true, "requires": { - "node-int64": "^0.4.0" + "@lerna/create-symlink": "3.16.2", + "@lerna/package": "3.16.0", + "fs-extra": "^8.1.0", + "p-map": "^2.1.0" } }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "@lerna/symlink-dependencies": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz", + "integrity": "sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "@lerna/create-symlink": "3.16.2", + "@lerna/resolve-symlink": "3.16.0", + "@lerna/symlink-binary": "3.17.0", + "fs-extra": "^8.1.0", + "p-finally": "^1.0.0", + "p-map": "^2.1.0", + "p-map-series": "^1.0.0" } }, - "caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "@lerna/timer": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-3.13.0.tgz", + "integrity": "sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==", + "dev": true + }, + "@lerna/validation-error": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-3.13.0.tgz", + "integrity": "sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==", "dev": true, "requires": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" + "npmlog": "^4.1.2" } }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "@lerna/version": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@lerna/version/-/version-3.18.5.tgz", + "integrity": "sha512-eSMxLIDuVxZIq0JZKNih50x1IZuMmViwF59uwOGMx0hHB84N3waE8HXOF9CJXDSjeP6sHB8tS+Y+X5fFpBop2Q==", "dev": true, "requires": { - "callsites": "^2.0.0" + "@lerna/check-working-tree": "3.16.5", + "@lerna/child-process": "3.16.5", + "@lerna/collect-updates": "3.18.0", + "@lerna/command": "3.18.5", + "@lerna/conventional-commits": "3.18.5", + "@lerna/github-client": "3.16.5", + "@lerna/gitlab-client": "3.15.0", + "@lerna/output": "3.13.0", + "@lerna/prerelease-id-from-version": "3.16.0", + "@lerna/prompt": "3.18.5", + "@lerna/run-lifecycle": "3.16.2", + "@lerna/run-topologically": "3.18.5", + "@lerna/validation-error": "3.13.0", + "chalk": "^2.3.1", + "dedent": "^0.7.0", + "load-json-file": "^5.3.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "p-map": "^2.1.0", + "p-pipe": "^1.2.0", + "p-reduce": "^1.0.0", + "p-waterfall": "^1.0.0", + "semver": "^6.2.0", + "slash": "^2.0.0", + "temp-write": "^3.4.0", + "write-json-file": "^3.2.0" }, "dependencies": { - "callsites": { + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", "dev": true } } }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "@lerna/write-log-file": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-3.13.0.tgz", + "integrity": "sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==", "dev": true, "requires": { - "caller-callsite": "^2.0.0" + "npmlog": "^4.1.2", + "write-file-atomic": "^2.3.0" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { - "rsvp": "^4.8.4" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@octokit/endpoint": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.1.tgz", + "integrity": "sha512-nBFhRUb5YzVTCX/iAK1MgQ4uWo89Gu0TH00qQHoYRCsE12dWcG1OiLd7v2EIo2+tpUKPMOQ62QFy9hy9Vg2ULg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@octokit/types": "^2.0.0", + "is-plain-object": "^3.0.0", + "universal-user-agent": "^4.0.0" }, "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "isobject": "^4.0.0" } + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true } } }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "@octokit/plugin-enterprise-rest": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-3.6.2.tgz", + "integrity": "sha512-3wF5eueS5OHQYuAEudkpN+xVeUsg8vYEMMenEzLphUZ7PRZ8OJtDcsreL3ad9zxXmBbaFWzLmFcdob5CLyZftA==", "dev": true }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "@octokit/request": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.3.1.tgz", + "integrity": "sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg==", + "dev": true, + "requires": { + "@octokit/endpoint": "^5.5.0", + "@octokit/request-error": "^1.0.1", + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "is-plain-object": "^3.0.0", + "node-fetch": "^2.3.0", + "once": "^1.4.0", + "universal-user-agent": "^4.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "isobject": "^4.0.0" } + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true } } }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "@octokit/request-error": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.0.tgz", + "integrity": "sha512-DNBhROBYjjV/I9n7A8kVkmQNkqFAMem90dSxqvPq57e2hBr7mNTX98y3R2zDpqMQHVRpBDjsvsfIGgBzy+4PAg==", "dev": true, "requires": { - "restore-cursor": "^3.1.0" + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" } }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "@octokit/rest": { + "version": "16.35.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.35.2.tgz", + "integrity": "sha512-iijaNZpn9hBpUdh8YdXqNiWazmq4R1vCUsmxpBB0kCQ0asHZpCx+HNs22eiHuwYKRhO31ZSAGBJLi0c+3XHaKQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "@octokit/request": "^5.2.0", + "@octokit/request-error": "^1.0.2", + "atob-lite": "^2.0.0", + "before-after-hook": "^2.0.0", + "btoa-lite": "^1.0.0", + "deprecation": "^2.0.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "lodash.uniq": "^4.5.0", + "octokit-pagination-methods": "^1.1.0", + "once": "^1.4.0", + "universal-user-agent": "^4.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "@octokit/types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.0.2.tgz", + "integrity": "sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "@sinonjs/commons": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "requires": { + "type-detect": "4.0.8" + } }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, + "@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", "requires": { - "color-name": "1.1.3" + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + } } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "@types/babel__generator": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", + "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", "dev": true, - "optional": true + "requires": { + "@babel/types": "^7.0.0" + } }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "confusing-browser-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", - "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "@types/babel__traverse": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", + "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "@babel/types": "^7.3.0" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", "dev": true }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "dependencies": { - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" } }, - "coveralls": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.9.tgz", - "integrity": "sha512-nNBg3B1+4iDox5A5zqHKzUTiwl2ey4k2o0NEcVZYvl+GOSJdKBj4AJGKLv6h3SvWch7tABHePAQOSZWM9E2hMg==", - "dev": true, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", "requires": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.88.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "@types/istanbul-lib-coverage": "*" } }, - "cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", - "dev": true, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", "requires": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - } + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "@types/jest": { + "version": "24.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.24.tgz", + "integrity": "sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "jest-diff": "^24.3.0" } }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "@types/json-schema": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", + "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==", "dev": true }, - "cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" + }, + "@types/lodash.escaperegexp": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/lodash.escaperegexp/-/lodash.escaperegexp-4.1.6.tgz", + "integrity": "sha512-uENiqxLlqh6RzeE1cC6Z2gHqakToN9vKlTVCFkSVjAfeMeh2fY0916tHwJHeeKs28qB/hGYvKuampGYH5QDVCw==", "requires": { - "cssom": "0.3.x" + "@types/lodash": "*" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, + "@types/lodash.groupby": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.groupby/-/lodash.groupby-4.6.6.tgz", + "integrity": "sha512-kwg3T7Ia63KtDNoQQR8hKrLHCAgrH4I44l5uEMuA6JCbj7DiSccaV4tNV1vbjtAOpX990SolVthJCmBVtRVRgw==", "requires": { - "assert-plus": "^1.0.0" + "@types/lodash": "*" } }, - "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, + "@types/lodash.isboolean": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isboolean/-/lodash.isboolean-3.0.6.tgz", + "integrity": "sha512-9ommZgIE6GlZW/GuSRIOSJP3X0FkOD2qqt8xBNqUVb/t4L62WiIGCPgIKK2PNfZem7bEZulM0djX9f8IG2Qg3Q==", "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" - }, - "dependencies": { - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } + "@types/lodash": "*" } }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, + "@types/lodash.isequal": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.5.tgz", + "integrity": "sha512-4IKbinG7MGP131wRfceK6W4E/Qt3qssEFLF30LnJbjYiSfHGGRU/Io8YxXrZX109ir+iDETC8hw8QsDijukUVg==", "requires": { - "ms": "^2.1.1" + "@types/lodash": "*" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "@types/lodash.isfunction": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isfunction/-/lodash.isfunction-3.0.6.tgz", + "integrity": "sha512-olhgKmBgzHnA5pxsOI6YHunzTBMSyBw1XjxIKFio8W+XhYiELGTt05FStE0suV0GWtlIMdn7V8M/UbYbSVdGYw==", + "requires": { + "@types/lodash": "*" + } }, - "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", - "dev": true, + "@types/lodash.isnil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isnil/-/lodash.isnil-4.0.6.tgz", + "integrity": "sha512-K+9ZVqwWUFKxijX7rPGnrubfTtCQ5VwW0xgPCL5iLBBLg5sUFFXdPG3QxkpGNJil8mgttRqNLSWNweEsUrBXTg==", "requires": { - "strip-bom": "^3.0.0" + "@types/lodash": "*" } }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, + "@types/lodash.isundefined": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isundefined/-/lodash.isundefined-3.0.6.tgz", + "integrity": "sha512-gXRrZ9MahWtxusjjUAbWaxUA4vU/NxXfI9kkfsjXYnBA0YjXVtl71toGBZ0X4+L023XS8NlO3BokLXFFuLtG/Q==", "requires": { - "object-keys": "^1.0.12" + "@types/lodash": "*" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, + "@types/lodash.partition": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.partition/-/lodash.partition-4.6.6.tgz", + "integrity": "sha512-s8ZNNFWhBgTKI4uNxVrTs3Aa7UQoi7Fesw55bfpBBMCLda+uSuwDyuax8ka9aBy8Ccsjp2SiS034DkSZa+CzVA==", "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "@types/lodash": "*" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "@types/lodash.uniq": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.6.tgz", + "integrity": "sha512-XHNMXBtiwsWZstZMyxOYjr0e8YYWv0RgPlzIHblTuwBBiWo2MzWVaTBihtBpslb5BglgAWIeBv69qt1+RTRW1A==", + "requires": { + "@types/lodash": "*" + } }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "@types/node": { + "version": "12.12.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", + "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "@types/sinon": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", + "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==" + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, + "@types/yargs": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", "requires": { - "esutils": "^2.0.2" + "@types/yargs-parser": "*" } }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.11.0.tgz", + "integrity": "sha512-G2HHA1vpMN0EEbUuWubiCCfd0R3a30BB+UdvnFkxwZIxYEGOrWEXDv8tBFO9f44CWc47Xv9lLM3VSn4ORLI2bA==", "dev": true, "requires": { - "webidl-conversions": "^4.0.2" + "@typescript-eslint/experimental-utils": "2.11.0", + "eslint-utils": "^1.4.3", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "@typescript-eslint/experimental-utils": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.11.0.tgz", + "integrity": "sha512-YxcA/y0ZJaCc/fB/MClhcDxHI0nOBB7v2/WxBju2cOTanX7jO9ttQq6Fy4yW9UaY5bPd9xL3cun3lDVqk67sPQ==", "dev": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.11.0", + "eslint-scope": "^5.0.0" } }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "@typescript-eslint/parser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.11.0.tgz", + "integrity": "sha512-DyGXeqhb3moMioEFZIHIp7oXBBh7dEfPTzGrlyP0Mi9ScCra4SWEGs3kPd18mG7Sy9Wy8z88zmrw5tSGL6r/6A==", "dev": true, "requires": { - "once": "^1.4.0" + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.11.0", + "@typescript-eslint/typescript-estree": "2.11.0", + "eslint-visitor-keys": "^1.1.0" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "@typescript-eslint/typescript-estree": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.11.0.tgz", + "integrity": "sha512-HGY4+d4MagO6cKMcKfIKaTMxcAv7dEVnji2Zi+vi5VV8uWAM631KjAB5GxFcexMYrwKT0EekRiiGK1/Sd7VFGA==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash.unescape": "4.0.1", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "es-abstract": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.3.tgz", - "integrity": "sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw==", + "@zkochan/cmd-shim": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz", + "integrity": "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==", "dev": true, "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "is-windows": "^1.0.0", + "mkdirp-promise": "^5.0.1", + "mz": "^2.5.0" } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" } }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "escodegen": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", - "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" }, "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true } } }, - "eslint": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz", - "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "globals": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", - "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true - } - } + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true }, - "eslint-config-airbnb-base": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz", - "integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==", + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { - "confusing-browser-globals": "^1.0.7", - "object.assign": "^4.1.0", - "object.entries": "^1.1.0" + "es6-promisify": "^5.0.0" } }, - "eslint-config-prettier": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz", - "integrity": "sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ==", + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", "dev": true, "requires": { - "get-stdin": "^6.0.0" - }, - "dependencies": { - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - } + "humanize-ms": "^1.2.1" } }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "eslint-module-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz", - "integrity": "sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw==", + "ansi-escapes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", "dev": true, "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "type-fest": "^0.8.1" } }, - "eslint-plugin-import": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz", - "integrity": "sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw==", - "dev": true, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.0", - "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } + "color-convert": "^1.9.0" } }, - "eslint-plugin-prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz", - "integrity": "sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==", + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "prettier-linter-helpers": "^1.0.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, - "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - }, - "espree": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", - "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "acorn": "^7.1.0", - "acorn-jsx": "^5.1.0", - "eslint-visitor-keys": "^1.1.0" + "sprintf-js": "~1.0.2" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "array-differ": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", + "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", "dev": true }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, - "exec-sh": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", - "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "array-includes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.0.tgz", + "integrity": "sha512-ONOEQoKrvXPKk7Su92Co0YMqYO32FfqJTzkKU9u2UpIXyYZIzLSvpdg4AwvSw4mSUW0czu6inK+zby6Oj6gDjQ==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "es-abstract": { + "version": "1.17.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.0.tgz", + "integrity": "sha512-7t0Ywrgy60w0u1bL1Zc9f6yj0re25yaEA6o+bQOxv6AmzKGWmRkHCXA9i+FtfnxL50mMxV1P3oLC+4vHLwfLPA==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, - "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" + "array-uniq": "^1.0.1" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flat": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.2.tgz", + "integrity": "sha512-VXjh7lAL4KXKF2hY4FnEW9eRW6IhdvFW1sN/JwLbmECbCgACCnBHNyP3lFiYuttr0jxRN9Bsc5+G27dMseSWqQ==", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "define-properties": "^1.1.3", + "es-abstract": "^1.15.0", + "function-bind": "^1.1.1" } }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "safer-buffer": "~2.1.0" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "atob-lite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", + "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", + "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", + "dev": true + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "dev": true, + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -2441,80 +2918,62 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "requires": { - "bser": "2.1.1" + "tweetnacl": "^0.14.3" } }, - "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "before-after-hook": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", + "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, + "optional": true, "requires": { - "escape-string-regexp": "^1.0.5" + "file-uri-to-path": "1.0.0" } }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "flat-cache": "^2.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -2528,736 +2987,3369 @@ } } }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "resolve": "1.1.7" }, "dependencies": { - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true } } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "fast-json-stable-stringify": "2.x" } }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" + "node-int64": "^0.4.0" + } + }, + "btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", + "dev": true + }, + "byte-size": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-5.0.1.tgz", + "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==", + "dev": true + }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" }, "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { - "glob": "^7.1.3" + "yallist": "^3.0.2" } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true } } }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", "dev": true, "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" }, "dependencies": { - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "has-flag": "^3.0.0" } } } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "map-cache": "^0.2.2" + "restore-cursor": "^3.1.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, - "optional": true, "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "columnify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "dev": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true + }, + "compare-func": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", + "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + } + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "confusing-browser-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "conventional-changelog-angular": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz", + "integrity": "sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-core": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz", + "integrity": "sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==", + "dev": true, + "requires": { + "conventional-changelog-writer": "^4.0.6", + "conventional-commits-parser": "^3.0.3", + "dateformat": "^3.0.0", + "get-pkg-repo": "^1.0.0", + "git-raw-commits": "2.0.0", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^2.0.3", + "lodash": "^4.2.1", + "normalize-package-data": "^2.3.5", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-changelog-preset-loader": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz", + "integrity": "sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ==", + "dev": true + }, + "conventional-changelog-writer": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz", + "integrity": "sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "conventional-commits-filter": "^2.0.2", + "dateformat": "^3.0.0", + "handlebars": "^4.4.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^5.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-commits-filter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz", + "integrity": "sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ==", + "dev": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz", + "integrity": "sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ==", + "dev": true, + "requires": { + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.1", + "lodash": "^4.17.15", + "meow": "^5.0.0", + "split2": "^2.0.0", + "through2": "^3.0.0", + "trim-off-newlines": "^1.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-recommended-bump": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz", + "integrity": "sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ==", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.1.1", + "conventional-commits-filter": "^2.0.2", + "conventional-commits-parser": "^3.0.3", + "git-raw-commits": "2.0.0", + "git-semver-tags": "^2.0.3", + "meow": "^4.0.0", + "q": "^1.5.1" + }, + "dependencies": { + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "coveralls": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.9.tgz", + "integrity": "sha512-nNBg3B1+4iDox5A5zqHKzUTiwl2ey4k2o0NEcVZYvl+GOSJdKBj4AJGKLv6h3SvWch7tABHePAQOSZWM9E2hMg==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.88.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "dargs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", + "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, + "detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + } + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.3.tgz", + "integrity": "sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz", + "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + } + } + }, + "eslint-config-airbnb-base": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz", + "integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.7", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "eslint-config-prettier": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz", + "integrity": "sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + }, + "dependencies": { + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + } + } + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz", + "integrity": "sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz", + "integrity": "sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "resolve": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", + "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz", + "integrity": "sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "exec-sh": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", + "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", + "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", + "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", + "requires": { + "reusify": "^1.0.0" + } + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, + "figures": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", + "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", "bundled": true, "dev": true, "optional": true }, - "ansi-regex": { - "version": "2.1.1", + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", "bundled": true, "dev": true, "optional": true }, - "aproba": { - "version": "1.2.0", + "os-tmpdir": { + "version": "1.0.2", "bundled": true, "dev": true, "optional": true }, - "are-we-there-yet": { - "version": "1.1.5", + "osenv": { + "version": "0.1.5", "bundled": true, "dev": true, "optional": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, - "balanced-match": { - "version": "1.0.0", + "path-is-absolute": { + "version": "1.0.1", "bundled": true, "dev": true, "optional": true }, - "brace-expansion": { - "version": "1.1.11", + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", "bundled": true, "dev": true, "optional": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } } }, - "chownr": { - "version": "1.1.3", + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", "bundled": true, "dev": true, "optional": true }, - "code-point-at": { - "version": "1.1.0", + "safer-buffer": { + "version": "2.1.2", "bundled": true, "dev": true, "optional": true }, - "concat-map": { - "version": "0.0.1", + "sax": { + "version": "1.2.4", "bundled": true, "dev": true, "optional": true }, - "console-control-strings": { - "version": "1.1.0", + "semver": { + "version": "5.7.1", "bundled": true, "dev": true, "optional": true }, - "core-util-is": { - "version": "1.0.2", + "set-blocking": { + "version": "2.0.0", "bundled": true, "dev": true, "optional": true }, - "debug": { - "version": "3.2.6", + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", "bundled": true, "dev": true, "optional": true, "requires": { - "ms": "^2.1.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, - "deep-extend": { - "version": "0.6.0", + "string_decoder": { + "version": "1.1.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, - "delegates": { - "version": "1.0.0", + "strip-ansi": { + "version": "3.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, - "detect-libc": { - "version": "1.0.3", + "strip-json-comments": { + "version": "2.0.1", "bundled": true, "dev": true, "optional": true }, - "fs-minipass": { - "version": "1.2.7", + "tar": { + "version": "4.4.13", "bundled": true, "dev": true, "optional": true, "requires": { - "minipass": "^2.6.0" + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" } }, - "fs.realpath": { - "version": "1.0.0", + "util-deprecate": { + "version": "1.0.2", "bundled": true, "dev": true, "optional": true }, - "gauge": { - "version": "2.7.4", + "wide-align": { + "version": "1.1.3", "bundled": true, "dev": true, "optional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "string-width": "^1.0.2 || 2" } }, - "glob": { - "version": "7.1.6", + "wrappy": { + "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "optional": true }, - "has-unicode": { - "version": "2.0.1", + "yallist": { + "version": "3.1.1", "bundled": true, "dev": true, "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-pkg-repo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", + "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "meow": "^3.3.0", + "normalize-package-data": "^2.3.0", + "parse-github-repo-url": "^1.3.0", + "through2": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, - "optional": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" } }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, - "optional": true, "requires": { - "minimatch": "^3.0.4" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "inflight": { - "version": "1.0.6", - "bundled": true, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, - "optional": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "repeating": "^2.0.0" } }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, - "optional": true, "requires": { - "number-is-nan": "^1.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true }, - "minimatch": { - "version": "3.0.4", - "bundled": true, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, - "optional": true, "requires": { - "brace-expansion": "^1.1.7" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" } }, "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, - "minipass": { - "version": "2.9.0", - "bundled": true, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, - "optional": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "pinkie-promise": "^2.0.0" } }, - "minizlib": { - "version": "1.3.3", - "bundled": true, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, - "optional": true, "requires": { - "minipass": "^2.9.0" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, - "optional": true, "requires": { - "minimist": "0.0.8" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" } }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, - "optional": true, "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" } }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, - "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" } }, - "nopt": { - "version": "4.0.1", - "bundled": true, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, - "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "is-utf8": "^0.2.0" } }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, - "optional": true, "requires": { - "npm-normalize-package-bin": "^1.0.1" + "get-stdin": "^4.0.1" } }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "bundled": true, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + } + } + }, + "get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "dev": true + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "git-raw-commits": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", + "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==", + "dev": true, + "requires": { + "dargs": "^4.0.1", + "lodash.template": "^4.0.2", + "meow": "^4.0.0", + "split2": "^2.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, - "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "locate-path": "^2.0.0" } }, - "npmlog": { - "version": "4.1.2", - "bundled": true, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, - "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, - "optional": true, "requires": { - "wrappy": "1" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", "dev": true, - "optional": true + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, - "osenv": { - "version": "0.1.5", - "bundled": true, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, - "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "p-try": "^1.0.0" } }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, - "optional": true + "requires": { + "p-limit": "^1.1.0" + } }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, - "rc": { - "version": "1.2.8", - "bundled": true, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, - "optional": true, "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, - "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "pify": "^3.0.0" } }, - "rimraf": { - "version": "2.7.1", - "bundled": true, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, - "optional": true, "requires": { - "glob": "^7.1.3" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" } }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + } + }, + "git-semver-tags": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-2.0.3.tgz", + "integrity": "sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==", + "dev": true, + "requires": { + "meow": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, - "optional": true + "requires": { + "locate-path": "^2.0.0" + } }, - "semver": { - "version": "5.7.1", - "bundled": true, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, - "optional": true + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } }, - "set-blocking": { + "locate-path": { "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, - "optional": true + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, - "string-width": { - "version": "1.0.2", - "bundled": true, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", "dev": true, - "optional": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" } }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, - "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "p-try": "^1.0.0" } }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, - "optional": true, "requires": { - "ansi-regex": "^2.0.0" + "p-limit": "^1.1.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, - "tar": { - "version": "4.4.13", - "bundled": true, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, - "optional": true, "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, - "optional": true, "requires": { - "string-width": "^1.0.2 || 2" + "pify": "^3.0.0" } }, - "wrappy": { - "version": "1.0.2", - "bundled": true, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, - "optional": true + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } }, - "yallist": { - "version": "3.1.1", - "bundled": true, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, - "optional": true + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "git-up": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.1.tgz", + "integrity": "sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw==", "dev": true, "requires": { - "pump": "^3.0.0" + "is-ssh": "^1.3.0", + "parse-url": "^5.0.0" } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "git-url-parse": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.1.2.tgz", + "integrity": "sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ==", + "dev": true, + "requires": { + "git-up": "^4.0.0" + } }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "ini": "^1.3.2" } }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3271,17 +6363,49 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "dev": true, "requires": { "is-glob": "^4.0.1" } }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, "globals": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, + "globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==" + } + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -3342,8 +6466,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.1", @@ -3351,6 +6474,12 @@ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3389,15 +6518,6 @@ } } }, - "hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", - "dev": true, - "requires": { - "is-stream": "^1.0.1" - } - }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -3413,6 +6533,39 @@ "whatwg-encoding": "^1.0.1" } }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -3424,6 +6577,36 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, "husky": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz", @@ -3527,12 +6710,27 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", @@ -3570,11 +6768,22 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3583,9 +6792,30 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "init-package-json": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.10.3.tgz", + "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + } + }, "inquirer": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", @@ -3681,10 +6911,10 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, "is-accessor-descriptor": { @@ -3800,8 +7030,16 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -3819,7 +7057,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -3850,6 +7087,18 @@ } } }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3874,6 +7123,15 @@ "has": "^1.0.1" } }, + "is-ssh": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", + "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", + "dev": true, + "requires": { + "protocols": "^1.1.0" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3889,12 +7147,27 @@ "has-symbols": "^1.0.1" } }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -3937,15 +7210,6 @@ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true }, - "istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", - "dev": true, - "requires": { - "append-transform": "^1.0.0" - } - }, "istanbul-lib-instrument": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", @@ -4179,7 +7443,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, "requires": { "chalk": "^2.0.1", "diff-sequences": "^24.9.0", @@ -4239,8 +7502,7 @@ "jest-get-type": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" }, "jest-haste-map": { "version": "24.9.0", @@ -4763,6 +8025,21 @@ } } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4778,8 +8055,7 @@ "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", - "dev": true + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==" }, "kind-of": { "version": "6.0.2", @@ -4793,15 +8069,6 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, "lcov-parse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", @@ -4814,6 +8081,31 @@ "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", "dev": true }, + "lerna": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-3.19.0.tgz", + "integrity": "sha512-YtMmwEqzWHQCh7Ynk7BvjrZri3EkSeVqTAcwZIqWlv9V/dCfvFPyRqp+2NIjPB5nj1FWXLRH6F05VT/qvzuuOA==", + "dev": true, + "requires": { + "@lerna/add": "3.19.0", + "@lerna/bootstrap": "3.18.5", + "@lerna/changed": "3.18.5", + "@lerna/clean": "3.18.5", + "@lerna/cli": "3.18.5", + "@lerna/create": "3.18.5", + "@lerna/diff": "3.18.5", + "@lerna/exec": "3.18.5", + "@lerna/import": "3.18.5", + "@lerna/init": "3.18.5", + "@lerna/link": "3.18.5", + "@lerna/list": "3.18.5", + "@lerna/publish": "3.18.5", + "@lerna/run": "3.18.5", + "@lerna/version": "3.18.5", + "import-local": "^2.0.0", + "npmlog": "^4.1.2" + } + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -4864,15 +8156,27 @@ "integrity": "sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA==", "dev": true }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, "lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, "lodash.groupby": { @@ -4895,16 +8199,17 @@ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" }, + "lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true + }, "lodash.isnil": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, "lodash.isundefined": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", @@ -4919,7 +8224,12 @@ "lodash.partition": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.partition/-/lodash.partition-4.6.0.tgz", - "integrity": "sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=", + "integrity": "sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=" + }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", "dev": true }, "lodash.sortby": { @@ -4928,6 +8238,25 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", @@ -4948,8 +8277,7 @@ "lolex": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", - "dev": true + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" }, "loose-envify": { "version": "1.4.0", @@ -4960,16 +8288,22 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" } }, + "macos-release": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz", + "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==", + "dev": true + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -4994,6 +8328,42 @@ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -5003,21 +8373,18 @@ "tmpl": "1.0.x" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -5027,39 +8394,138 @@ "object-visit": "^1.0.0" } }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" }, "dependencies": { - "mimic-fn": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "find-up": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true - } - } - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -5069,6 +8535,11 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -5115,7 +8586,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5126,6 +8596,61 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -5156,18 +8681,70 @@ "minimist": "0.0.8" } }, + "mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "dev": true, + "requires": { + "mkdirp": "*" + } + }, + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, + "multimatch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-3.0.0.tgz", + "integrity": "sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==", + "dev": true, + "requires": { + "array-differ": "^2.0.3", + "array-union": "^1.0.2", + "arrify": "^1.0.1", + "minimatch": "^3.0.4" + } + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -5206,12 +8783,6 @@ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, - "nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", - "dev": true - }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -5219,16 +8790,69 @@ "dev": true }, "nise": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", - "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", - "dev": true, + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", "requires": { "@sinonjs/formatio": "^3.2.1", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", - "lolex": "^4.1.0", + "lolex": "^5.0.1", "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } + } + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", + "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.0.7.tgz", + "integrity": "sha512-K8aByl8OJD51V0VbUURTKsmdswkQQusIvlvmTyhHlIT1hBvaSxzdxpSle857XuXa7uc02UEZx9OR5aDxSWS5Qw==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.1.2", + "request": "^2.88.0", + "rimraf": "^2.6.3", + "semver": "^5.7.1", + "tar": "^4.4.12", + "which": "^1.3.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "node-int64": { @@ -5256,6 +8880,16 @@ "which": "^1.3.0" } }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5277,6 +8911,76 @@ "remove-trailing-separator": "^1.0.1" } }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-lifecycle": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.4.tgz", + "integrity": "sha512-tgs1PaucZwkxECGKhC/stbEgFyc3TGh2TJcg2CDr6jbvQRdteHNhmMeljRzpe4wgFAXQADoy1cSqqi7mtiAa5A==", + "dev": true, + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.15", + "node-gyp": "^5.0.2", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz", + "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5286,6 +8990,18 @@ "path-key": "^2.0.0" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -5298,45 +9014,18 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, - "nyc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", - "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "caching-transform": "^3.0.2", - "convert-source-map": "^1.6.0", - "cp-file": "^6.2.0", - "find-cache-dir": "^2.1.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.5", - "istanbul-lib-hook": "^2.0.7", - "istanbul-lib-instrument": "^3.3.0", - "istanbul-lib-report": "^2.0.8", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^2.2.4", - "js-yaml": "^3.13.1", - "make-dir": "^2.1.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", - "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.2.3", - "uuid": "^3.3.2", - "yargs": "^13.2.2", - "yargs-parser": "^13.0.0" - } - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -5471,11 +9160,16 @@ "has": "^1.0.3" } }, + "octokit-pagination-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", + "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -5533,15 +9227,14 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { + "os-name": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" } }, "os-tmpdir": { @@ -5550,11 +9243,15 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "p-each-series": { "version": "1.0.0", @@ -5571,12 +9268,6 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, "p-limit": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", @@ -5595,6 +9286,36 @@ "p-limit": "^2.0.0" } }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-map-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", + "integrity": "sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, + "p-queue": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-4.0.0.tgz", + "integrity": "sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==", + "dev": true, + "requires": { + "eventemitter3": "^3.1.0" + } + }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", @@ -5607,16 +9328,24 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "p-waterfall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-1.0.0.tgz", + "integrity": "sha1-ftlLPOszMngjU69qrhGqn8I1uwA=", "dev": true, "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" + "p-reduce": "^1.0.0" + } + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" } }, "parent-module": { @@ -5628,6 +9357,12 @@ "callsites": "^3.0.0" } }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", + "dev": true + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -5637,6 +9372,28 @@ "error-ex": "^1.2.0" } }, + "parse-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.1.tgz", + "integrity": "sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } + }, + "parse-url": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.1.tgz", + "integrity": "sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^3.3.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" + } + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -5649,6 +9406,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -5658,8 +9421,7 @@ "path-is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", - "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", - "dev": true + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" }, "path-key": { "version": "2.0.1", @@ -5677,7 +9439,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, "requires": { "isarray": "0.0.1" }, @@ -5685,8 +9446,7 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" } } }, @@ -5705,12 +9465,32 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", @@ -5820,7 +9600,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "ansi-regex": "^4.0.0", @@ -5831,17 +9610,38 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" } } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + } + }, "prompts": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", @@ -5852,12 +9652,36 @@ "sisteransi": "^1.0.3" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "promzard": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "dev": true, + "requires": { + "read": "1" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "protocols": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz", + "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", "dev": true }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, "psl": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", @@ -5874,23 +9698,99 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, "react-is": { "version": "16.12.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", - "dev": true + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz", + "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-package-json": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz", + "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", + "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", + "dev": true, + "requires": { + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "util-promisify": "^2.1.0" + } }, "read-pkg": { "version": "2.0.0", @@ -5958,6 +9858,33 @@ } } }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, "realpath-native": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", @@ -5967,6 +9894,16 @@ "util.promisify": "^1.0.0" } }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -5983,15 +9920,6 @@ "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", "dev": true }, - "release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -6010,6 +9938,15 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -6132,6 +10069,17 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -6162,6 +10110,20 @@ "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", "dev": true }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rxjs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", @@ -6264,6 +10226,15 @@ } } }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -6295,7 +10266,6 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "dev": true, "requires": { "@sinonjs/commons": "^1.4.0", "@sinonjs/formatio": "^3.2.1", @@ -6304,17 +10274,6 @@ "lolex": "^4.2.0", "nise": "^1.5.2", "supports-color": "^5.5.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "sisteransi": { @@ -6326,8 +10285,7 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "slice-ansi": { "version": "2.1.0", @@ -6340,6 +10298,18 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -6468,6 +10438,46 @@ } } }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + } + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -6511,20 +10521,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", - "dev": true, - "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", @@ -6557,6 +10553,15 @@ "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", "dev": true }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6566,6 +10571,15 @@ "extend-shallow": "^3.0.0" } }, + "split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "requires": { + "through2": "^2.0.2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6589,6 +10603,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", @@ -6622,6 +10645,22 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -6662,6 +10701,15 @@ "function-bind": "^1.1.1" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -6683,6 +10731,39 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -6735,6 +10816,66 @@ } } }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "temp-write": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz", + "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "is-stream": "^1.1.0", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -6807,12 +10948,36 @@ } } }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", @@ -6825,6 +10990,16 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -6921,6 +11096,18 @@ "punycode": "^2.1.0" } }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "trim-off-newlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", + "dev": true + }, "ts-jest": { "version": "24.2.0", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.2.0.tgz", @@ -6956,27 +11143,6 @@ } } }, - "ts-node": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.4.tgz", - "integrity": "sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.6", - "yn": "^3.0.0" - }, - "dependencies": { - "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", - "dev": true - } - } - }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", @@ -7019,8 +11185,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { "version": "0.8.1", @@ -7028,6 +11193,12 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "typescript": { "version": "3.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", @@ -7054,6 +11225,18 @@ } } }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "dev": true + }, + "umask": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", + "dev": true + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -7066,6 +11249,39 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universal-user-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.0.tgz", + "integrity": "sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -7127,6 +11343,21 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util-promisify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", + "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", @@ -7159,6 +11390,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -7188,6 +11428,15 @@ "makeerror": "1.0.x" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -7235,64 +11484,34 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "windows-release": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.2.0.tgz", + "integrity": "sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==", + "dev": true, + "requires": { + "execa": "^1.0.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", @@ -7314,94 +11533,94 @@ "signal-exit": "^3.0.2" } }, - "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "write-json-file": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", + "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.15", + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "write-pkg": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz", + "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==", "dev": true, "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" + "sort-keys": "^2.0.0", + "write-json-file": "^2.2.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "pify": "^3.0.0" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "write-json-file": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", + "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" } } } }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "async-limiter": "~1.0.0" } }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true } } diff --git a/package.json b/package.json index 1b91565f..63a65f37 100644 --- a/package.json +++ b/package.json @@ -1,52 +1,25 @@ { "name": "fast-csv", "version": "4.0.0", - "description": "CSV parser and writer", - "main": "./build/src/index.js", - "types": "./build/src/index.d.ts", + "private": true, "scripts": { - "prepare": "npm run build", - "build": "npm run clean && tsc", - "clean": "rm -rf ./build", + "bootstrap": "lerna bootstrap --hoist", + "clean": "lerna run clean", + "build": "lerna run build", + "pub": "lerna publish", + "test": "npm run lint && npm run jest && npm run examples", + "lint": "eslint --ext=.ts,.js .", "jest": "jest --coverage", - "test": "npm run lint && npm run jest", - "lint": "eslint --ext=.js,.ts src/ __tests__/ examples/", - "lint-fix": "eslint --fix --ext=.js,.ts src/ __tests__/ examples/", - "benchmark": "node ./benchmark", + "examples": "lerna run all-examples", + "benchmarks": "lerna run benchmarks", "coverage": "jest --coverage --coverageReporters=text-lcov | coveralls" }, - "files": [ - "build/src/**" - ], "repository": { "type": "git", "url": "git@github.com:C2FO/fast-csv.git" }, - "keywords": [ - "csv", - "parser", - "fast", - "writer", - "csv writer", - "CSV" - ], - "homepage": "http://c2fo.github.com/fast-csv/index.html", - "author": "Doug Martin", - "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^0.1.3", "@types/jest": "^24.0.24", - "@types/lodash.escaperegexp": "^4.1.6", - "@types/lodash.groupby": "^4.6.6", - "@types/lodash.isboolean": "^3.0.6", - "@types/lodash.isequal": "^4.5.5", - "@types/lodash.isfunction": "^3.0.6", - "@types/lodash.isnil": "^4.0.6", - "@types/lodash.isstring": "^4.0.6", - "@types/lodash.isundefined": "^3.0.6", - "@types/lodash.partition": "^4.6.6", - "@types/lodash.uniq": "^4.5.6", - "@types/sinon": "^7.5.1", "@typescript-eslint/eslint-plugin": "^2.11.0", "@typescript-eslint/parser": "^2.11.0", "coveralls": "^3.0.9", @@ -57,28 +30,9 @@ "eslint-plugin-prettier": "^3.1.1", "husky": "^3.1.0", "jest": "^24.9.0", - "lodash.partition": "^4.6.0", - "nyc": "^14.1.1", + "lerna": "^3.19.0", "prettier": "^1.19.1", - "sinon": "^7.5.0", - "source-map-support": "^0.5.16", "ts-jest": "^24.2.0", - "ts-node": "^8.5.4", "typescript": "^3.7.3" - }, - "engines": { - "node": ">=8.0.0" - }, - "dependencies": { - "@types/node": "^12.12.17", - "lodash.escaperegexp": "^4.1.2", - "lodash.groupby": "^4.6.0", - "lodash.isboolean": "^3.0.3", - "lodash.isequal": "^4.5.0", - "lodash.isfunction": "^3.0.9", - "lodash.isnil": "^4.0.0", - "lodash.isstring": "^4.0.1", - "lodash.isundefined": "^3.0.1", - "lodash.uniq": "^4.5.0" } } diff --git a/packages/fast-csv/.eslintrc.js b/packages/fast-csv/.eslintrc.js new file mode 100644 index 00000000..eb38465f --- /dev/null +++ b/packages/fast-csv/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + parserOptions: { + project: "./tsconfig.build.json" + }, +}; \ No newline at end of file diff --git a/packages/fast-csv/README.md b/packages/fast-csv/README.md new file mode 100644 index 00000000..2d765f08 --- /dev/null +++ b/packages/fast-csv/README.md @@ -0,0 +1,31 @@ +# `fast-csv` + +Package that combines both [`@fast-csv/format`](../format) and [`@fast-csv/parse`](../parse) into a single package. + +## Installation + +`npm install -S fast-csv` + +## Usage + +To use `fast-csv` in `javascript` you can require the module + +```js +const csv = require('fast-csv'); +``` + +To import with typescript + +```typescript +import * as csv from 'fast-csv'; +``` + +## Documentation + +* [Parsing Docs](../parse/README.md) +* [Formatting Docs](../format/README.md) + +### Examples + +* [JS Examples](../../examples/fast-csv-js/README.md) + diff --git a/packages/fast-csv/__tests__/fast-csv.spec.ts b/packages/fast-csv/__tests__/fast-csv.spec.ts new file mode 100644 index 00000000..b7022e80 --- /dev/null +++ b/packages/fast-csv/__tests__/fast-csv.spec.ts @@ -0,0 +1,10 @@ +import * as csvFormat from '@fast-csv/format'; +import * as csv from '../src'; + +describe('formatting function', () => { + describe('format', () => { + it('should expose the format function', () => { + expect(csv.format).toBe(csvFormat.format); + }); + }); +}); diff --git a/packages/fast-csv/package.json b/packages/fast-csv/package.json new file mode 100644 index 00000000..18916a86 --- /dev/null +++ b/packages/fast-csv/package.json @@ -0,0 +1,44 @@ +{ + "name": "fast-csv", + "version": "4.0.0", + "description": "CSV parser and writer", + "main": "./build/src/index.js", + "types": "./build/src/index.d.ts", + "scripts": { + "build": "npm run clean && npm run compile", + "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo", + "compile": "tsc -p tsconfig.build.json" + }, + "directories": { + "lib": "src", + "test": "__tests__" + }, + "files": [ + "build/src/**" + ], + "repository": { + "type": "git", + "url": "git@github.com:C2FO/fast-csv.git" + }, + "keywords": [ + "csv", + "parser", + "fast", + "writer", + "csv writer", + "CSV" + ], + "homepage": "http://c2fo.github.com/fast-csv/index.html", + "author": "Doug Martin", + "license": "MIT", + "devDependencies": { + }, + "engines": { + "node": ">=8.0.0" + }, + "dependencies": { + "@types/node": "^12.12.17", + "@fast-csv/parse": "4.0.0", + "@fast-csv/format": "4.0.0" + } +} diff --git a/src/index.ts b/packages/fast-csv/src/index.ts similarity index 61% rename from src/index.ts rename to packages/fast-csv/src/index.ts index 4106fe7e..33abb3a1 100644 --- a/src/index.ts +++ b/packages/fast-csv/src/index.ts @@ -1,13 +1,3 @@ -/** - * @projectName fast-csv - * @github https://github.com/C2FO/fast-csv - * @includeDoc [Change Log] ../History.md - * @header [../README.md] - */ - -import { deprecate } from 'util'; -import { parseStream, parseString, parseFile, RowValidateCallback } from './parser'; - export { format, write, @@ -15,6 +5,8 @@ export { writeToBuffer, writeToString, writeToPath, + CsvFormatterStream, + FormatterOptions, FormatterOptionsArgs, Row as FormatterRow, RowMap as FormatterRowMap, @@ -22,12 +14,15 @@ export { RowHashArray as FormatterRowHashArray, RowTransformCallback as FormatterRowTransformCallback, RowTransformFunction as FormatterRowTransformFunction, -} from './formatter'; +} from '@fast-csv/format'; + export { parse, parseString, parseStream, parseFile, + ParserOptions, + CsvParserStream, ParserOptionsArgs, Row as ParserRow, RowMap as ParserRowMap, @@ -42,8 +37,4 @@ export { RowTransformFunction as ParserRowTransformFunction, HeaderArray as ParserHeaderArray, HeaderTransformFunction as ParserHeaderTransformFunction, -} from './parser'; - -export const fromString = deprecate(parseString, 'csv.fromString has been deprecated in favor of csv.parseString'); -export const fromStream = deprecate(parseStream, 'csv.fromStream has been deprecated in favor of csv.parseStream'); -export const fromPath = deprecate(parseFile, 'csv.fromPath has been deprecated in favor of csv.parseFile'); +} from '@fast-csv/parse'; diff --git a/packages/fast-csv/tsconfig.build.json b/packages/fast-csv/tsconfig.build.json new file mode 100644 index 00000000..bd8b5699 --- /dev/null +++ b/packages/fast-csv/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./build", + "rootDir": "." + }, + "exclude": [ + "node_modules", + "build" + ] +} diff --git a/packages/fast-csv/tsconfig.json b/packages/fast-csv/tsconfig.json new file mode 100644 index 00000000..6b9e22b4 --- /dev/null +++ b/packages/fast-csv/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./src", "./__tests__/**/*.ts"] +} diff --git a/packages/format/.eslintrc.js b/packages/format/.eslintrc.js new file mode 100644 index 00000000..eb38465f --- /dev/null +++ b/packages/format/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + parserOptions: { + project: "./tsconfig.build.json" + }, +}; \ No newline at end of file diff --git a/packages/format/README.md b/packages/format/README.md new file mode 100644 index 00000000..e2cdcf72 --- /dev/null +++ b/packages/format/README.md @@ -0,0 +1,252 @@ +# `@fast-csv/format` + +`fast-csv` package to create CSVs. + +## Installation + +`npm i -S @fast-csv/format` + +## Usage + +To use `fast-csv` in `javascript` you can require the module + +```js +const csv = require('@fast-csv/format'); +``` + +To import with typescript + +```typescript +import * as format csv '@fast-csv/format'; +``` + +* [Options](#options) +* [Valid Rows Types](#valid-row-types) +* [Formatting Methods](#formatting-methods) + * [`format`](#csv-format) + * [`write`](#csv-write) + * [`writeToStream`](#csv-write-to-stream) + * [`writeToBuffer`](#csv-write-to-buffer) + * [`writeToString`](#csv-write-to-string) + * [`writeToPath`](#csv-write-to-path) +* Examples + * [JS Examples](../../examples/formatting-js/README.md) + + +## Options + +* `delimiter: {string} = ','`: Specify an alternate field delimiter such as `;` or `\t`. + * **NOTE** When specifying an alternate `delimiter` you may only pass in a single character delimiter +* `rowDelimiter: {string} = '\n'`: Specify an alternate row delimiter (i.e `\r\n`) +* `quote: {string|boolean} = '"'`: + * If provided as a string it will be used to quote fields that contain a delimiter. + * `"first,name",last name` + * If `quote` is set to `true` the default quote will be used. + * **NOTE** This is the same as not providing the option + * If `quote` false then quoting will be disabled + * **CAUTION** If your field could contain a delimiter then you may end up with extra columns +* `escape: {string} = '"'`: The character to use when escaping a value that is `quoted` and contains a `quote` character that is not the end of the field. + * `i.e`: `First,"Name"' => '"First,""Name"""` +* `includeEndRowDelimiter: {boolean} = false`: Set to `true` to include a row delimiter at the end of the csv. +* `writeBOM: {boolean} = false`: Set to true if you want the first character written to the stream to be a utf-8 BOM character. +* `headers: {null|boolean|string[]} = null`: + * If true then the headers will be auto detected from the first row. + * 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 +* `alwaysWriteHeaders: {boolean} = false`: Set to true if you always want headers written, even if no rows are written. + * **NOTE** This will throw an error if headers are not specified as an array. +* `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) + * If it is an array then each item in the array that is true will have the column at the corresponding index quoted (unless `quoteHeaders` is specified) + * **NOTE** if `quoteHeaders` is not specified this option will apply to both columns and headers. +* `quoteHeaders: {boolean|boolean[]|{[string]: boolean} = quoteColumns` + * Defaults to the `quoteColumns` option. + * If `true` then all headers will be quoted. + * If it is an object then each key that has a true value will be quoted (see example below) + * If it is an array then each item in the array that is true will have the header at the corresponding index quoted (see example below) +* `transform: {(row) => Row | (row, cb) => void} = null`: A function that accepts a row and returns a transformed one to be written, or your function can accept an optional callback to do async transformations. + + +## Valid Row Types + +When creating a CSV `fast-csv` supports a few row formats. + +**`{[string]: any}`** + +You can pass in object to any formatter function if your CSV requires headers the keys of the first object will be used as the header names. + +```javascript +{ + a: "a1", + b: "b1", + c: "c1", +} + +//Generated CSV +//a,b,c +//a1,b1,c1 +``` + +**`string[]`** + +You can also pass in your rows as arrays. If your CSV requires headers the first row passed in will be the headers used. + +```javascript +[ + ["a", "b", "c"], + ["a1", "b1", "c1"] +] +//Generated CSV +//a,b,c +//a1,b1,c1 +``` + +**`[string, any][]`** + +This is the least commonly used format but can be useful if you have requirements to generate a CSV with headers with the same column name (Crazy we know but we have seen it). + +```javascript +[ + [ + ["a", "a1"], + ["a", "a2"], + ["b", "b1"], + ["b", "b2"], + ["c", "c1"], + ["c", "c2"] + ] +] + +//Generated CSV +//a,a,b,b,c,c +//a1,a2,b1,b2,c1,c2 +``` + + +## Formatting Methods + + +**`csv.format(options): CsvFormatterStream`** + +This is the main entry point for formatting CSVs. It is used by all other helper methods. + +```javascript +const stream = csv.format(); +stream.pipe(process.stdout); + +stream.write([ 'a', 'b' ]); +stream.write([ 'a1', 'b1' ]); +stream.write([ 'a2', 'b2' ]); +stream.end(); +``` + +Expected output + +``` +a,b +a1,b1 +a2,b2 +``` + + +**`write(rows[, options]): CsvFormatterStream`** + +Create a formatter, writes the rows and returns the `CsvFormatterStream`. + +```javascript +const rows = [ + [ 'a', 'b' ], + [ 'a1', 'b1' ], + [ 'a2', 'b2' ], +]; +csv.write(rows).pipe(process.stdout); +``` + +Expected output + +``` +a,b +a1,b1 +a2,b2 +``` + + +**`writeToStream(stream, rows[, options])`** + +Write an array of values to a `WritableStream`, and returns the original stream + +```javascript +const rows = [ + [ 'a', 'b' ], + [ 'a1', 'b1' ], + [ 'a2', 'b2' ], +]; +csv.writeToStream(process.stdout, rows); + +``` + +Expected output + +``` +a,b +a1,b1 +a2,b2 +``` + + +**`writeToPath(path, rows[, options])`** + +Write an array of values to the specified path + +```javascript +const rows = [ + [ 'a', 'b' ], + [ 'a1', 'b1' ], + [ 'a2', 'b2' ], +]; +csv.writeToPath(path.resolve(__dirname, 'tmp.csv'), rows) + .on('error', err => console.error(err)) + .on('finish', () => console.log('Done writing.')); + +``` + +Expected file content + +``` +a,b +a1,b1 +a2,b2 +``` + + +**`writeToString(arr[, options]): Promise`** + +Formats the rows and returns a `Promise` that will resolve with the CSV content as a `string`. + +```javascript +const rows = [ + [ 'a', 'b' ], + [ 'a1', 'b1' ], + [ 'a2', 'b2' ], +]; +csv.writeToString(rows).then(data => console.log(data)); +``` + + +**`writeToBuffer(arr[, options]): Promise`** + +Formats the rows and returns a `Promise` that will resolve with the CSV content as a `Buffer`. + +```javascript +const rows = [ + [ 'a', 'b' ], + [ 'a1', 'b1' ], + [ 'a2', 'b2' ], +]; +csv.writeToBuffer(rows).then(data => console.log(data.toString())); +``` \ No newline at end of file diff --git a/packages/format/__tests__/CsvFormatterStream.spec.ts b/packages/format/__tests__/CsvFormatterStream.spec.ts new file mode 100644 index 00000000..7a9a9296 --- /dev/null +++ b/packages/format/__tests__/CsvFormatterStream.spec.ts @@ -0,0 +1,347 @@ +import { + FormatterOptionsArgs, + Row, + RowArray, + RowMap, + RowHashArray, + CsvFormatterStream, + FormatterOptions, +} from '../src'; +import { arrayRows, multiDimensionalRows, objectRows, RecordingStream } from './__fixtures__'; + +describe('CsvFormatterStream', () => { + const pipeToRecordingStream = (formatter: CsvFormatterStream, rows: Row[]) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + formatter + .on('error', e => rej(e)) + .pipe(rs) + .on('finish', () => { + res(rs.data); + }); + rows.forEach(row => formatter.write(row)); + formatter.end(); + }); + + const formatRows = (rows: Row[], options: FormatterOptionsArgs = {}) => + pipeToRecordingStream(new CsvFormatterStream(new FormatterOptions(options)), rows); + + it('should write an array of arrays', () => + expect(formatRows(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of objects', () => + expect(formatRows(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + describe('transform option', () => { + it('should support transforming an array of arrays', () => + expect( + formatRows(arrayRows, { + headers: true, + transform(row: Row) { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + formatRows(multiDimensionalRows, { + headers: true, + transform(row: Row) { + return (row as RowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + it('should support transforming an array of objects', () => + expect( + formatRows(objectRows, { + headers: true, + transform(row: RowMap) { + return { A: row.a, B: row.b }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + }); + describe('#transform', () => { + it('should support transforming an array of arrays', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform((row: Row) => + (row as RowArray).map(entry => entry.toUpperCase()), + ); + await expect(pipeToRecordingStream(formatter, arrayRows)).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2']); + }); + + it('should support transforming an array of multi-dimensional arrays', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( + (row: Row): Row => (row as RowHashArray).map(entry => [entry[0], entry[1].toUpperCase()]), + ); + await expect(pipeToRecordingStream(formatter, multiDimensionalRows)).resolves.toEqual([ + 'a,b', + '\nA1,B1', + '\nA2,B2', + ]); + }); + + it('should support transforming an array of objects', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( + (row: Row): Row => ({ + A: (row as RowMap).a, + B: (row as RowMap).b, + }), + ); + await expect(pipeToRecordingStream(formatter, objectRows)).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2']); + }); + + it('should error if the transform fails', async () => { + const formatter = new CsvFormatterStream(new FormatterOptions({ headers: true })).transform( + (): Row => { + throw new Error('Expected error'); + }, + ); + await expect(pipeToRecordingStream(formatter, objectRows)).rejects.toThrowError('Expected error'); + }); + }); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect( + formatRows(objectRows, { + headers: true, + rowDelimiter: '\r\n', + }), + ).resolves.toEqual(['a,b', '\r\na1,b1', '\r\na2,b2'])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\n1', b: 'b1' }, + { a: 'a\n2', b: 'b2' }, + ]; + await expect( + formatRows(rows, { + headers: true, + rowDelimiter: '\n', + }), + ).resolves.toEqual(['a,b', '\n"a\n1",b1', '\n"a\n2",b2']); + }); + }); + + describe('quoteColumns option', () => { + describe('quote all columns and headers if quoteColumns is true and quoteHeaders is false', () => { + const opts = { + headers: true, + quoteColumns: true, + }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a","b"', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a","b"', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with multi-dimenional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual([ + '"a","b"', + '\n"a1","b1"', + '\n"a2","b2"', + ])); + }); + + describe('quote headers if quoteHeaders is true and not columns is quoteColumns is undefined', () => { + const opts = { headers: true, quoteHeaders: true }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a","b"', '\na1,b1', '\na2,b2'])); + }); + + describe('quote columns if quoteColumns is true and not quote headers if quoteHeaders is false', () => { + const opts = { headers: true, quoteHeaders: false, quoteColumns: true }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1","b1"', '\n"a2","b2"'])); + }); + + describe('if quoteColumns object it should only quote the specified column and header', () => { + const opts = { headers: true, quoteColumns: { a: true } }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteColumns object and quoteHeaders is false it should only quote the specified column and not the header', () => { + const opts = { + headers: true, + quoteHeaders: false, + quoteColumns: { a: true }, + }; + it('should work with objects', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,b', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteColumns is an array it should only quote the specified column index', () => { + const opts = { headers: true, quoteColumns: [true] }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteColumns is false and quoteHeaders is an object it should only quote the specified header and not the column', () => { + const opts = { + headers: true, + quoteHeaders: { a: true }, + quoteColumns: false, + }; + it('should work with object', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); + + it('should work with multi-dimenional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['"a",b', '\na1,b1', '\na2,b2'])); + }); + + describe('if quoteColumns is an object and quoteHeaders is an object it should only quote the specified header and column', () => { + const opts = { + headers: true, + quoteHeaders: { b: true }, + quoteColumns: { a: true }, + }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); + + it('should work with multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,"b"', '\n"a1",b1', '\n"a2",b2'])); + }); + + describe('if quoteHeaders is an array and quoteColumns is an false it should only quote the specified header and not the column', () => { + const opts = { + headers: true, + quoteHeaders: [false, true], + quoteColumns: false, + }; + it('should work with objects', () => + expect(formatRows(objectRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); + + it('should work with arrays', () => + expect(formatRows(arrayRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); + + it('should work with arrays of multi-dimensional arrays', () => + expect(formatRows(multiDimensionalRows, opts)).resolves.toEqual(['a,"b"', '\na1,b1', '\na2,b2'])); + }); + }); + + describe('header option', () => { + it('should write an array of objects without headers', () => + expect(formatRows(objectRows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2'])); + + it('should write an array of objects with headers', () => + expect(formatRows(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of arrays without headers', async () => { + const rows = [ + ['a1', 'b1'], + ['a2', 'b2'], + ]; + await expect(formatRows(rows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2']); + }); + + it('should write an array of arrays with headers', () => + expect(formatRows(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of multi-dimensional arrays without headers', () => + expect(formatRows(multiDimensionalRows, { headers: false })).resolves.toEqual(['a1,b1', '\na2,b2'])); + + it('should write an array of multi-dimensional arrays with headers', () => + expect(formatRows(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should not write anything if headers are provided but no rows are provided', () => + expect(formatRows([], { headers: true })).resolves.toEqual([])); + + describe('alwaysWriteHeaders option', () => { + it('should write the headers if rows are not provided', async () => { + const headers = ['h1', 'h2']; + await expect( + formatRows([], { + headers, + alwaysWriteHeaders: true, + }), + ).resolves.toEqual([headers.join(',')]); + }); + + it('should write the headers ones if rows are provided', async () => { + const headers = ['h1', 'h2']; + await expect( + formatRows(arrayRows, { + headers, + alwaysWriteHeaders: true, + }), + ).resolves.toEqual([headers.join(','), '\na,b', '\na1,b1', '\na2,b2']); + }); + + it('should fail if no headers are provided', async () => { + await expect(formatRows([], { alwaysWriteHeaders: true })).rejects.toThrowError( + '`alwaysWriteHeaders` option is set to true but `headers` option not provided.', + ); + }); + + it('should write the headers and an endRowDelimiter if includeEndRowDelimiter is true', async () => { + const headers = ['h1', 'h2']; + await expect( + formatRows([], { + headers, + includeEndRowDelimiter: true, + alwaysWriteHeaders: true, + }), + ).resolves.toEqual([headers.join(','), '\n']); + }); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect( + formatRows(objectRows, { + headers: true, + includeEndRowDelimiter: true, + }), + ).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2', '\n'])); + + it('should write a BOM character if writeBOM is true', () => + expect( + formatRows(objectRows, { + headers: true, + writeBOM: true, + }), + ).resolves.toEqual(['\ufeff', 'a,b', '\na1,b1', '\na2,b2'])); +}); diff --git a/__tests__/formatter/FormatterOptions.spec.ts b/packages/format/__tests__/FormatterOptions.spec.ts similarity index 98% rename from __tests__/formatter/FormatterOptions.spec.ts rename to packages/format/__tests__/FormatterOptions.spec.ts index b131416c..b27507f7 100644 --- a/__tests__/formatter/FormatterOptions.spec.ts +++ b/packages/format/__tests__/FormatterOptions.spec.ts @@ -1,5 +1,5 @@ -import { FormatterOptionsArgs } from '../../src'; -import { FormatterOptions } from '../../src/formatter'; +import { FormatterOptionsArgs } from '../src'; +import { FormatterOptions } from '../src/FormatterOptions'; describe('FormatterOptions', () => { const createOptions = (opts: FormatterOptionsArgs = {}) => new FormatterOptions(opts); diff --git a/examples/parsing/ignore_empty.example.js b/packages/format/__tests__/__fixtures__/.gitkeep similarity index 100% rename from examples/parsing/ignore_empty.example.js rename to packages/format/__tests__/__fixtures__/.gitkeep diff --git a/__tests__/RecordingStream.ts b/packages/format/__tests__/__fixtures__/RecordingStream.ts similarity index 82% rename from __tests__/RecordingStream.ts rename to packages/format/__tests__/__fixtures__/RecordingStream.ts index e6315ecc..3a6f8a50 100644 --- a/__tests__/RecordingStream.ts +++ b/packages/format/__tests__/__fixtures__/RecordingStream.ts @@ -1,6 +1,6 @@ import { Writable } from 'stream'; -export default class RecordingStream extends Writable { +export class RecordingStream extends Writable { public readonly data: string[] = []; public constructor() { diff --git a/packages/format/__tests__/__fixtures__/index.ts b/packages/format/__tests__/__fixtures__/index.ts new file mode 100644 index 00000000..ab4c884d --- /dev/null +++ b/packages/format/__tests__/__fixtures__/index.ts @@ -0,0 +1,22 @@ +export { RecordingStream } from './RecordingStream'; +export const objectRows = [ + { a: 'a1', b: 'b1' }, + { a: 'a2', b: 'b2' }, +]; + +export const arrayRows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; + +export const multiDimensionalRows = [ + [ + ['a', 'a1'], + ['b', 'b1'], + ], + [ + ['a', 'a2'], + ['b', 'b2'], + ], +]; diff --git a/packages/format/__tests__/format.spec.ts b/packages/format/__tests__/format.spec.ts new file mode 100644 index 00000000..3cf268b2 --- /dev/null +++ b/packages/format/__tests__/format.spec.ts @@ -0,0 +1,538 @@ +import * as path from 'path'; +import * as fs from 'fs'; +import { + FormatterOptionsArgs, + Row, + RowArray, + RowHashArray, + RowMap, + write, + writeToBuffer, + writeToPath, + writeToStream, + writeToString, +} from '../src'; +import { arrayRows, multiDimensionalRows, objectRows, RecordingStream } from './__fixtures__'; + +describe('.writeToString', () => { + it('should write an array of arrays', () => + expect(writeToString(arrayRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should support transforming an array of arrays', () => + expect( + writeToString(arrayRows, { + headers: true, + transform(row: Row): Row { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual('A,B\nA1,B1\nA2,B2')); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToString(multiDimensionalRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + writeToString(multiDimensionalRows, { + headers: true, + transform(row: Row) { + return (row as RowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual('a,b\nA1,B1\nA2,B2')); + + it('should write an array of objects', () => + expect( + writeToString(objectRows, { + headers: true, + transform(row: RowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual('A,B\na1,b1\na2,b2')); + + describe('header option', () => { + it('should write an array of objects without headers', () => + expect(writeToString(objectRows, { headers: false })).resolves.toEqual('a1,b1\na2,b2')); + + it('should write an array of objects with headers', () => + expect(writeToString(objectRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should write an array of arrays without headers', async () => { + const rows = [ + ['a1', 'b1'], + ['a2', 'b2'], + ]; + await expect(writeToString(rows, { headers: false })).resolves.toEqual('a1,b1\na2,b2'); + }); + + it('should write an array of arrays with headers', () => + expect(writeToString(arrayRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + + it('should write an array of multi-dimensional arrays without headers', () => + expect(writeToString(multiDimensionalRows, { headers: false })).resolves.toEqual('a1,b1\na2,b2')); + + it('should write an array of multi-dimensional arrays with headers', () => + expect(writeToString(multiDimensionalRows, { headers: true })).resolves.toEqual('a,b\na1,b1\na2,b2')); + }); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToString(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + 'a,b\r\na1,b1\r\na2,b2', + )); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\t1', b: 'b1' }, + { a: 'a\t2', b: 'b2' }, + ]; + await expect(writeToString(rows, { headers: true, rowDelimiter: '\t' })).resolves.toEqual( + 'a,b\t"a\t1",b1\t"a\t2",b2', + ); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeToString(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( + 'a,b\na1,b1\na2,b2\n', + )); +}); + +describe('.writeToBuffer', () => { + it('should write an array of arrays', () => + expect(writeToBuffer(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should support transforming an array of arrays', () => + expect( + writeToBuffer(arrayRows, { + headers: true, + transform(row: Row): Row { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(Buffer.from('A,B\nA1,B1\nA2,B2'))); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToBuffer(multiDimensionalRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + writeToBuffer(multiDimensionalRows, { + headers: true, + transform(row: Row) { + return (row as RowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(Buffer.from('a,b\nA1,B1\nA2,B2'))); + + it('should write an array of objects', () => + expect( + writeToBuffer(objectRows, { + headers: true, + transform(row: RowMap): Row { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(Buffer.from('A,B\na1,b1\na2,b2'))); + + describe('header option', () => { + it('should write an array of objects without headers', () => + expect(writeToBuffer(objectRows, { headers: false })).resolves.toEqual(Buffer.from('a1,b1\na2,b2'))); + + it('should write an array of objects with headers', () => + expect(writeToBuffer(objectRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should write an array of arrays without headers', async () => { + const rows = [ + ['a1', 'b1'], + ['a2', 'b2'], + ]; + await expect(writeToBuffer(rows, { headers: false })).resolves.toEqual(Buffer.from('a1,b1\na2,b2')); + }); + + it('should write an array of arrays with headers', () => + expect(writeToBuffer(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should write an array of multi-dimensional arrays without headers', () => + expect(writeToBuffer(multiDimensionalRows, { headers: false })).resolves.toEqual( + Buffer.from('a1,b1\na2,b2'), + )); + + it('should write an array of multi-dimensional arrays with headers', () => + expect(writeToBuffer(multiDimensionalRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + }); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToBuffer(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + Buffer.from('a,b\r\na1,b1\r\na2,b2'), + )); + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\t1', b: 'b1' }, + { a: 'a\t2', b: 'b2' }, + ]; + await expect(writeToBuffer(rows, { headers: true, rowDelimiter: '\t' })).resolves.toEqual( + Buffer.from('a,b\t"a\t1",b1\t"a\t2",b2'), + ); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeToBuffer(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2\n'), + )); +}); + +describe('.write', () => { + const writeToRecordingStream = (rows: Row[], options = {}) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + write(rows, options) + .on('error', rej) + .pipe(rs) + .on('finish', () => { + res(rs.data); + }); + }); + + it('should write an array of arrays', () => + expect(writeToRecordingStream(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should support transforming an array of arrays', () => + expect( + writeToRecordingStream(arrayRows, { + headers: true, + transform(row: Row) { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToRecordingStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + writeToRecordingStream(multiDimensionalRows, { + headers: true, + transform(row: Row) { + return (row as RowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of objects', () => + expect(writeToRecordingStream(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should support transforming an array of objects', () => + expect( + writeToRecordingStream(objectRows, { + headers: true, + transform(row: RowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\na1,b1', + '\r\na2,b2', + ])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\n1', b: 'b1' }, + { a: 'a\n2', b: 'b2' }, + ]; + await expect(writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' })).resolves.toEqual([ + 'a,b', + '\n"a\n1",b1', + '\n"a\n2",b2', + ]); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + '\n', + ])); +}); + +describe('.writeToPath', () => { + const writeRowsToPath = (rows: Row[], options = {}) => + new Promise((res, rej) => { + const csvPath = path.resolve(__dirname, '__fixtures__', 'test_output.csv'); + writeToPath(csvPath, rows, options) + .on('error', rej) + .on('finish', () => { + const content = fs.readFileSync(csvPath); + fs.unlinkSync(csvPath); + res(content); + }); + }); + + it('should write an array of arrays', () => + expect(writeRowsToPath(arrayRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should write an array of objects', () => + expect(writeRowsToPath(objectRows, { headers: true })).resolves.toEqual(Buffer.from('a,b\na1,b1\na2,b2'))); + + it('should write an array of multi-dimensional arrays', () => + expect(writeRowsToPath(multiDimensionalRows, { headers: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2'), + )); + + it('should support transforming an array of arrays', () => + expect( + writeRowsToPath(arrayRows, { + headers: true, + transform(row: Row) { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(Buffer.from('A,B\nA1,B1\nA2,B2'))); + + it('should transforming an array of objects', () => + expect( + writeRowsToPath(objectRows, { + headers: true, + transform(row: RowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(Buffer.from('A,B\na1,b1\na2,b2'))); + + it('should transforming an array of multi-dimensional array', () => + expect( + writeRowsToPath(multiDimensionalRows, { + headers: true, + transform(row: Row) { + return (row as RowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(Buffer.from('a,b\nA1,B1\nA2,B2'))); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeRowsToPath(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + Buffer.from('a,b\r\na1,b1\r\na2,b2'), + )); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\r\n1', b: 'b1' }, + { a: 'a\r\n2', b: 'b2' }, + ]; + await expect(writeRowsToPath(rows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual( + Buffer.from('a,b\r\n"a\r\n1",b1\r\n"a\r\n2",b2'), + ); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeRowsToPath(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual( + Buffer.from('a,b\na1,b1\na2,b2\n'), + )); +}); + +describe('.write', () => { + const writeToRecordingStream = (rows: Row[], options = {}) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + write(rows, options) + .on('error', rej) + .pipe(rs) + .on('finish', () => { + res(rs.data); + }); + }); + + it('should write an array of arrays', () => + expect(writeToRecordingStream(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should support transforming an array of arrays', () => + expect( + writeToRecordingStream(arrayRows, { + headers: true, + transform(row: Row) { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of multi-dimensional arrays', () => + expect(writeToRecordingStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of multi-dimensional arrays', () => + expect( + writeToRecordingStream(multiDimensionalRows, { + headers: true, + transform(row: Row) { + return (row as RowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + it('should write an array of objects', () => + expect(writeToRecordingStream(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should support transforming an array of objects', () => + expect( + writeToRecordingStream(objectRows, { + headers: true, + transform(row: RowMap) { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeToRecordingStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\na1,b1', + '\r\na2,b2', + ])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\n1', b: 'b1' }, + { a: 'a\n2', b: 'b2' }, + ]; + await expect(writeToRecordingStream(rows, { headers: true, rowDelimiter: '\n' })).resolves.toEqual([ + 'a,b', + '\n"a\n1",b1', + '\n"a\n2",b2', + ]); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeToRecordingStream(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + '\n', + ])); +}); + +describe('.writeToStream', () => { + const writeRowsToStream = (rows: Row[], options: FormatterOptionsArgs = {}) => + new Promise((res, rej) => { + const rs = new RecordingStream(); + writeToStream(rs, rows, options); + rs.on('error', rej).on('finish', () => { + res(rs.data); + }); + }); + + it('should write an array of arrays', () => + expect(writeRowsToStream(arrayRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of objects', () => + expect(writeRowsToStream(objectRows, { headers: true })).resolves.toEqual(['a,b', '\na1,b1', '\na2,b2'])); + + it('should write an array of multi-dimensional arrays', () => + expect(writeRowsToStream(multiDimensionalRows, { headers: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + ])); + + it('should support transforming an array of arrays', () => + expect( + writeRowsToStream(arrayRows, { + headers: true, + transform(row: Row): Row { + return (row as RowArray).map(entry => entry.toUpperCase()); + }, + }), + ).resolves.toEqual(['A,B', '\nA1,B1', '\nA2,B2'])); + + it('should transforming an array of objects', () => + expect( + writeRowsToStream(objectRows, { + headers: true, + transform(row: RowMap): Row { + return { + A: row.a, + B: row.b, + }; + }, + }), + ).resolves.toEqual(['A,B', '\na1,b1', '\na2,b2'])); + + it('should transforming an array of multi-dimensional array', () => + expect( + writeRowsToStream(multiDimensionalRows, { + headers: true, + transform(row: Row): Row { + return (row as RowHashArray).map(col => [col[0], col[1].toUpperCase()]); + }, + }), + ).resolves.toEqual(['a,b', '\nA1,B1', '\nA2,B2'])); + + describe('rowDelimiter option', () => { + it('should support specifying an alternate row delimiter', () => + expect(writeRowsToStream(objectRows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\na1,b1', + '\r\na2,b2', + ])); + + it('should escape values that contain the alternate row delimiter', async () => { + const rows = [ + { a: 'a\r\n1', b: 'b1' }, + { a: 'a\r\n2', b: 'b2' }, + ]; + await expect(writeRowsToStream(rows, { headers: true, rowDelimiter: '\r\n' })).resolves.toEqual([ + 'a,b', + '\r\n"a\r\n1",b1', + '\r\n"a\r\n2",b2', + ]); + }); + }); + + it('should add a final rowDelimiter if includeEndRowDelimiter is true', () => + expect(writeRowsToStream(objectRows, { headers: true, includeEndRowDelimiter: true })).resolves.toEqual([ + 'a,b', + '\na1,b1', + '\na2,b2', + '\n', + ])); +}); diff --git a/__tests__/formatter/formatter/FieldFormatter.spec.ts b/packages/format/__tests__/formatter/FieldFormatter.spec.ts similarity index 97% rename from __tests__/formatter/formatter/FieldFormatter.spec.ts rename to packages/format/__tests__/formatter/FieldFormatter.spec.ts index ff26c8a6..9f1cf5fe 100644 --- a/__tests__/formatter/formatter/FieldFormatter.spec.ts +++ b/packages/format/__tests__/formatter/FieldFormatter.spec.ts @@ -1,5 +1,5 @@ -import { FormatterOptionsArgs } from '../../../src'; -import { FormatterOptions, FieldFormatter } from '../../../src/formatter'; +import { FormatterOptions, FormatterOptionsArgs } from '../../src'; +import { FieldFormatter } from '../../src/formatter'; describe('FieldFormatter', () => { const createFormatter = (formatterOptions: FormatterOptionsArgs = {}) => { diff --git a/__tests__/formatter/formatter/RowFormatter.spec.ts b/packages/format/__tests__/formatter/RowFormatter.spec.ts similarity index 98% rename from __tests__/formatter/formatter/RowFormatter.spec.ts rename to packages/format/__tests__/formatter/RowFormatter.spec.ts index 64b68864..870440a4 100644 --- a/__tests__/formatter/formatter/RowFormatter.spec.ts +++ b/packages/format/__tests__/formatter/RowFormatter.spec.ts @@ -1,11 +1,6 @@ -import { - FormatterRow as Row, - FormatterRowArray as RowArray, - FormatterRowHashArray as RowHashArray, - FormatterRowMap as RowMap, - FormatterRowTransformCallback as RowTransformCallback, -} from '../../../src'; -import { RowFormatter, FormatterOptions } from '../../../src/formatter'; +import { RowFormatter } from '../../src/formatter'; +import { FormatterOptions } from '../../src/FormatterOptions'; +import { Row, RowArray, RowHashArray, RowMap, RowTransformCallback } from '../../src'; describe('RowFormatter', () => { const createFormatter = (formatterOptions = {}): RowFormatter => diff --git a/packages/format/__tests__/issues/__fixtures__/.gitkeep b/packages/format/__tests__/issues/__fixtures__/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/__tests__/issues/issue158.spec.ts b/packages/format/__tests__/issues/issue158.spec.ts similarity index 95% rename from __tests__/issues/issue158.spec.ts rename to packages/format/__tests__/issues/issue158.spec.ts index f794c22b..a0e45a8b 100644 --- a/__tests__/issues/issue158.spec.ts +++ b/packages/format/__tests__/issues/issue158.spec.ts @@ -1,5 +1,5 @@ import * as csv from '../../src'; -import RecordingStream from '../RecordingStream'; +import { RecordingStream } from '../__fixtures__'; describe('Issue #158 - https://github.com/C2FO/fast-csv/issues/158', () => { class Place { diff --git a/__tests__/issues/issue252.spec.ts b/packages/format/__tests__/issues/issue252.spec.ts similarity index 92% rename from __tests__/issues/issue252.spec.ts rename to packages/format/__tests__/issues/issue252.spec.ts index 0c797c41..33fbdfc9 100644 --- a/__tests__/issues/issue252.spec.ts +++ b/packages/format/__tests__/issues/issue252.spec.ts @@ -1,5 +1,5 @@ import * as csv from '../../src'; -import RecordingStream from '../RecordingStream'; +import { RecordingStream } from '../__fixtures__'; describe('Issue #252 - https://github.com/C2FO/fast-csv/issues/252', () => { it('should keep the original row', next => { diff --git a/__tests__/issues/issue77.spec.ts b/packages/format/__tests__/issues/issue77.spec.ts similarity index 100% rename from __tests__/issues/issue77.spec.ts rename to packages/format/__tests__/issues/issue77.spec.ts diff --git a/__tests__/issues/issue97.spec.ts b/packages/format/__tests__/issues/issue97.spec.ts similarity index 78% rename from __tests__/issues/issue97.spec.ts rename to packages/format/__tests__/issues/issue97.spec.ts index 0e287f60..974a1a99 100644 --- a/__tests__/issues/issue97.spec.ts +++ b/packages/format/__tests__/issues/issue97.spec.ts @@ -1,5 +1,5 @@ -import * as csv from '../../src'; -import RecordingStream from '../RecordingStream'; +import { RecordingStream } from '../__fixtures__'; +import { write } from '../../src'; describe('Issue #97 - https://github.com/C2FO/fast-csv/issues/97', () => { it('should keep the original row', next => { @@ -9,7 +9,7 @@ describe('Issue #97 - https://github.com/C2FO/fast-csv/issues/97', () => { { field1: 'a2"a', field2: 'b2"b' }, ]; - csv.write(data, { quote: false, headers: true }) + write(data, { quote: false, headers: true }) .pipe(rs) .on('error', next) .on('finish', () => { diff --git a/packages/format/package-lock.json b/packages/format/package-lock.json new file mode 100644 index 00000000..a1568e8a --- /dev/null +++ b/packages/format/package-lock.json @@ -0,0 +1,84 @@ +{ + "name": "@fast-csv/format", + "version": "4.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, + "@types/lodash.escaperegexp": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/lodash.escaperegexp/-/lodash.escaperegexp-4.1.6.tgz", + "integrity": "sha512-uENiqxLlqh6RzeE1cC6Z2gHqakToN9vKlTVCFkSVjAfeMeh2fY0916tHwJHeeKs28qB/hGYvKuampGYH5QDVCw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isboolean": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isboolean/-/lodash.isboolean-3.0.6.tgz", + "integrity": "sha512-9ommZgIE6GlZW/GuSRIOSJP3X0FkOD2qqt8xBNqUVb/t4L62WiIGCPgIKK2PNfZem7bEZulM0djX9f8IG2Qg3Q==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isequal": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.5.tgz", + "integrity": "sha512-4IKbinG7MGP131wRfceK6W4E/Qt3qssEFLF30LnJbjYiSfHGGRU/Io8YxXrZX109ir+iDETC8hw8QsDijukUVg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isfunction": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isfunction/-/lodash.isfunction-3.0.6.tgz", + "integrity": "sha512-olhgKmBgzHnA5pxsOI6YHunzTBMSyBw1XjxIKFio8W+XhYiELGTt05FStE0suV0GWtlIMdn7V8M/UbYbSVdGYw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isnil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isnil/-/lodash.isnil-4.0.6.tgz", + "integrity": "sha512-K+9ZVqwWUFKxijX7rPGnrubfTtCQ5VwW0xgPCL5iLBBLg5sUFFXdPG3QxkpGNJil8mgttRqNLSWNweEsUrBXTg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + } + } +} diff --git a/packages/format/package.json b/packages/format/package.json new file mode 100644 index 00000000..9235ecb4 --- /dev/null +++ b/packages/format/package.json @@ -0,0 +1,51 @@ +{ + "name": "@fast-csv/format", + "version": "4.0.0", + "description": "fast-csv formatting module", + "keywords": [ + "csv", + "format", + "write" + ], + "author": "doug-martin ", + "homepage": "http://c2fo.github.com/fast-csv/index.html/tree/master/packages/format#readme", + "license": "ISC", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "directories": { + "lib": "src", + "test": "__tests__" + }, + "files": [ + "build/src/**" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/C2FO/fast-csv.git" + }, + "scripts": { + "build": "npm run clean && npm run compile", + "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo", + "compile": "tsc -p tsconfig.build.json" + }, + "bugs": { + "url": "https://github.com/C2FO/fast-csv/issues" + }, + "dependencies": { + "lodash.escaperegexp": "^4.1.2", + "lodash.isboolean": "^3.0.3", + "lodash.isequal": "^4.5.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0" + }, + "devDependencies": { + "@types/lodash.escaperegexp": "^4.1.6", + "@types/lodash.isboolean": "^3.0.6", + "@types/lodash.isequal": "^4.5.5", + "@types/lodash.isfunction": "^3.0.6", + "@types/lodash.isnil": "^4.0.6" + } +} diff --git a/src/formatter/CsvFormatterStream.ts b/packages/format/src/CsvFormatterStream.ts similarity index 94% rename from src/formatter/CsvFormatterStream.ts rename to packages/format/src/CsvFormatterStream.ts index 0bd20110..8f340747 100644 --- a/src/formatter/CsvFormatterStream.ts +++ b/packages/format/src/CsvFormatterStream.ts @@ -1,9 +1,9 @@ import { Transform, TransformCallback } from 'stream'; import { FormatterOptions } from './FormatterOptions'; import { Row, RowTransformFunction } from './types'; -import RowFormatter from './formatter/RowFormatter'; +import { RowFormatter } from './formatter'; -export default class CsvFormatterStream extends Transform { +export class CsvFormatterStream extends Transform { private formatterOptions: FormatterOptions; private rowFormatter: RowFormatter; diff --git a/src/formatter/FormatterOptions.ts b/packages/format/src/FormatterOptions.ts similarity index 100% rename from src/formatter/FormatterOptions.ts rename to packages/format/src/FormatterOptions.ts diff --git a/src/formatter/formatter/FieldFormatter.ts b/packages/format/src/formatter/FieldFormatter.ts similarity index 98% rename from src/formatter/formatter/FieldFormatter.ts rename to packages/format/src/formatter/FieldFormatter.ts index 04e2baa8..2b74db6f 100644 --- a/src/formatter/formatter/FieldFormatter.ts +++ b/packages/format/src/formatter/FieldFormatter.ts @@ -3,7 +3,7 @@ import isNil from 'lodash.isnil'; import escapeRegExp from 'lodash.escaperegexp'; import { FormatterOptions } from '../FormatterOptions'; -export default class FieldFormatter { +export class FieldFormatter { private readonly formatterOptions: FormatterOptions; private _headers: string[] | null = null; diff --git a/src/formatter/formatter/RowFormatter.ts b/packages/format/src/formatter/RowFormatter.ts similarity index 98% rename from src/formatter/formatter/RowFormatter.ts rename to packages/format/src/formatter/RowFormatter.ts index 52541622..7f3db374 100644 --- a/src/formatter/formatter/RowFormatter.ts +++ b/packages/format/src/formatter/RowFormatter.ts @@ -1,7 +1,7 @@ import isFunction from 'lodash.isfunction'; import isEqual from 'lodash.isequal'; import { FormatterOptions } from '../FormatterOptions'; -import FieldFormatter from './FieldFormatter'; +import { FieldFormatter } from './FieldFormatter'; import { Row, RowHashArray, RowTransformFunction } from '../types'; type RowCallback = (err?: Error | null, row?: Row) => void; @@ -10,7 +10,7 @@ type RowFormatterTransform = (row: Row, cb: RowCallback) => void; type RowFormatterCallback = (error: Error | null, data?: string[]) => void; -export default class RowFormatter { +export class RowFormatter { private static isHashArray(row: Row): row is RowHashArray { if (Array.isArray(row)) { return Array.isArray(row[0]) && row[0].length === 2; diff --git a/packages/format/src/formatter/index.ts b/packages/format/src/formatter/index.ts new file mode 100644 index 00000000..1fa76069 --- /dev/null +++ b/packages/format/src/formatter/index.ts @@ -0,0 +1,2 @@ +export { RowFormatter } from './RowFormatter'; +export { FieldFormatter } from './FieldFormatter'; diff --git a/src/formatter/index.ts b/packages/format/src/index.ts similarity index 91% rename from src/formatter/index.ts rename to packages/format/src/index.ts index d769dfd3..bfc25d30 100644 --- a/src/formatter/index.ts +++ b/packages/format/src/index.ts @@ -3,12 +3,11 @@ import { Writable } from 'stream'; import * as fs from 'fs'; import { Row as FormatterRow } from './types'; import { FormatterOptions, FormatterOptionsArgs } from './FormatterOptions'; -import CsvFormatterStream from './CsvFormatterStream'; +import { CsvFormatterStream } from './CsvFormatterStream'; -export { default as CsvFormatterStream } from './CsvFormatterStream'; export * from './types'; -export * from './FormatterOptions'; -export * from './formatter'; +export { CsvFormatterStream } from './CsvFormatterStream'; +export { FormatterOptions, FormatterOptionsArgs } from './FormatterOptions'; export const format = (options?: FormatterOptionsArgs): CsvFormatterStream => new CsvFormatterStream(new FormatterOptions(options)); diff --git a/src/formatter/types.ts b/packages/format/src/types.ts similarity index 100% rename from src/formatter/types.ts rename to packages/format/src/types.ts diff --git a/packages/format/tsconfig.build.json b/packages/format/tsconfig.build.json new file mode 100644 index 00000000..22b9804b --- /dev/null +++ b/packages/format/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./build", + "rootDir": "." + } +} diff --git a/packages/format/tsconfig.json b/packages/format/tsconfig.json new file mode 100644 index 00000000..6b9e22b4 --- /dev/null +++ b/packages/format/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./src", "./__tests__/**/*.ts"] +} diff --git a/packages/parse/.eslintrc.js b/packages/parse/.eslintrc.js new file mode 100644 index 00000000..eb38465f --- /dev/null +++ b/packages/parse/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + parserOptions: { + project: "./tsconfig.build.json" + }, +}; \ No newline at end of file diff --git a/packages/parse/README.md b/packages/parse/README.md new file mode 100644 index 00000000..58279a29 --- /dev/null +++ b/packages/parse/README.md @@ -0,0 +1,184 @@ +# `@fast-csv/parse` + +`fast-csv` package to parse CSVs. + +## Installation + +`npm i -S @fast-csv/parse` + +## Usage + +To use `fast-csv` in `javascript` you can require the module + +```js +const csv = require('@fast-csv/parse'); +``` + +To import with typescript + +```typescript +import * as format csv '@fast-csv/parse'; +``` + +* [Options](#parsing-options) +* [Events](#parsing-events) +* [Parsing Methods](#parsing-methods) + * [`csv.parse`](#csv-parse) + * [`csv.parseStream`](#csv-parse-stream) + * [`csv.parseFile`](#csv-parse-path) + * [`csv.parseString`](#csv-parse-string) +* Examples + * [JS Examples](../../examples/parsing-js/README.md) + + +## Options + +* `objectMode: {boolean} = true`: Ensure that `data` events have an object emitted rather than the stringified version set to false to have a stringified buffer. +* `delimiter: {string} = ','`: If your data uses an alternate delimiter such as `;` or `\t`. + * **NOTE** When specifying an alternate `delimiter` you may only pass in a single character delimiter +* `quote: {string} = '"'`: The character to use to quote fields that contain a delimiter. If you set to `null` then all quoting will be ignored. + * `"first,name",last name` +* `escape: {string} = '"'`: The character to used tp escape quotes inside of a quoted field. + * `i.e`: `First,"Name"' => '"First,""Name"""` +* `headers: {boolean|string[]|(string[]) => string[])} = false`: + * If you want the first row to be treated as headers then set to `true` + * If there is not a headers row and you want to provide one then set to a `string[]` + * If you wish to discard the first row and use your own headers set to a `string[]` and set the `renameHeaders` option to `true` + * If you wish to transform the headers you can provide a transform function. + * **NOTE** This will always rename the headers + * **NOTE** If headers either parsed, provided or transformed are NOT unique, then an error will be emitted and the stream will stop parsing. +* `renameHeaders: {boolean} = false`: If you want the first line of the file to be removed and replaced by the one provided in the `headers` option. + * **NOTE** This option should only be used if the `headers` option is a `string[]` + * **NOTE** If the `headers` option is a function then this option is always set to true. +* `ignoreEmpty: {boolean} = false`: If you wish to ignore empty rows. + * **NOTE** this will discard columns that are all white space or delimiters. +* `comment: {string} = null`: If your CSV contains comments you can use this option to ignore lines that begin with the specified character (e.g. `#`). +* `discardUnmappedColumns: {boolean} = false`: If you want to discard columns that do not map to a header. + * **NOTE** this is only valid in the case that there are headers and the number of fields parsed is greater than the number of header fields. +* `strictColumnHandling: {boolean} = false`: If you want to consider empty lines/lines with too few fields as invalid and emit a `data-invalid` event + * **NOTE** This option is only considered when `headers` are present. +* `trim: {boolean} = false`: Set to `true` to trim all fields +* `rtrim: {boolean} = false`: Set to `true` to right trim all fields. +* `ltrim: {boolean} = false`: Set to `true` to left trim all fields. +* `encoding: {string} = 'utf8'`: Passed to [StringDecoder](https://nodejs.org/api/string_decoder.html#string_decoder_new_stringdecoder_encoding) when decoding incoming buffers. Change if incoming content is not 'utf8' encoded. +* `maxRows: {number} = 0`: If number is `> 0` the specified number of rows will be parsed.(e.g. `100` would return the first 100 rows of data). +* `skipRows: {number} = 0`: If number is `> 0` the specified number of **parsed** rows will be skipped. +* `skipLines: {number} = 0`: If number is `> 0` the specified number of lines will be skipped. + + +## Events + +* `data`: Emitted when a record is parsed. + * If headers are present then all rows will be an object. + * If headers are not present then all rows will be an array. + * **NOTE** if `objectMode` is set to false then all rows will be a buffer with a JSON row. +* `data-invalid`: Emitted if there was invalid row encounted; + * Emitted when a `validate` function is provided and an invalid row is encountered. + * Emitted when `strictColumnHandling` is `true` and a row with a different number of fields than headers is encountered. + + +## Methods + + +**`csv.parse([options]): CsvParserStream`** + +Creates a Csv Parsing Stream that can be piped or written to. + +This is the main entrypoint and is used by all the other parsing helpers. + +```javascript + +//creates a stream you can pipe +const stream = csv.parse() + +stream + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +``` + +To pipe to the stream from a file you can do the following. + +```javascript +const csv = require('fast-csv'); + +fs.createReadStream('my.csv') + .pipe(csv.parse()) + .on('error', error => console.error(error)) + .on('data', row => console.log(`ROW=${JSON.stringify(row)}`)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +``` + +```javascript +const csv = require('fast-csv'); + +const fileStream = fs.createReadStream("my.csv"); +const parser = csv.parse(); + +fileStream + .pipe(parser) + .on('error', error => console.error(error)) + .on('readable', () => { + for (let row = parser.read(); row; row = parser.read()) { + console.log(`ROW=${JSON.stringify(row)}`); + } + }) + .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`)); +``` + + +**`csv.parseStream(readableStream[, options]): CsvParserStream`** + +Accepts a readable stream and pipes it to a `CsvParserStream`. + +```javascript +const stream = fs.createReadStream('./path/to/my.csv'); + +csv + .parseStream(stream) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); + +``` + + +**`csv.parseFile(path[, options]): CsvParserStream`** + +Parses a file from the specified path and returns the `CsvParserStream`. + +```javascript +const csv = require('fast-csv'); + +csv + .parseFile('./path/to/my.csv') + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +``` + + +**`csv.parseString(string[, options]): CsvParserStream`** + +This method parses a string and returns the `CsvParserStream`. + +```javascript +const { EOL } = require('os'); +const csv = require('fast-csv'); + +const CSV_STRING = [ + 'a,b', + 'a1,b1', + 'a2,b2', +].join(EOL); + +csv + .parseString(CSV_STRING, { headers: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', rowCount => console.log(`Parsed ${rowCount} rows`)); +``` + + + + diff --git a/__tests__/parser/CsvParsingStream.spec.ts b/packages/parse/__tests__/CsvParsingStream.spec.ts similarity index 53% rename from __tests__/parser/CsvParsingStream.spec.ts rename to packages/parse/__tests__/CsvParsingStream.spec.ts index fe4fbadd..3c12d5ac 100644 --- a/__tests__/parser/CsvParsingStream.spec.ts +++ b/packages/parse/__tests__/CsvParsingStream.spec.ts @@ -2,13 +2,37 @@ import * as fs from 'fs'; import * as domain from 'domain'; import partition from 'lodash.partition'; -import * as csv from '../../src'; -import assets, { PathAndContent } from './__fixtures__'; -import { CsvParserStream } from '../../src/parser'; +import { CsvParserStream } from '../src/CsvParserStream'; +import { parseFile, ParserOptionsArgs, Row, RowMap, RowValidateCallback } from '../src'; +import { ParserOptions } from '../src/ParserOptions'; +import { + PathAndContent, + ParseResults, + expectParsed, + parseContentAndCollectFromStream, + write, + duplicateHeaders, + headerColumnMismatch, + noHeadersAndQuotes, + withHeaders, + withHeadersAndAlternateQuote, + withHeadersAndMissingColumns, + withHeadersAndSkippedLines, + withHeadersAndQuotes, + alternateEncoding, + trailingComma, + emptyRows, + withHeadersAlternateDelimiter, + skipLines, + malformed, +} from './__fixtures__'; import DoneCallback = jest.DoneCallback; describe('CsvParserStream', () => { + const createParserStream = (args?: ParserOptionsArgs): CsvParserStream => + new CsvParserStream(new ParserOptions(args)); + const listenForError = (stream: CsvParserStream, message: string, next: DoneCallback) => { let called = false; stream @@ -22,46 +46,11 @@ describe('CsvParserStream', () => { .on('end', () => next(new Error(`Expected and error to occur [expectedMessage=${message}]`))); }; - interface ParseResults { - count: number; - rows: csv.ParserRow[]; - invalidRows: csv.ParserRow[]; - } - - const collectData = (stream: CsvParserStream): Promise => - new Promise((res, rej) => { - const rows: csv.ParserRow[] = []; - const invalidRows: csv.ParserRow[] = []; - stream - .on('data', (row: csv.ParserRow) => rows.push(row)) - .on('data-invalid', (row: csv.ParserRow) => invalidRows.push(row)) - .on('error', rej) - .on('end', (count: number) => { - res({ count, rows, invalidRows }); - }); - }); - - const parseContentAndCollectFromStream = (data: PathAndContent, parser: CsvParserStream): Promise => - new Promise((res, rej) => { - const rows: csv.ParserRow[] = []; - const invalidRows: csv.ParserRow[] = []; - parser - .on('data', row => rows.push(row)) - .on('data-invalid', row => invalidRows.push(row)) - .on('error', rej) - .on('end', (count: number) => { - res({ count, rows, invalidRows }); - }); - parser.write(data.content); - parser.end(); - }); - - const parseContentAndCollect = (data: PathAndContent, options: csv.ParserOptionsArgs = {}): Promise => + const parseContentAndCollect = (data: PathAndContent, options: ParserOptionsArgs = {}): Promise => new Promise((res, rej) => { - const rows: csv.ParserRow[] = []; - const invalidRows: csv.ParserRow[] = []; - const parser = csv - .parse(options) + const rows: Row[] = []; + const invalidRows: Row[] = []; + const parser = createParserStream(options) .on('data', row => rows.push(row)) .on('data-invalid', row => invalidRows.push(row)) .on('error', rej) @@ -72,26 +61,14 @@ describe('CsvParserStream', () => { parser.end(); }); - const expectParsed = ( - resultsPromise: Promise, - expectedRows: any[], - expectedInvalidRows: any[] = [], - ): Promise => { - return expect(resultsPromise).resolves.toEqual({ - count: expectedRows.length + expectedInvalidRows.length, - rows: expectedRows, - invalidRows: expectedInvalidRows, - }); - }; - it('should parse a csv without quotes or escapes', () => - expectParsed(parseContentAndCollect(assets.withHeaders, { headers: true }), assets.withHeaders.parsed)); + expectParsed(parseContentAndCollect(withHeaders, { headers: true }), withHeaders.parsed)); it('should emit a readable event ', next => { - const actual: csv.ParserRow[] = []; - const parser = csv.parse({ headers: true }); + const actual: Row[] = []; + const parser = createParserStream({ headers: true }); const stream = parser.on('error', next).on('end', (count: number) => { - expect(actual).toEqual(assets.withHeaders.parsed); + expect(actual).toEqual(withHeaders.parsed); expect(count).toBe(actual.length); next(); }); @@ -102,49 +79,43 @@ describe('CsvParserStream', () => { index += 1; } }); - stream.write(assets.withHeaders.content); + stream.write(withHeaders.content); stream.end(); }); it('should emit data as a buffer if objectMode is false', async () => { - const expected = assets.withHeaders.parsed.map(r => Buffer.from(JSON.stringify(r))); - await expectParsed(parseContentAndCollect(assets.withHeaders, { headers: true, objectMode: false }), expected); + const expected = withHeaders.parsed.map(r => Buffer.from(JSON.stringify(r))); + await expectParsed(parseContentAndCollect(withHeaders, { headers: true, objectMode: false }), expected); }); it('should emit data as an object if objectMode is true', () => - expectParsed( - parseContentAndCollect(assets.withHeaders, { headers: true, objectMode: true }), - assets.withHeaders.parsed, - )); + expectParsed(parseContentAndCollect(withHeaders, { headers: true, objectMode: true }), withHeaders.parsed)); it('should emit data as an object if objectMode is not specified', () => - expectParsed(parseContentAndCollect(assets.withHeaders, { headers: true }), assets.withHeaders.parsed)); + expectParsed(parseContentAndCollect(withHeaders, { headers: true }), withHeaders.parsed)); it('should parse a csv with quotes', () => - expectParsed( - parseContentAndCollect(assets.withHeadersAndQuotes, { headers: true }), - assets.withHeadersAndQuotes.parsed, - )); + expectParsed(parseContentAndCollect(withHeadersAndQuotes, { headers: true }), withHeadersAndQuotes.parsed)); it('should parse a csv with without headers', () => - expectParsed(parseContentAndCollect(assets.noHeadersAndQuotes), assets.noHeadersAndQuotes.parsed)); + expectParsed(parseContentAndCollect(noHeadersAndQuotes), noHeadersAndQuotes.parsed)); it("should parse a csv with ' escapes", () => expectParsed( - parseContentAndCollect(assets.withHeadersAndAlternateQuote, { headers: true, quote: "'" }), - assets.withHeadersAndAlternateQuote.parsed, + parseContentAndCollect(withHeadersAndAlternateQuote, { headers: true, quote: "'" }), + withHeadersAndAlternateQuote.parsed, )); describe('headers option', () => { it('should allow specifying of headers', async () => { - const expected = assets.noHeadersAndQuotes.parsed.map(r => ({ + const expected = noHeadersAndQuotes.parsed.map(r => ({ first_name: r[0], last_name: r[1], email_address: r[2], address: r[3], })); await expectParsed( - parseContentAndCollect(assets.noHeadersAndQuotes, { + parseContentAndCollect(noHeadersAndQuotes, { headers: ['first_name', 'last_name', 'email_address', 'address'], }), expected, @@ -152,28 +123,28 @@ describe('CsvParserStream', () => { }); it('should allow transforming headers with a function', async () => { - const expected = assets.withHeadersAndQuotes.parsed.map(r => ({ + const expected = withHeadersAndQuotes.parsed.map(r => ({ firstName: r.first_name, lastName: r.last_name, emailAddress: r.email_address, address: r.address, })); const transform = jest.fn().mockReturnValue(['firstName', 'lastName', 'emailAddress', 'address']); - await expectParsed(parseContentAndCollect(assets.withHeadersAndQuotes, { headers: transform }), expected); + await expectParsed(parseContentAndCollect(withHeadersAndQuotes, { headers: transform }), expected); expect(transform).toBeCalledTimes(1); expect(transform).toBeCalledWith(['first_name', 'last_name', 'email_address', 'address']); }); describe('renameHeaders option', () => { it('should allow renaming headers', async () => { - const expected = assets.withHeadersAndQuotes.parsed.map(r => ({ + const expected = withHeadersAndQuotes.parsed.map(r => ({ firstName: r.first_name, lastName: r.last_name, emailAddress: r.email_address, address: r.address, })); await expectParsed( - parseContentAndCollect(assets.withHeadersAndQuotes, { + parseContentAndCollect(withHeadersAndQuotes, { headers: ['firstName', 'lastName', 'emailAddress', 'address'], renameHeaders: true, }), @@ -182,7 +153,7 @@ describe('CsvParserStream', () => { }); it('should ignore the renameHeaders option if transforming headers with a function', async () => { - const expected = assets.withHeadersAndQuotes.parsed.map(r => ({ + const expected = withHeadersAndQuotes.parsed.map(r => ({ firstName: r.first_name, lastName: r.last_name, emailAddress: r.email_address, @@ -190,7 +161,7 @@ describe('CsvParserStream', () => { })); const transform = jest.fn().mockReturnValue(['firstName', 'lastName', 'emailAddress', 'address']); await expectParsed( - parseContentAndCollect(assets.withHeadersAndQuotes, { headers: transform, renameHeaders: true }), + parseContentAndCollect(withHeadersAndQuotes, { headers: transform, renameHeaders: true }), expected, ); expect(transform).toBeCalledTimes(1); @@ -198,47 +169,47 @@ describe('CsvParserStream', () => { }); it('should propagate an error when trying to rename headers without providing new ones', next => { - const stream = csv.parse({ renameHeaders: true }); + const stream = createParserStream({ renameHeaders: true }); listenForError(stream, 'Error renaming headers: new headers must be provided in an array', next); - stream.write(assets.withHeadersAndQuotes.content); + stream.write(withHeadersAndQuotes.content); stream.end(); }); it('should propagate an error when trying to rename headers without providing proper ones', next => { - const stream = csv.parse({ renameHeaders: true, headers: true }); + const stream = createParserStream({ renameHeaders: true, headers: true }); listenForError(stream, 'Error renaming headers: new headers must be provided in an array', next); - stream.write(assets.withHeadersAndQuotes.content); + stream.write(withHeadersAndQuotes.content); stream.end(); }); }); it('should propagate an error header length does not match column length', next => { - const stream = csv.parse({ headers: true }); + const stream = createParserStream({ headers: true }); listenForError(stream, 'Unexpected Error: column header mismatch expected: 4 columns got: 5', next); - stream.write(assets.headerColumnMismatch.content); + stream.write(headerColumnMismatch.content); stream.end(); }); it('should propagate an error if headers are not unique', next => { - const stream = csv.parse({ headers: true }); + const stream = createParserStream({ headers: true }); listenForError(stream, 'Duplicate headers found ["first_name"]', next); - stream.write(assets.duplicateHeaders.content); + stream.write(duplicateHeaders.content); stream.end(); }); it('should discard extra columns that do not map to a header when discardUnmappedColumns is true', () => expectParsed( - parseContentAndCollect(assets.headerColumnMismatch, { headers: true, discardUnmappedColumns: true }), - assets.headerColumnMismatch.parsed, + parseContentAndCollect(headerColumnMismatch, { headers: true, discardUnmappedColumns: true }), + headerColumnMismatch.parsed, )); it('should report missing columns that do not exist but have a header with strictColumnHandling option', async () => { - const expectedRows = assets.withHeadersAndMissingColumns.parsed.filter(r => r.address !== null); - const expectedInvalidRows = assets.withHeadersAndMissingColumns.parsed + const expectedRows = withHeadersAndMissingColumns.parsed.filter(r => r.address !== null); + const expectedInvalidRows = withHeadersAndMissingColumns.parsed .filter(r => r.address === null) .map(r => Object.values(r).filter(v => !!v)); await expectParsed( - parseContentAndCollect(assets.withHeadersAndMissingColumns, { + parseContentAndCollect(withHeadersAndMissingColumns, { headers: true, strictColumnHandling: true, }), @@ -248,12 +219,12 @@ describe('CsvParserStream', () => { }); it('should allow specifying of columns as a sparse array', async () => { - const expected = assets.noHeadersAndQuotes.parsed.map(r => ({ + const expected = noHeadersAndQuotes.parsed.map(r => ({ first_name: r[0], email_address: r[2], })); await expectParsed( - parseContentAndCollect(assets.noHeadersAndQuotes, { + parseContentAndCollect(noHeadersAndQuotes, { headers: ['first_name', undefined, 'email_address', undefined], }), expected, @@ -263,24 +234,24 @@ describe('CsvParserStream', () => { it('should parse data with an alternate encoding', () => expectParsed( - parseContentAndCollect(assets.alternateEncoding, { headers: true, encoding: 'utf16le' }), - assets.alternateEncoding.parsed, + parseContentAndCollect(alternateEncoding, { headers: true, encoding: 'utf16le' }), + alternateEncoding.parsed, )); it('should handle a trailing comma', () => - expectParsed(parseContentAndCollect(assets.trailingComma, { headers: true }), assets.trailingComma.parsed)); + expectParsed(parseContentAndCollect(trailingComma, { headers: true }), trailingComma.parsed)); it('should skip valid, but empty rows when ignoreEmpty is true', () => - expectParsed(parseContentAndCollect(assets.emptyRows, { headers: true, ignoreEmpty: true }), [])); + expectParsed(parseContentAndCollect(emptyRows, { headers: true, ignoreEmpty: true }), [])); describe('alternate delimiters', () => { ['\t', '|', ';'].forEach(delimiter => { it(`should support '${delimiter.replace(/\t/, '\\t')}' delimiters`, async () => { - const { path: assetPath, content } = assets.withHeadersAlternateDelimiter; + const { path: assetPath, content } = withHeadersAlternateDelimiter; const data = { path: assetPath, content: content(delimiter) }; await expectParsed( parseContentAndCollect(data, { headers: true, delimiter }), - assets.withHeadersAlternateDelimiter.parsed, + withHeadersAlternateDelimiter.parsed, ); }); }); @@ -290,69 +261,66 @@ describe('CsvParserStream', () => { it('should parse up to the specified number of maxRows', async () => { const maxRows = 3; await expectParsed( - parseContentAndCollect(assets.withHeaders, { headers: true, maxRows }), - assets.withHeaders.parsed.slice(0, maxRows), + parseContentAndCollect(withHeaders, { headers: true, maxRows }), + withHeaders.parsed.slice(0, maxRows), ); }); it('should parse all rows if maxRows === 0', async () => { const maxRows = 0; - await expectParsed( - parseContentAndCollect(assets.withHeaders, { headers: true, maxRows }), - assets.withHeaders.parsed, - ); + await expectParsed(parseContentAndCollect(withHeaders, { headers: true, maxRows }), withHeaders.parsed); }); }); describe('skipLines option', () => { it('should skip up to the specified number of rows using the first non-skipped line as headers', async () => { - const skipLines = 2; + const linesToSkip = 2; await expectParsed( - parseContentAndCollect(assets.withHeadersSkippedLines, { headers: true, skipLines }), - assets.withHeadersSkippedLines.parsed, + parseContentAndCollect(withHeadersAndSkippedLines, { headers: true, skipLines: linesToSkip }), + withHeadersAndSkippedLines.parsed, ); }); it('should skip up to the specified number of rows not withoutHeaders', async () => { - const skipLines = 2; - await expectParsed(parseContentAndCollect(assets.skipLines, { skipLines }), assets.skipLines.parsed); + const linesToSkip = 2; + await expectParsed(parseContentAndCollect(skipLines, { skipLines: linesToSkip }), skipLines.parsed); }); describe('with transform', () => { it('should not transform skipped rows', async () => { - let transformedRows: csv.ParserRow[] = []; - const transformer = (row: csv.ParserRow): csv.ParserRow => { + let transformedRows: Row[] = []; + const transformer = (row: Row): Row => { const transformed = { - firstName: (row as csv.ParserRowMap).first_name, - lastName: (row as csv.ParserRowMap).last_name, - emailAddress: (row as csv.ParserRowMap).email_address, + firstName: (row as RowMap).first_name, + lastName: (row as RowMap).last_name, + emailAddress: (row as RowMap).email_address, }; transformedRows.push(transformed); return transformed; }; - const skipLines = 2; - const expected = assets.withHeadersSkippedLines.parsed.map(transformer); + const linesToSkip = 2; + const expected = withHeadersAndSkippedLines.parsed.map(transformer); transformedRows = []; - const parser = csv.parse({ headers: true, skipLines }).transform(transformer); - await expectParsed(parseContentAndCollectFromStream(assets.withHeadersSkippedLines, parser), expected); + const parser = createParserStream({ headers: true, skipLines: linesToSkip }).transform(transformer); + await expectParsed(parseContentAndCollectFromStream(withHeadersAndSkippedLines, parser), expected); expect(transformedRows).toEqual(expected); }); }); describe('with validate', () => { it('should not validate skipped rows', async () => { - let validatedRows: csv.ParserRow[] = []; - const validator = (row: csv.ParserRow): boolean => { + let validatedRows: Row[] = []; + const validator = (row: Row): boolean => { validatedRows.push(row); return (validatedRows.length - 1) % 2 === 0; }; - const skipLines = 2; - const nonSkippedRows = assets.withHeadersSkippedLines.parsed; + const linesToSkip = 2; + const nonSkippedRows = withHeadersAndSkippedLines.parsed; const [expected, invalid] = partition(nonSkippedRows, validator); validatedRows = []; - const parser = csv.parse({ headers: true, skipLines }).validate(validator); + const parser = createParserStream({ headers: true, skipLines: linesToSkip }).validate(validator); await expectParsed( - parseContentAndCollectFromStream(assets.withHeadersSkippedLines, parser), + parseContentAndCollectFromStream(withHeadersAndSkippedLines, parser), expected, invalid, ); @@ -361,10 +329,10 @@ describe('CsvParserStream', () => { }); it('should parse all rows if maxRows === 0', async () => { - const skipLines = 0; + const linesToSkip = 0; await expectParsed( - parseContentAndCollect(assets.withHeaders, { headers: true, skipLines }), - assets.withHeaders.parsed, + parseContentAndCollect(withHeaders, { headers: true, skipLines: linesToSkip }), + withHeaders.parsed, ); }); }); @@ -374,14 +342,14 @@ describe('CsvParserStream', () => { it('should skip up to the specified number of rows not including the header row in the count', async () => { const skipRows = 3; await expectParsed( - parseContentAndCollect(assets.withHeaders, { headers: true, skipRows }), - assets.withHeaders.parsed.slice(skipRows), + parseContentAndCollect(withHeaders, { headers: true, skipRows }), + withHeaders.parsed.slice(skipRows), ); }); it('should skip up to the specified number of rows and allow renaming the headers', async () => { const skipRows = 3; - const expected = assets.withHeaders.parsed.slice(skipRows).map(r => { + const expected = withHeaders.parsed.slice(skipRows).map(r => { return { h1: r.first_name, h2: r.last_name, @@ -389,7 +357,7 @@ describe('CsvParserStream', () => { }; }); await expectParsed( - parseContentAndCollect(assets.withHeaders, { + parseContentAndCollect(withHeaders, { headers: ['h1', 'h2', 'h3'], renameHeaders: true, skipRows, @@ -402,13 +370,13 @@ describe('CsvParserStream', () => { describe('without headers', () => { it('should skip up to the specified number of rows without headers', async () => { const skipRows = 3; - const expected = assets.noHeadersAndQuotes.parsed.slice(skipRows); - await expectParsed(parseContentAndCollect(assets.noHeadersAndQuotes, { skipRows }), expected); + const expected = noHeadersAndQuotes.parsed.slice(skipRows); + await expectParsed(parseContentAndCollect(noHeadersAndQuotes, { skipRows }), expected); }); it('should skip up to the specified number of rows without headers and allow specifying headers', async () => { const skipRows = 3; - const expected = assets.noHeadersAndQuotes.parsed.slice(skipRows).map(r => { + const expected = noHeadersAndQuotes.parsed.slice(skipRows).map(r => { return { h1: r[0], h2: r[1], @@ -417,7 +385,7 @@ describe('CsvParserStream', () => { }; }); await expectParsed( - parseContentAndCollect(assets.noHeadersAndQuotes, { headers: ['h1', 'h2', 'h3', 'h4'], skipRows }), + parseContentAndCollect(noHeadersAndQuotes, { headers: ['h1', 'h2', 'h3', 'h4'], skipRows }), expected, ); }); @@ -425,109 +393,106 @@ describe('CsvParserStream', () => { describe('with transform', () => { it('should not transform skipped rows', async () => { - let transformedRows: csv.ParserRow[] = []; - const transformer = (row: csv.ParserRow): csv.ParserRow => { + let transformedRows: Row[] = []; + const transformer = (row: Row): Row => { const transformed = { - firstName: (row as csv.ParserRowMap).first_name, - lastName: (row as csv.ParserRowMap).last_name, - emailAddress: (row as csv.ParserRowMap).email_address, - address: (row as csv.ParserRowMap).address, + firstName: (row as RowMap).first_name, + lastName: (row as RowMap).last_name, + emailAddress: (row as RowMap).email_address, + address: (row as RowMap).address, }; transformedRows.push(transformed); return transformed; }; const skipRows = 3; - const expected = assets.withHeaders.parsed.slice(skipRows).map(transformer); + const expected = withHeaders.parsed.slice(skipRows).map(transformer); transformedRows = []; - const parser = csv.parse({ headers: true, skipRows }).transform(transformer); - await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected); + const parser = createParserStream({ headers: true, skipRows }).transform(transformer); + await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected); expect(transformedRows).toEqual(expected); }); }); describe('with validate', () => { it('should not validate skipped rows', async () => { - let validatedRows: csv.ParserRow[] = []; - const validator = (row: csv.ParserRow): boolean => { + let validatedRows: Row[] = []; + const validator = (row: Row): boolean => { validatedRows.push(row); return (validatedRows.length - 1) % 2 === 0; }; const skipRows = 3; - const nonSkippedRows = assets.withHeaders.parsed.slice(skipRows); + const nonSkippedRows = withHeaders.parsed.slice(skipRows); const [expected, invalid] = partition(nonSkippedRows, validator); validatedRows = []; - const parser = csv.parse({ headers: true, skipRows }).validate(validator); - await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected, invalid); + const parser = createParserStream({ headers: true, skipRows }).validate(validator); + await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected, invalid); expect(validatedRows).toEqual(nonSkippedRows); }); }); it('should parse all rows if maxRows === 0', async () => { const skipRows = 0; - await expectParsed( - parseContentAndCollect(assets.withHeaders, { headers: true, skipRows }), - assets.withHeaders.parsed, - ); + await expectParsed(parseContentAndCollect(withHeaders, { headers: true, skipRows }), withHeaders.parsed); }); }); it('should emit an error for malformed rows', next => { - assets.write(assets.malformed); - const stream = csv.parseFile(assets.malformed.path, { headers: true }); + write(malformed); + const stream = parseFile(malformed.path, { headers: true }); listenForError(stream, "Parse Error: expected: ',' OR new line got: 'a'. at 'a \", Las", next); }); describe('#validate', () => { - const syncValidator = (row: csv.ParserRow): boolean => - parseInt((row as csv.ParserRowMap).first_name.replace(/^First/, ''), 10) % 2 === 1; - const asyncValidator = (row: csv.ParserRow, cb: csv.ParserRowValidateCallback) => { + const syncValidator = (row: Row): boolean => + parseInt((row as RowMap).first_name.replace(/^First/, ''), 10) % 2 === 1; + const asyncValidator = (row: Row, cb: RowValidateCallback) => { cb(null, syncValidator(row)); }; it('should allow validation of rows', async () => { - const [valid, invalid] = partition(assets.withHeaders.parsed, syncValidator); - const parser = csv.parse({ headers: true }).validate(syncValidator); - await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), valid, invalid); + const [valid, invalid] = partition(withHeaders.parsed, syncValidator); + const parser = createParserStream({ headers: true }).validate(syncValidator); + await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), valid, invalid); }); it('should allow async validation of rows', async () => { - const validator = (row: csv.ParserRow): boolean => - parseInt((row as csv.ParserRowMap).first_name.replace(/^First/, ''), 10) % 2 !== 0; - const [valid, invalid] = partition(assets.withHeaders.parsed, validator); - const parser = csv.parse({ headers: true }).validate(asyncValidator); - await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), valid, invalid); + const validator = (row: Row): boolean => + parseInt((row as RowMap).first_name.replace(/^First/, ''), 10) % 2 !== 0; + const [valid, invalid] = partition(withHeaders.parsed, validator); + const parser = createParserStream({ headers: true }).validate(asyncValidator); + await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), valid, invalid); }); it('should propagate errors from async validation', next => { - assets.write(assets.withHeaders); + write(withHeaders); let index = -1; - const stream = csv - .parseFile(assets.withHeaders.path, { headers: true }) - .validate((data: csv.ParserRow, validateNext): void => { - setImmediate(() => { - index += 1; - if (index === 8) { - validateNext(new Error('Validation ERROR!!!!')); - } else { - validateNext(null, true); - } - }); + const stream = createParserStream({ headers: true }).validate((data: Row, validateNext): void => { + setImmediate(() => { + index += 1; + if (index === 8) { + validateNext(new Error('Validation ERROR!!!!')); + } else { + validateNext(null, true); + } }); + }); + stream.write(withHeaders.content); + stream.end(); listenForError(stream, 'Validation ERROR!!!!', next); }); it('should propagate async errors at the beginning', next => { - assets.write(assets.withHeaders); - const stream = csv - .parseFile(assets.withHeaders.path, { headers: true }) - .validate((data, validateNext) => validateNext(new Error('Validation ERROR!!!!'))); + write(withHeaders); + const stream = parseFile(withHeaders.path, { headers: true }).validate((data, validateNext) => + validateNext(new Error('Validation ERROR!!!!')), + ); listenForError(stream, 'Validation ERROR!!!!', next); }); it('should propagate thrown errors', next => { - assets.write(assets.withHeaders); + write(withHeaders); let index = -1; - const stream = csv.parseFile(assets.withHeaders.path, { headers: true }).validate((data, validateNext) => { + const stream = parseFile(withHeaders.path, { headers: true }).validate((data, validateNext) => { index += 1; if (index === 8) { throw new Error('Validation ERROR!!!!'); @@ -539,8 +504,8 @@ describe('CsvParserStream', () => { }); it('should propagate thrown errors at the beginning', next => { - assets.write(assets.withHeaders); - const stream = csv.parseFile(assets.withHeaders.path, { headers: true }).validate(() => { + write(withHeaders); + const stream = parseFile(withHeaders.path, { headers: true }).validate(() => { throw new Error('Validation ERROR!!!!'); }); listenForError(stream, 'Validation ERROR!!!!', next); @@ -548,38 +513,38 @@ describe('CsvParserStream', () => { it('should throw an error if validate is not called with a function', () => { // @ts-ignore - expect(() => csv.parse({ headers: true }).validate('hello')).toThrowError( + expect(() => createParserStream({ headers: true }).validate('hello')).toThrowError( 'The validate should be a function', ); }); }); describe('#transform', () => { - const transformer = (row: csv.ParserRow): csv.ParserRow => ({ - firstName: (row as csv.ParserRowMap).first_name, - lastName: (row as csv.ParserRowMap).last_name, - emailAddress: (row as csv.ParserRowMap).email_address, - address: (row as csv.ParserRowMap).address, + const transformer = (row: Row): Row => ({ + firstName: (row as RowMap).first_name, + lastName: (row as RowMap).last_name, + emailAddress: (row as RowMap).email_address, + address: (row as RowMap).address, }); it('should allow transforming of data', async () => { - const expected = assets.withHeaders.parsed.map(transformer); - const parser = csv.parse({ headers: true }).transform(transformer); - await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected); + const expected = withHeaders.parsed.map(transformer); + const parser = createParserStream({ headers: true }).transform(transformer); + await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected); }); it('should async transformation of data', async () => { - const expected = assets.withHeaders.parsed.map(transformer); - const parser = csv - .parse({ headers: true }) - .transform((row, next) => setImmediate(() => next(null, transformer(row)))); - await expectParsed(parseContentAndCollectFromStream(assets.withHeaders, parser), expected); + const expected = withHeaders.parsed.map(transformer); + const parser = createParserStream({ headers: true }).transform((row, next) => + setImmediate(() => next(null, transformer(row))), + ); + await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected); }); it('should propogate errors when transformation of data', next => { - assets.write(assets.withHeaders); + write(withHeaders); let index = -1; - const stream = csv.parseFile(assets.withHeaders.path, { headers: true }).transform((data, cb) => + const stream = parseFile(withHeaders.path, { headers: true }).transform((data, cb) => setImmediate(() => { index += 1; if (index === 8) { @@ -593,17 +558,17 @@ describe('CsvParserStream', () => { }); it('should propogate errors when transformation of data at the beginning', next => { - assets.write(assets.withHeaders); - const stream = csv - .parseFile(assets.withHeaders.path, { headers: true }) - .transform((data, cb) => setImmediate(() => cb(new Error('transformation ERROR!!!!')))); + write(withHeaders); + const stream = parseFile(withHeaders.path, { headers: true }).transform((data, cb) => + setImmediate(() => cb(new Error('transformation ERROR!!!!'))), + ); listenForError(stream, 'transformation ERROR!!!!', next); }); it('should propagate thrown errors at the end', next => { - assets.write(assets.withHeaders); + write(withHeaders); let index = -1; - const stream = csv.parseFile(assets.withHeaders.path, { headers: true }).transform((data, cb) => { + const stream = parseFile(withHeaders.path, { headers: true }).transform((data, cb) => { index += 1; if (index === 8) { throw new Error('transformation ERROR!!!!'); @@ -615,8 +580,8 @@ describe('CsvParserStream', () => { }); it('should propagate thrown errors at the beginning', next => { - assets.write(assets.withHeaders); - const stream = csv.parseFile(assets.withHeaders.path, { headers: true }).transform(() => { + write(withHeaders); + const stream = parseFile(withHeaders.path, { headers: true }).transform(() => { throw new Error('transformation ERROR!!!!'); }); listenForError(stream, 'transformation ERROR!!!!', next); @@ -624,7 +589,7 @@ describe('CsvParserStream', () => { it('should throw an error if a transform is not called with a function', () => { // @ts-ignore - expect(() => csv.parse({ headers: true }).transform('hello')).toThrowError( + expect(() => createParserStream({ headers: true }).transform('hello')).toThrowError( 'The transform should be a function', ); }); @@ -632,12 +597,12 @@ describe('CsvParserStream', () => { describe('pause/resume', () => { it('should support pausing a stream', () => { - assets.write(assets.withHeaders); + write(withHeaders); return new Promise((res, rej) => { - const rows: csv.ParserRow[] = []; + const rows: Row[] = []; let paused = false; - const stream = csv.parse({ headers: true }); - fs.createReadStream(assets.withHeaders.path) + const stream = createParserStream({ headers: true }); + fs.createReadStream(withHeaders.path) .on('error', rej) .pipe(stream) .on('data', row => { @@ -653,7 +618,7 @@ describe('CsvParserStream', () => { }) .on('error', rej) .on('end', (count: number) => { - expect(rows).toEqual(assets.withHeaders.parsed); + expect(rows).toEqual(withHeaders.parsed); expect(count).toBe(rows.length); res(); }); @@ -662,7 +627,7 @@ describe('CsvParserStream', () => { }); it('should not catch errors thrown in end', next => { - assets.write(assets.withHeaders); + write(withHeaders); const d = domain.create(); let called = false; d.on('error', err => { @@ -676,9 +641,9 @@ describe('CsvParserStream', () => { }); d.run(() => fs - .createReadStream(assets.withHeaders.path) + .createReadStream(withHeaders.path) .on('error', next) - .pipe(csv.parse({ headers: true })) + .pipe(createParserStream({ headers: true })) .on('error', () => next(new Error('Should not get here!'))) // eslint-disable-next-line @typescript-eslint/no-empty-function .on('data', () => {}) @@ -687,28 +652,4 @@ describe('CsvParserStream', () => { }), ); }); - - describe('.parseStream', () => { - it('should accept a stream', async () => { - assets.write(assets.withHeaders); - const stream = csv.parseStream(fs.createReadStream(assets.withHeaders.path), { headers: true }); - await expectParsed(collectData(stream), assets.withHeaders.parsed); - }); - }); - - describe('.parseFile', () => { - it('parse a csv from the given path', async () => { - assets.write(assets.withHeaders); - const stream = csv.parseFile(assets.withHeaders.path, { headers: true }); - await expectParsed(collectData(stream), assets.withHeaders.parsed); - }); - }); - - describe('.parseString', () => { - it('should accept a csv string', () => - expectParsed( - collectData(csv.parseString(assets.withHeaders.content, { headers: true })), - assets.withHeaders.parsed, - )); - }); }); diff --git a/__tests__/parser/ParserOptions.spec.ts b/packages/parse/__tests__/ParserOptions.spec.ts similarity index 98% rename from __tests__/parser/ParserOptions.spec.ts rename to packages/parse/__tests__/ParserOptions.spec.ts index e35a4432..a2afba50 100644 --- a/__tests__/parser/ParserOptions.spec.ts +++ b/packages/parse/__tests__/ParserOptions.spec.ts @@ -1,5 +1,5 @@ -import { ParserOptionsArgs } from '../../src'; -import { ParserOptions } from '../../src/parser'; +import { ParserOptionsArgs } from '../src'; +import { ParserOptions } from '../src/ParserOptions'; describe('ParserOptions', () => { const createOptions = (opts: ParserOptionsArgs = {}) => new ParserOptions(opts); diff --git a/packages/parse/__tests__/__fixtures__/RecordingStream.ts b/packages/parse/__tests__/__fixtures__/RecordingStream.ts new file mode 100644 index 00000000..3a6f8a50 --- /dev/null +++ b/packages/parse/__tests__/__fixtures__/RecordingStream.ts @@ -0,0 +1,14 @@ +import { Writable } from 'stream'; + +export class RecordingStream extends Writable { + public readonly data: string[] = []; + + public constructor() { + super({ + write: (data, enc, cb): void => { + this.data.push(data.toString()); + cb(); + }, + }); + } +} diff --git a/__tests__/parser/__fixtures__/alternateEncoding.ts b/packages/parse/__tests__/__fixtures__/alternateEncoding.ts similarity index 96% rename from __tests__/parser/__fixtures__/alternateEncoding.ts rename to packages/parse/__tests__/__fixtures__/alternateEncoding.ts index 09803bc9..18187aac 100644 --- a/__tests__/parser/__fixtures__/alternateEncoding.ts +++ b/packages/parse/__tests__/__fixtures__/alternateEncoding.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const alternateEncoding = { path: resolve(__dirname, 'tmp', 'alternate_encoding.csv'), content: Buffer.from( diff --git a/__tests__/parser/__fixtures__/duplicateHeaders.ts b/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts similarity index 89% rename from __tests__/parser/__fixtures__/duplicateHeaders.ts rename to packages/parse/__tests__/__fixtures__/duplicateHeaders.ts index aded4275..bba16be5 100644 --- a/__tests__/parser/__fixtures__/duplicateHeaders.ts +++ b/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts @@ -1,7 +1,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const duplicateHeaders = { path: resolve(__dirname, 'tmp', 'duplicate_header.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/emptyRows.ts b/packages/parse/__tests__/__fixtures__/emptyRows.ts similarity index 96% rename from __tests__/parser/__fixtures__/emptyRows.ts rename to packages/parse/__tests__/__fixtures__/emptyRows.ts index 0a246b44..314bf2fd 100644 --- a/__tests__/parser/__fixtures__/emptyRows.ts +++ b/packages/parse/__tests__/__fixtures__/emptyRows.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const emptyRows = { path: resolve(__dirname, 'tmp', 'empty_rows.csv'), content: ['first_name,last_name,email_address', '"","",""', '"","",""', '"","",', '"",,""', ',,', ''].join(EOL), diff --git a/__tests__/parser/__fixtures__/headerColumnMismatch.ts b/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts similarity index 93% rename from __tests__/parser/__fixtures__/headerColumnMismatch.ts rename to packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts index 777e3f75..2784f831 100644 --- a/__tests__/parser/__fixtures__/headerColumnMismatch.ts +++ b/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const headerColumnMismatch = { path: resolve(__dirname, 'tmp', 'header_column_mismatch.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/helpers.ts b/packages/parse/__tests__/__fixtures__/helpers.ts new file mode 100644 index 00000000..bbfc6deb --- /dev/null +++ b/packages/parse/__tests__/__fixtures__/helpers.ts @@ -0,0 +1,55 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { CsvParserStream, Row } from '../../src'; + +export interface PathAndContent { + path: string; + content: string | Buffer; +} +export interface ParseResults { + count: number; + rows: Row[]; + invalidRows: Row[]; +} + +export const collectData = (stream: CsvParserStream): Promise => + new Promise((res, rej) => { + const rows: Row[] = []; + const invalidRows: Row[] = []; + stream + .on('data', (row: Row) => rows.push(row)) + .on('data-invalid', (row: Row) => invalidRows.push(row)) + .on('error', rej) + .on('end', (count: number) => { + res({ count, rows, invalidRows }); + }); + }); + +export const parseContentAndCollectFromStream = ( + data: PathAndContent, + parser: CsvParserStream, +): Promise => + new Promise((res, rej) => { + const rows: Row[] = []; + const invalidRows: Row[] = []; + parser + .on('data', row => rows.push(row)) + .on('data-invalid', row => invalidRows.push(row)) + .on('error', rej) + .on('end', (count: number) => { + res({ count, rows, invalidRows }); + }); + parser.write(data.content); + parser.end(); + }); + +export const expectParsed = ( + resultsPromise: Promise, + expectedRows: any[], + expectedInvalidRows: any[] = [], +): Promise => { + return expect(resultsPromise).resolves.toEqual({ + count: expectedRows.length + expectedInvalidRows.length, + rows: expectedRows, + invalidRows: expectedInvalidRows, + }); +}; diff --git a/packages/parse/__tests__/__fixtures__/index.ts b/packages/parse/__tests__/__fixtures__/index.ts new file mode 100644 index 00000000..bc88e547 --- /dev/null +++ b/packages/parse/__tests__/__fixtures__/index.ts @@ -0,0 +1,32 @@ +import { existsSync, mkdirSync, writeFileSync } from 'fs'; +import * as path from 'path'; +import { PathAndContent } from './helpers'; + +export * from './alternateEncoding'; +export * from './noHeadersAndQuotes'; +export * from './skipLines'; +export * from './withHeaders'; +export * from './withHeadersAndQuotes'; +export * from './withHeadersAndAlternateQuote'; +export * from './withHeadersAndMissingColumns'; +export * from './withHeadersAlternateDelimiter'; +export * from './withHeadersAndSkippedLines'; +export * from './headerColumnMismatch'; +export * from './malformed'; +export * from './trailingComma'; +export * from './emptyRows'; +export * from './duplicateHeaders'; +export * from './RecordingStream'; +export * from './helpers'; + +const mkDirIfNotExists = (filePath: string): void => { + const dir = path.dirname(filePath); + if (!existsSync(dir)) { + mkdirSync(dir); + } +}; + +export const write = (opts: PathAndContent): void => { + mkDirIfNotExists(opts.path); + writeFileSync(opts.path, opts.content); +}; diff --git a/__tests__/parser/__fixtures__/malformed.ts b/packages/parse/__tests__/__fixtures__/malformed.ts similarity index 93% rename from __tests__/parser/__fixtures__/malformed.ts rename to packages/parse/__tests__/__fixtures__/malformed.ts index c8992b1a..e73b05c4 100644 --- a/__tests__/parser/__fixtures__/malformed.ts +++ b/packages/parse/__tests__/__fixtures__/malformed.ts @@ -1,7 +1,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const malformed = { path: resolve(__dirname, 'tmp', 'malformed.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/noHeadersAndQuotes.ts b/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts similarity index 97% rename from __tests__/parser/__fixtures__/noHeadersAndQuotes.ts rename to packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts index af8fc60c..affe383c 100644 --- a/__tests__/parser/__fixtures__/noHeadersAndQuotes.ts +++ b/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts @@ -1,7 +1,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const noHeadersAndQuotes = { path: resolve(__dirname, 'tmp', 'no_headers_and_quotes.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/skipLines.ts b/packages/parse/__tests__/__fixtures__/skipLines.ts similarity index 97% rename from __tests__/parser/__fixtures__/skipLines.ts rename to packages/parse/__tests__/__fixtures__/skipLines.ts index d94b48bc..882d59bc 100644 --- a/__tests__/parser/__fixtures__/skipLines.ts +++ b/packages/parse/__tests__/__fixtures__/skipLines.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const skipLines = { path: resolve(__dirname, 'tmp', 'skip_lines.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/trailingComma.ts b/packages/parse/__tests__/__fixtures__/trailingComma.ts similarity index 98% rename from __tests__/parser/__fixtures__/trailingComma.ts rename to packages/parse/__tests__/__fixtures__/trailingComma.ts index 0bfcda9b..8e42c589 100644 --- a/__tests__/parser/__fixtures__/trailingComma.ts +++ b/packages/parse/__tests__/__fixtures__/trailingComma.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const trailingComma = { path: resolve(__dirname, 'tmp', 'trailing_comma.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/withHeaders.ts b/packages/parse/__tests__/__fixtures__/withHeaders.ts similarity index 98% rename from __tests__/parser/__fixtures__/withHeaders.ts rename to packages/parse/__tests__/__fixtures__/withHeaders.ts index 8a5a102e..2dfb20e6 100644 --- a/__tests__/parser/__fixtures__/withHeaders.ts +++ b/packages/parse/__tests__/__fixtures__/withHeaders.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const withHeaders = { path: resolve(__dirname, 'tmp', 'with_headers.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/withHeadersAlternateDelimiter.ts b/packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts similarity index 97% rename from __tests__/parser/__fixtures__/withHeadersAlternateDelimiter.ts rename to packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts index f4f68d16..721d4a8a 100644 --- a/__tests__/parser/__fixtures__/withHeadersAlternateDelimiter.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const withHeadersAlternateDelimiter = { path: resolve(__dirname, 'tmp', 'with_headers_alternate_delimiter.tsv'), content: (delimiter = '\t'): string => diff --git a/__tests__/parser/__fixtures__/withHeadersAndAlternateQuote.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts similarity index 98% rename from __tests__/parser/__fixtures__/withHeadersAndAlternateQuote.ts rename to packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts index 9f19d4de..c297c5cf 100644 --- a/__tests__/parser/__fixtures__/withHeadersAndAlternateQuote.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const withHeadersAndAlternateQuote = { path: resolve(__dirname, 'tmp', 'no_headers_and_quotes.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/withHeadersAndMissingColumns.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts similarity index 95% rename from __tests__/parser/__fixtures__/withHeadersAndMissingColumns.ts rename to packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts index 467b05d7..363acfd3 100644 --- a/__tests__/parser/__fixtures__/withHeadersAndMissingColumns.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const withHeadersAndMissingColumns = { path: resolve(__dirname, 'tmp', 'with_headers_and_missing_columns.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/withHeadersAndQuotes.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts similarity index 98% rename from __tests__/parser/__fixtures__/withHeadersAndQuotes.ts rename to packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts index 7764f9cc..9e92a1e8 100644 --- a/__tests__/parser/__fixtures__/withHeadersAndQuotes.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const withHeadersAndQuotes = { path: resolve(__dirname, 'tmp', 'with_headers_and_quotes.csv'), content: [ diff --git a/__tests__/parser/__fixtures__/withHeadersSkippedLines.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts similarity index 97% rename from __tests__/parser/__fixtures__/withHeadersSkippedLines.ts rename to packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts index 1b29f4cf..b8b6d258 100644 --- a/__tests__/parser/__fixtures__/withHeadersSkippedLines.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts @@ -2,7 +2,7 @@ import { resolve } from 'path'; import { EOL } from 'os'; -export default { +export const withHeadersAndSkippedLines = { path: resolve(__dirname, 'tmp', 'with_headers_skip_lines.csv'), content: [ diff --git a/__tests__/issues/__fixtures__/issue102.csv b/packages/parse/__tests__/issues/__fixtures__/issue102.csv similarity index 100% rename from __tests__/issues/__fixtures__/issue102.csv rename to packages/parse/__tests__/issues/__fixtures__/issue102.csv diff --git a/__tests__/issues/__fixtures__/issue68-invalid.tsv b/packages/parse/__tests__/issues/__fixtures__/issue68-invalid.tsv similarity index 100% rename from __tests__/issues/__fixtures__/issue68-invalid.tsv rename to packages/parse/__tests__/issues/__fixtures__/issue68-invalid.tsv diff --git a/__tests__/issues/__fixtures__/issue68.tsv b/packages/parse/__tests__/issues/__fixtures__/issue68.tsv similarity index 100% rename from __tests__/issues/__fixtures__/issue68.tsv rename to packages/parse/__tests__/issues/__fixtures__/issue68.tsv diff --git a/__tests__/issues/__fixtures__/issue87.csv b/packages/parse/__tests__/issues/__fixtures__/issue87.csv similarity index 100% rename from __tests__/issues/__fixtures__/issue87.csv rename to packages/parse/__tests__/issues/__fixtures__/issue87.csv diff --git a/__tests__/issues/issue102.spec.ts b/packages/parse/__tests__/issues/issue102.spec.ts similarity index 100% rename from __tests__/issues/issue102.spec.ts rename to packages/parse/__tests__/issues/issue102.spec.ts diff --git a/__tests__/issues/issue111.spec.ts b/packages/parse/__tests__/issues/issue111.spec.ts similarity index 97% rename from __tests__/issues/issue111.spec.ts rename to packages/parse/__tests__/issues/issue111.spec.ts index 57ab5316..7e20dcc2 100644 --- a/__tests__/issues/issue111.spec.ts +++ b/packages/parse/__tests__/issues/issue111.spec.ts @@ -1,4 +1,5 @@ -import { ParserOptions, Parser } from '../../src/parser'; +import { Parser } from '../../src/parser'; +import { ParserOptions } from '../../src/ParserOptions'; describe('Issue #111 - https://github.com/C2FO/fast-csv/issues/111', () => { const createParser = (parserOptions = {}) => new Parser(new ParserOptions(parserOptions)); diff --git a/__tests__/issues/issue131.spec.ts b/packages/parse/__tests__/issues/issue131.spec.ts similarity index 93% rename from __tests__/issues/issue131.spec.ts rename to packages/parse/__tests__/issues/issue131.spec.ts index 3a556ebe..0897f2fa 100644 --- a/__tests__/issues/issue131.spec.ts +++ b/packages/parse/__tests__/issues/issue131.spec.ts @@ -8,7 +8,7 @@ describe('Issue #131 - https://github.com/C2FO/fast-csv/issues/131', () => { ].join(EOL); it('should parse a csv with a UTF-8 Byte Order Mark', next => { - const actual: csv.ParserRowMap[] = []; + const actual: csv.RowMap[] = []; csv.parseString(csvWithBom, { headers: true }) .on('data', data => actual.push(data)) .on('end', (count: number) => { diff --git a/__tests__/issues/issue150.spec.ts b/packages/parse/__tests__/issues/issue150.spec.ts similarity index 87% rename from __tests__/issues/issue150.spec.ts rename to packages/parse/__tests__/issues/issue150.spec.ts index db0ba99c..c8ecc531 100644 --- a/__tests__/issues/issue150.spec.ts +++ b/packages/parse/__tests__/issues/issue150.spec.ts @@ -1,4 +1,5 @@ -import { ParserOptions, Parser } from '../../src/parser'; +import { Parser } from '../../src/parser'; +import { ParserOptions } from '../../src/ParserOptions'; describe('Issue #150 - https://github.com/C2FO/fast-csv/issues/150', () => { const createParser = (parserOptions = {}) => new Parser(new ParserOptions(parserOptions)); diff --git a/__tests__/issues/issue174.spec.ts b/packages/parse/__tests__/issues/issue174.spec.ts similarity index 89% rename from __tests__/issues/issue174.spec.ts rename to packages/parse/__tests__/issues/issue174.spec.ts index c976a215..61a82e5b 100644 --- a/__tests__/issues/issue174.spec.ts +++ b/packages/parse/__tests__/issues/issue174.spec.ts @@ -1,6 +1,7 @@ import { EOL } from 'os'; import { ParserOptionsArgs } from '../../src'; -import { Parser, ParserOptions } from '../../src/parser'; +import { Parser } from '../../src/parser'; +import { ParserOptions } from '../../src/ParserOptions'; describe('Issue #174 - https://github.com/C2FO/fast-csv/issues/174', () => { const createParser = (parserOptions: ParserOptionsArgs = {}) => new Parser(new ParserOptions(parserOptions)); diff --git a/__tests__/issues/issue214.spec.ts b/packages/parse/__tests__/issues/issue214.spec.ts similarity index 86% rename from __tests__/issues/issue214.spec.ts rename to packages/parse/__tests__/issues/issue214.spec.ts index 2c9cf50a..be0e8391 100644 --- a/__tests__/issues/issue214.spec.ts +++ b/packages/parse/__tests__/issues/issue214.spec.ts @@ -18,9 +18,9 @@ describe('Issue #214 - https://github.com/C2FO/fast-csv/issues/214', () => { ]; it('should emit data when using the on method', next => { - const rows: csv.ParserRowMap[] = []; + const rows: csv.RowMap[] = []; csv.parseString(CSV_CONTENT, { headers: true }) - .on('data', (r: csv.ParserRowMap) => rows.push(r)) + .on('data', (r: csv.RowMap) => rows.push(r)) .on('error', next) .on('end', (count: number) => { expect(rows).toEqual(expectedRows); @@ -30,9 +30,9 @@ describe('Issue #214 - https://github.com/C2FO/fast-csv/issues/214', () => { }); it('should emit data when using the addListener method', next => { - const rows: csv.ParserRowMap[] = []; + const rows: csv.RowMap[] = []; csv.parseString(CSV_CONTENT, { headers: true }) - .addListener('data', (r: csv.ParserRowMap) => rows.push(r)) + .addListener('data', (r: csv.RowMap) => rows.push(r)) .on('error', next) .on('end', (count: number) => { expect(rows).toEqual(expectedRows); diff --git a/__tests__/issues/issue223.spec.ts b/packages/parse/__tests__/issues/issue223.spec.ts similarity index 88% rename from __tests__/issues/issue223.spec.ts rename to packages/parse/__tests__/issues/issue223.spec.ts index 68b7967e..220518f0 100644 --- a/__tests__/issues/issue223.spec.ts +++ b/packages/parse/__tests__/issues/issue223.spec.ts @@ -1,5 +1,6 @@ import { EOL } from 'os'; -import { Parser, ParserOptions } from '../../src/parser'; +import { Parser } from '../../src/parser'; +import { ParserOptions } from '../../src/ParserOptions'; describe('Issue #223 - https://github.com/C2FO/fast-csv/issues/223', () => { const createParser = (parserOptions = {}) => new Parser(new ParserOptions(parserOptions)); diff --git a/__tests__/issues/issue68.spec.ts b/packages/parse/__tests__/issues/issue68.spec.ts similarity index 100% rename from __tests__/issues/issue68.spec.ts rename to packages/parse/__tests__/issues/issue68.spec.ts diff --git a/__tests__/issues/issue87.spec.ts b/packages/parse/__tests__/issues/issue87.spec.ts similarity index 93% rename from __tests__/issues/issue87.spec.ts rename to packages/parse/__tests__/issues/issue87.spec.ts index 556fcea1..58933871 100644 --- a/__tests__/issues/issue87.spec.ts +++ b/packages/parse/__tests__/issues/issue87.spec.ts @@ -17,7 +17,7 @@ describe('Issue #87 - https://github.com/C2FO/fast-csv/issues/87', () => { this.rowCount = 0; } - private transform(data: csv.ParserRow, encoding: string, done: TransformCallback) { + private transform(data: csv.Row, encoding: string, done: TransformCallback) { this.rowCount += 1; if (this.rowCount % 2 === 0) { setTimeout(() => done(), 10); diff --git a/__tests__/issues/issue93.spec.ts b/packages/parse/__tests__/issues/issue93.spec.ts similarity index 100% rename from __tests__/issues/issue93.spec.ts rename to packages/parse/__tests__/issues/issue93.spec.ts diff --git a/packages/parse/__tests__/parse.spec.ts b/packages/parse/__tests__/parse.spec.ts new file mode 100644 index 00000000..4109576f --- /dev/null +++ b/packages/parse/__tests__/parse.spec.ts @@ -0,0 +1,30 @@ +import * as fs from 'fs'; +import { collectData, expectParsed, withHeaders, write } from './__fixtures__'; +import { CsvParserStream, parse, parseFile, parseStream, parseString } from '../src'; + +describe('.parse', () => { + it('should accept a stream', async () => { + expect(parse({ headers: true })).toBeInstanceOf(CsvParserStream); + }); +}); + +describe('.parseStream', () => { + it('should accept a stream', async () => { + write(withHeaders); + const stream = parseStream(fs.createReadStream(withHeaders.path), { headers: true }); + await expectParsed(collectData(stream), withHeaders.parsed); + }); +}); + +describe('.parseFile', () => { + it('parse a csv from the given path', async () => { + write(withHeaders); + const stream = parseFile(withHeaders.path, { headers: true }); + await expectParsed(collectData(stream), withHeaders.parsed); + }); +}); + +describe('.parseString', () => { + it('should accept a csv string', () => + expectParsed(collectData(parseString(withHeaders.content, { headers: true })), withHeaders.parsed)); +}); diff --git a/__tests__/parser/parser/Parser.spec.ts b/packages/parse/__tests__/parser/Parser.spec.ts similarity index 99% rename from __tests__/parser/parser/Parser.spec.ts rename to packages/parse/__tests__/parser/Parser.spec.ts index 896e46a8..e903aa77 100644 --- a/__tests__/parser/parser/Parser.spec.ts +++ b/packages/parse/__tests__/parser/Parser.spec.ts @@ -1,5 +1,6 @@ -import { ParserOptionsArgs } from '../../../src'; -import { ParserOptions, Parser } from '../../../src/parser'; +import { ParserOptionsArgs } from '../../src'; +import { ParserOptions } from '../../src/ParserOptions'; +import { Parser } from '../../src/parser'; describe('Parser', () => { const createParser = (parserOptions: ParserOptionsArgs = {}) => new Parser(new ParserOptions(parserOptions)); diff --git a/__tests__/parser/parser/RowParser.spec.ts b/packages/parse/__tests__/parser/RowParser.spec.ts similarity index 97% rename from __tests__/parser/parser/RowParser.spec.ts rename to packages/parse/__tests__/parser/RowParser.spec.ts index 8d7c0df9..26aef5b8 100644 --- a/__tests__/parser/parser/RowParser.spec.ts +++ b/packages/parse/__tests__/parser/RowParser.spec.ts @@ -1,5 +1,6 @@ -import { ParserOptionsArgs } from '../../../src'; -import { ParserOptions, Scanner, RowParser } from '../../../src/parser'; +import { ParserOptionsArgs } from '../../src'; +import { ParserOptions } from '../../src/ParserOptions'; +import { RowParser, Scanner } from '../../src/parser'; describe('RowParser', () => { const parse = (line: string, hasMoreData = false, parserOpts: ParserOptionsArgs = {}) => { diff --git a/__tests__/parser/parser/Scanner.spec.ts b/packages/parse/__tests__/parser/Scanner.spec.ts similarity index 98% rename from __tests__/parser/parser/Scanner.spec.ts rename to packages/parse/__tests__/parser/Scanner.spec.ts index 11ffde9c..0ef0db38 100644 --- a/__tests__/parser/parser/Scanner.spec.ts +++ b/packages/parse/__tests__/parser/Scanner.spec.ts @@ -1,5 +1,6 @@ -import { ParserOptionsArgs } from '../../../src'; -import { ParserOptions, Scanner, Token, MaybeToken } from '../../../src/parser'; +import { ParserOptionsArgs } from '../../src'; +import { ParserOptions } from '../../src/ParserOptions'; +import { MaybeToken, Scanner, Token } from '../../src/parser'; const createOptions = (opts: ParserOptionsArgs = {}) => new ParserOptions(opts); describe('Scanner', () => { diff --git a/__tests__/parser/parser/column/ColumnParser.spec.ts b/packages/parse/__tests__/parser/column/ColumnParser.spec.ts similarity index 91% rename from __tests__/parser/parser/column/ColumnParser.spec.ts rename to packages/parse/__tests__/parser/column/ColumnParser.spec.ts index d09ed87f..5e8e4781 100644 --- a/__tests__/parser/parser/column/ColumnParser.spec.ts +++ b/packages/parse/__tests__/parser/column/ColumnParser.spec.ts @@ -1,5 +1,7 @@ import * as sinon from 'sinon'; -import { ParserOptions, Scanner, ColumnParser } from '../../../../src/parser'; +import { ParserOptions } from '../../../src/ParserOptions'; +import { ColumnParser } from '../../../src/parser/column'; +import { Scanner } from '../../../src/parser'; describe('ColumnParser', () => { describe('#parse', () => { diff --git a/__tests__/parser/parser/column/NonQuotedColumnParser.spec.ts b/packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts similarity index 96% rename from __tests__/parser/parser/column/NonQuotedColumnParser.spec.ts rename to packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts index 30dad12f..38dd632f 100644 --- a/__tests__/parser/parser/column/NonQuotedColumnParser.spec.ts +++ b/packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts @@ -1,5 +1,7 @@ -import { ParserOptionsArgs } from '../../../../src'; -import { ParserOptions, Scanner, NonQuotedColumnParser } from '../../../../src/parser'; +import { ParserOptionsArgs } from '../../../src'; +import { ParserOptions } from '../../../src/ParserOptions'; +import { NonQuotedColumnParser } from '../../../src/parser/column'; +import { Scanner } from '../../../src/parser'; describe('NonQuotedColumnParser', () => { const parse = (line: string, hasMoreData = false, parserOpts: ParserOptionsArgs = {}) => { diff --git a/__tests__/parser/parser/column/QuotedColumnParser.spec.ts b/packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts similarity index 99% rename from __tests__/parser/parser/column/QuotedColumnParser.spec.ts rename to packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts index b51278d4..e99dc76e 100644 --- a/__tests__/parser/parser/column/QuotedColumnParser.spec.ts +++ b/packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts @@ -1,5 +1,7 @@ -import { ParserOptionsArgs } from '../../../../src'; -import { ParserOptions, QuotedColumnParser, Scanner } from '../../../../src/parser'; +import { ParserOptionsArgs } from '../../../src'; +import { ParserOptions } from '../../../src/ParserOptions'; +import { QuotedColumnParser } from '../../../src/parser/column'; +import { Scanner } from '../../../src/parser'; describe('QuotedColumnParser', () => { const parse = (line: string, hasMoreData = false, parserOpts: ParserOptionsArgs = {}) => { diff --git a/__tests__/parser/transforms/HeaderTransformer.spec.ts b/packages/parse/__tests__/transforms/HeaderTransformer.spec.ts similarity index 97% rename from __tests__/parser/transforms/HeaderTransformer.spec.ts rename to packages/parse/__tests__/transforms/HeaderTransformer.spec.ts index 5f980d94..30088287 100644 --- a/__tests__/parser/transforms/HeaderTransformer.spec.ts +++ b/packages/parse/__tests__/transforms/HeaderTransformer.spec.ts @@ -1,5 +1,6 @@ -import { ParserOptionsArgs, ParserRowArray as RowArray } from '../../../src'; -import { ParserOptions, RowValidationResult, HeaderTransformer } from '../../../src/parser'; +import { ParserOptionsArgs, RowArray, RowValidationResult } from '../../src'; +import { HeaderTransformer } from '../../src/transforms'; +import { ParserOptions } from '../../src/ParserOptions'; describe('HeaderTransformer', () => { const createHeaderTransformer = (opts?: ParserOptionsArgs) => new HeaderTransformer(new ParserOptions(opts)); diff --git a/__tests__/parser/transforms/RowTransformerValidator.spec.ts b/packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts similarity index 97% rename from __tests__/parser/transforms/RowTransformerValidator.spec.ts rename to packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts index 2e648529..e746a4fc 100644 --- a/__tests__/parser/transforms/RowTransformerValidator.spec.ts +++ b/packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts @@ -1,5 +1,5 @@ -import { ParserRow as Row, ParserRowArray as RowArray } from '../../../src'; -import { RowValidationResult, RowTransformerValidator } from '../../../src/parser'; +import { Row, RowArray, RowValidationResult } from '../../src'; +import { RowTransformerValidator } from '../../src/transforms'; describe('RowTransformerValidator', () => { const createRowTransformerValidator = () => new RowTransformerValidator(); diff --git a/packages/parse/package-lock.json b/packages/parse/package-lock.json new file mode 100644 index 00000000..32322033 --- /dev/null +++ b/packages/parse/package-lock.json @@ -0,0 +1,260 @@ +{ + "name": "@fast-csv/parse", + "version": "4.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@sinonjs/commons": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, + "@types/lodash.escaperegexp": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/lodash.escaperegexp/-/lodash.escaperegexp-4.1.6.tgz", + "integrity": "sha512-uENiqxLlqh6RzeE1cC6Z2gHqakToN9vKlTVCFkSVjAfeMeh2fY0916tHwJHeeKs28qB/hGYvKuampGYH5QDVCw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.groupby": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.groupby/-/lodash.groupby-4.6.6.tgz", + "integrity": "sha512-kwg3T7Ia63KtDNoQQR8hKrLHCAgrH4I44l5uEMuA6JCbj7DiSccaV4tNV1vbjtAOpX990SolVthJCmBVtRVRgw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isfunction": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isfunction/-/lodash.isfunction-3.0.6.tgz", + "integrity": "sha512-olhgKmBgzHnA5pxsOI6YHunzTBMSyBw1XjxIKFio8W+XhYiELGTt05FStE0suV0GWtlIMdn7V8M/UbYbSVdGYw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isnil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isnil/-/lodash.isnil-4.0.6.tgz", + "integrity": "sha512-K+9ZVqwWUFKxijX7rPGnrubfTtCQ5VwW0xgPCL5iLBBLg5sUFFXdPG3QxkpGNJil8mgttRqNLSWNweEsUrBXTg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isundefined": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isundefined/-/lodash.isundefined-3.0.6.tgz", + "integrity": "sha512-gXRrZ9MahWtxusjjUAbWaxUA4vU/NxXfI9kkfsjXYnBA0YjXVtl71toGBZ0X4+L023XS8NlO3BokLXFFuLtG/Q==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.partition": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.partition/-/lodash.partition-4.6.6.tgz", + "integrity": "sha512-s8ZNNFWhBgTKI4uNxVrTs3Aa7UQoi7Fesw55bfpBBMCLda+uSuwDyuax8ka9aBy8Ccsjp2SiS034DkSZa+CzVA==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.uniq": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.6.tgz", + "integrity": "sha512-XHNMXBtiwsWZstZMyxOYjr0e8YYWv0RgPlzIHblTuwBBiWo2MzWVaTBihtBpslb5BglgAWIeBv69qt1+RTRW1A==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/sinon": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", + "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", + "dev": true + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + }, + "lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" + }, + "lodash.partition": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.partition/-/lodash.partition-4.6.0.tgz", + "integrity": "sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", + "dev": true + }, + "nise": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } + } + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + }, + "sinon": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } + } +} diff --git a/packages/parse/package.json b/packages/parse/package.json new file mode 100644 index 00000000..6efdd963 --- /dev/null +++ b/packages/parse/package.json @@ -0,0 +1,58 @@ +{ + "name": "@fast-csv/parse", + "version": "4.0.0", + "description": "fast-csv parsing package", + "keywords": [ + "csv", + "parse", + "fast-csv", + "parser" + ], + "author": "doug-martin ", + "homepage": "http://c2fo.github.com/fast-csv/index.html/tree/master/packages/parse#readme", + "license": "MIT", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "directories": { + "lib": "src", + "test": "__tests__" + }, + "files": [ + "build/src/**" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/C2FO/fast-csv.git" + }, + "scripts": { + "build": "npm run clean && npm run compile", + "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo", + "compile": "tsc -p tsconfig.build.json" + }, + "bugs": { + "url": "https://github.com/C2FO/fast-csv/issues" + }, + "dependencies": { + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + }, + "devDependencies": { + "@types/lodash.escaperegexp": "^4.1.6", + "@types/lodash.groupby": "^4.6.6", + "@types/lodash.isfunction": "^3.0.6", + "@types/lodash.isnil": "^4.0.6", + "@types/lodash.isundefined": "^3.0.6", + "@types/lodash.partition": "^4.6.6", + "@types/lodash.uniq": "^4.5.6", + "@types/sinon": "^7.5.1", + "lodash.partition": "^4.6.0", + "sinon": "^7.5.0" + } +} diff --git a/src/parser/CsvParserStream.ts b/packages/parse/src/CsvParserStream.ts similarity index 99% rename from src/parser/CsvParserStream.ts rename to packages/parse/src/CsvParserStream.ts index b5fdc05b..7509274f 100644 --- a/src/parser/CsvParserStream.ts +++ b/packages/parse/src/CsvParserStream.ts @@ -5,7 +5,7 @@ import { HeaderTransformer, RowTransformerValidator } from './transforms'; import { Parser } from './parser'; import { Row, RowArray, RowTransformFunction, RowValidate, RowValidatorCallback } from './types'; -export default class CsvParserStream extends Transform { +export class CsvParserStream extends Transform { private readonly parserOptions: ParserOptions; private readonly decoder: StringDecoder; diff --git a/src/parser/ParserOptions.ts b/packages/parse/src/ParserOptions.ts similarity index 100% rename from src/parser/ParserOptions.ts rename to packages/parse/src/ParserOptions.ts diff --git a/src/parser/index.ts b/packages/parse/src/index.ts similarity index 81% rename from src/parser/index.ts rename to packages/parse/src/index.ts index 2279d91f..a1de19d8 100644 --- a/src/parser/index.ts +++ b/packages/parse/src/index.ts @@ -1,13 +1,11 @@ import * as fs from 'fs'; import { Readable } from 'stream'; import { ParserOptions, ParserOptionsArgs } from './ParserOptions'; -import CsvParserStream from './CsvParserStream'; +import { CsvParserStream } from './CsvParserStream'; -export { default as CsvParserStream } from './CsvParserStream'; export * from './types'; -export * from './ParserOptions'; -export * from './parser'; -export * from './transforms'; +export { CsvParserStream } from './CsvParserStream'; +export { ParserOptions, ParserOptionsArgs } from './ParserOptions'; export const parse = (args?: ParserOptionsArgs): CsvParserStream => new CsvParserStream(new ParserOptions(args)); diff --git a/src/parser/parser/Parser.ts b/packages/parse/src/parser/Parser.ts similarity index 97% rename from src/parser/parser/Parser.ts rename to packages/parse/src/parser/Parser.ts index bf3e1b62..6e4335da 100644 --- a/src/parser/parser/Parser.ts +++ b/packages/parse/src/parser/Parser.ts @@ -1,5 +1,5 @@ import { Scanner } from './Scanner'; -import RowParser from './RowParser'; +import { RowParser } from './RowParser'; import { ParserOptions } from '../ParserOptions'; import { RowArray } from '../types'; import { Token } from './Token'; @@ -10,7 +10,7 @@ export interface ParseResult { line: string; rows: string[][]; } -export default class Parser { +export class Parser { private static removeBOM(line: string): string { // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string // conversion translates it to FEFF (UTF-16 BOM) diff --git a/src/parser/parser/RowParser.ts b/packages/parse/src/parser/RowParser.ts similarity index 98% rename from src/parser/parser/RowParser.ts rename to packages/parse/src/parser/RowParser.ts index 7a7bf2cc..d94a9180 100644 --- a/src/parser/parser/RowParser.ts +++ b/packages/parse/src/parser/RowParser.ts @@ -6,7 +6,7 @@ import { MaybeToken, Token } from './Token'; const { isTokenRowDelimiter, isTokenCarriageReturn, isTokenDelimiter } = Token; -export default class RowParser { +export class RowParser { private readonly parserOptions: ParserOptions; private readonly columnParser: ColumnParser; diff --git a/src/parser/parser/Scanner.ts b/packages/parse/src/parser/Scanner.ts similarity index 100% rename from src/parser/parser/Scanner.ts rename to packages/parse/src/parser/Scanner.ts diff --git a/src/parser/parser/Token.ts b/packages/parse/src/parser/Token.ts similarity index 100% rename from src/parser/parser/Token.ts rename to packages/parse/src/parser/Token.ts diff --git a/src/parser/parser/column/ColumnFormatter.ts b/packages/parse/src/parser/column/ColumnFormatter.ts similarity index 93% rename from src/parser/parser/column/ColumnFormatter.ts rename to packages/parse/src/parser/column/ColumnFormatter.ts index 79a9382c..320b4183 100644 --- a/src/parser/parser/column/ColumnFormatter.ts +++ b/packages/parse/src/parser/column/ColumnFormatter.ts @@ -1,6 +1,6 @@ import { ParserOptions } from '../../ParserOptions'; -export default class ColumnFormatter { +export class ColumnFormatter { public readonly format: (col: string) => string; public constructor(parserOptions: ParserOptions) { diff --git a/src/parser/parser/column/ColumnParser.ts b/packages/parse/src/parser/column/ColumnParser.ts similarity index 86% rename from src/parser/parser/column/ColumnParser.ts rename to packages/parse/src/parser/column/ColumnParser.ts index 5360c364..ee287365 100644 --- a/src/parser/parser/column/ColumnParser.ts +++ b/packages/parse/src/parser/column/ColumnParser.ts @@ -1,10 +1,10 @@ import { ParserOptions } from '../../ParserOptions'; -import NonQuotedColumnParser from './NonQuotedColumnParser'; -import QuotedColumnParser from './QuotedColumnParser'; +import { NonQuotedColumnParser } from './NonQuotedColumnParser'; +import { QuotedColumnParser } from './QuotedColumnParser'; import { Scanner } from '../Scanner'; import { Token } from '../Token'; -export default class ColumnParser { +export class ColumnParser { private readonly parserOptions: ParserOptions; public readonly nonQuotedColumnParser: NonQuotedColumnParser; diff --git a/src/parser/parser/column/NonQuotedColumnParser.ts b/packages/parse/src/parser/column/NonQuotedColumnParser.ts similarity index 92% rename from src/parser/parser/column/NonQuotedColumnParser.ts rename to packages/parse/src/parser/column/NonQuotedColumnParser.ts index 4c30d330..fe6826bd 100644 --- a/src/parser/parser/column/NonQuotedColumnParser.ts +++ b/packages/parse/src/parser/column/NonQuotedColumnParser.ts @@ -1,11 +1,11 @@ import { ParserOptions } from '../../ParserOptions'; -import ColumnFormatter from './ColumnFormatter'; +import { ColumnFormatter } from './ColumnFormatter'; import { Scanner } from '../Scanner'; import { Token } from '../Token'; const { isTokenDelimiter, isTokenRowDelimiter } = Token; -export default class NonQuotedColumnParser { +export class NonQuotedColumnParser { private readonly parserOptions: ParserOptions; private readonly columnFormatter: ColumnFormatter; diff --git a/src/parser/parser/column/QuotedColumnParser.ts b/packages/parse/src/parser/column/QuotedColumnParser.ts similarity index 98% rename from src/parser/parser/column/QuotedColumnParser.ts rename to packages/parse/src/parser/column/QuotedColumnParser.ts index 4495ef77..b265c417 100644 --- a/src/parser/parser/column/QuotedColumnParser.ts +++ b/packages/parse/src/parser/column/QuotedColumnParser.ts @@ -1,4 +1,4 @@ -import ColumnFormatter from './ColumnFormatter'; +import { ColumnFormatter } from './ColumnFormatter'; import { ParserOptions } from '../../ParserOptions'; import { Scanner } from '../Scanner'; import { Token } from '../Token'; @@ -10,7 +10,7 @@ interface DataBetweenQuotes { col: string; } -export default class QuotedColumnParser { +export class QuotedColumnParser { private readonly parserOptions: ParserOptions; private readonly columnFormatter: ColumnFormatter; diff --git a/packages/parse/src/parser/column/index.ts b/packages/parse/src/parser/column/index.ts new file mode 100644 index 00000000..2c574ead --- /dev/null +++ b/packages/parse/src/parser/column/index.ts @@ -0,0 +1,4 @@ +export { ColumnParser } from './ColumnParser'; +export { NonQuotedColumnParser } from './NonQuotedColumnParser'; +export { QuotedColumnParser } from './QuotedColumnParser'; +export { ColumnFormatter } from './ColumnFormatter'; diff --git a/src/parser/parser/index.ts b/packages/parse/src/parser/index.ts similarity index 62% rename from src/parser/parser/index.ts rename to packages/parse/src/parser/index.ts index e360e451..2f64fcb9 100644 --- a/src/parser/parser/index.ts +++ b/packages/parse/src/parser/index.ts @@ -1,5 +1,5 @@ -export { default as Parser } from './Parser'; -export { default as RowParser } from './RowParser'; +export { Parser } from './Parser'; +export { RowParser } from './RowParser'; export { Scanner } from './Scanner'; export { Token, MaybeToken } from './Token'; export { ColumnParser, NonQuotedColumnParser, QuotedColumnParser } from './column'; diff --git a/src/parser/transforms/HeaderTransformer.ts b/packages/parse/src/transforms/HeaderTransformer.ts similarity index 99% rename from src/parser/transforms/HeaderTransformer.ts rename to packages/parse/src/transforms/HeaderTransformer.ts index 6fcc7fc2..1b933151 100644 --- a/src/parser/transforms/HeaderTransformer.ts +++ b/packages/parse/src/transforms/HeaderTransformer.ts @@ -13,7 +13,7 @@ import { RowValidatorCallback, } from '../types'; -export default class HeaderTransformer { +export class HeaderTransformer { private readonly parserOptions: ParserOptions; private headers: HeaderArray | null = null; diff --git a/src/parser/transforms/RowTransformerValidator.ts b/packages/parse/src/transforms/RowTransformerValidator.ts similarity index 98% rename from src/parser/transforms/RowTransformerValidator.ts rename to packages/parse/src/transforms/RowTransformerValidator.ts index 87368727..6ba3c53a 100644 --- a/src/parser/transforms/RowTransformerValidator.ts +++ b/packages/parse/src/transforms/RowTransformerValidator.ts @@ -13,7 +13,7 @@ import { type RowValidator = (row: Row, cb: RowValidatorCallback) => void; -export default class RowTransformerValidator { +export class RowTransformerValidator { private static createTransform(transformFunction: RowTransformFunction): AsyncRowTransform { if (isSyncTransform(transformFunction)) { return (row, cb): void => { diff --git a/packages/parse/src/transforms/index.ts b/packages/parse/src/transforms/index.ts new file mode 100644 index 00000000..26df69bf --- /dev/null +++ b/packages/parse/src/transforms/index.ts @@ -0,0 +1,2 @@ +export { RowTransformerValidator } from './RowTransformerValidator'; +export { HeaderTransformer } from './HeaderTransformer'; diff --git a/src/parser/types.ts b/packages/parse/src/types.ts similarity index 100% rename from src/parser/types.ts rename to packages/parse/src/types.ts diff --git a/packages/parse/tsconfig.build.json b/packages/parse/tsconfig.build.json new file mode 100644 index 00000000..bd8b5699 --- /dev/null +++ b/packages/parse/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./build", + "rootDir": "." + }, + "exclude": [ + "node_modules", + "build" + ] +} diff --git a/packages/parse/tsconfig.json b/packages/parse/tsconfig.json new file mode 100644 index 00000000..6b9e22b4 --- /dev/null +++ b/packages/parse/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./src", "./__tests__/**/*.ts"] +} diff --git a/src/formatter/formatter/index.ts b/src/formatter/formatter/index.ts deleted file mode 100644 index 2879426e..00000000 --- a/src/formatter/formatter/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as RowFormatter } from './RowFormatter'; -export { default as FieldFormatter } from './FieldFormatter'; diff --git a/src/parser/parser/column/index.ts b/src/parser/parser/column/index.ts deleted file mode 100644 index fdb521dd..00000000 --- a/src/parser/parser/column/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { default as ColumnParser } from './ColumnParser'; -export { default as NonQuotedColumnParser } from './NonQuotedColumnParser'; -export { default as QuotedColumnParser } from './QuotedColumnParser'; -export { default as ColumnFormatter } from './ColumnFormatter'; diff --git a/src/parser/transforms/index.ts b/src/parser/transforms/index.ts deleted file mode 100644 index 3353a646..00000000 --- a/src/parser/transforms/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as RowTransformerValidator } from './RowTransformerValidator'; -export { default as HeaderTransformer } from './HeaderTransformer'; diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..e34fb009 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es2016"], + "module": "commonjs", + "noEmitOnError": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "pretty": true, + "sourceMap": true, + "strict": true, + "target": "es2017", + "rootDir": ".", + "outDir": "build" + }, + "exclude": [ + "**/node_modules/**", + "**/build/**" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index e7bfd658..75258ea5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,27 +1,17 @@ { + "extends": "./tsconfig.build.json", "compilerOptions": { - "allowUnreachableCode": false, - "allowUnusedLabels": false, - "declaration": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "lib": ["es2016"], - "module": "commonjs", - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "pretty": true, - "sourceMap": true, - "strict": true, - "target": "es2017", - "rootDir": ".", - "outDir": "build" + "baseUrl": "./packages", + "composite": true, + "paths": { + "fast-csv": ["fast-csv"], + "@fast-csv/format": ["format"], + "@fast-csv/parse": ["parse"] + } }, - "exclude": [ - "node_modules" - ], - "include": [ - "src/**/*.ts", - "__tests__/**/*.ts" + "references": [ + {"path": "./packages/fast-csv"}, + {"path": "./packages/format"}, + {"path": "./packages/parse"} ] -} \ No newline at end of file +} From ef2c7d698e946b9d43372d85e2a523eebb2d0dba Mon Sep 17 00:00:00 2001 From: doug-martin Date: Mon, 23 Dec 2019 22:19:43 -0600 Subject: [PATCH 4/8] Clean up package-lock.json files --- examples/fast-csv-js/package-lock.json | 568 ------------------------- examples/parsing-js/package-lock.json | 568 ------------------------- package-lock.json | 201 ++++++--- packages/format/package-lock.json | 84 ---- packages/parse/package-lock.json | 260 ----------- 5 files changed, 134 insertions(+), 1547 deletions(-) delete mode 100644 examples/fast-csv-js/package-lock.json delete mode 100644 examples/parsing-js/package-lock.json delete mode 100644 packages/format/package-lock.json delete mode 100644 packages/parse/package-lock.json diff --git a/examples/fast-csv-js/package-lock.json b/examples/fast-csv-js/package-lock.json deleted file mode 100644 index 89b1d2b2..00000000 --- a/examples/fast-csv-js/package-lock.json +++ /dev/null @@ -1,568 +0,0 @@ -{ - "name": "@fast-csv/parse-js-examples", - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@fast-csv/parse": { - "version": "4.0.0", - "requires": { - "lodash.escaperegexp": "^4.1.2", - "lodash.groupby": "^4.6.0", - "lodash.isfunction": "^3.0.9", - "lodash.isnil": "^4.0.0", - "lodash.isundefined": "^3.0.1", - "lodash.uniq": "^4.5.0" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", - "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "just-extend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==" - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "lodash.groupby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.isnil": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" - }, - "lodash.isundefined": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - }, - "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" - }, - "nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "requires": { - "@sinonjs/commons": "^1.7.0" - } - } - } - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - } - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" - }, - "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "requires": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" - } - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" - }, - "@types/istanbul-lib-report": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", - "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" - }, - "@types/node": { - "version": "12.12.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", - "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" - }, - "@types/yargs": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", - "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "requires": { - "path-type": "^4.0.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "fast-glob": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", - "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2" - } - }, - "fastq": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", - "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "requires": { - "reusify": "^1.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" - }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - }, - "picomatch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", - "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - } - }, - "react-is": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - } - } -} diff --git a/examples/parsing-js/package-lock.json b/examples/parsing-js/package-lock.json deleted file mode 100644 index 89b1d2b2..00000000 --- a/examples/parsing-js/package-lock.json +++ /dev/null @@ -1,568 +0,0 @@ -{ - "name": "@fast-csv/parse-js-examples", - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@fast-csv/parse": { - "version": "4.0.0", - "requires": { - "lodash.escaperegexp": "^4.1.2", - "lodash.groupby": "^4.6.0", - "lodash.isfunction": "^3.0.9", - "lodash.isnil": "^4.0.0", - "lodash.isundefined": "^3.0.1", - "lodash.uniq": "^4.5.0" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", - "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "just-extend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==" - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "lodash.groupby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.isnil": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" - }, - "lodash.isundefined": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - }, - "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" - }, - "nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "requires": { - "@sinonjs/commons": "^1.7.0" - } - } - } - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - } - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" - }, - "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "requires": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" - } - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" - }, - "@types/istanbul-lib-report": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", - "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" - }, - "@types/node": { - "version": "12.12.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", - "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" - }, - "@types/yargs": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", - "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "requires": { - "path-type": "^4.0.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "fast-glob": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", - "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2" - } - }, - "fastq": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", - "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "requires": { - "reusify": "^1.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" - }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - }, - "picomatch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", - "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - } - }, - "react-is": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - } - } -} diff --git a/package-lock.json b/package-lock.json index 7c7ccf70..a3d24160 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5196,25 +5196,29 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, "requires": { @@ -5224,13 +5228,15 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, "requires": { @@ -5240,37 +5246,43 @@ }, "chownr": { "version": "1.1.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "3.2.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "optional": true, "requires": { @@ -5279,25 +5291,29 @@ }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.7", - "bundled": true, + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "optional": true, "requires": { @@ -5306,13 +5322,15 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -5328,7 +5346,8 @@ }, "glob": { "version": "7.1.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "optional": true, "requires": { @@ -5342,13 +5361,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { @@ -5357,7 +5378,8 @@ }, "ignore-walk": { "version": "3.0.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "optional": true, "requires": { @@ -5366,7 +5388,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, "requires": { @@ -5376,19 +5399,22 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, "requires": { @@ -5397,13 +5423,15 @@ }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, "requires": { @@ -5412,13 +5440,15 @@ }, "minimist": { "version": "0.0.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "optional": true, "requires": { @@ -5428,7 +5458,8 @@ }, "minizlib": { "version": "1.3.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "optional": true, "requires": { @@ -5437,7 +5468,8 @@ }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, "requires": { @@ -5446,13 +5478,15 @@ }, "ms": { "version": "2.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "optional": true }, "needle": { "version": "2.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", "dev": true, "optional": true, "requires": { @@ -5463,7 +5497,8 @@ }, "node-pre-gyp": { "version": "0.14.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", "dev": true, "optional": true, "requires": { @@ -5481,7 +5516,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, "requires": { @@ -5491,7 +5527,8 @@ }, "npm-bundled": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", "dev": true, "optional": true, "requires": { @@ -5500,13 +5537,15 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.7", - "bundled": true, + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz", + "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", "dev": true, "optional": true, "requires": { @@ -5516,7 +5555,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, "requires": { @@ -5528,19 +5568,22 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, "requires": { @@ -5549,19 +5592,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, "requires": { @@ -5571,19 +5617,22 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, "requires": { @@ -5595,7 +5644,8 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true } @@ -5603,7 +5653,8 @@ }, "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, "requires": { @@ -5618,7 +5669,8 @@ }, "rimraf": { "version": "2.7.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "optional": true, "requires": { @@ -5627,43 +5679,50 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, "requires": { @@ -5674,7 +5733,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, "requires": { @@ -5683,7 +5743,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, "requires": { @@ -5692,13 +5753,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.13", - "bundled": true, + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "optional": true, "requires": { @@ -5713,13 +5776,15 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, "requires": { @@ -5728,13 +5793,15 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "optional": true } diff --git a/packages/format/package-lock.json b/packages/format/package-lock.json deleted file mode 100644 index a1568e8a..00000000 --- a/packages/format/package-lock.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "@fast-csv/format", - "version": "4.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", - "dev": true - }, - "@types/lodash.escaperegexp": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/lodash.escaperegexp/-/lodash.escaperegexp-4.1.6.tgz", - "integrity": "sha512-uENiqxLlqh6RzeE1cC6Z2gHqakToN9vKlTVCFkSVjAfeMeh2fY0916tHwJHeeKs28qB/hGYvKuampGYH5QDVCw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isboolean": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isboolean/-/lodash.isboolean-3.0.6.tgz", - "integrity": "sha512-9ommZgIE6GlZW/GuSRIOSJP3X0FkOD2qqt8xBNqUVb/t4L62WiIGCPgIKK2PNfZem7bEZulM0djX9f8IG2Qg3Q==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isequal": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.5.tgz", - "integrity": "sha512-4IKbinG7MGP131wRfceK6W4E/Qt3qssEFLF30LnJbjYiSfHGGRU/Io8YxXrZX109ir+iDETC8hw8QsDijukUVg==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isfunction": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isfunction/-/lodash.isfunction-3.0.6.tgz", - "integrity": "sha512-olhgKmBgzHnA5pxsOI6YHunzTBMSyBw1XjxIKFio8W+XhYiELGTt05FStE0suV0GWtlIMdn7V8M/UbYbSVdGYw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isnil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isnil/-/lodash.isnil-4.0.6.tgz", - "integrity": "sha512-K+9ZVqwWUFKxijX7rPGnrubfTtCQ5VwW0xgPCL5iLBBLg5sUFFXdPG3QxkpGNJil8mgttRqNLSWNweEsUrBXTg==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.isnil": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" - } - } -} diff --git a/packages/parse/package-lock.json b/packages/parse/package-lock.json deleted file mode 100644 index 32322033..00000000 --- a/packages/parse/package-lock.json +++ /dev/null @@ -1,260 +0,0 @@ -{ - "name": "@fast-csv/parse", - "version": "4.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@sinonjs/commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", - "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", - "dev": true - }, - "@types/lodash.escaperegexp": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/lodash.escaperegexp/-/lodash.escaperegexp-4.1.6.tgz", - "integrity": "sha512-uENiqxLlqh6RzeE1cC6Z2gHqakToN9vKlTVCFkSVjAfeMeh2fY0916tHwJHeeKs28qB/hGYvKuampGYH5QDVCw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.groupby": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.groupby/-/lodash.groupby-4.6.6.tgz", - "integrity": "sha512-kwg3T7Ia63KtDNoQQR8hKrLHCAgrH4I44l5uEMuA6JCbj7DiSccaV4tNV1vbjtAOpX990SolVthJCmBVtRVRgw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isfunction": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isfunction/-/lodash.isfunction-3.0.6.tgz", - "integrity": "sha512-olhgKmBgzHnA5pxsOI6YHunzTBMSyBw1XjxIKFio8W+XhYiELGTt05FStE0suV0GWtlIMdn7V8M/UbYbSVdGYw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isnil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isnil/-/lodash.isnil-4.0.6.tgz", - "integrity": "sha512-K+9ZVqwWUFKxijX7rPGnrubfTtCQ5VwW0xgPCL5iLBBLg5sUFFXdPG3QxkpGNJil8mgttRqNLSWNweEsUrBXTg==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isundefined": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isundefined/-/lodash.isundefined-3.0.6.tgz", - "integrity": "sha512-gXRrZ9MahWtxusjjUAbWaxUA4vU/NxXfI9kkfsjXYnBA0YjXVtl71toGBZ0X4+L023XS8NlO3BokLXFFuLtG/Q==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.partition": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.partition/-/lodash.partition-4.6.6.tgz", - "integrity": "sha512-s8ZNNFWhBgTKI4uNxVrTs3Aa7UQoi7Fesw55bfpBBMCLda+uSuwDyuax8ka9aBy8Ccsjp2SiS034DkSZa+CzVA==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.uniq": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.6.tgz", - "integrity": "sha512-XHNMXBtiwsWZstZMyxOYjr0e8YYWv0RgPlzIHblTuwBBiWo2MzWVaTBihtBpslb5BglgAWIeBv69qt1+RTRW1A==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/sinon": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", - "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", - "dev": true - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "just-extend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "lodash.groupby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.isnil": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" - }, - "lodash.isundefined": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" - }, - "lodash.partition": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.partition/-/lodash.partition-4.6.0.tgz", - "integrity": "sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - }, - "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", - "dev": true - }, - "nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "dev": true, - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - } - } - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "sinon": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.3", - "diff": "^3.5.0", - "lolex": "^4.2.0", - "nise": "^1.5.2", - "supports-color": "^5.5.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } -} From 0f78bc4986b1a6aa72846bfcf5fbac24ae21faca Mon Sep 17 00:00:00 2001 From: doug-martin Date: Wed, 25 Dec 2019 23:39:09 -0600 Subject: [PATCH 5/8] Added typescript examples --- .eslintrc.js | 3 +- .gitignore | 3 +- History.md | 4 +- README.md | 11 +- examples/example-runner/.eslintrc.js | 8 + examples/example-runner/bin/run-examples | 75 +- examples/example-runner/package.json | 5 +- examples/fast-csv-js/README.md | 6 +- examples/fast-csv-js/package.json | 9 +- examples/fast-csv-ts/.eslintrc.js | 8 + examples/fast-csv-ts/README.md | 172 ++++ examples/fast-csv-ts/assets/parse.csv | 6 + .../fast-csv-ts/assets/snake_case_users.csv | 10 + .../fast-csv-ts/examples/format.example.ts | 20 + examples/fast-csv-ts/examples/models/user.ts | 24 + .../fast-csv-ts/examples/parse.example.ts | 17 + ...arse_and_format_transform_async.example.ts | 64 ++ examples/fast-csv-ts/package.json | 18 + examples/fast-csv-ts/tsconfig.build.json | 7 + examples/fast-csv-ts/tsconfig.json | 4 + examples/formatting-js/README.md | 10 +- .../formatting-js/examples/append.example.js | 2 +- examples/formatting-js/examples/tmp/.gitkeep | 0 .../examples/write_to_path.example.js | 2 +- examples/formatting-js/package.json | 9 +- examples/formatting-ts/.eslintrc.js | 8 + examples/formatting-ts/README.md | 861 ++++++++++++++++++ .../formatting-ts/examples/append.example.ts | 68 ++ .../examples/delimiter_option.example.ts | 14 + .../examples/escape_option.example.ts | 15 + .../formatting-ts/examples/format.example.ts | 14 + .../examples/hash_array.example.ts | 30 + ...aders_auto_discovery_hash_array.example.ts | 30 + .../headers_auto_discovery_object.example.ts | 18 + .../headers_provided_array.example.ts | 18 + .../headers_provided_hash_array.example.ts | 30 + .../headers_provided_object.example.ts | 18 + ...s_provided_object_remove_column.example.ts | 18 + .../examples/quote_all_columns.example.ts | 18 + .../examples/quote_all_headers.example.ts | 18 + .../examples/quote_columns_array.example.ts | 18 + .../quote_columns_not_headers.example.ts | 18 + .../examples/quote_columns_object.example.ts | 18 + .../examples/quote_headers_array.example.ts | 18 + .../examples/quote_headers_object.example.ts | 18 + .../examples/quote_option.example.ts | 15 + .../quote_some_columns_and_headers.example.ts | 22 + .../examples/row_delimiter_option.example.ts | 12 + .../examples/transform.example.ts | 26 + .../examples/transform_async.example.ts | 30 + .../examples/transform_option.example.ts | 28 + .../formatting-ts/examples/write.example.ts | 13 + .../examples/write_to_buffer.example.ts | 13 + .../examples/write_to_path.example.ts | 22 + .../examples/write_to_stream.example.ts | 13 + .../examples/write_to_string.example.ts | 13 + .../write_to_string_no_headers.example.ts | 19 + .../write_to_string_transform.example.ts | 20 + examples/formatting-ts/package.json | 18 + examples/formatting-ts/tsconfig.build.json | 7 + examples/formatting-ts/tsconfig.json | 4 + examples/parsing-js/README.md | 6 +- examples/parsing-js/package.json | 3 +- examples/parsing-ts/.eslintrc.js | 8 + examples/parsing-ts/README.md | 655 +++++++++++++ .../parsing-ts/assets/snake_case_users.csv | 10 + .../examples/alternate_delimiter.example.ts | 17 + .../examples/custom_headers.example.ts | 17 + .../examples/first_row_as_headers.example.ts | 17 + .../examples/ignore_empty_rows.example.ts | 17 + .../examples/manual_write.example.ts | 14 + .../parsing-ts/examples/max_rows.example.ts | 31 + .../examples/parse_string.example.ts | 14 + examples/parsing-ts/examples/pipe.example.ts | 22 + .../examples/rename_headers.example.ts | 17 + .../parsing-ts/examples/skip_lines.example.ts | 26 + .../parsing-ts/examples/skip_rows.example.ts | 26 + .../examples/skipping_columns.example.ts | 17 + .../parsing-ts/examples/transform.example.ts | 34 + .../examples/transform_async.example.ts | 36 + .../examples/transform_headers.example.ts | 19 + .../parsing-ts/examples/validate.example.ts | 25 + .../examples/validate_async.example.ts | 27 + .../examples/validate_with_reason.example.ts | 33 + examples/parsing-ts/package.json | 18 + examples/parsing-ts/tsconfig.build.json | 7 + examples/parsing-ts/tsconfig.json | 4 + package-lock.json | 243 ++++- packages/fast-csv/README.md | 3 +- packages/format/README.md | 3 +- .../__tests__/CsvFormatterStream.spec.ts | 4 +- .../format/__tests__/FormatterOptions.spec.ts | 5 +- packages/format/__tests__/format.spec.ts | 2 +- .../formatter/FieldFormatter.spec.ts | 4 +- .../__tests__/formatter/RowFormatter.spec.ts | 53 +- .../format/__tests__/issues/issue252.spec.ts | 2 +- .../format/__tests__/issues/issue97.spec.ts | 4 +- packages/format/src/CsvFormatterStream.ts | 12 +- packages/format/src/FormatterOptions.ts | 12 +- .../format/src/formatter/FieldFormatter.ts | 7 +- packages/format/src/formatter/RowFormatter.ts | 44 +- packages/format/src/index.ts | 36 +- packages/format/src/types.ts | 15 +- packages/format/tsconfig.build.json | 7 +- packages/format/tsconfig.json | 2 +- packages/parse/README.md | 3 +- .../parse/__tests__/CsvParsingStream.spec.ts | 109 +-- .../__fixtures__/alternateEncoding.ts | 4 +- .../__fixtures__/duplicateHeaders.ts | 4 +- .../parse/__tests__/__fixtures__/emptyRows.ts | 4 +- .../__fixtures__/headerColumnMismatch.ts | 4 +- .../parse/__tests__/__fixtures__/helpers.ts | 32 +- .../parse/__tests__/__fixtures__/index.ts | 3 +- .../parse/__tests__/__fixtures__/malformed.ts | 3 +- .../__fixtures__/noHeadersAndQuotes.ts | 4 +- .../parse/__tests__/__fixtures__/skipLines.ts | 4 +- .../__tests__/__fixtures__/tmp/malformed.csv | 3 + .../__fixtures__/tmp/with_headers.csv | 10 + .../__tests__/__fixtures__/trailingComma.ts | 4 +- .../__tests__/__fixtures__/withHeaders.ts | 4 +- .../withHeadersAlternateDelimiter.ts | 35 +- .../withHeadersAndAlternateQuote.ts | 4 +- .../withHeadersAndMissingColumns.ts | 4 +- .../__fixtures__/withHeadersAndQuotes.ts | 4 +- .../withHeadersAndSkippedLines.ts | 4 +- packages/parse/__tests__/parse.spec.ts | 2 +- .../transforms/HeaderTransformer.spec.ts | 11 +- .../RowTransformerValidator.spec.ts | 26 +- packages/parse/src/CsvParserStream.ts | 14 +- packages/parse/src/index.ts | 21 +- .../parse/src/transforms/HeaderTransformer.ts | 16 +- .../src/transforms/RowTransformerValidator.ts | 34 +- packages/parse/src/types.ts | 30 +- tsconfig.build.json | 3 +- 134 files changed, 3689 insertions(+), 332 deletions(-) create mode 100644 examples/example-runner/.eslintrc.js create mode 100644 examples/fast-csv-ts/.eslintrc.js create mode 100644 examples/fast-csv-ts/README.md create mode 100644 examples/fast-csv-ts/assets/parse.csv create mode 100644 examples/fast-csv-ts/assets/snake_case_users.csv create mode 100644 examples/fast-csv-ts/examples/format.example.ts create mode 100644 examples/fast-csv-ts/examples/models/user.ts create mode 100644 examples/fast-csv-ts/examples/parse.example.ts create mode 100644 examples/fast-csv-ts/examples/parse_and_format_transform_async.example.ts create mode 100644 examples/fast-csv-ts/package.json create mode 100644 examples/fast-csv-ts/tsconfig.build.json create mode 100644 examples/fast-csv-ts/tsconfig.json delete mode 100644 examples/formatting-js/examples/tmp/.gitkeep create mode 100644 examples/formatting-ts/.eslintrc.js create mode 100644 examples/formatting-ts/README.md create mode 100644 examples/formatting-ts/examples/append.example.ts create mode 100644 examples/formatting-ts/examples/delimiter_option.example.ts create mode 100644 examples/formatting-ts/examples/escape_option.example.ts create mode 100644 examples/formatting-ts/examples/format.example.ts create mode 100644 examples/formatting-ts/examples/hash_array.example.ts create mode 100644 examples/formatting-ts/examples/headers_auto_discovery_hash_array.example.ts create mode 100644 examples/formatting-ts/examples/headers_auto_discovery_object.example.ts create mode 100644 examples/formatting-ts/examples/headers_provided_array.example.ts create mode 100644 examples/formatting-ts/examples/headers_provided_hash_array.example.ts create mode 100644 examples/formatting-ts/examples/headers_provided_object.example.ts create mode 100644 examples/formatting-ts/examples/headers_provided_object_remove_column.example.ts create mode 100644 examples/formatting-ts/examples/quote_all_columns.example.ts create mode 100644 examples/formatting-ts/examples/quote_all_headers.example.ts create mode 100644 examples/formatting-ts/examples/quote_columns_array.example.ts create mode 100644 examples/formatting-ts/examples/quote_columns_not_headers.example.ts create mode 100644 examples/formatting-ts/examples/quote_columns_object.example.ts create mode 100644 examples/formatting-ts/examples/quote_headers_array.example.ts create mode 100644 examples/formatting-ts/examples/quote_headers_object.example.ts create mode 100644 examples/formatting-ts/examples/quote_option.example.ts create mode 100644 examples/formatting-ts/examples/quote_some_columns_and_headers.example.ts create mode 100644 examples/formatting-ts/examples/row_delimiter_option.example.ts create mode 100644 examples/formatting-ts/examples/transform.example.ts create mode 100644 examples/formatting-ts/examples/transform_async.example.ts create mode 100644 examples/formatting-ts/examples/transform_option.example.ts create mode 100644 examples/formatting-ts/examples/write.example.ts create mode 100644 examples/formatting-ts/examples/write_to_buffer.example.ts create mode 100644 examples/formatting-ts/examples/write_to_path.example.ts create mode 100644 examples/formatting-ts/examples/write_to_stream.example.ts create mode 100644 examples/formatting-ts/examples/write_to_string.example.ts create mode 100644 examples/formatting-ts/examples/write_to_string_no_headers.example.ts create mode 100644 examples/formatting-ts/examples/write_to_string_transform.example.ts create mode 100644 examples/formatting-ts/package.json create mode 100644 examples/formatting-ts/tsconfig.build.json create mode 100644 examples/formatting-ts/tsconfig.json create mode 100644 examples/parsing-ts/.eslintrc.js create mode 100644 examples/parsing-ts/README.md create mode 100644 examples/parsing-ts/assets/snake_case_users.csv create mode 100644 examples/parsing-ts/examples/alternate_delimiter.example.ts create mode 100644 examples/parsing-ts/examples/custom_headers.example.ts create mode 100644 examples/parsing-ts/examples/first_row_as_headers.example.ts create mode 100644 examples/parsing-ts/examples/ignore_empty_rows.example.ts create mode 100644 examples/parsing-ts/examples/manual_write.example.ts create mode 100644 examples/parsing-ts/examples/max_rows.example.ts create mode 100644 examples/parsing-ts/examples/parse_string.example.ts create mode 100644 examples/parsing-ts/examples/pipe.example.ts create mode 100644 examples/parsing-ts/examples/rename_headers.example.ts create mode 100644 examples/parsing-ts/examples/skip_lines.example.ts create mode 100644 examples/parsing-ts/examples/skip_rows.example.ts create mode 100644 examples/parsing-ts/examples/skipping_columns.example.ts create mode 100644 examples/parsing-ts/examples/transform.example.ts create mode 100644 examples/parsing-ts/examples/transform_async.example.ts create mode 100644 examples/parsing-ts/examples/transform_headers.example.ts create mode 100644 examples/parsing-ts/examples/validate.example.ts create mode 100644 examples/parsing-ts/examples/validate_async.example.ts create mode 100644 examples/parsing-ts/examples/validate_with_reason.example.ts create mode 100644 examples/parsing-ts/package.json create mode 100644 examples/parsing-ts/tsconfig.build.json create mode 100644 examples/parsing-ts/tsconfig.json create mode 100644 packages/parse/__tests__/__fixtures__/tmp/malformed.csv create mode 100644 packages/parse/__tests__/__fixtures__/tmp/with_headers.csv diff --git a/.eslintrc.js b/.eslintrc.js index e6665952..ead7824f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -77,7 +77,8 @@ module.exports = { }, { "files": [ - "*.js" + "*.js", + "examples/example-runner/bin/run-examples" ], "rules": { "@typescript-eslint/explicit-function-return-type": "off", diff --git a/.gitignore b/.gitignore index 780a0a50..6fa84ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ benchmark/results .nyc_output build coverage -**/tmp/*.csv \ No newline at end of file +**/*.tmp.csv +**/*.tsbuildinfo \ No newline at end of file diff --git a/History.md b/History.md index 18afa570..d5a2d44c 100644 --- a/History.md +++ b/History.md @@ -4,7 +4,9 @@ * Moved to `lerna`. * Split `parse` and `format` packages * Added running examples and checking output as part of the tests -* Updated docs +* Updated docs for new directory layout +* Added typescript examples +* Added generics type support to format and parse streams # v3.7.0 diff --git a/README.md b/README.md index 3ea08289..d51e0958 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,14 @@ There are three packages published from this repo. ### Examples -* [`fast-csv` Examples](./examples/fast-csv-js/README.md) -* [`@fast-csv/format` Examples](./examples/formatting-js/README.md) -* [`@fast-csv/parse` Examples](./examples/parsing-js/README.md) +* JavaScript + * [`fast-csv`](./examples/fast-csv-js/README.md) + * [`@fast-csv/format`](./examples/formatting-js/README.md) + * [`@fast-csv/parse`](./examples/parsing-js/README.md) +* TypeScript + * [`fast-csv`](./examples/fast-csv-ts/README.md) + * [`@fast-csv/format`](./examples/formatting-ts/README.md) + * [`@fast-csv/parse`](./examples/parsing-ts/README.md) ### Migrating from older versions diff --git a/examples/example-runner/.eslintrc.js b/examples/example-runner/.eslintrc.js new file mode 100644 index 00000000..6571794b --- /dev/null +++ b/examples/example-runner/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + parserOptions: { + project: null, + }, + rules: { + 'no-console': 0, + }, +}; diff --git a/examples/example-runner/bin/run-examples b/examples/example-runner/bin/run-examples index d68e2912..ea846610 100755 --- a/examples/example-runner/bin/run-examples +++ b/examples/example-runner/bin/run-examples @@ -1,4 +1,5 @@ #!/usr/bin/env node +/* eslint-disable no-shadow */ const { EOL } = require('os'); const fs = require('fs'); @@ -6,13 +7,13 @@ const cp = require('child_process'); const path = require('path'); const globby = require('globby'); const diffDefault = require('jest-diff'); - -const exampleNameArg = process.argv[2]; +const yargs = require('yargs'); const OUTPUT_REGEXP = new RegExp(`\\/\\/ Output: *${EOL}`); +const OUTPUT_LINE_REGEXP = /^\/\/ /; -const getExampleFiles = async () => { - const files = await globby(path.resolve(process.cwd(), 'examples', '**', '*.example.js'), { stats: true }); +const getExampleFiles = async examplesDir => { + const files = await globby(path.resolve(process.cwd(), examplesDir, '**', '*.example.js'), { stats: true }); return files.reduce((map, f) => ({ ...map, ...{ [f.name.replace('.example.js', '')]: f.path } }), {}); }; @@ -28,8 +29,9 @@ const getExpectedOutput = examplePath => { return contents .slice(startIndex) .split(EOL) + .filter(l => OUTPUT_LINE_REGEXP.test(l)) .map(l => { - return l.replace(/\/\/ /, ''); + return l.replace(OUTPUT_LINE_REGEXP, ''); }) .join(EOL); }; @@ -61,21 +63,48 @@ const runExample = (exampleName, examples) => { }); }; -(async () => { - const examples = await getExampleFiles(); - if (!exampleNameArg) { - return printExamples(examples); - } - if (exampleNameArg === 'all') { - return Object.keys(examples).reduce(async (prev, exampleName) => { - await prev; - const output = await runExample(exampleName, examples); - checkOutput(exampleName, examples, output); - }, Promise.resolve()); - } - const output = await runExample(exampleNameArg, examples); - return checkOutput(exampleNameArg, examples, output); -})().catch(err => { - console.error(err.stack); - process.exit(1); -}); +yargs + .scriptName('example-runner') + .option('dir', { + alias: 'examplesDir', + default: 'examples', + describe: 'location of examples', + type: 'string', + }) + .command( + 'list', + 'list all examples', + yarg => yarg.option('examplesDir'), + async argv => { + const examples = await getExampleFiles(argv.examplesDir); + printExamples(examples); + }, + ) + .command( + 'all', + 'run all examples', + yarg => yarg.option('examplesDir'), + async argv => { + const examples = await getExampleFiles(argv.examplesDir); + return Object.keys(examples).reduce(async (prev, exampleName) => { + await prev; + const output = await runExample(exampleName, examples); + checkOutput(exampleName, examples, output); + }, Promise.resolve()); + }, + ) + .command( + 'run [example]', + 'run a specific example', + yargs => { + return yargs.option('examplesDir').positional('example', { + type: 'string', + describe: 'the example to run', + }); + }, + async argv => { + const examples = await getExampleFiles(argv.examplesDir); + const output = await runExample(argv.example, examples); + await checkOutput(argv.example, examples, output); + }, + ).argv; diff --git a/examples/example-runner/package.json b/examples/example-runner/package.json index c0ffe38a..92d0bf6a 100644 --- a/examples/example-runner/package.json +++ b/examples/example-runner/package.json @@ -8,7 +8,10 @@ "run-examples": "./bin/run-examples" }, "dependencies": { + "@types/yargs": "^13.0.4", "globby": "^10.0.1", - "jest-diff": "^24.9.0" + "jest-diff": "^24.9.0", + "typescript": "^3.7.3", + "yargs": "^15.0.2" } } diff --git a/examples/fast-csv-js/README.md b/examples/fast-csv-js/README.md index 60217ff5..06e65c7d 100644 --- a/examples/fast-csv-js/README.md +++ b/examples/fast-csv-js/README.md @@ -1,4 +1,4 @@ -`fast-csv` examples. +`fast-csv` javascript examples. ## Usage @@ -11,10 +11,10 @@ npm run all-examples To see a list of all available examples ```sh -npm run example +npm run list ``` -To run a sepcific example +To run a specific example ```sh npm run example -- {example_name} diff --git a/examples/fast-csv-js/package.json b/examples/fast-csv-js/package.json index bad94932..00e9d196 100644 --- a/examples/fast-csv-js/package.json +++ b/examples/fast-csv-js/package.json @@ -2,12 +2,13 @@ "name": "fast-csv-js-examples", "private": true, "description": "fast-csv examples", + "scripts": { + "list": "run-examples list", + "all-examples": "run-examples all", + "example": "run-examples run" + }, "dependencies": { "example-runner": "^4.0.0", "fast-csv": "^4.0.0" - }, - "scripts": { - "all-examples": "run-examples all", - "example": "run-examples" } } diff --git a/examples/fast-csv-ts/.eslintrc.js b/examples/fast-csv-ts/.eslintrc.js new file mode 100644 index 00000000..fcbdb09f --- /dev/null +++ b/examples/fast-csv-ts/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + parserOptions: { + project: "./tsconfig.build.json" + }, + rules: { + 'no-console': 0, + }, +}; \ No newline at end of file diff --git a/examples/fast-csv-ts/README.md b/examples/fast-csv-ts/README.md new file mode 100644 index 00000000..4a320df4 --- /dev/null +++ b/examples/fast-csv-ts/README.md @@ -0,0 +1,172 @@ +`fast-csv` typescript examples. + +## Usage + +```sh +npm run build +``` + +To run all examples + +```sh +npm run all-examples +``` + +To see a list of all available examples + +```sh +npm run example +``` + +To run a specific example + +```sh +npm run example -- {example_name} +``` + +## Examples + +* [Format](#format) +* [Parse](#parse) +* [Parse And Format](#parse-and-format) + + +### Format + +[`examples/format.example.ts`](./examples/format.example.ts) +```sh +npm run example -- format +``` +```typescript +import * as csv from 'fast-csv'; + +const csvStream = csv.format({ headers: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'row1-col1', header2: 'row1-col2' }); +csvStream.write({ header1: 'row2-col1', header2: 'row2-col2' }); +csvStream.write({ header1: 'row3-col1', header2: 'row3-col2' }); +csvStream.write({ header1: 'row4-col1', header2: 'row4-col2' }); +csvStream.write({ header1: 'row5-col1', header2: 'row5-col2' }); +csvStream.end(); +``` + +Expected output + +``` +header1,header2 +row1-col1,row1-col2 +row2-col1,row2-col2 +row3-col1,row3-col2 +row4-col1,row4-col2 +``` +--- + + +### Parse + +[`examples/parse.example.ts`](./examples/parse.example.ts) +```sh +npm run example -- parse +``` +```typescript +import * as fs from 'fs'; +import * as path from 'path'; +import * as csv from 'fast-csv'; + +fs.createReadStream(path.resolve(__dirname, 'assets', 'parse.csv')) + .pipe(csv.parse({ headers: true })) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); +``` + +Expected output + +``` +{ header1: 'row1-col1', header2: 'row1-col2' } +{ header1: 'row2-col1', header2: 'row2-col2' } +{ header1: 'row3-col1', header2: 'row3-col2' } +{ header1: 'row4-col1', header2: 'row4-col2' } +{ header1: 'row5-col1', header2: 'row5-col2' } +Parsed 5 rows +``` +--- + + +### Parse And Format + +[`examples/parse_and_format_transform_async.example.ts`](./examples/parse_and_format_transform_async.example.ts) +```sh +npm run example -- parse_and_format_transform_async +``` +```typescript +import * as fs from 'fs'; +import * as path from 'path'; +import * as csv from 'fast-csv'; +import { User } from './models/user'; + +interface UserCsvRow { + id: string; + first_name: string; + last_name: string; + address: string; +} + +interface UserDetailsRow { + id: number; + firstName: string; + lastName: string; + address: string; + // properties from user + isVerified: boolean; + hasLoggedIn: boolean; + age: number; +} + +fs.createReadStream(path.resolve(__dirname, 'assets', 'snake_case_users.csv')) + .pipe(csv.parse({ headers: true })) + // pipe the parsed input into a csv formatter + .pipe( + csv.format({ headers: true }), + ) + // Using the transform function from the formatting stream + .transform((row, next): void => { + User.findById(+row.id, (err, user) => { + if (err) { + return next(err); + } + if (!user) { + return next(err); + } + return next(null, { + id: user.id, + firstName: row.first_name, + lastName: row.last_name, + address: row.address, + // properties from user + isVerified: user.isVerified, + hasLoggedIn: user.hasLoggedIn, + age: user.age, + }); + }); + }) + .pipe(process.stdout) + .on('end', process.exit); +``` + +Expected output + +``` +id,firstName,lastName,address,isVerified,hasLoggedIn,age +1,Bob,Yukon,1111 State St. Yukon AK,false,false,11 +2,Sally,Yukon,1111 State St. Yukon AK,true,false,12 +3,Bobby,Yukon,1111 State St. Yukon AK,false,false,13 +4,Jane,Yukon,1111 State St. Yukon AK,true,true,14 +5,Dick,Yukon,1111 State St. Yukon AK,false,false,15 +6,John,Doe,1112 State St. Yukon AK,true,false,16 +7,Jane,Doe,1113 State St. Yukon AK,false,false,17 +8,Billy,Doe,1112 State St. Yukon AK,true,true,18 +9,Edith,Doe,1112 State St. Yukon AK,false,false,19 +``` \ No newline at end of file diff --git a/examples/fast-csv-ts/assets/parse.csv b/examples/fast-csv-ts/assets/parse.csv new file mode 100644 index 00000000..667fa402 --- /dev/null +++ b/examples/fast-csv-ts/assets/parse.csv @@ -0,0 +1,6 @@ +header1,header2 +row1-col1,row1-col2 +row2-col1,row2-col2 +row3-col1,row3-col2 +row4-col1,row4-col2 +row5-col1,row5-col2 \ No newline at end of file diff --git a/examples/fast-csv-ts/assets/snake_case_users.csv b/examples/fast-csv-ts/assets/snake_case_users.csv new file mode 100644 index 00000000..68d197a2 --- /dev/null +++ b/examples/fast-csv-ts/assets/snake_case_users.csv @@ -0,0 +1,10 @@ +id,first_name,last_name,address +1,Bob,Yukon,1111 State St. Yukon AK +2,Sally,Yukon,1111 State St. Yukon AK +3,Bobby,Yukon,1111 State St. Yukon AK +4,Jane,Yukon,1111 State St. Yukon AK +5,Dick,Yukon,1111 State St. Yukon AK +6,John,Doe,1112 State St. Yukon AK +7,Jane,Doe,1113 State St. Yukon AK +8,Billy,Doe,1112 State St. Yukon AK +9,Edith,Doe,1112 State St. Yukon AK \ No newline at end of file diff --git a/examples/fast-csv-ts/examples/format.example.ts b/examples/fast-csv-ts/examples/format.example.ts new file mode 100644 index 00000000..b54ca3db --- /dev/null +++ b/examples/fast-csv-ts/examples/format.example.ts @@ -0,0 +1,20 @@ +import * as csv from 'fast-csv'; + +const csvStream = csv.format({ headers: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'row1-col1', header2: 'row1-col2' }); +csvStream.write({ header1: 'row2-col1', header2: 'row2-col2' }); +csvStream.write({ header1: 'row3-col1', header2: 'row3-col2' }); +csvStream.write({ header1: 'row4-col1', header2: 'row4-col2' }); +csvStream.write({ header1: 'row5-col1', header2: 'row5-col2' }); +csvStream.end(); + +// Output: +// header1,header2 +// row1-col1,row1-col2 +// row2-col1,row2-col2 +// row3-col1,row3-col2 +// row4-col1,row4-col2 +// row5-col1,row5-col2 diff --git a/examples/fast-csv-ts/examples/models/user.ts b/examples/fast-csv-ts/examples/models/user.ts new file mode 100644 index 00000000..f1787c85 --- /dev/null +++ b/examples/fast-csv-ts/examples/models/user.ts @@ -0,0 +1,24 @@ +export type UserCallback = (err: Error | null, user?: User) => void; + +export class User { + public readonly id: number; + + public readonly isVerified: boolean; + + public readonly hasLoggedIn: boolean; + + public readonly age: number; + + static findById(id: number, cb: UserCallback): void { + setImmediate(() => { + cb(null, new User(id)); + }); + } + + constructor(id: number) { + this.id = id; + this.isVerified = id % 2 === 0; + this.hasLoggedIn = this.isVerified ? id % 4 === 0 : false; + this.age = +id + 10; + } +} diff --git a/examples/fast-csv-ts/examples/parse.example.ts b/examples/fast-csv-ts/examples/parse.example.ts new file mode 100644 index 00000000..8f2cb4b4 --- /dev/null +++ b/examples/fast-csv-ts/examples/parse.example.ts @@ -0,0 +1,17 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as csv from 'fast-csv'; + +fs.createReadStream(path.resolve(__dirname, '..', 'assets', 'parse.csv')) + .pipe(csv.parse({ headers: true })) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +// Output: +// { header1: 'row1-col1', header2: 'row1-col2' } +// { header1: 'row2-col1', header2: 'row2-col2' } +// { header1: 'row3-col1', header2: 'row3-col2' } +// { header1: 'row4-col1', header2: 'row4-col2' } +// { header1: 'row5-col1', header2: 'row5-col2' } +// Parsed 5 rows diff --git a/examples/fast-csv-ts/examples/parse_and_format_transform_async.example.ts b/examples/fast-csv-ts/examples/parse_and_format_transform_async.example.ts new file mode 100644 index 00000000..2a1f587d --- /dev/null +++ b/examples/fast-csv-ts/examples/parse_and_format_transform_async.example.ts @@ -0,0 +1,64 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as csv from 'fast-csv'; +import { User } from './models/user'; + +interface UserCsvRow { + id: string; + first_name: string; + last_name: string; + address: string; +} + +interface UserDetailsRow { + id: number; + firstName: string; + lastName: string; + address: string; + // properties from user + isVerified: boolean; + hasLoggedIn: boolean; + age: number; +} + +fs.createReadStream(path.resolve(__dirname, '..', 'assets', 'snake_case_users.csv')) + .pipe(csv.parse({ headers: true })) + // pipe the parsed input into a csv formatter + .pipe( + csv.format({ headers: true }), + ) + // Using the transform function from the formatting stream + .transform((row, next): void => { + User.findById(+row.id, (err, user) => { + if (err) { + return next(err); + } + if (!user) { + return next(err); + } + return next(null, { + id: user.id, + firstName: row.first_name, + lastName: row.last_name, + address: row.address, + // properties from user + isVerified: user.isVerified, + hasLoggedIn: user.hasLoggedIn, + age: user.age, + }); + }); + }) + .pipe(process.stdout) + .on('end', process.exit); + +// Output: +// id,firstName,lastName,address,isVerified,hasLoggedIn,age +// 1,Bob,Yukon,1111 State St. Yukon AK,false,false,11 +// 2,Sally,Yukon,1111 State St. Yukon AK,true,false,12 +// 3,Bobby,Yukon,1111 State St. Yukon AK,false,false,13 +// 4,Jane,Yukon,1111 State St. Yukon AK,true,true,14 +// 5,Dick,Yukon,1111 State St. Yukon AK,false,false,15 +// 6,John,Doe,1112 State St. Yukon AK,true,false,16 +// 7,Jane,Doe,1113 State St. Yukon AK,false,false,17 +// 8,Billy,Doe,1112 State St. Yukon AK,true,true,18 +// 9,Edith,Doe,1112 State St. Yukon AK,false,false,19 diff --git a/examples/fast-csv-ts/package.json b/examples/fast-csv-ts/package.json new file mode 100644 index 00000000..0ff65e06 --- /dev/null +++ b/examples/fast-csv-ts/package.json @@ -0,0 +1,18 @@ +{ + "name": "fast-csv-ts-examples", + "private": true, + "description": "fast-csv examples", + "scripts": { + "list": "run-examples --dir=build list", + "all-examples": "run-examples --dir=build all", + "example": "run-examples --dir=build run", + "build": "npm run clean && npm run compile", + "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo", + "compile": "tsc -p tsconfig.build.json" + }, + "dependencies": { + "example-runner": "^4.0.0", + "fast-csv": "^4.0.0", + "typescript": "^3.7.3" + } +} diff --git a/examples/fast-csv-ts/tsconfig.build.json b/examples/fast-csv-ts/tsconfig.build.json new file mode 100644 index 00000000..ea5a1715 --- /dev/null +++ b/examples/fast-csv-ts/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./build", + "rootDir": "./examples" + } +} diff --git a/examples/fast-csv-ts/tsconfig.json b/examples/fast-csv-ts/tsconfig.json new file mode 100644 index 00000000..50217932 --- /dev/null +++ b/examples/fast-csv-ts/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./examples"] +} diff --git a/examples/formatting-js/README.md b/examples/formatting-js/README.md index 2832a8d3..f9d78d58 100644 --- a/examples/formatting-js/README.md +++ b/examples/formatting-js/README.md @@ -1,4 +1,4 @@ -`@fast-csv/format` formatting examples. +`@fast-csv/format` javascript formatting examples. ## Usage @@ -11,10 +11,10 @@ npm run all-examples To see a list of all available examples ```sh -npm run example +npm run list ``` -To run a sepcific example +To run a specific example ```sh npm run example -- {example_name} @@ -419,10 +419,10 @@ Expected output Setting `quoteColumns` to a `boolean[]` will quote the columns thats are set to true at each index in the array. -[`examples/quote_all_columns_array.example.js`](./examples/quote_all_columns_array.example.js) +[`examples/quote_columns_array.example.js`](./examples/quote_columns_array.example.js) ```sh -npm run example -- quote_all_columns_array +npm run example -- quote_columns_array ``` ```javascript diff --git a/examples/formatting-js/examples/append.example.js b/examples/formatting-js/examples/append.example.js index 1aacea84..aef28bea 100644 --- a/examples/formatting-js/examples/append.example.js +++ b/examples/formatting-js/examples/append.example.js @@ -35,7 +35,7 @@ const readFile = filePath => { }); }; -const csvFilePath = path.resolve(__dirname, 'tmp', 'append.csv'); +const csvFilePath = path.resolve(__dirname, 'append.tmp.csv'); // 1. create the csv createCsv(csvFilePath, [ diff --git a/examples/formatting-js/examples/tmp/.gitkeep b/examples/formatting-js/examples/tmp/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/formatting-js/examples/write_to_path.example.js b/examples/formatting-js/examples/write_to_path.example.js index 77e19bff..3de9ed52 100644 --- a/examples/formatting-js/examples/write_to_path.example.js +++ b/examples/formatting-js/examples/write_to_path.example.js @@ -7,7 +7,7 @@ const rows = [ ['a1', 'b1'], ['a2', 'b2'], ]; -const filePath = path.resolve(__dirname, 'tmp', 'tmp.csv'); +const filePath = path.resolve(__dirname, 'write_to_path.tmp.csv'); csv.writeToPath(filePath, rows) .on('error', err => console.error(err)) .on('finish', () => { diff --git a/examples/formatting-js/package.json b/examples/formatting-js/package.json index 215bcc7c..309d708b 100644 --- a/examples/formatting-js/package.json +++ b/examples/formatting-js/package.json @@ -2,12 +2,13 @@ "name": "@fast-csv/format-js-examples", "private": true, "description": "fast-csv formatting examples", + "scripts": { + "list": "run-examples list", + "all-examples": "run-examples all", + "example": "run-examples run" + }, "dependencies": { "example-runner": "^4.0.0", "@fast-csv/format": "^4.0.0" - }, - "scripts": { - "all-examples": "run-examples all", - "example": "run-examples" } } diff --git a/examples/formatting-ts/.eslintrc.js b/examples/formatting-ts/.eslintrc.js new file mode 100644 index 00000000..fcbdb09f --- /dev/null +++ b/examples/formatting-ts/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + parserOptions: { + project: "./tsconfig.build.json" + }, + rules: { + 'no-console': 0, + }, +}; \ No newline at end of file diff --git a/examples/formatting-ts/README.md b/examples/formatting-ts/README.md new file mode 100644 index 00000000..efb511f4 --- /dev/null +++ b/examples/formatting-ts/README.md @@ -0,0 +1,861 @@ +`@fast-csv/format` typescript formatting examples. + +## Usage + +```sh +npm run build +``` + +To run all examples + +```sh +npm run all-examples +``` + +To see a list of all available examples + +```sh +npm run list +``` + +To run a specific example + +```sh +npm run example -- {example_name} +``` + +## Examples + +* [Alternate `delimiter`](#examples-alternate-delimiter) +* [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) +* [Appending To A CSV](#examples-appending) + + +### Alternate `delimiter` + +You can change the default delimiter `,` by specifying the `delimiter` option + +[`examples/delimiter_option.example.ts`](./examples/delimiter_option.example.ts) + +```sh +npm run example -- delimiter_option +``` + +```typescript +import { format } from '@fast-csv/format'; + +const stream = format({ delimiter: '\t' }); +stream.pipe(process.stdout); + +stream.write(['a', 'b']); +stream.write(['a1', 'b1']); +stream.write(['a2', 'b2']); +stream.end(); +``` + +Expected output + +``` +a\tb +a1\tb1 +a2\tb2 +``` + +--- + +### Alternate `rowDelimiter` + +You can change the default row delimiter `\n` by specifying the `rowDelimiter` option. + +[`examples/row_delimiter_option.example.ts`](./examples/row_delimiter_option.example.ts) + +```sh +npm run example -- row_delimiter_option +``` + +```typescript +import { format } from '@fast-csv/format'; + +const stream = format({ rowDelimiter: '||' }); +stream.pipe(process.stdout); + +stream.write(['a', 'b']); +stream.write(['a1', 'b1']); +stream.write(['a2', 'b2']); +stream.end(); +``` + +Expected output + +``` +a,b +a1,b1 +a2,b2 +``` + +--- + +### Alternate `quote` + +You change change the default quote `"` option by specifying the `quote` option. + +[`examples/quote_option.example.ts`](./examples/quote_option.example.ts) + +```sh +npm run example -- quote_option +``` + +```typescript +import { format } from '@fast-csv/format'; + +const stream = format({ quote: "'" }); +stream.pipe(process.stdout); + +// each field will be quoted because it contains a delimiter +stream.write(['a,a', 'b,b']); +stream.write(['a1,a1', 'b1,b1']); +stream.write(['a2,a2', 'b2,b2']); +stream.end(); +``` + +Expected output + +``` +'a,a','b,b' +'a1,a1','b1,b1' +'a2,a2','b2,b2' +``` + +--- + +### Alternate `escape` + +You change change the default escape `"` option by specifying the `escpae` option. + +[`examples/escape_option.example.ts`](./examples/escape_option.example.ts) + +```sh +npm run example -- escape_option +``` + +```typescript +import { format } from '@fast-csv/format'; + +const stream = format({ escape: "'" }); +stream.pipe(process.stdout); + +// wrap each field in a quote so it is escaped and quoted +stream.write(['"a"', '"b"']); +stream.write(['"a1"', '"b1"']); +stream.write(['"a2"', '"b2"']); +stream.end(); +``` + +Expected output + +``` +"'"a'"","'"b'"" +"'"a1'"","'"b1'"" +"'"a2'"","'"b2'"" +``` + +--- + + +### 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. + + + +[`examples/headers_auto_discovery_object.example.ts`](./examples/headers_auto_discovery_object.example.ts) + +In this example the headers are auto-discovered from the objects passed in. + +```sh +npm run example -- headers_auto_discovery_object +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = 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 +``` + + + +[`examples/headers_auto_discovery_hash_array.example.ts`](./examples/headers_auto_discovery_hash_array.example.ts) + +In this example the headers are auto-discovered from the hash arrays passed in. + +```sh +npm run example -- headers_auto_discovery_hash_array +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = 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. + + + +[`examples/headers_provided_array.example.ts`](./examples/headers_provided_array.example.ts) + +In this example a custom set of headers is provided for rows that are arrays. + +```sh +npm run example -- headers_provided_array +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = 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 +``` + + + +[`examples/headers_provided_hash_array.example.ts`](./examples/headers_provided_hash_array.example.ts) + +In this example the headers are overridden with a custom set of headers + +```sh +npm run example -- headers_provided_hash_array +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = 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 +``` + + +[`examples/headers_provided_object.example.ts`](./examples/headers_provided_object.example.ts) + +In this example the columns are reordered. + +```sh +npm run example -- headers_provided_object +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = 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 +``` + + +[`examples/headers_provided_object_remove_column.example.ts`](./examples/headers_provided_object_remove_column.example.ts) + +In this example the one of the columns is removed. + +```sh +npm run example -- headers_provided_object_remove_column +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = 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 +``` + +--- + +### `quoteColumns` + +Sometimes you may need to quote columns is certain ways in order to meet certain requirements. `fast-csv` can quote columns and headers almost anyway you may need. + +Setting `quoteColumns` to true will by default quote all columns and headers. + +[`examples/quote_all_columns.example.ts`](./examples/quote_all_columns.example.ts) + +```sh +npm run example -- quote_all_columns +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteColumns: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output + +``` +"header1","header2" +"value1a","value2a" +"value1a","value2a" +"value1a","value2a" +"value1a","value2a" +``` + +Setting `quoteColumns` to a `boolean[]` will quote the columns thats are set to true at each index in the array. + +[`examples/quote_columns_array.example.ts`](./examples/quote_columns_array.example.ts) + +```sh +npm run example -- quote_columns_array +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: ['header1', 'header2'], quoteColumns: [false, true] }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output + +``` +header1,"header2" +value1a,"value2a" +value1a,"value2a" +value1a,"value2a" +value1a,"value2a" +``` + +Setting `quoteColumns` to a `{[string]: boolean}` will quote the columns that are in the object with a value of true + +[`examples/quote_columns_object.example.ts`](./examples/quote_columns_object.example.ts) + +```sh +npm run example -- quote_columns_object +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteColumns: { header2: true } }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output + +``` +header1,"header2" +value1a,"value2a" +value1a,"value2a" +value1a,"value2a" +value1a,"value2a" +``` + +If you need to quote columns and not headers you can set `quoteHeaders` to `null` or using the set it to a different configuration. + +[`examples/quote_columns_not_headers.example.ts`](./examples/quote_columns_not_headers.example.ts) + +```sh +npm run example -- quote_columns_not_headers +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteColumns: { header2: true }, quoteHeaders: false }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +``` + +Expected output. + +``` +header1,header2 +value1a,"value2a" +value1a,"value2a" +value1a,"value2a" +value1a,"value2a" +``` + +--- + +### `quoteHeaders` + +The `quoteHeaders` option uses the same types as `quoteColumns`. + +[`examples/quote_all_headers.example.ts`](./examples/quote_all_headers.example.ts) + +```sh +npm run example -- quote_all_headers +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteHeaders: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output: + +``` +"header1","header2" +value1a,value2a +value1a,value2a +value1a,value2a +value1a,value2a +``` + +[`examples/quote_headers_array.example.ts`](./examples/quote_headers_array.example.ts) + +```sh +npm run example -- quote_headers_array +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: ['header1', 'header2'], quoteHeaders: [false, true] }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output: +``` +header1,"header2" +value1a,value2a +value1a,value2a +value1a,value2a +value1a,value2a +``` + +[`examples/quote_headers_object.example.ts`](./examples/quote_headers_object.example.ts) + +```sh +npm run example -- quote_headers_object +``` + +```typescript +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteHeaders: { header2: true } }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output: +``` +header1,"header2" +value1a,value2a +value1a,value2a +value1a,value2a +value1a,value2a +``` + +--- + +### Transforming Rows + +You can transform rows by using the `.transform` method. + +[`examples/transform.example.ts`](./examples/transform.example.ts) + +```sh +npm run example -- transform +``` + +```typescript +import { format } from '@fast-csv/format'; + +interface CsvRow { + header1: string; + header2: string; +} + +const csvStream = format({ headers: true }).transform((row: CsvRow) => ({ + header1: row.header1.toUpperCase(), + header2: row.header2.toUpperCase(), +})); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output + +``` +header1,header2 +VALUE1A,VALUE2A +VALUE1A,VALUE2A +VALUE1A,VALUE2A +VALUE1A,VALUE2A +``` + +You can also specify your transform method as an option. + +[`examples/transform_option.example.ts`](./examples/transform_option.example.ts) + +```sh +npm run example -- transform_option +``` + +```typescript +import { format } from '@fast-csv/format'; + +interface CsvRow { + header1: string; + header2: string; +} + +const transform = (row: CsvRow): CsvRow => ({ + header1: row.header1.toUpperCase(), + header2: row.header2.toUpperCase(), +}); + +const csvStream = format({ headers: true, transform }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output + +``` +header1,header2 +VALUE1A,VALUE2A +VALUE1A,VALUE2A +VALUE1A,VALUE2A +VALUE1A,VALUE2A +``` + +Transform can also be async by accepting a callback. + +[`examples/transform_async.example.ts`](./examples/transform_async.example.ts) + +```sh +npm run example -- transform_async +``` + +```typescript +import { format } from '@fast-csv/format'; + +interface CsvRow { + header1: string; + header2: string; +} + +const csvStream = format({ headers: true }).transform((row, cb) => { + setImmediate(() => + cb(null, { + header1: row.header1.toUpperCase(), + header2: row.header2.toUpperCase(), + }), + ); +}); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); +``` + +Expected output + +``` +header1,header2 +VALUE1A,VALUE2A +VALUE1A,VALUE2A +VALUE1A,VALUE2A +VALUE1A,VALUE2A +``` + +--- + +### Appending To A CSV + +[`examples/append.example.ts`](./examples/append.example.ts) + +```sh +npm run example -- append +``` + +In this example a new csv is created then appended to. + +```typescript +import * as path from 'path'; +import * as fs from 'fs'; +import { FormatterOptionsArgs, Row, writeToStream } from '@fast-csv/format'; + +const write = (stream: NodeJS.WritableStream, rows: Row[], options: FormatterOptionsArgs): Promise => { + return new Promise((res, rej) => { + writeToStream(stream, rows, options) + .on('error', err => rej(err)) + .on('finish', () => res()); + }); +}; + +// create a new csv +const createCsv = (filePath: string, rows: Row[]): Promise => { + const csvFile = fs.createWriteStream(filePath); + return write(csvFile, rows, { headers: true, includeEndRowDelimiter: true }); +}; + +// append the rows to the csv +const appendToCsv = (filePath: string, rows: Row[] = []): Promise => { + const csvFile = fs.createWriteStream(filePath, { flags: 'a' }); + // notice how headers are set to false + return write(csvFile, rows, { headers: false }); +}; + +// read the file +const readFile = (filePath: string): Promise => { + return new Promise((res, rej) => { + fs.readFile(filePath, (err, contents) => { + if (err) { + return rej(err); + } + return res(contents); + }); + }); +}; + +const csvFilePath = path.resolve(__dirname, 'tmp', 'append.csv'); + +// 1. create the csv +createCsv(csvFilePath, [ + { a: 'a1', b: 'b1', c: 'c1' }, + { a: 'a2', b: 'b2', c: 'c2' }, + { a: 'a3', b: 'b3', c: 'c3' }, +]) + // 2. append to the csv + .then(() => + appendToCsv(csvFilePath, [ + { a: 'a4', b: 'b4', c: 'c4' }, + { a: 'a5', b: 'b5', c: 'c5' }, + { a: 'a6', b: 'b6', c: 'c6' }, + ]), + ) + .then(() => readFile(csvFilePath)) + .then(contents => console.log(`${contents}`)) + .catch(err => { + console.error(err.stack); + process.exit(1); + }); +``` + +Expected output + +``` +a,b,c +a1,b1,c1 +a2,b2,c2 +a3,b3,c3 +a4,b4,c4 +a5,b5,c5 +a6,b6,c6 +``` \ No newline at end of file diff --git a/examples/formatting-ts/examples/append.example.ts b/examples/formatting-ts/examples/append.example.ts new file mode 100644 index 00000000..897a2307 --- /dev/null +++ b/examples/formatting-ts/examples/append.example.ts @@ -0,0 +1,68 @@ +import * as path from 'path'; +import * as fs from 'fs'; +import { FormatterOptionsArgs, Row, writeToStream } from '@fast-csv/format'; + +const write = (stream: NodeJS.WritableStream, rows: Row[], options: FormatterOptionsArgs): Promise => { + return new Promise((res, rej) => { + writeToStream(stream, rows, options) + .on('error', err => rej(err)) + .on('finish', () => res()); + }); +}; + +// create a new csv +const createCsv = (filePath: string, rows: Row[]): Promise => { + const csvFile = fs.createWriteStream(filePath); + return write(csvFile, rows, { headers: true, includeEndRowDelimiter: true }); +}; + +// append the rows to the csv +const appendToCsv = (filePath: string, rows: Row[] = []): Promise => { + const csvFile = fs.createWriteStream(filePath, { flags: 'a' }); + // notice how headers are set to false + return write(csvFile, rows, { headers: false }); +}; + +// read the file +const readFile = (filePath: string): Promise => { + return new Promise((res, rej) => { + fs.readFile(filePath, (err, contents) => { + if (err) { + return rej(err); + } + return res(contents); + }); + }); +}; + +const csvFilePath = path.resolve(__dirname, 'append.csv'); + +// 1. create the csv +createCsv(csvFilePath, [ + { a: 'a1', b: 'b1', c: 'c1' }, + { a: 'a2', b: 'b2', c: 'c2' }, + { a: 'a3', b: 'b3', c: 'c3' }, +]) + // 2. append to the csv + .then(() => + appendToCsv(csvFilePath, [ + { a: 'a4', b: 'b4', c: 'c4' }, + { a: 'a5', b: 'b5', c: 'c5' }, + { a: 'a6', b: 'b6', c: 'c6' }, + ]), + ) + .then(() => readFile(csvFilePath)) + .then(contents => console.log(`${contents}`)) + .catch(err => { + console.error(err.stack); + process.exit(1); + }); + +// Output: +// a,b,c +// a1,b1,c1 +// a2,b2,c2 +// a3,b3,c3 +// a4,b4,c4 +// a5,b5,c5 +// a6,b6,c6 diff --git a/examples/formatting-ts/examples/delimiter_option.example.ts b/examples/formatting-ts/examples/delimiter_option.example.ts new file mode 100644 index 00000000..83d1c483 --- /dev/null +++ b/examples/formatting-ts/examples/delimiter_option.example.ts @@ -0,0 +1,14 @@ +import { format } from '@fast-csv/format'; + +const stream = format({ delimiter: '\t' }); +stream.pipe(process.stdout); + +stream.write(['a', 'b']); +stream.write(['a1', 'b1']); +stream.write(['a2', 'b2']); +stream.end(); + +// Output: +// a b +// a1 b1 +// a2 b2 diff --git a/examples/formatting-ts/examples/escape_option.example.ts b/examples/formatting-ts/examples/escape_option.example.ts new file mode 100644 index 00000000..a8ab965c --- /dev/null +++ b/examples/formatting-ts/examples/escape_option.example.ts @@ -0,0 +1,15 @@ +import { format } from '@fast-csv/format'; + +const stream = format({ escape: "'" }); +stream.pipe(process.stdout); + +// wrap each field in a quote so it is escaped and quoted +stream.write(['"a"', '"b"']); +stream.write(['"a1"', '"b1"']); +stream.write(['"a2"', '"b2"']); +stream.end(); + +// Output: +// "'"a'"","'"b'"" +// "'"a1'"","'"b1'"" +// "'"a2'"","'"b2'"" diff --git a/examples/formatting-ts/examples/format.example.ts b/examples/formatting-ts/examples/format.example.ts new file mode 100644 index 00000000..b216166b --- /dev/null +++ b/examples/formatting-ts/examples/format.example.ts @@ -0,0 +1,14 @@ +import { format } from '@fast-csv/format'; + +const stream = format(); +stream.pipe(process.stdout); + +stream.write(['a', 'b']); +stream.write(['a1', 'b1']); +stream.write(['a2', 'b2']); +stream.end(); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/hash_array.example.ts b/examples/formatting-ts/examples/hash_array.example.ts new file mode 100644 index 00000000..ada99a40 --- /dev/null +++ b/examples/formatting-ts/examples/hash_array.example.ts @@ -0,0 +1,30 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write([ + ['header', 'value1a'], + ['header2', 'value2a'], +]); +csvStream.write([ + ['header', 'value1b'], + ['header2', 'value2b'], +]); +csvStream.write([ + ['header', 'value1c'], + ['header2', 'value2c'], +]); +csvStream.write([ + ['header', 'value1d'], + ['header2', 'value2d'], +]); +csvStream.end(); + +// Output: +// header,header2 +// value1a,value2a +// value1b,value2b +// value1c,value2c +// value1d,value2d diff --git a/examples/formatting-ts/examples/headers_auto_discovery_hash_array.example.ts b/examples/formatting-ts/examples/headers_auto_discovery_hash_array.example.ts new file mode 100644 index 00000000..2c9ab6c9 --- /dev/null +++ b/examples/formatting-ts/examples/headers_auto_discovery_hash_array.example.ts @@ -0,0 +1,30 @@ +import { format } from '@fast-csv/format'; + +const csvStream = 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(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting-ts/examples/headers_auto_discovery_object.example.ts b/examples/formatting-ts/examples/headers_auto_discovery_object.example.ts new file mode 100644 index 00000000..b873dd2d --- /dev/null +++ b/examples/formatting-ts/examples/headers_auto_discovery_object.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = 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(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting-ts/examples/headers_provided_array.example.ts b/examples/formatting-ts/examples/headers_provided_array.example.ts new file mode 100644 index 00000000..79f0e710 --- /dev/null +++ b/examples/formatting-ts/examples/headers_provided_array.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = 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(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting-ts/examples/headers_provided_hash_array.example.ts b/examples/formatting-ts/examples/headers_provided_hash_array.example.ts new file mode 100644 index 00000000..44dbb263 --- /dev/null +++ b/examples/formatting-ts/examples/headers_provided_hash_array.example.ts @@ -0,0 +1,30 @@ +import { format } from '@fast-csv/format'; + +const csvStream = 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(); + +// Output: +// header1,header2 +// value1a,value1b +// value2a,value2b +// value3a,value3b +// value4a,value4b diff --git a/examples/formatting-ts/examples/headers_provided_object.example.ts b/examples/formatting-ts/examples/headers_provided_object.example.ts new file mode 100644 index 00000000..b98212a4 --- /dev/null +++ b/examples/formatting-ts/examples/headers_provided_object.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = 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(); + +// Output: +// header2,header1 +// value1b,value1a +// value2b,value2a +// value3b,value3a +// value4b,value4a diff --git a/examples/formatting-ts/examples/headers_provided_object_remove_column.example.ts b/examples/formatting-ts/examples/headers_provided_object_remove_column.example.ts new file mode 100644 index 00000000..0b795875 --- /dev/null +++ b/examples/formatting-ts/examples/headers_provided_object_remove_column.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = 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(); + +// Output: +// header2 +// value1b +// value2b +// value3b +// value4b diff --git a/examples/formatting-ts/examples/quote_all_columns.example.ts b/examples/formatting-ts/examples/quote_all_columns.example.ts new file mode 100644 index 00000000..c3d69b34 --- /dev/null +++ b/examples/formatting-ts/examples/quote_all_columns.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteColumns: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// "header1","header2" +// "value1a","value2a" +// "value1a","value2a" +// "value1a","value2a" +// "value1a","value2a" diff --git a/examples/formatting-ts/examples/quote_all_headers.example.ts b/examples/formatting-ts/examples/quote_all_headers.example.ts new file mode 100644 index 00000000..d05a8779 --- /dev/null +++ b/examples/formatting-ts/examples/quote_all_headers.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteHeaders: true }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// "header1","header2" +// value1a,value2a +// value1a,value2a +// value1a,value2a +// value1a,value2a diff --git a/examples/formatting-ts/examples/quote_columns_array.example.ts b/examples/formatting-ts/examples/quote_columns_array.example.ts new file mode 100644 index 00000000..67665b8d --- /dev/null +++ b/examples/formatting-ts/examples/quote_columns_array.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: ['header1', 'header2'], quoteColumns: [false, true] }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,"header2" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" diff --git a/examples/formatting-ts/examples/quote_columns_not_headers.example.ts b/examples/formatting-ts/examples/quote_columns_not_headers.example.ts new file mode 100644 index 00000000..09f94522 --- /dev/null +++ b/examples/formatting-ts/examples/quote_columns_not_headers.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteColumns: { header2: true }, quoteHeaders: false }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,header2 +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" diff --git a/examples/formatting-ts/examples/quote_columns_object.example.ts b/examples/formatting-ts/examples/quote_columns_object.example.ts new file mode 100644 index 00000000..80b693f8 --- /dev/null +++ b/examples/formatting-ts/examples/quote_columns_object.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteColumns: { header2: true } }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,"header2" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" +// value1a,"value2a" diff --git a/examples/formatting-ts/examples/quote_headers_array.example.ts b/examples/formatting-ts/examples/quote_headers_array.example.ts new file mode 100644 index 00000000..3c7db8d3 --- /dev/null +++ b/examples/formatting-ts/examples/quote_headers_array.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: ['header1', 'header2'], quoteHeaders: [false, true] }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,"header2" +// value1a,value2a +// value1a,value2a +// value1a,value2a +// value1a,value2a diff --git a/examples/formatting-ts/examples/quote_headers_object.example.ts b/examples/formatting-ts/examples/quote_headers_object.example.ts new file mode 100644 index 00000000..9d781c34 --- /dev/null +++ b/examples/formatting-ts/examples/quote_headers_object.example.ts @@ -0,0 +1,18 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ headers: true, quoteHeaders: { header2: true } }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,"header2" +// value1a,value2a +// value1a,value2a +// value1a,value2a +// value1a,value2a diff --git a/examples/formatting-ts/examples/quote_option.example.ts b/examples/formatting-ts/examples/quote_option.example.ts new file mode 100644 index 00000000..625eb18a --- /dev/null +++ b/examples/formatting-ts/examples/quote_option.example.ts @@ -0,0 +1,15 @@ +import { format } from '@fast-csv/format'; + +const stream = format({ quote: "'" }); +stream.pipe(process.stdout); + +// each field will be quoted because it contains a delimiter +stream.write(['a,a', 'b,b']); +stream.write(['a1,a1', 'b1,b1']); +stream.write(['a2,a2', 'b2,b2']); +stream.end(); + +// Output: +// 'a,a','b,b' +// 'a1,a1','b1,b1' +// 'a2,a2','b2,b2' diff --git a/examples/formatting-ts/examples/quote_some_columns_and_headers.example.ts b/examples/formatting-ts/examples/quote_some_columns_and_headers.example.ts new file mode 100644 index 00000000..026cbad5 --- /dev/null +++ b/examples/formatting-ts/examples/quote_some_columns_and_headers.example.ts @@ -0,0 +1,22 @@ +import { format } from '@fast-csv/format'; + +const csvStream = format({ + headers: true, + quoteColumns: { header1: true }, + quoteHeaders: { header2: true }, +}); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,"header2" +// "value1a",value2a +// "value1a",value2a +// "value1a",value2a +// "value1a",value2a diff --git a/examples/formatting-ts/examples/row_delimiter_option.example.ts b/examples/formatting-ts/examples/row_delimiter_option.example.ts new file mode 100644 index 00000000..3dc5c86d --- /dev/null +++ b/examples/formatting-ts/examples/row_delimiter_option.example.ts @@ -0,0 +1,12 @@ +import { format } from '@fast-csv/format'; + +const stream = format({ rowDelimiter: '||' }); +stream.pipe(process.stdout); + +stream.write(['a', 'b']); +stream.write(['a1', 'b1']); +stream.write(['a2', 'b2']); +stream.end(); + +// Output: +// a,b||a1,b1||a2,b2 diff --git a/examples/formatting-ts/examples/transform.example.ts b/examples/formatting-ts/examples/transform.example.ts new file mode 100644 index 00000000..d3ba0d84 --- /dev/null +++ b/examples/formatting-ts/examples/transform.example.ts @@ -0,0 +1,26 @@ +import { format } from '@fast-csv/format'; + +interface CsvRow { + header1: string; + header2: string; +} + +const csvStream = format({ headers: true }).transform((row: CsvRow) => ({ + header1: row.header1.toUpperCase(), + header2: row.header2.toUpperCase(), +})); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,header2 +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A diff --git a/examples/formatting-ts/examples/transform_async.example.ts b/examples/formatting-ts/examples/transform_async.example.ts new file mode 100644 index 00000000..2de9d6cd --- /dev/null +++ b/examples/formatting-ts/examples/transform_async.example.ts @@ -0,0 +1,30 @@ +import { format } from '@fast-csv/format'; + +interface CsvRow { + header1: string; + header2: string; +} + +const csvStream = format({ headers: true }).transform((row, cb) => { + setImmediate(() => + cb(null, { + header1: row.header1.toUpperCase(), + header2: row.header2.toUpperCase(), + }), + ); +}); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,header2 +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A diff --git a/examples/formatting-ts/examples/transform_option.example.ts b/examples/formatting-ts/examples/transform_option.example.ts new file mode 100644 index 00000000..881dc43a --- /dev/null +++ b/examples/formatting-ts/examples/transform_option.example.ts @@ -0,0 +1,28 @@ +import { format } from '@fast-csv/format'; + +interface CsvRow { + header1: string; + header2: string; +} + +const transform = (row: CsvRow): CsvRow => ({ + header1: row.header1.toUpperCase(), + header2: row.header2.toUpperCase(), +}); + +const csvStream = format({ headers: true, transform }); + +csvStream.pipe(process.stdout).on('end', process.exit); + +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.write({ header1: 'value1a', header2: 'value2a' }); +csvStream.end(); + +// Output: +// header1,header2 +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A +// VALUE1A,VALUE2A diff --git a/examples/formatting-ts/examples/write.example.ts b/examples/formatting-ts/examples/write.example.ts new file mode 100644 index 00000000..668cf88c --- /dev/null +++ b/examples/formatting-ts/examples/write.example.ts @@ -0,0 +1,13 @@ +import { write } from '@fast-csv/format'; + +const rows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; +write(rows).pipe(process.stdout); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/write_to_buffer.example.ts b/examples/formatting-ts/examples/write_to_buffer.example.ts new file mode 100644 index 00000000..296bd117 --- /dev/null +++ b/examples/formatting-ts/examples/write_to_buffer.example.ts @@ -0,0 +1,13 @@ +import { writeToBuffer } from '@fast-csv/format'; + +const rows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; +writeToBuffer(rows).then(data => console.log(data.toString())); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/write_to_path.example.ts b/examples/formatting-ts/examples/write_to_path.example.ts new file mode 100644 index 00000000..d8ff2f82 --- /dev/null +++ b/examples/formatting-ts/examples/write_to_path.example.ts @@ -0,0 +1,22 @@ +import { resolve } from 'path'; +import { readFileSync } from 'fs'; +import { writeToPath } from '@fast-csv/format'; + +const rows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; +const filePath = resolve(__dirname, 'write_to_path.tmp.csv'); +writeToPath(filePath, rows) + .on('error', err => console.error(err)) + .on('finish', () => { + console.log('File Contents:'); + console.log(readFileSync(filePath).toString()); + }); + +// Output: +// File Contents: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/write_to_stream.example.ts b/examples/formatting-ts/examples/write_to_stream.example.ts new file mode 100644 index 00000000..e653bd08 --- /dev/null +++ b/examples/formatting-ts/examples/write_to_stream.example.ts @@ -0,0 +1,13 @@ +import { writeToStream } from '@fast-csv/format'; + +const rows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; +writeToStream(process.stdout, rows); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/write_to_string.example.ts b/examples/formatting-ts/examples/write_to_string.example.ts new file mode 100644 index 00000000..7901adf2 --- /dev/null +++ b/examples/formatting-ts/examples/write_to_string.example.ts @@ -0,0 +1,13 @@ +import { writeToString } from '@fast-csv/format'; + +const rows = [ + ['a', 'b'], + ['a1', 'b1'], + ['a2', 'b2'], +]; +writeToString(rows).then(data => console.log(data)); + +// Output: +// a,b +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/write_to_string_no_headers.example.ts b/examples/formatting-ts/examples/write_to_string_no_headers.example.ts new file mode 100644 index 00000000..654126c6 --- /dev/null +++ b/examples/formatting-ts/examples/write_to_string_no_headers.example.ts @@ -0,0 +1,19 @@ +import { writeToString } from '@fast-csv/format'; + +const data = [ + { a: 'a1', b: 'b1' }, + { a: 'a2', b: 'b2' }, +]; +writeToString(data, { headers: false }) + .then(formattedCsv => { + console.log(formattedCsv); + process.exit(); + }) + .catch(err => { + console.error(err.stack); + process.exit(1); + }); + +// Output: +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/examples/write_to_string_transform.example.ts b/examples/formatting-ts/examples/write_to_string_transform.example.ts new file mode 100644 index 00000000..0db9cca6 --- /dev/null +++ b/examples/formatting-ts/examples/write_to_string_transform.example.ts @@ -0,0 +1,20 @@ +import { RowMap, writeToString } from '@fast-csv/format'; + +const data = [ + { a: 'a1', b: 'b1' }, + { a: 'a2', b: 'b2' }, +]; + +const transform = (row: RowMap): RowMap => ({ + A: row.a, + B: row.b, +}); + +writeToString(data, { headers: true, transform }) + .then(formattedCsv => console.log(formattedCsv)) + .catch(err => console.error(err.stack)); + +// Output: +// A,B +// a1,b1 +// a2,b2 diff --git a/examples/formatting-ts/package.json b/examples/formatting-ts/package.json new file mode 100644 index 00000000..ea27c3d6 --- /dev/null +++ b/examples/formatting-ts/package.json @@ -0,0 +1,18 @@ +{ + "name": "@fast-csv/formatting-ts-examples", + "private": true, + "description": "fast-csv formatting typescript examples", + "scripts": { + "list": "run-examples --dir=build list", + "all-examples": "run-examples --dir=build all", + "example": "run-examples --dir=build run", + "build": "npm run clean && npm run compile", + "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo", + "compile": "tsc -p tsconfig.build.json" + }, + "dependencies": { + "example-runner": "^4.0.0", + "@fast-csv/format": "^4.0.0", + "typescript": "^3.7.3" + } +} diff --git a/examples/formatting-ts/tsconfig.build.json b/examples/formatting-ts/tsconfig.build.json new file mode 100644 index 00000000..ea5a1715 --- /dev/null +++ b/examples/formatting-ts/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./build", + "rootDir": "./examples" + } +} diff --git a/examples/formatting-ts/tsconfig.json b/examples/formatting-ts/tsconfig.json new file mode 100644 index 00000000..50217932 --- /dev/null +++ b/examples/formatting-ts/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./examples"] +} diff --git a/examples/parsing-js/README.md b/examples/parsing-js/README.md index fbb308ec..4444bc79 100644 --- a/examples/parsing-js/README.md +++ b/examples/parsing-js/README.md @@ -1,4 +1,4 @@ -`@fast-csv/parse` parsing examples. +`@fast-csv/parse` javascript parsing examples. ## Usage @@ -11,10 +11,10 @@ npm run all-examples To see a list of all available examples ```sh -npm run example +npm run list ``` -To run a sepcific example +To run a specific example ```sh npm run example -- {example_name} diff --git a/examples/parsing-js/package.json b/examples/parsing-js/package.json index 169e6438..dc521335 100644 --- a/examples/parsing-js/package.json +++ b/examples/parsing-js/package.json @@ -3,8 +3,9 @@ "private": true, "description": "fast-csv parsing examples", "scripts": { + "list": "run-examples list", "all-examples": "run-examples all", - "example": "run-examples" + "example": "run-examples run" }, "dependencies": { "example-runner": "^4.0.0", diff --git a/examples/parsing-ts/.eslintrc.js b/examples/parsing-ts/.eslintrc.js new file mode 100644 index 00000000..fcbdb09f --- /dev/null +++ b/examples/parsing-ts/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + parserOptions: { + project: "./tsconfig.build.json" + }, + rules: { + 'no-console': 0, + }, +}; \ No newline at end of file diff --git a/examples/parsing-ts/README.md b/examples/parsing-ts/README.md new file mode 100644 index 00000000..ca13edc1 --- /dev/null +++ b/examples/parsing-ts/README.md @@ -0,0 +1,655 @@ +`@fast-csv/parse` typescript parsing examples. + +## Usage + +```sh +npm run build +``` + +To run all examples + +```sh +npm run all-examples +``` + +To see a list of all available examples + +```sh +npm run list +``` + +To run a specific example + +```sh +npm run example -- {example_name} +``` + +## Examples + +* [Manual Write](#manual-write) +* [Alternate Delimiters](#alternate-delimiters) +* [First Row As Headers](#first-row-as-headers) +* [Custom Headers](#custom-headers) +* [Renaming Headers](#renaming-headers) +* [Transforming Headers](#transforming-headers) +* [Skipping Columns](#skipping-columns) +* [Ignoring Empty Rows](#ignoring-empty-rows) +* [Transforming Rows](#transforming) +* [Validating Rows](#validation) +* [Max Rows](#max-rows) +* [Skip Rows](#skip-rows) +* [Skip Lines](#skip-lines) + + +### Manual Write + +[`examples/manual_write.example.ts`](./examples/manual_write.example.ts) +```sh +npm run example -- manual_write +``` +```typescript +import { parse } from '@fast-csv/parse'; + +const stream = parse({ headers: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write('header1,header2\n'); +stream.write('col1,col2'); +stream.end(); +``` + +Expected output + +``` +{ header1: 'col1', header2: 'col2' } +Parsed 1 rows +``` +--- + +### Alternate Delimiter + +You can provide a `delimiter` option to change the delimiter from a `,` character. + +[`examples/alternate_delimiter.example.ts`](./examples/alternate_delimiter.example.ts) +```sh +npm run example -- alternate_delimiter +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1\tb1', 'a2\tb2'].join(EOL); + +const stream = parse({ delimiter: '\t' }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +[ 'a1', 'b1' ] +[ 'a2', 'b2' ] +Parsed 2 rows +``` +--- + +### First Row As Headers + +If you expect the first line your CSV to be headers you may pass in a `headers` option. + +Setting the `headers` option to `true` will cause change each row to an object rather than an array. + +[`examples/first_row_as_headers.example.ts`](./examples/first_row_as_headers.example.ts) +```sh +npm run example -- first_row_as_headers +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ headers: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output +``` +{ a: 'a1', b: 'b1' } +{ a: 'a2', b: 'b2' } +Parsed 2 rows +``` +--- + +### Custom Headers + +You may alternatively pass an array of header names. + +**NOTE** The order of the headers array will should match the order of fields in the CSV, otherwise the data columns will not match. + +[`examples/custom_headers.example.ts`](./examples/custom_headers.example.ts) +```sh +npm run example -- custom_headers +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ headers: ['a', 'b'] }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +{ a: 'a1', b: 'b1' } +{ a: 'a2', b: 'b2' } +Parsed 2 rows +``` +--- + +### Renaming Headers + +If the CSV contains a header row but you want to provide custom headers you can pass an array of headers, and set `renameHeaders` to true. + +[`examples/rename_headers.example.ts`](./examples/rename_headers.example.ts) +```sh +npm run example -- rename_headers +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ headers: ['a', 'b'], renameHeaders: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +{ a: 'a1', b: 'b1' } +{ a: 'a2', b: 'b2' } +Parsed 2 rows +``` +--- + +### Transforming Headers + +If the CSV contains a header row but you want transform the headers you can provide a function to the `headers` option. + +[`examples/transform_headers.example.ts`](./examples/transform_headers.example.ts) +```sh +npm run example -- transform_headers +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ + headers: headers => headers.map(h => h?.toUpperCase()), +}) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +{ HEADER1: 'a1', HEADER2: 'b1' } +{ HEADER1: 'a2', HEADER2: 'b2' } +Parsed 2 rows +``` +--- + +### Skipping Columns + +To omit some of the data columns you may not need, pass a sparse array as `headers`. + +[`examples/skipping_columns.example.ts`](./examples/skipping_columns.example.ts) +```sh +npm run example -- skipping_columns +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1,b1,c1', 'a2,b2,c2'].join(EOL); + +const stream = parse({ headers: ['a', undefined, 'c'] }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +{ a: 'a1', c: 'c1' } +{ a: 'a2', c: 'c2' } +Parsed 2 rows +``` +--- + +### Ignoring Empty Rows + +If your data includes empty rows, the sort Excel might include at the end of the file for instance, you can ignore these by including the `ignoreEmpty` option. + +Any rows consisting of nothing but empty strings and/or commas will be skipped, without emitting a 'data', 'data-invalid', or 'error' event. + +[`examples/ignore_empty_rows.example.ts`](./examples/ignore_empty_rows.example.ts) +```sh +npm run example -- ignore_empty_rows +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1,b1', ',', 'a2,b2', ' ,\t', ''].join(EOL); + +const stream = parse({ ignoreEmpty: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +[ 'a1', 'b1' ] +[ 'a2', 'b2' ] +Parsed 2 rows +``` +--- + +### Transforming + +You can transform data by providing a transform function. What is returned from the transform function will be provided to validate and emitted as a row. + +[`examples/transform.example.ts`](./examples/transform.example.ts) +```sh +npm run example -- transform +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +type TransformedUserRow = UserRow & { + properName: string; +}; + +const stream = parse({ headers: true }) + .transform( + (data: UserRow): TransformedUserRow => ({ + firstName: data.firstName.toUpperCase(), + lastName: data.lastName.toUpperCase(), + properName: `${data.firstName} ${data.lastName}`, + }), + ) + .on('error', error => console.error(error)) + .on('data', (row: TransformedUserRow) => console.log(JSON.stringify(row))) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +{"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"} +{"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"} +{"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"} +Parsed 3 rows +``` + +`fast-csv` also supports async transformation with a callback. + +[`examples/transform_async.example.ts`](./examples/transform_async.example.ts) +```sh +npm run example -- transform_async +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +type TransformedUserRow = UserRow & { + properName: string; +}; + +const stream = parse({ headers: true }) + .transform((data, cb): void => { + setImmediate(() => + cb(null, { + firstName: data.firstName.toUpperCase(), + lastName: data.lastName.toUpperCase(), + properName: `${data.firstName} ${data.lastName}`, + }), + ); + }) + .on('error', error => console.error(error)) + .on('data', row => console.log(JSON.stringify(row))) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +{"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"} +{"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"} +{"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"} +Parsed 3 rows +``` + +--- + +### Validation + +You can validate each row in the CSV by providing a validate handler. If a row is invalid then a `data-invalid` event will be emitted with the row and the index. + +[`examples/validate.example.ts`](./examples/validate.example.ts) +```sh +npm run example -- validate +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); +type UserRow = { + firstName: string; + lastName: string; +}; +const stream = parse({ headers: true }) + .validate((data: UserRow): boolean => data.firstName !== 'bob') + .on('error', error => console.error(error)) + .on('data', (row: UserRow) => console.log(`Valid [row=${JSON.stringify(row)}]`)) + .on('data-invalid', (row, rowNumber) => + console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}]`), + ) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] +Valid [row={"firstName":"sally","lastName":"yukon"}] +Valid [row={"firstName":"timmy","lastName":"yukon"}] +Parsed 2 rows +``` + +`fast-csv` also supports async validation, with a callback. + +[`examples/validate_async.example.ts`](./examples/validate_async.example.ts) +```sh +npm run example -- validate_async +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +const stream = parse({ headers: true }) + .validate((row, cb): void => { + setImmediate(() => cb(null, row.firstName !== 'bob')); + }) + .on('error', error => console.error(error)) + .on('data', row => console.log(`Valid [row=${JSON.stringify(row)}]`)) + .on('data-invalid', row => console.log(`Invalid [row=${JSON.stringify(row)}]`)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +Invalid [row={"firstName":"bob","lastName":"yukon"}] +Valid [row={"firstName":"sally","lastName":"yukon"}] +Valid [row={"firstName":"timmy","lastName":"yukon"}] +Parsed 3 rows +``` + +Sometimes you may wish to provide a reason that the row was invalid, you can use the callback to provide additional info. + +[`examples/validate_with_reason.example.ts`](./examples/validate_with_reason.example.ts) +```sh +npm run example -- validate_with_reason +``` +```typescript +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +const stream = parse({ headers: true }) + .validate((row, cb): void => { + const isValid = row.firstName !== 'bob'; + if (!isValid) { + return cb(null, false, 'Name is bob'); + } + return cb(null, true); + }) + .on('error', error => console.error(error)) + .on('data', row => console.log(`Valid [row=${JSON.stringify(row)}]`)) + .on('data-invalid', (row, rowNumber, reason) => { + console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}] [reason=${reason}]`); + }) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); +``` + +Expected output + +``` +Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] [reason=Name is bob] +Valid [row={"firstName":"sally","lastName":"yukon"}] +Valid [row={"firstName":"timmy","lastName":"yukon"}] +Parsed 2 rows +``` +--- + +### Max Rows + +In the following example there are 10 rows, but only 5 will be parsed because of the `maxRows` option. + +[`examples/max_rows.example.example.ts`](./examples/max_rows.example.ts) +```sh +npm run example -- max_rows +``` +```typescript +import { parse } from '@fast-csv/parse'; + +const rows = [ + 'header1,header2\n', + 'col1,col1\n', + 'col2,col2\n', + 'col3,col3\n', + 'col4,col4\n', + 'col5,col5\n', + 'col6,col6\n', + 'col7,col7\n', + 'col8,col8\n', + 'col9,col9\n', + 'col10,col10', +]; + +const stream = parse({ headers: true, maxRows: 5 }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +rows.forEach(row => stream.write(row)); +stream.end(); +``` + +Expected output + +``` +{ header1: 'col1', header2: 'col1' } +{ header1: 'col2', header2: 'col2' } +{ header1: 'col3', header2: 'col3' } +{ header1: 'col4', header2: 'col4' } +{ header1: 'col5', header2: 'col5' } +Parsed 5 rows +``` +--- + +### Skip Rows + +In the following example the first 2 rows are skipped. + +**NOTE** Notice how the header row is not skipped, only the row. + +[`examples/skip_rows.example.example.ts`](./examples/skip_rows.example.ts) +```sh +npm run example -- skip_rows +``` +```typescript +import { parse } from '@fast-csv/parse'; + +const rows = [ + 'header1,header2\n', + 'col1,col1\n', + 'col2,col2\n', + 'col3,col3\n', + 'col4,col4\n', + 'col5,col5\n', + 'col6,col6\n', +]; + +const stream = parse({ headers: true, skipRows: 2 }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +rows.forEach(row => stream.write(row)); +stream.end(); +``` + +Expected output + +``` +{ header1: 'col3', header2: 'col3' } +{ header1: 'col4', header2: 'col4' } +{ header1: 'col5', header2: 'col5' } +{ header1: 'col6', header2: 'col6' } +Parsed 4 rows +``` +--- + +### Skip Lines + +In the following example the first 2 lines are skipped. + +**NOTE** Notice how the headers come from the third line because the first two are skipped. + +[`examples/skip_lines.example.example.ts`](./examples/skip_lines.example.ts) +```sh +npm run example -- skip_lines +``` +```typescript +import { parse } from '@fast-csv/parse'; + +const rows = [ + 'skip1_header1,skip1_header2\n', + 'skip2_header1,skip2_header2\n', + 'header1,header2\n', + 'col1,col1\n', + 'col2,col2\n', + 'col3,col3\n', + 'col4,col4\n', +]; + +const stream = parse({ headers: true, skipLines: 2 }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +rows.forEach(row => stream.write(row)); +stream.end(); +``` + +Expected output + +``` +{ header1: 'col1', header2: 'col1' } +{ header1: 'col2', header2: 'col2' } +{ header1: 'col3', header2: 'col3' } +{ header1: 'col4', header2: 'col4' } +Parsed 4 rows +``` + + diff --git a/examples/parsing-ts/assets/snake_case_users.csv b/examples/parsing-ts/assets/snake_case_users.csv new file mode 100644 index 00000000..68d197a2 --- /dev/null +++ b/examples/parsing-ts/assets/snake_case_users.csv @@ -0,0 +1,10 @@ +id,first_name,last_name,address +1,Bob,Yukon,1111 State St. Yukon AK +2,Sally,Yukon,1111 State St. Yukon AK +3,Bobby,Yukon,1111 State St. Yukon AK +4,Jane,Yukon,1111 State St. Yukon AK +5,Dick,Yukon,1111 State St. Yukon AK +6,John,Doe,1112 State St. Yukon AK +7,Jane,Doe,1113 State St. Yukon AK +8,Billy,Doe,1112 State St. Yukon AK +9,Edith,Doe,1112 State St. Yukon AK \ No newline at end of file diff --git a/examples/parsing-ts/examples/alternate_delimiter.example.ts b/examples/parsing-ts/examples/alternate_delimiter.example.ts new file mode 100644 index 00000000..76a8c46a --- /dev/null +++ b/examples/parsing-ts/examples/alternate_delimiter.example.ts @@ -0,0 +1,17 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1\tb1', 'a2\tb2'].join(EOL); + +const stream = parse({ delimiter: '\t' }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// [ 'a1', 'b1' ] +// [ 'a2', 'b2' ] +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/custom_headers.example.ts b/examples/parsing-ts/examples/custom_headers.example.ts new file mode 100644 index 00000000..ea2a7495 --- /dev/null +++ b/examples/parsing-ts/examples/custom_headers.example.ts @@ -0,0 +1,17 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ headers: ['a', 'b'] }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/first_row_as_headers.example.ts b/examples/parsing-ts/examples/first_row_as_headers.example.ts new file mode 100644 index 00000000..4f9368ea --- /dev/null +++ b/examples/parsing-ts/examples/first_row_as_headers.example.ts @@ -0,0 +1,17 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ headers: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/ignore_empty_rows.example.ts b/examples/parsing-ts/examples/ignore_empty_rows.example.ts new file mode 100644 index 00000000..73a6add9 --- /dev/null +++ b/examples/parsing-ts/examples/ignore_empty_rows.example.ts @@ -0,0 +1,17 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1,b1', ',', 'a2,b2', ' ,\t', ''].join(EOL); + +const stream = parse({ ignoreEmpty: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// [ 'a1', 'b1' ] +// [ 'a2', 'b2' ] +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/manual_write.example.ts b/examples/parsing-ts/examples/manual_write.example.ts new file mode 100644 index 00000000..e8b5c747 --- /dev/null +++ b/examples/parsing-ts/examples/manual_write.example.ts @@ -0,0 +1,14 @@ +import { parse } from '@fast-csv/parse'; + +const stream = parse({ headers: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write('header1,header2\n'); +stream.write('col1,col2'); +stream.end(); + +// Output: +// { header1: 'col1', header2: 'col2' } +// Parsed 1 rows diff --git a/examples/parsing-ts/examples/max_rows.example.ts b/examples/parsing-ts/examples/max_rows.example.ts new file mode 100644 index 00000000..c0922f18 --- /dev/null +++ b/examples/parsing-ts/examples/max_rows.example.ts @@ -0,0 +1,31 @@ +import { parse } from '@fast-csv/parse'; + +const rows = [ + 'header1,header2\n', + 'col1,col1\n', + 'col2,col2\n', + 'col3,col3\n', + 'col4,col4\n', + 'col5,col5\n', + 'col6,col6\n', + 'col7,col7\n', + 'col8,col8\n', + 'col9,col9\n', + 'col10,col10', +]; + +const stream = parse({ headers: true, maxRows: 5 }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +rows.forEach(row => stream.write(row)); +stream.end(); + +// Output: +// { header1: 'col1', header2: 'col1' } +// { header1: 'col2', header2: 'col2' } +// { header1: 'col3', header2: 'col3' } +// { header1: 'col4', header2: 'col4' } +// { header1: 'col5', header2: 'col5' } +// Parsed 5 rows diff --git a/examples/parsing-ts/examples/parse_string.example.ts b/examples/parsing-ts/examples/parse_string.example.ts new file mode 100644 index 00000000..00dbe50b --- /dev/null +++ b/examples/parsing-ts/examples/parse_string.example.ts @@ -0,0 +1,14 @@ +import { EOL } from 'os'; +import { parseString } from '@fast-csv/parse'; + +const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL); + +parseString(CSV_STRING, { headers: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/pipe.example.ts b/examples/parsing-ts/examples/pipe.example.ts new file mode 100644 index 00000000..b07c8081 --- /dev/null +++ b/examples/parsing-ts/examples/pipe.example.ts @@ -0,0 +1,22 @@ +import { createReadStream } from 'fs'; +import { resolve } from 'path'; +import { parse } from '@fast-csv/parse'; + +createReadStream(resolve(__dirname, '..', 'assets', 'snake_case_users.csv')) + .pipe(parse()) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +// Output: +// [ 'id', 'first_name', 'last_name', 'address' ] +// [ '1', 'Bob', 'Yukon', '1111 State St. Yukon AK' ] +// [ '2', 'Sally', 'Yukon', '1111 State St. Yukon AK' ] +// [ '3', 'Bobby', 'Yukon', '1111 State St. Yukon AK' ] +// [ '4', 'Jane', 'Yukon', '1111 State St. Yukon AK' ] +// [ '5', 'Dick', 'Yukon', '1111 State St. Yukon AK' ] +// [ '6', 'John', 'Doe', '1112 State St. Yukon AK' ] +// [ '7', 'Jane', 'Doe', '1113 State St. Yukon AK' ] +// [ '8', 'Billy', 'Doe', '1112 State St. Yukon AK' ] +// [ '9', 'Edith', 'Doe', '1112 State St. Yukon AK' ] +// Parsed 10 rows diff --git a/examples/parsing-ts/examples/rename_headers.example.ts b/examples/parsing-ts/examples/rename_headers.example.ts new file mode 100644 index 00000000..3315a8bb --- /dev/null +++ b/examples/parsing-ts/examples/rename_headers.example.ts @@ -0,0 +1,17 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ headers: ['a', 'b'], renameHeaders: true }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// { a: 'a1', b: 'b1' } +// { a: 'a2', b: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/skip_lines.example.ts b/examples/parsing-ts/examples/skip_lines.example.ts new file mode 100644 index 00000000..08d4a270 --- /dev/null +++ b/examples/parsing-ts/examples/skip_lines.example.ts @@ -0,0 +1,26 @@ +import { parse } from '@fast-csv/parse'; + +const rows = [ + 'skip1_header1,skip1_header2\n', + 'skip2_header1,skip2_header2\n', + 'header1,header2\n', + 'col1,col1\n', + 'col2,col2\n', + 'col3,col3\n', + 'col4,col4\n', +]; + +const stream = parse({ headers: true, skipLines: 2 }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +rows.forEach(row => stream.write(row)); +stream.end(); + +// Output: +// { header1: 'col1', header2: 'col1' } +// { header1: 'col2', header2: 'col2' } +// { header1: 'col3', header2: 'col3' } +// { header1: 'col4', header2: 'col4' } +// Parsed 4 rows diff --git a/examples/parsing-ts/examples/skip_rows.example.ts b/examples/parsing-ts/examples/skip_rows.example.ts new file mode 100644 index 00000000..efec48ae --- /dev/null +++ b/examples/parsing-ts/examples/skip_rows.example.ts @@ -0,0 +1,26 @@ +import { parse } from '@fast-csv/parse'; + +const rows = [ + 'header1,header2\n', + 'col1,col1\n', + 'col2,col2\n', + 'col3,col3\n', + 'col4,col4\n', + 'col5,col5\n', + 'col6,col6\n', +]; + +const stream = parse({ headers: true, skipRows: 2 }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +rows.forEach(row => stream.write(row)); +stream.end(); + +// Output: +// { header1: 'col3', header2: 'col3' } +// { header1: 'col4', header2: 'col4' } +// { header1: 'col5', header2: 'col5' } +// { header1: 'col6', header2: 'col6' } +// Parsed 4 rows diff --git a/examples/parsing-ts/examples/skipping_columns.example.ts b/examples/parsing-ts/examples/skipping_columns.example.ts new file mode 100644 index 00000000..f1a1b5e6 --- /dev/null +++ b/examples/parsing-ts/examples/skipping_columns.example.ts @@ -0,0 +1,17 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['a1,b1,c1', 'a2,b2,c2'].join(EOL); + +const stream = parse({ headers: ['a', undefined, 'c'] }) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// { a: 'a1', c: 'c1' } +// { a: 'a2', c: 'c2' } +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/transform.example.ts b/examples/parsing-ts/examples/transform.example.ts new file mode 100644 index 00000000..e41a12b9 --- /dev/null +++ b/examples/parsing-ts/examples/transform.example.ts @@ -0,0 +1,34 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +type TransformedUserRow = UserRow & { + properName: string; +}; + +const stream = parse({ headers: true }) + .transform( + (data: UserRow): TransformedUserRow => ({ + firstName: data.firstName.toUpperCase(), + lastName: data.lastName.toUpperCase(), + properName: `${data.firstName} ${data.lastName}`, + }), + ) + .on('error', error => console.error(error)) + .on('data', (row: TransformedUserRow) => console.log(JSON.stringify(row))) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"} +// {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"} +// {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"} +// Parsed 3 rows diff --git a/examples/parsing-ts/examples/transform_async.example.ts b/examples/parsing-ts/examples/transform_async.example.ts new file mode 100644 index 00000000..85733653 --- /dev/null +++ b/examples/parsing-ts/examples/transform_async.example.ts @@ -0,0 +1,36 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +type TransformedUserRow = UserRow & { + properName: string; +}; + +const stream = parse({ headers: true }) + .transform((data, cb): void => { + setImmediate(() => + cb(null, { + firstName: data.firstName.toUpperCase(), + lastName: data.lastName.toUpperCase(), + properName: `${data.firstName} ${data.lastName}`, + }), + ); + }) + .on('error', error => console.error(error)) + .on('data', row => console.log(JSON.stringify(row))) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"} +// {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"} +// {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"} +// Parsed 3 rows diff --git a/examples/parsing-ts/examples/transform_headers.example.ts b/examples/parsing-ts/examples/transform_headers.example.ts new file mode 100644 index 00000000..81496596 --- /dev/null +++ b/examples/parsing-ts/examples/transform_headers.example.ts @@ -0,0 +1,19 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL); + +const stream = parse({ + headers: headers => headers.map(h => h?.toUpperCase()), +}) + .on('error', error => console.error(error)) + .on('data', row => console.log(row)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// { HEADER1: 'a1', HEADER2: 'b1' } +// { HEADER1: 'a2', HEADER2: 'b2' } +// Parsed 2 rows diff --git a/examples/parsing-ts/examples/validate.example.ts b/examples/parsing-ts/examples/validate.example.ts new file mode 100644 index 00000000..c5bb82a8 --- /dev/null +++ b/examples/parsing-ts/examples/validate.example.ts @@ -0,0 +1,25 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); +type UserRow = { + firstName: string; + lastName: string; +}; +const stream = parse({ headers: true }) + .validate((data: UserRow): boolean => data.firstName !== 'bob') + .on('error', error => console.error(error)) + .on('data', (row: UserRow) => console.log(`Valid [row=${JSON.stringify(row)}]`)) + .on('data-invalid', (row, rowNumber) => + console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}]`), + ) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] +// Valid [row={"firstName":"sally","lastName":"yukon"}] +// Valid [row={"firstName":"timmy","lastName":"yukon"}] +// Parsed 3 rows diff --git a/examples/parsing-ts/examples/validate_async.example.ts b/examples/parsing-ts/examples/validate_async.example.ts new file mode 100644 index 00000000..3009a5c9 --- /dev/null +++ b/examples/parsing-ts/examples/validate_async.example.ts @@ -0,0 +1,27 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +const stream = parse({ headers: true }) + .validate((row, cb): void => { + setImmediate(() => cb(null, row.firstName !== 'bob')); + }) + .on('error', error => console.error(error)) + .on('data', row => console.log(`Valid [row=${JSON.stringify(row)}]`)) + .on('data-invalid', row => console.log(`Invalid [row=${JSON.stringify(row)}]`)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// Invalid [row={"firstName":"bob","lastName":"yukon"}] +// Valid [row={"firstName":"sally","lastName":"yukon"}] +// Valid [row={"firstName":"timmy","lastName":"yukon"}] +// Parsed 3 rows diff --git a/examples/parsing-ts/examples/validate_with_reason.example.ts b/examples/parsing-ts/examples/validate_with_reason.example.ts new file mode 100644 index 00000000..bd258ed4 --- /dev/null +++ b/examples/parsing-ts/examples/validate_with_reason.example.ts @@ -0,0 +1,33 @@ +import { EOL } from 'os'; +import { parse } from '@fast-csv/parse'; + +const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL); + +type UserRow = { + firstName: string; + lastName: string; +}; + +const stream = parse({ headers: true }) + .validate((row, cb): void => { + const isValid = row.firstName !== 'bob'; + if (!isValid) { + return cb(null, false, 'Name is bob'); + } + return cb(null, true); + }) + .on('error', error => console.error(error)) + .on('data', row => console.log(`Valid [row=${JSON.stringify(row)}]`)) + .on('data-invalid', (row, rowNumber, reason) => { + console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}] [reason=${reason}]`); + }) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); + +stream.write(CSV_STRING); +stream.end(); + +// Output: +// Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] [reason=Name is bob] +// Valid [row={"firstName":"sally","lastName":"yukon"}] +// Valid [row={"firstName":"timmy","lastName":"yukon"}] +// Parsed 3 rows diff --git a/examples/parsing-ts/package.json b/examples/parsing-ts/package.json new file mode 100644 index 00000000..4d9446dd --- /dev/null +++ b/examples/parsing-ts/package.json @@ -0,0 +1,18 @@ +{ + "name": "@fast-csv/parse-ts-examples", + "private": true, + "description": "fast-csv parsing typescript examples", + "scripts": { + "list": "run-examples --dir=build list", + "all-examples": "run-examples --dir=build all", + "example": "run-examples --dir=build run", + "build": "npm run clean && npm run compile", + "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo", + "compile": "tsc -p tsconfig.build.json" + }, + "dependencies": { + "example-runner": "^4.0.0", + "@fast-csv/parse": "^4.0.0", + "typescript": "^3.7.3" + } +} diff --git a/examples/parsing-ts/tsconfig.build.json b/examples/parsing-ts/tsconfig.build.json new file mode 100644 index 00000000..ea5a1715 --- /dev/null +++ b/examples/parsing-ts/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./build", + "rootDir": "./examples" + } +} diff --git a/examples/parsing-ts/tsconfig.json b/examples/parsing-ts/tsconfig.json new file mode 100644 index 00000000..50217932 --- /dev/null +++ b/examples/parsing-ts/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./examples"] +} diff --git a/package-lock.json b/package-lock.json index a3d24160..3e9f2061 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2223,6 +2223,11 @@ "@babel/types": "^7.3.0" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -2386,9 +2391,9 @@ "dev": true }, "@types/yargs": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", - "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", + "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", "requires": { "@types/yargs-parser": "*" } @@ -3156,8 +3161,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-keys": { "version": "4.2.0", @@ -3269,6 +3273,51 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -4049,8 +4098,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decamelize-keys": { "version": "1.1.0", @@ -5881,8 +5929,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-pkg-repo": { "version": "1.4.0", @@ -9339,7 +9386,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -9392,8 +9438,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "p-waterfall": { "version": "1.0.0", @@ -10073,14 +10118,12 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { "version": "1.10.0", @@ -10267,8 +10310,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { "version": "2.0.1", @@ -11548,8 +11590,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wide-align": { "version": "1.1.3", @@ -11575,6 +11616,73 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", + "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -11687,8 +11795,99 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", + "integrity": "sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "yargs-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } } diff --git a/packages/fast-csv/README.md b/packages/fast-csv/README.md index 2d765f08..f7d73a01 100644 --- a/packages/fast-csv/README.md +++ b/packages/fast-csv/README.md @@ -27,5 +27,6 @@ import * as csv from 'fast-csv'; ### Examples -* [JS Examples](../../examples/fast-csv-js/README.md) +* [JavaScript Examples](../../examples/fast-csv-js/README.md) +* [TypeScript Examples](../../examples/fast-csv-ts/README.md) diff --git a/packages/format/README.md b/packages/format/README.md index e2cdcf72..af3ecada 100644 --- a/packages/format/README.md +++ b/packages/format/README.md @@ -30,7 +30,8 @@ import * as format csv '@fast-csv/format'; * [`writeToString`](#csv-write-to-string) * [`writeToPath`](#csv-write-to-path) * Examples - * [JS Examples](../../examples/formatting-js/README.md) + * [JavaScript Examples](../../examples/formatting-js/README.md) + * [TypeScript Examples](../../examples/formatting-ts/README.md) ## Options diff --git a/packages/format/__tests__/CsvFormatterStream.spec.ts b/packages/format/__tests__/CsvFormatterStream.spec.ts index 7a9a9296..e026e3c8 100644 --- a/packages/format/__tests__/CsvFormatterStream.spec.ts +++ b/packages/format/__tests__/CsvFormatterStream.spec.ts @@ -10,7 +10,7 @@ import { import { arrayRows, multiDimensionalRows, objectRows, RecordingStream } from './__fixtures__'; describe('CsvFormatterStream', () => { - const pipeToRecordingStream = (formatter: CsvFormatterStream, rows: Row[]) => + const pipeToRecordingStream = (formatter: CsvFormatterStream, rows: Row[]) => new Promise((res, rej) => { const rs = new RecordingStream(); formatter @@ -23,7 +23,7 @@ describe('CsvFormatterStream', () => { formatter.end(); }); - const formatRows = (rows: Row[], options: FormatterOptionsArgs = {}) => + const formatRows = (rows: Row[], options: FormatterOptionsArgs = {}) => pipeToRecordingStream(new CsvFormatterStream(new FormatterOptions(options)), rows); it('should write an array of arrays', () => diff --git a/packages/format/__tests__/FormatterOptions.spec.ts b/packages/format/__tests__/FormatterOptions.spec.ts index b27507f7..d4e1b3b1 100644 --- a/packages/format/__tests__/FormatterOptions.spec.ts +++ b/packages/format/__tests__/FormatterOptions.spec.ts @@ -1,8 +1,9 @@ -import { FormatterOptionsArgs } from '../src'; +import { FormatterOptionsArgs, Row } from '../src'; import { FormatterOptions } from '../src/FormatterOptions'; describe('FormatterOptions', () => { - const createOptions = (opts: FormatterOptionsArgs = {}) => new FormatterOptions(opts); + const createOptions = (opts: FormatterOptionsArgs = {}) => + new FormatterOptions(opts); describe('#objectMode', () => { it('should have default objectMode', () => { diff --git a/packages/format/__tests__/format.spec.ts b/packages/format/__tests__/format.spec.ts index 3cf268b2..cc2ee092 100644 --- a/packages/format/__tests__/format.spec.ts +++ b/packages/format/__tests__/format.spec.ts @@ -452,7 +452,7 @@ describe('.write', () => { }); describe('.writeToStream', () => { - const writeRowsToStream = (rows: Row[], options: FormatterOptionsArgs = {}) => + const writeRowsToStream = (rows: I[], options: FormatterOptionsArgs = {}) => new Promise((res, rej) => { const rs = new RecordingStream(); writeToStream(rs, rows, options); diff --git a/packages/format/__tests__/formatter/FieldFormatter.spec.ts b/packages/format/__tests__/formatter/FieldFormatter.spec.ts index 9f1cf5fe..f9b534e6 100644 --- a/packages/format/__tests__/formatter/FieldFormatter.spec.ts +++ b/packages/format/__tests__/formatter/FieldFormatter.spec.ts @@ -1,8 +1,8 @@ -import { FormatterOptions, FormatterOptionsArgs } from '../../src'; +import { FormatterOptions, FormatterOptionsArgs, Row } from '../../src'; import { FieldFormatter } from '../../src/formatter'; describe('FieldFormatter', () => { - const createFormatter = (formatterOptions: FormatterOptionsArgs = {}) => { + const createFormatter = (formatterOptions: FormatterOptionsArgs = {}) => { return new FieldFormatter(new FormatterOptions(formatterOptions)); }; diff --git a/packages/format/__tests__/formatter/RowFormatter.spec.ts b/packages/format/__tests__/formatter/RowFormatter.spec.ts index 870440a4..8c4f97ca 100644 --- a/packages/format/__tests__/formatter/RowFormatter.spec.ts +++ b/packages/format/__tests__/formatter/RowFormatter.spec.ts @@ -1,12 +1,20 @@ +import { + FormatterOptions, + FormatterOptionsArgs, + Row, + RowArray, + RowHashArray, + RowMap, + RowTransformCallback, +} from '../../src'; import { RowFormatter } from '../../src/formatter'; -import { FormatterOptions } from '../../src/FormatterOptions'; -import { Row, RowArray, RowHashArray, RowMap, RowTransformCallback } from '../../src'; describe('RowFormatter', () => { - const createFormatter = (formatterOptions = {}): RowFormatter => - new RowFormatter(new FormatterOptions(formatterOptions)); + const createFormatter = ( + formatterOptions: FormatterOptionsArgs = {}, + ): RowFormatter => new RowFormatter(new FormatterOptions(formatterOptions)); - const formatRow = (row: Row, formatter: RowFormatter): Promise => + const formatRow = (row: I, formatter: RowFormatter): Promise => new Promise((res, rej): void => { formatter.format(row, (err, formatted): void => { if (err) { @@ -16,7 +24,7 @@ describe('RowFormatter', () => { }); }); - const finish = (formatter: RowFormatter): Promise => + const finish = (formatter: RowFormatter): Promise => new Promise((res, rej): void => { formatter.finish((err, formatted): void => { if (err) { @@ -31,15 +39,20 @@ describe('RowFormatter', () => { const headerRow = ['a', 'b']; const columnsRow = ['a1', 'b1']; - const syncTransform = (row: RowArray): Row => row.map(col => col.toUpperCase()); + const syncTransform = (row: RowArray): RowArray => row.map(col => col.toUpperCase()); // eslint-disable-next-line @typescript-eslint/no-unused-vars - const syncError = (row: RowArray): Row => { + const syncError = (): Row => { throw new Error('Expected Error'); }; - const asyncTransform = (row: RowArray, cb: RowTransformCallback): void => { - setImmediate(() => cb(null, syncTransform(row))); + const asyncTransform = (row: RowArray, cb: RowTransformCallback): void => { + setImmediate(() => + cb( + null, + row.map(col => col.toUpperCase()), + ), + ); }; - const asyncErrorTransform = (row: RowArray, cb: RowTransformCallback): void => { + const asyncErrorTransform = (row: Row, cb: RowTransformCallback): void => { setImmediate(() => cb(new Error('Expected Error'))); }; @@ -120,21 +133,21 @@ describe('RowFormatter', () => { }); describe('with multi-dimensional arrays', () => { - const row: Row = [ + const row: RowHashArray = [ ['a', 'a1'], ['b', 'b1'], ]; - const syncTransform = (rowToTransform: RowHashArray): Row => + const syncTransform = (rowToTransform: RowHashArray): RowHashArray => rowToTransform.map(([header, col]) => [header, col.toUpperCase()]); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const syncError = (rowToTransform: RowHashArray): Row => { + const syncError = (): Row => { throw new Error('Expected Error'); }; - const asyncTransform = (rowToTransform: RowHashArray, cb: RowTransformCallback) => { - setImmediate(() => cb(null, syncTransform(rowToTransform))); + const asyncTransform = (rowToTransform: RowHashArray, cb: RowTransformCallback) => { + const transformed: RowHashArray = rowToTransform.map(([header, col]) => [header, col.toUpperCase()]); + setImmediate(() => cb(null, transformed)); }; - const asyncErrorTransform = (rowToTransform: RowHashArray, cb: RowTransformCallback) => + const asyncErrorTransform = (rowToTransform: Row, cb: RowTransformCallback) => setImmediate(() => cb(new Error('Expected Error'))); it('should format a multi-dimensional array with headers true', async () => { @@ -218,9 +231,9 @@ describe('RowFormatter', () => { const syncError = () => { throw new Error('Expected Error'); }; - const asyncTransform = (rowToTransform: RowMap, cb: RowTransformCallback) => + const asyncTransform = (rowToTransform: RowMap, cb: RowTransformCallback) => setImmediate(() => cb(null, syncTransform(rowToTransform))); - const asyncErrorTransform = (rowToTransform: RowMap, cb: RowTransformCallback) => + const asyncErrorTransform = (rowToTransform: RowMap, cb: RowTransformCallback) => setImmediate(() => cb(new Error('Expected Error'))); it('should return a headers row with when headers true', async () => { diff --git a/packages/format/__tests__/issues/issue252.spec.ts b/packages/format/__tests__/issues/issue252.spec.ts index 33fbdfc9..2b98cc89 100644 --- a/packages/format/__tests__/issues/issue252.spec.ts +++ b/packages/format/__tests__/issues/issue252.spec.ts @@ -4,7 +4,7 @@ import { RecordingStream } from '../__fixtures__'; describe('Issue #252 - https://github.com/C2FO/fast-csv/issues/252', () => { it('should keep the original row', next => { const rs = new RecordingStream(); - const data = [ + const data: csv.RowArray[] = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ]; diff --git a/packages/format/__tests__/issues/issue97.spec.ts b/packages/format/__tests__/issues/issue97.spec.ts index 974a1a99..0b91513d 100644 --- a/packages/format/__tests__/issues/issue97.spec.ts +++ b/packages/format/__tests__/issues/issue97.spec.ts @@ -1,10 +1,10 @@ import { RecordingStream } from '../__fixtures__'; -import { write } from '../../src'; +import { RowMap, write } from '../../src'; describe('Issue #97 - https://github.com/C2FO/fast-csv/issues/97', () => { it('should keep the original row', next => { const rs = new RecordingStream(); - const data = [ + const data: RowMap[] = [ { field1: 'a1"a', field2: 'b1"b' }, { field1: 'a2"a', field2: 'b2"b' }, ]; diff --git a/packages/format/src/CsvFormatterStream.ts b/packages/format/src/CsvFormatterStream.ts index 8f340747..6eb8c1af 100644 --- a/packages/format/src/CsvFormatterStream.ts +++ b/packages/format/src/CsvFormatterStream.ts @@ -3,14 +3,14 @@ import { FormatterOptions } from './FormatterOptions'; import { Row, RowTransformFunction } from './types'; import { RowFormatter } from './formatter'; -export class CsvFormatterStream extends Transform { - private formatterOptions: FormatterOptions; +export class CsvFormatterStream extends Transform { + private formatterOptions: FormatterOptions; - private rowFormatter: RowFormatter; + private rowFormatter: RowFormatter; private hasWrittenBOM = false; - public constructor(formatterOptions: FormatterOptions) { + public constructor(formatterOptions: FormatterOptions) { super({ objectMode: formatterOptions.objectMode }); this.formatterOptions = formatterOptions; this.rowFormatter = new RowFormatter(formatterOptions); @@ -19,12 +19,12 @@ export class CsvFormatterStream extends Transform { this.hasWrittenBOM = !formatterOptions.writeBOM; } - public transform(transformFunction: RowTransformFunction): CsvFormatterStream { + public transform(transformFunction: RowTransformFunction): CsvFormatterStream { this.rowFormatter.rowTransform = transformFunction; return this; } - public _transform(row: Row, encoding: string, cb: TransformCallback): void { + public _transform(row: I, encoding: string, cb: TransformCallback): void { let cbCalled = false; try { if (!this.hasWrittenBOM) { diff --git a/packages/format/src/FormatterOptions.ts b/packages/format/src/FormatterOptions.ts index 759ce295..54e3ba19 100644 --- a/packages/format/src/FormatterOptions.ts +++ b/packages/format/src/FormatterOptions.ts @@ -1,4 +1,4 @@ -import { RowTransformFunction } from './types'; +import { Row, RowTransformFunction } from './types'; interface QuoteColumnMap { [s: string]: boolean; @@ -6,7 +6,7 @@ interface QuoteColumnMap { type QuoteColumns = boolean | boolean[] | QuoteColumnMap; -export interface FormatterOptionsArgs { +export interface FormatterOptionsArgs { objectMode?: boolean; delimiter?: string; rowDelimiter?: string; @@ -17,11 +17,11 @@ export interface FormatterOptionsArgs { headers?: null | boolean | string[]; includeEndRowDelimiter?: boolean; writeBOM?: boolean; - transform?: RowTransformFunction; + transform?: RowTransformFunction; alwaysWriteHeaders?: boolean; } -export class FormatterOptions { +export class FormatterOptions { public readonly objectMode: boolean = true; public readonly delimiter: string = ','; @@ -40,7 +40,7 @@ export class FormatterOptions { public readonly includeEndRowDelimiter: boolean = false; - public readonly transform: RowTransformFunction | null = null; + public readonly transform?: RowTransformFunction; public readonly shouldWriteHeaders: boolean; @@ -52,7 +52,7 @@ export class FormatterOptions { public readonly alwaysWriteHeaders: boolean = false; - public constructor(opts: FormatterOptionsArgs = {}) { + public constructor(opts: FormatterOptionsArgs = {}) { Object.assign(this, opts || {}); if (typeof opts?.quoteHeaders === 'undefined') { diff --git a/packages/format/src/formatter/FieldFormatter.ts b/packages/format/src/formatter/FieldFormatter.ts index 2b74db6f..31e539eb 100644 --- a/packages/format/src/formatter/FieldFormatter.ts +++ b/packages/format/src/formatter/FieldFormatter.ts @@ -2,9 +2,10 @@ import isBoolean from 'lodash.isboolean'; import isNil from 'lodash.isnil'; import escapeRegExp from 'lodash.escaperegexp'; import { FormatterOptions } from '../FormatterOptions'; +import { Row } from '../types'; -export class FieldFormatter { - private readonly formatterOptions: FormatterOptions; +export class FieldFormatter { + private readonly formatterOptions: FormatterOptions; private _headers: string[] | null = null; @@ -12,7 +13,7 @@ export class FieldFormatter { private readonly ESCAPE_REGEXP: RegExp; - public constructor(formatterOptions: FormatterOptions) { + public constructor(formatterOptions: FormatterOptions) { this.formatterOptions = formatterOptions; if (formatterOptions.headers !== null) { this.headers = formatterOptions.headers; diff --git a/packages/format/src/formatter/RowFormatter.ts b/packages/format/src/formatter/RowFormatter.ts index 7f3db374..5dcdbceb 100644 --- a/packages/format/src/formatter/RowFormatter.ts +++ b/packages/format/src/formatter/RowFormatter.ts @@ -2,15 +2,13 @@ import isFunction from 'lodash.isfunction'; import isEqual from 'lodash.isequal'; import { FormatterOptions } from '../FormatterOptions'; import { FieldFormatter } from './FieldFormatter'; -import { Row, RowHashArray, RowTransformFunction } from '../types'; +import { isSyncTransform, Row, RowArray, RowHashArray, RowTransformCallback, RowTransformFunction } from '../types'; -type RowCallback = (err?: Error | null, row?: Row) => void; +type RowFormatterTransform = (row: I, cb: RowTransformCallback) => void; -type RowFormatterTransform = (row: Row, cb: RowCallback) => void; +type RowFormatterCallback = (error: Error | null, data?: RowArray) => void; -type RowFormatterCallback = (error: Error | null, data?: string[]) => void; - -export class RowFormatter { +export class RowFormatter { private static isHashArray(row: Row): row is RowHashArray { if (Array.isArray(row)) { return Array.isArray(row[0]) && row[0].length === 2; @@ -30,10 +28,11 @@ export class RowFormatter { return Object.keys(row); } - private static createTransform(transformFunction: RowTransformFunction): RowFormatterTransform { - const isSync = transformFunction.length === 1; - if (isSync) { - return (row, cb): void => { + private static createTransform( + transformFunction: RowTransformFunction, + ): RowFormatterTransform { + if (isSyncTransform(transformFunction)) { + return (row: I, cb: RowTransformCallback): void => { let transformedRow = null; try { transformedRow = transformFunction(row); @@ -43,29 +42,28 @@ export class RowFormatter { return cb(null, transformedRow); }; } - return (row, cb): void => { + return (row: I, cb): void => { transformFunction(row, cb); }; } - private readonly formatterOptions: FormatterOptions; + private readonly formatterOptions: FormatterOptions; - private readonly fieldFormatter: FieldFormatter; + private readonly fieldFormatter: FieldFormatter; - private _rowTransform?: null | RowFormatterTransform; + private readonly shouldWriteHeaders: boolean; - private headers: string[] | null; + private _rowTransform?: RowFormatterTransform; - private shouldWriteHeaders: boolean; + private headers: string[] | null; private hasWrittenHeaders: boolean; private rowCount = 0; - public constructor(formatterOptions: FormatterOptions) { + public constructor(formatterOptions: FormatterOptions) { this.formatterOptions = formatterOptions; this.fieldFormatter = new FieldFormatter(formatterOptions); - this._rowTransform = null; this.headers = formatterOptions.headers; this.shouldWriteHeaders = formatterOptions.shouldWriteHeaders; @@ -73,19 +71,19 @@ export class RowFormatter { if (this.headers !== null) { this.fieldFormatter.headers = this.headers; } - if (formatterOptions.transform !== null) { + if (formatterOptions.transform) { this.rowTransform = formatterOptions.transform; } } - public set rowTransform(transformFunction: RowTransformFunction) { + public set rowTransform(transformFunction: RowTransformFunction) { if (!isFunction(transformFunction)) { throw new TypeError('The transform should be a function'); } this._rowTransform = RowFormatter.createTransform(transformFunction); } - public format(row: Row, cb: RowFormatterCallback): void { + public format(row: I, cb: RowFormatterCallback): void { this.callTransformer(row, (err, transformedRow?: Row): void => { if (err) { return cb(err); @@ -163,9 +161,9 @@ export class RowFormatter { return this.headers.map((header, i): string => row[i]); } - private callTransformer(row: Row, cb: RowCallback): void { + private callTransformer(row: I, cb: RowTransformCallback): void { if (!this._rowTransform) { - return cb(null, row); + return cb(null, (row as unknown) as O); } return this._rowTransform(row, cb); } diff --git a/packages/format/src/index.ts b/packages/format/src/index.ts index bfc25d30..f8460fa8 100644 --- a/packages/format/src/index.ts +++ b/packages/format/src/index.ts @@ -1,7 +1,7 @@ import { promisify } from 'util'; import { Writable } from 'stream'; import * as fs from 'fs'; -import { Row as FormatterRow } from './types'; +import { Row } from './types'; import { FormatterOptions, FormatterOptionsArgs } from './FormatterOptions'; import { CsvFormatterStream } from './CsvFormatterStream'; @@ -9,16 +9,19 @@ export * from './types'; export { CsvFormatterStream } from './CsvFormatterStream'; export { FormatterOptions, FormatterOptionsArgs } from './FormatterOptions'; -export const format = (options?: FormatterOptionsArgs): CsvFormatterStream => +export const format = (options?: FormatterOptionsArgs): CsvFormatterStream => new CsvFormatterStream(new FormatterOptions(options)); -export const write = (rows: FormatterRow[], options?: FormatterOptionsArgs): CsvFormatterStream => { +export const write = ( + rows: I[], + options?: FormatterOptionsArgs, +): CsvFormatterStream => { const csvStream = format(options); - const promiseWrite = promisify((row: FormatterRow, cb: (error?: Error | null) => void): void => { + const promiseWrite = promisify((row: I, cb: (error?: Error | null) => void): void => { csvStream.write(row, undefined, cb); }); rows.reduce( - (prev: Promise, row: FormatterRow): Promise => prev.then((): Promise => promiseWrite(row)), + (prev: Promise, row: I): Promise => prev.then((): Promise => promiseWrite(row)), Promise.resolve(), ) .then((): void => csvStream.end()) @@ -28,13 +31,16 @@ export const write = (rows: FormatterRow[], options?: FormatterOptionsArgs): Csv return csvStream; }; -export const writeToStream = ( +export const writeToStream = ( ws: T, - rows: FormatterRow[], - options?: FormatterOptionsArgs, + rows: I[], + options?: FormatterOptionsArgs, ): T => write(rows, options).pipe(ws); -export const writeToBuffer = (rows: FormatterRow[], opts: FormatterOptionsArgs = {}): Promise => { +export const writeToBuffer = ( + rows: I[], + opts: FormatterOptionsArgs = {}, +): Promise => { const buffers: Buffer[] = []; const ws = new Writable({ write(data, enc, writeCb): void { @@ -48,10 +54,16 @@ export const writeToBuffer = (rows: FormatterRow[], opts: FormatterOptionsArgs = }); }; -export const writeToString = (rows: FormatterRow[], options?: FormatterOptionsArgs): Promise => - writeToBuffer(rows, options).then((buffer): string => buffer.toString()); +export const writeToString = ( + rows: I[], + options?: FormatterOptionsArgs, +): Promise => writeToBuffer(rows, options).then((buffer): string => buffer.toString()); -export const writeToPath = (path: string, rows: FormatterRow[], options?: FormatterOptionsArgs): fs.WriteStream => { +export const writeToPath = ( + path: string, + rows: I[], + options?: FormatterOptionsArgs, +): fs.WriteStream => { const stream = fs.createWriteStream(path, { encoding: 'utf8' }); return write(rows, options).pipe(stream); }; diff --git a/packages/format/src/types.ts b/packages/format/src/types.ts index fe77528c..26916bdc 100644 --- a/packages/format/src/types.ts +++ b/packages/format/src/types.ts @@ -6,10 +6,13 @@ export interface RowMap { export type RowHashArray = [string, any][]; export type RowArray = string[]; -export type Row = RowArray | RowMap | RowHashArray; +export type Row = RowArray | RowHashArray | RowMap; -export type RowTransformCallback = (error?: Error | null, row?: Row) => void; -export interface RowTransformFunction { - (row: Row, callback: RowTransformCallback): void; - (row: Row): Row; -} +export type RowTransformCallback = (error?: Error | null, row?: R) => void; +export type SyncRowTransform = (row: I) => O; +export type AsyncRowTransform = (row: I, cb: RowTransformCallback) => void; +export type RowTransformFunction = SyncRowTransform | AsyncRowTransform; + +export const isSyncTransform = ( + transform: RowTransformFunction, +): transform is SyncRowTransform => transform.length === 1; diff --git a/packages/format/tsconfig.build.json b/packages/format/tsconfig.build.json index 22b9804b..7aaa7eac 100644 --- a/packages/format/tsconfig.build.json +++ b/packages/format/tsconfig.build.json @@ -3,5 +3,10 @@ "compilerOptions": { "outDir": "./build", "rootDir": "." - } + }, + "include": ["**/*.ts"], + "exclude": [ + "node_modules", + "build" + ] } diff --git a/packages/format/tsconfig.json b/packages/format/tsconfig.json index 6b9e22b4..ac42fcc2 100644 --- a/packages/format/tsconfig.json +++ b/packages/format/tsconfig.json @@ -1,4 +1,4 @@ { "extends": "../../tsconfig.json", - "include": ["./src", "./__tests__/**/*.ts"] + "include": ["**/*.ts"] } diff --git a/packages/parse/README.md b/packages/parse/README.md index 58279a29..417b0a67 100644 --- a/packages/parse/README.md +++ b/packages/parse/README.md @@ -28,7 +28,8 @@ import * as format csv '@fast-csv/parse'; * [`csv.parseFile`](#csv-parse-path) * [`csv.parseString`](#csv-parse-string) * Examples - * [JS Examples](../../examples/parsing-js/README.md) + * [JavaScript Examples](../../examples/parsing-js/README.md) + * [TypeScript Examples](../../examples/parsing-ts/README.md) ## Options diff --git a/packages/parse/__tests__/CsvParsingStream.spec.ts b/packages/parse/__tests__/CsvParsingStream.spec.ts index 3c12d5ac..f44121b5 100644 --- a/packages/parse/__tests__/CsvParsingStream.spec.ts +++ b/packages/parse/__tests__/CsvParsingStream.spec.ts @@ -2,9 +2,7 @@ import * as fs from 'fs'; import * as domain from 'domain'; import partition from 'lodash.partition'; -import { CsvParserStream } from '../src/CsvParserStream'; -import { parseFile, ParserOptionsArgs, Row, RowMap, RowValidateCallback } from '../src'; -import { ParserOptions } from '../src/ParserOptions'; +import { ParserOptions, CsvParserStream, parseFile, ParserOptionsArgs, Row, RowMap, RowValidateCallback } from '../src'; import { PathAndContent, ParseResults, @@ -30,10 +28,14 @@ import { import DoneCallback = jest.DoneCallback; describe('CsvParserStream', () => { - const createParserStream = (args?: ParserOptionsArgs): CsvParserStream => + const createParserStream = (args?: ParserOptionsArgs): CsvParserStream => new CsvParserStream(new ParserOptions(args)); - const listenForError = (stream: CsvParserStream, message: string, next: DoneCallback) => { + const listenForError = ( + stream: CsvParserStream, + message: string, + next: DoneCallback, + ) => { let called = false; stream .on('error', (err: Error) => { @@ -46,9 +48,12 @@ describe('CsvParserStream', () => { .on('end', () => next(new Error(`Expected and error to occur [expectedMessage=${message}]`))); }; - const parseContentAndCollect = (data: PathAndContent, options: ParserOptionsArgs = {}): Promise => - new Promise((res, rej) => { - const rows: Row[] = []; + const parseContentAndCollect = ( + data: PathAndContent, + options: ParserOptionsArgs = {}, + ): Promise> => { + return new Promise((res, rej) => { + const rows: R[] = []; const invalidRows: Row[] = []; const parser = createParserStream(options) .on('data', row => rows.push(row)) @@ -60,6 +65,7 @@ describe('CsvParserStream', () => { parser.write(data.content); parser.end(); }); + }; it('should parse a csv without quotes or escapes', () => expectParsed(parseContentAndCollect(withHeaders, { headers: true }), withHeaders.parsed)); @@ -204,7 +210,7 @@ describe('CsvParserStream', () => { )); it('should report missing columns that do not exist but have a header with strictColumnHandling option', async () => { - const expectedRows = withHeadersAndMissingColumns.parsed.filter(r => r.address !== null); + const expectedRows = withHeadersAndMissingColumns.parsed?.filter(r => r.address !== null); const expectedInvalidRows = withHeadersAndMissingColumns.parsed .filter(r => r.address === null) .map(r => Object.values(r).filter(v => !!v)); @@ -247,12 +253,8 @@ describe('CsvParserStream', () => { describe('alternate delimiters', () => { ['\t', '|', ';'].forEach(delimiter => { it(`should support '${delimiter.replace(/\t/, '\\t')}' delimiters`, async () => { - const { path: assetPath, content } = withHeadersAlternateDelimiter; - const data = { path: assetPath, content: content(delimiter) }; - await expectParsed( - parseContentAndCollect(data, { headers: true, delimiter }), - withHeadersAlternateDelimiter.parsed, - ); + const asset = withHeadersAlternateDelimiter(delimiter); + await expectParsed(parseContentAndCollect(asset, { headers: true, delimiter }), asset.parsed); }); }); }); @@ -289,11 +291,11 @@ describe('CsvParserStream', () => { describe('with transform', () => { it('should not transform skipped rows', async () => { let transformedRows: Row[] = []; - const transformer = (row: Row): Row => { + const transformer = (row: RowMap): RowMap => { const transformed = { - firstName: (row as RowMap).first_name, - lastName: (row as RowMap).last_name, - emailAddress: (row as RowMap).email_address, + firstName: row.first_name, + lastName: row.last_name, + emailAddress: row.email_address, }; transformedRows.push(transformed); return transformed; @@ -301,7 +303,9 @@ describe('CsvParserStream', () => { const linesToSkip = 2; const expected = withHeadersAndSkippedLines.parsed.map(transformer); transformedRows = []; - const parser = createParserStream({ headers: true, skipLines: linesToSkip }).transform(transformer); + const parser = createParserStream({ headers: true, skipLines: linesToSkip }).transform( + transformer, + ); await expectParsed(parseContentAndCollectFromStream(withHeadersAndSkippedLines, parser), expected); expect(transformedRows).toEqual(expected); }); @@ -394,12 +398,12 @@ describe('CsvParserStream', () => { describe('with transform', () => { it('should not transform skipped rows', async () => { let transformedRows: Row[] = []; - const transformer = (row: Row): Row => { + const transformer = (row: RowMap): RowMap => { const transformed = { - firstName: (row as RowMap).first_name, - lastName: (row as RowMap).last_name, - emailAddress: (row as RowMap).email_address, - address: (row as RowMap).address, + firstName: row.first_name, + lastName: row.last_name, + emailAddress: row.email_address, + address: row.address, }; transformedRows.push(transformed); return transformed; @@ -407,7 +411,7 @@ describe('CsvParserStream', () => { const skipRows = 3; const expected = withHeaders.parsed.slice(skipRows).map(transformer); transformedRows = []; - const parser = createParserStream({ headers: true, skipRows }).transform(transformer); + const parser = createParserStream({ headers: true, skipRows }).transform(transformer); await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected); expect(transformedRows).toEqual(expected); }); @@ -443,23 +447,23 @@ describe('CsvParserStream', () => { }); describe('#validate', () => { - const syncValidator = (row: Row): boolean => - parseInt((row as RowMap).first_name.replace(/^First/, ''), 10) % 2 === 1; - const asyncValidator = (row: Row, cb: RowValidateCallback) => { + const syncValidator = (row: RowMap): boolean => + parseInt(row.first_name ? row.first_name.replace(/^First/, '') : '0', 10) % 2 === 1; + const asyncValidator = (row: RowMap, cb: RowValidateCallback) => { cb(null, syncValidator(row)); }; it('should allow validation of rows', async () => { const [valid, invalid] = partition(withHeaders.parsed, syncValidator); - const parser = createParserStream({ headers: true }).validate(syncValidator); + const parser = createParserStream({ headers: true }).validate(syncValidator); await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), valid, invalid); }); it('should allow async validation of rows', async () => { - const validator = (row: Row): boolean => - parseInt((row as RowMap).first_name.replace(/^First/, ''), 10) % 2 !== 0; + const validator = (row: RowMap): boolean => + parseInt(row.first_name ? row.first_name.replace(/^First/, '') : '0', 10) % 2 === 1; const [valid, invalid] = partition(withHeaders.parsed, validator); - const parser = createParserStream({ headers: true }).validate(asyncValidator); + const parser = createParserStream({ headers: true }).validate(asyncValidator); await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), valid, invalid); }); @@ -483,9 +487,9 @@ describe('CsvParserStream', () => { it('should propagate async errors at the beginning', next => { write(withHeaders); - const stream = parseFile(withHeaders.path, { headers: true }).validate((data, validateNext) => - validateNext(new Error('Validation ERROR!!!!')), - ); + const stream = parseFile(withHeaders.path, { + headers: true, + }).validate((data: RowMap, validateNext) => validateNext(new Error('Validation ERROR!!!!'))); listenForError(stream, 'Validation ERROR!!!!', next); }); @@ -520,22 +524,22 @@ describe('CsvParserStream', () => { }); describe('#transform', () => { - const transformer = (row: Row): Row => ({ - firstName: (row as RowMap).first_name, - lastName: (row as RowMap).last_name, - emailAddress: (row as RowMap).email_address, - address: (row as RowMap).address, + const transformer = (row: RowMap): RowMap => ({ + firstName: row.first_name, + lastName: row.last_name, + emailAddress: row.email_address, + address: row.address, }); it('should allow transforming of data', async () => { const expected = withHeaders.parsed.map(transformer); - const parser = createParserStream({ headers: true }).transform(transformer); + const parser = createParserStream({ headers: true }).transform(transformer); await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected); }); it('should async transformation of data', async () => { const expected = withHeaders.parsed.map(transformer); - const parser = createParserStream({ headers: true }).transform((row, next) => + const parser = createParserStream({ headers: true }).transform((row, next) => setImmediate(() => next(null, transformer(row))), ); await expectParsed(parseContentAndCollectFromStream(withHeaders, parser), expected); @@ -544,15 +548,16 @@ describe('CsvParserStream', () => { it('should propogate errors when transformation of data', next => { write(withHeaders); let index = -1; - const stream = parseFile(withHeaders.path, { headers: true }).transform((data, cb) => - setImmediate(() => { - index += 1; - if (index === 8) { - cb(new Error('transformation ERROR!!!!')); - } else { - cb(null, transformer(data)); - } - }), + const stream = parseFile(withHeaders.path, { headers: true }).transform( + (data: RowMap, cb) => + setImmediate(() => { + index += 1; + if (index === 8) { + cb(new Error('transformation ERROR!!!!')); + } else { + cb(null, transformer(data)); + } + }), ); listenForError(stream, 'transformation ERROR!!!!', next); }); diff --git a/packages/parse/__tests__/__fixtures__/alternateEncoding.ts b/packages/parse/__tests__/__fixtures__/alternateEncoding.ts index 18187aac..39d5ce2c 100644 --- a/packages/parse/__tests__/__fixtures__/alternateEncoding.ts +++ b/packages/parse/__tests__/__fixtures__/alternateEncoding.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const alternateEncoding = { +export const alternateEncoding: PathAndContent = { path: resolve(__dirname, 'tmp', 'alternate_encoding.csv'), content: Buffer.from( diff --git a/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts b/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts index bba16be5..aa97cdf8 100644 --- a/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts +++ b/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts @@ -1,7 +1,9 @@ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const duplicateHeaders = { +export const duplicateHeaders: PathAndContent = { path: resolve(__dirname, 'tmp', 'duplicate_header.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/emptyRows.ts b/packages/parse/__tests__/__fixtures__/emptyRows.ts index 314bf2fd..ea6f9096 100644 --- a/packages/parse/__tests__/__fixtures__/emptyRows.ts +++ b/packages/parse/__tests__/__fixtures__/emptyRows.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const emptyRows = { +export const emptyRows: PathAndContent = { path: resolve(__dirname, 'tmp', 'empty_rows.csv'), content: ['first_name,last_name,email_address', '"","",""', '"","",""', '"","",', '"",,""', ',,', ''].join(EOL), diff --git a/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts b/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts index 2784f831..da608db2 100644 --- a/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts +++ b/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const headerColumnMismatch = { +export const headerColumnMismatch: PathAndContent = { path: resolve(__dirname, 'tmp', 'header_column_mismatch.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/helpers.ts b/packages/parse/__tests__/__fixtures__/helpers.ts index bbfc6deb..6c5c51ed 100644 --- a/packages/parse/__tests__/__fixtures__/helpers.ts +++ b/packages/parse/__tests__/__fixtures__/helpers.ts @@ -1,22 +1,23 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { CsvParserStream, Row } from '../../src'; -export interface PathAndContent { +export interface PathAndContent { path: string; content: string | Buffer; + parsed: T[]; } -export interface ParseResults { +export interface ParseResults { count: number; - rows: Row[]; + rows: O[]; invalidRows: Row[]; } -export const collectData = (stream: CsvParserStream): Promise => +export const collectData = (stream: CsvParserStream): Promise> => new Promise((res, rej) => { - const rows: Row[] = []; + const rows: O[] = []; const invalidRows: Row[] = []; stream - .on('data', (row: Row) => rows.push(row)) + .on('data', (row: O) => rows.push(row)) .on('data-invalid', (row: Row) => invalidRows.push(row)) .on('error', rej) .on('end', (count: number) => { @@ -24,15 +25,15 @@ export const collectData = (stream: CsvParserStream): Promise => }); }); -export const parseContentAndCollectFromStream = ( - data: PathAndContent, - parser: CsvParserStream, -): Promise => - new Promise((res, rej) => { - const rows: Row[] = []; +export const parseContentAndCollectFromStream = ( + data: PathAndContent, + parser: CsvParserStream, +): Promise> => { + return new Promise((res, rej) => { + const rows: O[] = []; const invalidRows: Row[] = []; parser - .on('data', row => rows.push(row)) + .on('data', (row: O) => rows.push(row)) .on('data-invalid', row => invalidRows.push(row)) .on('error', rej) .on('end', (count: number) => { @@ -41,9 +42,10 @@ export const parseContentAndCollectFromStream = ( parser.write(data.content); parser.end(); }); +}; -export const expectParsed = ( - resultsPromise: Promise, +export const expectParsed = ( + resultsPromise: Promise>, expectedRows: any[], expectedInvalidRows: any[] = [], ): Promise => { diff --git a/packages/parse/__tests__/__fixtures__/index.ts b/packages/parse/__tests__/__fixtures__/index.ts index bc88e547..11f50c38 100644 --- a/packages/parse/__tests__/__fixtures__/index.ts +++ b/packages/parse/__tests__/__fixtures__/index.ts @@ -1,6 +1,7 @@ import { existsSync, mkdirSync, writeFileSync } from 'fs'; import * as path from 'path'; import { PathAndContent } from './helpers'; +import { Row } from '../../src'; export * from './alternateEncoding'; export * from './noHeadersAndQuotes'; @@ -26,7 +27,7 @@ const mkDirIfNotExists = (filePath: string): void => { } }; -export const write = (opts: PathAndContent): void => { +export const write = (opts: PathAndContent): void => { mkDirIfNotExists(opts.path); writeFileSync(opts.path, opts.content); }; diff --git a/packages/parse/__tests__/__fixtures__/malformed.ts b/packages/parse/__tests__/__fixtures__/malformed.ts index e73b05c4..50df691d 100644 --- a/packages/parse/__tests__/__fixtures__/malformed.ts +++ b/packages/parse/__tests__/__fixtures__/malformed.ts @@ -1,7 +1,8 @@ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; -export const malformed = { +export const malformed: PathAndContent = { path: resolve(__dirname, 'tmp', 'malformed.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts b/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts index affe383c..fffe785c 100644 --- a/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts +++ b/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts @@ -1,7 +1,9 @@ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowArray } from '../../src'; -export const noHeadersAndQuotes = { +export const noHeadersAndQuotes: PathAndContent = { path: resolve(__dirname, 'tmp', 'no_headers_and_quotes.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/skipLines.ts b/packages/parse/__tests__/__fixtures__/skipLines.ts index 882d59bc..6fc3eb0f 100644 --- a/packages/parse/__tests__/__fixtures__/skipLines.ts +++ b/packages/parse/__tests__/__fixtures__/skipLines.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowArray } from '../../src'; -export const skipLines = { +export const skipLines: PathAndContent = { path: resolve(__dirname, 'tmp', 'skip_lines.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/tmp/malformed.csv b/packages/parse/__tests__/__fixtures__/tmp/malformed.csv new file mode 100644 index 00000000..9ab5a5f9 --- /dev/null +++ b/packages/parse/__tests__/__fixtures__/tmp/malformed.csv @@ -0,0 +1,3 @@ +first_name,last_name,email_address,address +"First1"a ", Last1 ,email1@email.com,"1 Street St, State ST, 88888" +First2,Last2,email2@email.com,"2 Street St, State ST, 88888" \ No newline at end of file diff --git a/packages/parse/__tests__/__fixtures__/tmp/with_headers.csv b/packages/parse/__tests__/__fixtures__/tmp/with_headers.csv new file mode 100644 index 00000000..b02811ef --- /dev/null +++ b/packages/parse/__tests__/__fixtures__/tmp/with_headers.csv @@ -0,0 +1,10 @@ +first_name,last_name,email_address +First1,Last1,email1@email.com +First2,Last2,email2@email.com +First3,Last3,email3@email.com +First4,Last4,email4@email.com +First5,Last5,email5@email.com +First6,Last6,email6@email.com +First7,Last7,email7@email.com +First8,Last8,email8@email.com +First9,Last9,email9@email.com \ No newline at end of file diff --git a/packages/parse/__tests__/__fixtures__/trailingComma.ts b/packages/parse/__tests__/__fixtures__/trailingComma.ts index 8e42c589..2aa60603 100644 --- a/packages/parse/__tests__/__fixtures__/trailingComma.ts +++ b/packages/parse/__tests__/__fixtures__/trailingComma.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const trailingComma = { +export const trailingComma: PathAndContent = { path: resolve(__dirname, 'tmp', 'trailing_comma.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/withHeaders.ts b/packages/parse/__tests__/__fixtures__/withHeaders.ts index 2dfb20e6..22cd8e50 100644 --- a/packages/parse/__tests__/__fixtures__/withHeaders.ts +++ b/packages/parse/__tests__/__fixtures__/withHeaders.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const withHeaders = { +export const withHeaders: PathAndContent = { path: resolve(__dirname, 'tmp', 'with_headers.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts b/packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts index 721d4a8a..6c6d8bdb 100644 --- a/packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAlternateDelimiter.ts @@ -1,25 +1,26 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const withHeadersAlternateDelimiter = { +export const withHeadersAlternateDelimiter = (delimiter = '\t'): PathAndContent => ({ path: resolve(__dirname, 'tmp', 'with_headers_alternate_delimiter.tsv'), - content: (delimiter = '\t'): string => - [ - 'first_name{delimiter}last_name{delimiter}email_address', - 'First1{delimiter}Last1{delimiter}email1@email.com', - 'First2{delimiter}Last2{delimiter}email2@email.com', - 'First3{delimiter}Last3{delimiter}email3@email.com', - 'First4{delimiter}Last4{delimiter}email4@email.com', - 'First5{delimiter}Last5{delimiter}email5@email.com', - 'First6{delimiter}Last6{delimiter}email6@email.com', - 'First7{delimiter}Last7{delimiter}email7@email.com', - 'First8{delimiter}Last8{delimiter}email8@email.com', - 'First9{delimiter}Last9{delimiter}email9@email.com', - ] - .map(r => r.replace(/{delimiter}/g, delimiter)) - .join(EOL), + content: [ + 'first_name{delimiter}last_name{delimiter}email_address', + 'First1{delimiter}Last1{delimiter}email1@email.com', + 'First2{delimiter}Last2{delimiter}email2@email.com', + 'First3{delimiter}Last3{delimiter}email3@email.com', + 'First4{delimiter}Last4{delimiter}email4@email.com', + 'First5{delimiter}Last5{delimiter}email5@email.com', + 'First6{delimiter}Last6{delimiter}email6@email.com', + 'First7{delimiter}Last7{delimiter}email7@email.com', + 'First8{delimiter}Last8{delimiter}email8@email.com', + 'First9{delimiter}Last9{delimiter}email9@email.com', + ] + .map(r => r.replace(/{delimiter}/g, delimiter)) + .join(EOL), parsed: [ { @@ -68,4 +69,4 @@ export const withHeadersAlternateDelimiter = { email_address: 'email9@email.com', }, ], -}; +}); diff --git a/packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts index c297c5cf..ff8c1bce 100644 --- a/packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndAlternateQuote.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const withHeadersAndAlternateQuote = { +export const withHeadersAndAlternateQuote: PathAndContent = { path: resolve(__dirname, 'tmp', 'no_headers_and_quotes.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts index 363acfd3..d1afab98 100644 --- a/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const withHeadersAndMissingColumns = { +export const withHeadersAndMissingColumns: PathAndContent = { path: resolve(__dirname, 'tmp', 'with_headers_and_missing_columns.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts index 9e92a1e8..c8996566 100644 --- a/packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndQuotes.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const withHeadersAndQuotes = { +export const withHeadersAndQuotes: PathAndContent = { path: resolve(__dirname, 'tmp', 'with_headers_and_quotes.csv'), content: [ diff --git a/packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts b/packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts index b8b6d258..ba30f2be 100644 --- a/packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts +++ b/packages/parse/__tests__/__fixtures__/withHeadersAndSkippedLines.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/camelcase */ import { resolve } from 'path'; import { EOL } from 'os'; +import { PathAndContent } from './helpers'; +import { RowMap } from '../../src'; -export const withHeadersAndSkippedLines = { +export const withHeadersAndSkippedLines: PathAndContent = { path: resolve(__dirname, 'tmp', 'with_headers_skip_lines.csv'), content: [ diff --git a/packages/parse/__tests__/parse.spec.ts b/packages/parse/__tests__/parse.spec.ts index 4109576f..13b335a3 100644 --- a/packages/parse/__tests__/parse.spec.ts +++ b/packages/parse/__tests__/parse.spec.ts @@ -26,5 +26,5 @@ describe('.parseFile', () => { describe('.parseString', () => { it('should accept a csv string', () => - expectParsed(collectData(parseString(withHeaders.content, { headers: true })), withHeaders.parsed)); + expectParsed(collectData(parseString(withHeaders.content as string, { headers: true })), withHeaders.parsed)); }); diff --git a/packages/parse/__tests__/transforms/HeaderTransformer.spec.ts b/packages/parse/__tests__/transforms/HeaderTransformer.spec.ts index 30088287..42ae40a7 100644 --- a/packages/parse/__tests__/transforms/HeaderTransformer.spec.ts +++ b/packages/parse/__tests__/transforms/HeaderTransformer.spec.ts @@ -1,11 +1,14 @@ -import { ParserOptionsArgs, RowArray, RowValidationResult } from '../../src'; +import { ParserOptions, ParserOptionsArgs, RowArray, RowValidationResult } from '../../src'; import { HeaderTransformer } from '../../src/transforms'; -import { ParserOptions } from '../../src/ParserOptions'; describe('HeaderTransformer', () => { - const createHeaderTransformer = (opts?: ParserOptionsArgs) => new HeaderTransformer(new ParserOptions(opts)); + const createHeaderTransformer = (opts?: ParserOptionsArgs) => + new HeaderTransformer(new ParserOptions(opts)); - const transform = (row: RowArray, transformer: HeaderTransformer): Promise => + const transform = ( + row: RowArray, + transformer: HeaderTransformer, + ): Promise> => new Promise((res, rej) => { transformer.transform(row, (err, results) => { if (err) { diff --git a/packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts b/packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts index e746a4fc..3ad2197a 100644 --- a/packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts +++ b/packages/parse/__tests__/transforms/RowTransformerValidator.spec.ts @@ -2,10 +2,13 @@ import { Row, RowArray, RowValidationResult } from '../../src'; import { RowTransformerValidator } from '../../src/transforms'; describe('RowTransformerValidator', () => { - const createRowTransformerValidator = () => new RowTransformerValidator(); + const createRowTransformerValidator = () => new RowTransformerValidator(); - const transformAndValidate = (row: RowArray, transformer: RowTransformerValidator): Promise => - new Promise((res, rej) => { + const transformAndValidate = ( + row: I, + transformer: RowTransformerValidator, + ): Promise> => { + return new Promise((res, rej) => { transformer.transformAndValidate(row, (err, results) => { if (err) { return rej(err); @@ -16,6 +19,7 @@ describe('RowTransformerValidator', () => { return res(results); }); }); + }; describe('#transformAndValidate', () => { it('should return a valid row if validator and transform are not defined', async () => { @@ -35,8 +39,8 @@ describe('RowTransformerValidator', () => { it('should transform a row synchronously', async () => { const row = ['a', 'b']; - const transformer = createRowTransformerValidator(); - transformer.rowTransform = (r: Row) => (r as RowArray).map(col => col.toUpperCase()); + const transformer = createRowTransformerValidator(); + transformer.rowTransform = (r: RowArray): RowArray => r.map(col => col.toUpperCase()); await expect(transformAndValidate(row, transformer)).resolves.toEqual({ row: ['A', 'B'], isValid: true, @@ -45,8 +49,8 @@ describe('RowTransformerValidator', () => { it('should transform a row synchronously', async () => { const row = ['a', 'b']; - const transformer = createRowTransformerValidator(); - transformer.rowTransform = (r: Row) => (r as RowArray).map(col => col.toUpperCase()); + const transformer = createRowTransformerValidator(); + transformer.rowTransform = (r: RowArray): RowArray => r.map(col => col.toUpperCase()); await expect(transformAndValidate(row, transformer)).resolves.toEqual({ row: ['A', 'B'], isValid: true, @@ -65,12 +69,12 @@ describe('RowTransformerValidator', () => { it('should transform a row asynchronously', async () => { const row = ['a', 'b']; - const transformer = createRowTransformerValidator(); - transformer.rowTransform = (r: Row, cb) => { + const transformer = createRowTransformerValidator(); + transformer.rowTransform = (r: RowArray, cb) => { setImmediate(() => { cb( null, - (r as RowArray).map(col => col.toUpperCase()), + r.map(col => col.toUpperCase()), ); }); }; @@ -82,7 +86,7 @@ describe('RowTransformerValidator', () => { it('should resolve with an error if an error is provided to the callback', async () => { const row = ['a', 'b']; - const transformer = createRowTransformerValidator(); + const transformer = createRowTransformerValidator(); transformer.rowTransform = (r: Row, cb) => { setImmediate(() => { cb(new Error('Expected error')); diff --git a/packages/parse/src/CsvParserStream.ts b/packages/parse/src/CsvParserStream.ts index 7509274f..49b4f393 100644 --- a/packages/parse/src/CsvParserStream.ts +++ b/packages/parse/src/CsvParserStream.ts @@ -5,16 +5,16 @@ import { HeaderTransformer, RowTransformerValidator } from './transforms'; import { Parser } from './parser'; import { Row, RowArray, RowTransformFunction, RowValidate, RowValidatorCallback } from './types'; -export class CsvParserStream extends Transform { +export class CsvParserStream extends Transform { private readonly parserOptions: ParserOptions; private readonly decoder: StringDecoder; private readonly parser: Parser; - private readonly headerTransformer: HeaderTransformer; + private readonly headerTransformer: HeaderTransformer; - private readonly rowTransformerValidator: RowTransformerValidator; + private readonly rowTransformerValidator: RowTransformerValidator; private lines = ''; @@ -47,12 +47,12 @@ export class CsvParserStream extends Transform { return this.parsedLineCount <= this.parserOptions.skipLines; } - public transform(transformFunction: RowTransformFunction): CsvParserStream { + public transform(transformFunction: RowTransformFunction): CsvParserStream { this.rowTransformerValidator.rowTransform = transformFunction; return this; } - public validate(validateFunction: RowValidate): CsvParserStream { + public validate(validateFunction: RowValidate): CsvParserStream { this.rowTransformerValidator.rowValidator = validateFunction; return this; } @@ -153,7 +153,7 @@ export class CsvParserStream extends Transform { iterate(0); } - private transformRow(parsedRow: RowArray, cb: RowValidatorCallback): void { + private transformRow(parsedRow: RowArray, cb: RowValidatorCallback): void { try { this.headerTransformer.transform(parsedRow, (err, withHeaders): void => { if (err) { @@ -163,7 +163,7 @@ export class CsvParserStream extends Transform { return cb(new Error('Expected result from header transform')); } if (!withHeaders.isValid) { - return cb(null, { isValid: false, row: parsedRow }); + return cb(null, { isValid: false, row: (parsedRow as never) as O }); } if (withHeaders.row) { if (this.shouldEmitRows) { diff --git a/packages/parse/src/index.ts b/packages/parse/src/index.ts index a1de19d8..9740f546 100644 --- a/packages/parse/src/index.ts +++ b/packages/parse/src/index.ts @@ -2,20 +2,29 @@ import * as fs from 'fs'; import { Readable } from 'stream'; import { ParserOptions, ParserOptionsArgs } from './ParserOptions'; import { CsvParserStream } from './CsvParserStream'; +import { Row } from './types'; export * from './types'; export { CsvParserStream } from './CsvParserStream'; export { ParserOptions, ParserOptionsArgs } from './ParserOptions'; -export const parse = (args?: ParserOptionsArgs): CsvParserStream => new CsvParserStream(new ParserOptions(args)); +export const parse = (args?: ParserOptionsArgs): CsvParserStream => + new CsvParserStream(new ParserOptions(args)); -export const parseStream = (stream: NodeJS.ReadableStream, options?: ParserOptionsArgs): CsvParserStream => - stream.pipe(new CsvParserStream(new ParserOptions(options))); +export const parseStream = ( + stream: NodeJS.ReadableStream, + options?: ParserOptionsArgs, +): CsvParserStream => stream.pipe(new CsvParserStream(new ParserOptions(options))); -export const parseFile = (location: string, options: ParserOptionsArgs = {}): CsvParserStream => - fs.createReadStream(location).pipe(new CsvParserStream(new ParserOptions(options))); +export const parseFile = ( + location: string, + options: ParserOptionsArgs = {}, +): CsvParserStream => fs.createReadStream(location).pipe(new CsvParserStream(new ParserOptions(options))); -export const parseString = (string: string, options?: ParserOptionsArgs): CsvParserStream => { +export const parseString = ( + string: string, + options?: ParserOptionsArgs, +): CsvParserStream => { const rs = new Readable(); rs.push(string); rs.push(null); diff --git a/packages/parse/src/transforms/HeaderTransformer.ts b/packages/parse/src/transforms/HeaderTransformer.ts index 1b933151..b607a4c7 100644 --- a/packages/parse/src/transforms/HeaderTransformer.ts +++ b/packages/parse/src/transforms/HeaderTransformer.ts @@ -13,7 +13,7 @@ import { RowValidatorCallback, } from '../types'; -export class HeaderTransformer { +export class HeaderTransformer { private readonly parserOptions: ParserOptions; private headers: HeaderArray | null = null; @@ -39,7 +39,7 @@ export class HeaderTransformer { } } - public transform(row: RowArray, cb: RowValidatorCallback): void { + public transform(row: RowArray, cb: RowValidatorCallback): void { if (!this.shouldMapRow(row)) { return cb(null, { row: null, isValid: true }); } @@ -69,9 +69,9 @@ export class HeaderTransformer { return true; } - private processRow(row: RowArray): RowValidationResult { + private processRow(row: RowArray): RowValidationResult { if (!this.headers) { - return { row, isValid: true }; + return { row: (row as never) as O, isValid: true }; } const { parserOptions } = this; if (!parserOptions.discardUnmappedColumns && row.length > this.headersLength) { @@ -81,14 +81,14 @@ export class HeaderTransformer { ); } return { - row, + row: (row as never) as O, isValid: false, reason: `Column header mismatch expected: ${this.headersLength} columns got: ${row.length}`, }; } if (parserOptions.strictColumnHandling && row.length < this.headersLength) { return { - row, + row: (row as never) as O, isValid: false, reason: `Column header mismatch expected: ${this.headersLength} columns got: ${row.length}`, }; @@ -96,7 +96,7 @@ export class HeaderTransformer { return { row: this.mapHeaders(row), isValid: true }; } - private mapHeaders(row: RowArray): Row { + private mapHeaders(row: RowArray): O { const rowMap: RowMap = {}; const { headers, headersLength } = this; for (let i = 0; i < headersLength; i += 1) { @@ -111,7 +111,7 @@ export class HeaderTransformer { } } } - return rowMap; + return rowMap as O; } private setHeaders(headers: HeaderArray): void { diff --git a/packages/parse/src/transforms/RowTransformerValidator.ts b/packages/parse/src/transforms/RowTransformerValidator.ts index 6ba3c53a..a1766d19 100644 --- a/packages/parse/src/transforms/RowTransformerValidator.ts +++ b/packages/parse/src/transforms/RowTransformerValidator.ts @@ -11,13 +11,15 @@ import { RowTransformCallback, } from '../types'; -type RowValidator = (row: Row, cb: RowValidatorCallback) => void; +type RowValidator = (row: R, cb: RowValidatorCallback) => void; -export class RowTransformerValidator { - private static createTransform(transformFunction: RowTransformFunction): AsyncRowTransform { +export class RowTransformerValidator { + private static createTransform( + transformFunction: RowTransformFunction, + ): AsyncRowTransform { if (isSyncTransform(transformFunction)) { return (row, cb): void => { - let transformed: Row | null = null; + let transformed: O | null = null; try { transformed = transformFunction(row); } catch (e) { @@ -26,17 +28,17 @@ export class RowTransformerValidator { return cb(null, transformed); }; } - return transformFunction as AsyncRowTransform; + return transformFunction as AsyncRowTransform; } - private static createValidator(validateFunction: RowValidate): RowValidator { + private static createValidator(validateFunction: RowValidate): RowValidator { if (isSyncValidate(validateFunction)) { - return (row, cb): void => { + return (row: R, cb: RowValidatorCallback): void => { cb(null, { row, isValid: validateFunction(row) }); }; } return (row, cb): void => { - (validateFunction as AsyncRowValidate)(row, (err, isValid, reason): void => { + (validateFunction as AsyncRowValidate)(row, (err, isValid, reason): void => { if (err) { return cb(err); } @@ -48,25 +50,25 @@ export class RowTransformerValidator { }; } - private _rowTransform: AsyncRowTransform | null = null; + private _rowTransform: AsyncRowTransform | null = null; - private _rowValidator: RowValidator | null = null; + private _rowValidator: RowValidator | null = null; - public set rowTransform(transformFunction: RowTransformFunction) { + public set rowTransform(transformFunction: RowTransformFunction) { if (!isFunction(transformFunction)) { throw new TypeError('The transform should be a function'); } this._rowTransform = RowTransformerValidator.createTransform(transformFunction); } - public set rowValidator(validateFunction: RowValidate) { + public set rowValidator(validateFunction: RowValidate) { if (!isFunction(validateFunction)) { throw new TypeError('The validate should be a function'); } this._rowValidator = RowTransformerValidator.createValidator(validateFunction); } - public transformAndValidate(row: Row, cb: RowValidatorCallback): void { + public transformAndValidate(row: I, cb: RowValidatorCallback): void { return this.callTransformer(row, (transformErr, transformedRow): void => { if (transformErr) { return cb(transformErr); @@ -86,14 +88,14 @@ export class RowTransformerValidator { }); } - private callTransformer(row: Row, cb: RowTransformCallback): void { + private callTransformer(row: I, cb: RowTransformCallback): void { if (!this._rowTransform) { - return cb(null, row); + return cb(null, (row as never) as O); } return this._rowTransform(row, cb); } - private callValidator(row: Row, cb: RowValidatorCallback): void { + private callValidator(row: O, cb: RowValidatorCallback): void { if (!this._rowValidator) { return cb(null, { row, isValid: true }); } diff --git a/packages/parse/src/types.ts b/packages/parse/src/types.ts index 6e083cb0..221925c8 100644 --- a/packages/parse/src/types.ts +++ b/packages/parse/src/types.ts @@ -1,32 +1,34 @@ export interface RowMap { - [s: string]: string; + [s: string]: string | undefined | null; } export type RowArray = string[]; export type Row = RowMap | RowArray; -export interface RowValidationResult { - row: Row | null; +export interface RowValidationResult { + row: R | null; isValid: boolean; reason?: string; } -export type RowValidatorCallback = (error: Error | null, result?: RowValidationResult) => void; +export type RowValidatorCallback = (error: Error | null, result?: RowValidationResult) => void; -export type RowTransformCallback = (error?: Error | null, row?: Row) => void; -export type SyncRowTransform = (row: Row) => Row; -export type AsyncRowTransform = (row: Row, cb: RowTransformCallback) => void; -export type RowTransformFunction = SyncRowTransform | AsyncRowTransform; +export type RowTransformCallback = (error?: Error | null, row?: R) => void; +export type SyncRowTransform = (row: I) => O; +export type AsyncRowTransform = (row: I, cb: RowTransformCallback) => void; +export type RowTransformFunction = SyncRowTransform | AsyncRowTransform; -export const isSyncTransform = (transform: RowTransformFunction): transform is SyncRowTransform => - transform.length === 1; +export const isSyncTransform = ( + transform: RowTransformFunction, +): transform is SyncRowTransform => transform.length === 1; export type RowValidateCallback = (error?: Error | null, isValid?: boolean, reason?: string) => void; -export type SyncRowValidate = (row: Row) => boolean; -export type AsyncRowValidate = (row: Row, cb: RowValidateCallback) => void; -export type RowValidate = AsyncRowValidate | SyncRowValidate; +export type SyncRowValidate = (row: R) => boolean; +export type AsyncRowValidate = (row: R, cb: RowValidateCallback) => void; +export type RowValidate = AsyncRowValidate | SyncRowValidate; -export const isSyncValidate = (validate: RowValidate): validate is SyncRowValidate => validate.length === 1; +export const isSyncValidate = (validate: RowValidate): validate is SyncRowValidate => + validate.length === 1; export type HeaderArray = (string | undefined | null)[]; export type HeaderTransformFunction = (headers: HeaderArray) => HeaderArray; diff --git a/tsconfig.build.json b/tsconfig.build.json index e34fb009..36bf17fa 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -18,7 +18,6 @@ "outDir": "build" }, "exclude": [ - "**/node_modules/**", - "**/build/**" + "node_modules" ] } \ No newline at end of file From ba0a6b2cceab09c031c74b0b4665f0f5b06eff8c Mon Sep 17 00:00:00 2001 From: doug-martin Date: Thu, 26 Dec 2019 14:50:30 -0600 Subject: [PATCH 6/8] Update main README and fix import paths --- README.md | 39 +++++++++---------- .../parse/__tests__/ParserOptions.spec.ts | 3 +- .../parse/__tests__/parser/Parser.spec.ts | 3 +- .../parse/__tests__/parser/RowParser.spec.ts | 3 +- .../parse/__tests__/parser/Scanner.spec.ts | 3 +- .../parser/column/ColumnParser.spec.ts | 2 +- .../column/NonQuotedColumnParser.spec.ts | 3 +- .../parser/column/QuotedColumnParser.spec.ts | 3 +- 8 files changed, 26 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index d51e0958..3e6b58b7 100644 --- a/README.md +++ b/README.md @@ -7,34 +7,33 @@ Fast-csv is library for parsing and formatting csvs or any other delimited value file in node. -## Installation - -`npm install -S fast-csv` - ## Packages There are three packages published from this repo. -* [`fast-csv`](./packages/fast-csv) - Exposes both formatting and parsing methods in a single package -* [`@fast-csv/parse`](./packages/parse) - Parsing package, use this if you only need to parse files. -* [`@fast-csv/format`](./packages/format) - Formatting package, use this if you only need to format files. +### [`fast-csv`](./packages/fast-csv) + +Exposes both formatting and parsing methods in a single package, use this if you need to parse and format files. + +* [Docs](./packages/fast-csv/README.md) +* [JavaScript Examples](./examples/fast-csv-js/README.md) +* [TypeScript Examples](./examples/fast-csv-ts/README.md) + +###[`@fast-csv/parse`](./packages/parse) -## Documentation +Parsing package, use this if you only need to parse files. -* [`fast-csv` Docs](./packages/fast-csv/README.md) -* [Parsing Docs](./packages/parse/README.md) -* [Formatting Docs](./packages/format/README.md) +* [Docs](./packages/parse/README.md) +* [JavaScript Examples](./examples/parsing-js/README.md) +* [TypeScript Examples](./examples/parsing-ts/README.md) -### Examples +### [`@fast-csv/format`](./packages/format) -* JavaScript - * [`fast-csv`](./examples/fast-csv-js/README.md) - * [`@fast-csv/format`](./examples/formatting-js/README.md) - * [`@fast-csv/parse`](./examples/parsing-js/README.md) -* TypeScript - * [`fast-csv`](./examples/fast-csv-ts/README.md) - * [`@fast-csv/format`](./examples/formatting-ts/README.md) - * [`@fast-csv/parse`](./examples/parsing-ts/README.md) +Formatting package, use this if you only need to format files. + +* [Docs](./packages/format/README.md) +* [JavaScript Examples](./examples/formatting-js/README.md) +* [TypeScript Examples](./examples/formatting-ts/README.md) ### Migrating from older versions diff --git a/packages/parse/__tests__/ParserOptions.spec.ts b/packages/parse/__tests__/ParserOptions.spec.ts index a2afba50..fb8477cf 100644 --- a/packages/parse/__tests__/ParserOptions.spec.ts +++ b/packages/parse/__tests__/ParserOptions.spec.ts @@ -1,5 +1,4 @@ -import { ParserOptionsArgs } from '../src'; -import { ParserOptions } from '../src/ParserOptions'; +import { ParserOptions, ParserOptionsArgs } from '../src'; describe('ParserOptions', () => { const createOptions = (opts: ParserOptionsArgs = {}) => new ParserOptions(opts); diff --git a/packages/parse/__tests__/parser/Parser.spec.ts b/packages/parse/__tests__/parser/Parser.spec.ts index e903aa77..67c7275d 100644 --- a/packages/parse/__tests__/parser/Parser.spec.ts +++ b/packages/parse/__tests__/parser/Parser.spec.ts @@ -1,5 +1,4 @@ -import { ParserOptionsArgs } from '../../src'; -import { ParserOptions } from '../../src/ParserOptions'; +import { ParserOptions, ParserOptionsArgs } from '../../src'; import { Parser } from '../../src/parser'; describe('Parser', () => { diff --git a/packages/parse/__tests__/parser/RowParser.spec.ts b/packages/parse/__tests__/parser/RowParser.spec.ts index 26aef5b8..cdc105cf 100644 --- a/packages/parse/__tests__/parser/RowParser.spec.ts +++ b/packages/parse/__tests__/parser/RowParser.spec.ts @@ -1,5 +1,4 @@ -import { ParserOptionsArgs } from '../../src'; -import { ParserOptions } from '../../src/ParserOptions'; +import { ParserOptions, ParserOptionsArgs } from '../../src'; import { RowParser, Scanner } from '../../src/parser'; describe('RowParser', () => { diff --git a/packages/parse/__tests__/parser/Scanner.spec.ts b/packages/parse/__tests__/parser/Scanner.spec.ts index 0ef0db38..5adad938 100644 --- a/packages/parse/__tests__/parser/Scanner.spec.ts +++ b/packages/parse/__tests__/parser/Scanner.spec.ts @@ -1,5 +1,4 @@ -import { ParserOptionsArgs } from '../../src'; -import { ParserOptions } from '../../src/ParserOptions'; +import { ParserOptions, ParserOptionsArgs } from '../../src'; import { MaybeToken, Scanner, Token } from '../../src/parser'; const createOptions = (opts: ParserOptionsArgs = {}) => new ParserOptions(opts); diff --git a/packages/parse/__tests__/parser/column/ColumnParser.spec.ts b/packages/parse/__tests__/parser/column/ColumnParser.spec.ts index 5e8e4781..c44f983d 100644 --- a/packages/parse/__tests__/parser/column/ColumnParser.spec.ts +++ b/packages/parse/__tests__/parser/column/ColumnParser.spec.ts @@ -1,5 +1,5 @@ import * as sinon from 'sinon'; -import { ParserOptions } from '../../../src/ParserOptions'; +import { ParserOptions } from '../../../src'; import { ColumnParser } from '../../../src/parser/column'; import { Scanner } from '../../../src/parser'; diff --git a/packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts b/packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts index 38dd632f..6d9604a8 100644 --- a/packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts +++ b/packages/parse/__tests__/parser/column/NonQuotedColumnParser.spec.ts @@ -1,5 +1,4 @@ -import { ParserOptionsArgs } from '../../../src'; -import { ParserOptions } from '../../../src/ParserOptions'; +import { ParserOptions, ParserOptionsArgs } from '../../../src'; import { NonQuotedColumnParser } from '../../../src/parser/column'; import { Scanner } from '../../../src/parser'; diff --git a/packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts b/packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts index e99dc76e..6a152d4a 100644 --- a/packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts +++ b/packages/parse/__tests__/parser/column/QuotedColumnParser.spec.ts @@ -1,5 +1,4 @@ -import { ParserOptionsArgs } from '../../../src'; -import { ParserOptions } from '../../../src/ParserOptions'; +import { ParserOptions, ParserOptionsArgs } from '../../../src'; import { QuotedColumnParser } from '../../../src/parser/column'; import { Scanner } from '../../../src/parser'; From bcb4eedebf9b14873d0f63575bbf8ebac0ca19f1 Mon Sep 17 00:00:00 2001 From: doug-martin Date: Thu, 26 Dec 2019 15:26:52 -0600 Subject: [PATCH 7/8] [ADDED] Docs around using `strictColumnHandling` to emit errors when there are more columns than headers [#195] --- History.md | 1 + packages/parse/README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/History.md b/History.md index d5a2d44c..736d6f5a 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,7 @@ * Updated docs for new directory layout * Added typescript examples * Added generics type support to format and parse streams +* [ADDED] Docs around using `strictColumnHandling` to emit errors when there are more columns than headers [#195] # v3.7.0 diff --git a/packages/parse/README.md b/packages/parse/README.md index 417b0a67..f9f2e6cb 100644 --- a/packages/parse/README.md +++ b/packages/parse/README.md @@ -47,6 +47,7 @@ import * as format csv '@fast-csv/parse'; * If you wish to discard the first row and use your own headers set to a `string[]` and set the `renameHeaders` option to `true` * If you wish to transform the headers you can provide a transform function. * **NOTE** This will always rename the headers + * **NOTE** If you specify headers and there are more columns than headers an error WILL NOT be emitted unless `strictColumnHandling` is set to `true` * **NOTE** If headers either parsed, provided or transformed are NOT unique, then an error will be emitted and the stream will stop parsing. * `renameHeaders: {boolean} = false`: If you want the first line of the file to be removed and replaced by the one provided in the `headers` option. * **NOTE** This option should only be used if the `headers` option is a `string[]` From 9b3bcc76a7ee0ae689069eb575b39a6676f157ae Mon Sep 17 00:00:00 2001 From: doug-martin Date: Thu, 26 Dec 2019 15:46:09 -0600 Subject: [PATCH 8/8] Bump version to alpha version --- .gitignore | 3 ++- examples/benchmark/package.json | 3 ++- examples/example-runner/package.json | 2 +- examples/fast-csv-js/package.json | 5 +++-- examples/fast-csv-ts/package.json | 5 +++-- examples/formatting-js/package.json | 5 +++-- examples/formatting-ts/package.json | 5 +++-- examples/parsing-js/package.json | 5 +++-- examples/parsing-ts/package.json | 5 +++-- lerna.json | 6 +++--- package-lock.json | 3 +-- package.json | 1 - packages/fast-csv/package.json | 10 ++++------ packages/format/package.json | 2 +- packages/parse/package.json | 2 +- 15 files changed, 33 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 6fa84ca6..4ed9ace8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ benchmark/results build coverage **/*.tmp.csv -**/*.tsbuildinfo \ No newline at end of file +**/*.tsbuildinfo +lerna-debug.log \ No newline at end of file diff --git a/examples/benchmark/package.json b/examples/benchmark/package.json index 04eb1b97..ebb345c1 100644 --- a/examples/benchmark/package.json +++ b/examples/benchmark/package.json @@ -1,9 +1,10 @@ { "name": "fast-csv-benchmarks", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv examples", "dependencies": { - "fast-csv": "^4.0.0" + "fast-csv": "^4.0.0-alpha.0" }, "scripts": { "benchmarks": "node ./index.js" diff --git a/examples/example-runner/package.json b/examples/example-runner/package.json index 92d0bf6a..b6924f05 100644 --- a/examples/example-runner/package.json +++ b/examples/example-runner/package.json @@ -1,6 +1,6 @@ { "name": "example-runner", - "version": "4.0.0", + "version": "4.0.0-alpha.0", "private": true, "description": "Runs examples and checks output", "bin": { diff --git a/examples/fast-csv-js/package.json b/examples/fast-csv-js/package.json index 00e9d196..cd473d57 100644 --- a/examples/fast-csv-js/package.json +++ b/examples/fast-csv-js/package.json @@ -1,5 +1,6 @@ { "name": "fast-csv-js-examples", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv examples", "scripts": { @@ -8,7 +9,7 @@ "example": "run-examples run" }, "dependencies": { - "example-runner": "^4.0.0", - "fast-csv": "^4.0.0" + "example-runner": "^4.0.0-alpha.0", + "fast-csv": "^4.0.0-alpha.0" } } diff --git a/examples/fast-csv-ts/package.json b/examples/fast-csv-ts/package.json index 0ff65e06..b0ee4103 100644 --- a/examples/fast-csv-ts/package.json +++ b/examples/fast-csv-ts/package.json @@ -1,5 +1,6 @@ { "name": "fast-csv-ts-examples", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv examples", "scripts": { @@ -11,8 +12,8 @@ "compile": "tsc -p tsconfig.build.json" }, "dependencies": { - "example-runner": "^4.0.0", - "fast-csv": "^4.0.0", + "example-runner": "^4.0.0-alpha.0", + "fast-csv": "^4.0.0-alpha.0", "typescript": "^3.7.3" } } diff --git a/examples/formatting-js/package.json b/examples/formatting-js/package.json index 309d708b..b328a001 100644 --- a/examples/formatting-js/package.json +++ b/examples/formatting-js/package.json @@ -1,5 +1,6 @@ { "name": "@fast-csv/format-js-examples", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv formatting examples", "scripts": { @@ -8,7 +9,7 @@ "example": "run-examples run" }, "dependencies": { - "example-runner": "^4.0.0", - "@fast-csv/format": "^4.0.0" + "@fast-csv/format": "^4.0.0-alpha.0", + "example-runner": "^4.0.0-alpha.0" } } diff --git a/examples/formatting-ts/package.json b/examples/formatting-ts/package.json index ea27c3d6..1d9923c7 100644 --- a/examples/formatting-ts/package.json +++ b/examples/formatting-ts/package.json @@ -1,5 +1,6 @@ { "name": "@fast-csv/formatting-ts-examples", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv formatting typescript examples", "scripts": { @@ -11,8 +12,8 @@ "compile": "tsc -p tsconfig.build.json" }, "dependencies": { - "example-runner": "^4.0.0", - "@fast-csv/format": "^4.0.0", + "@fast-csv/format": "^4.0.0-alpha.0", + "example-runner": "^4.0.0-alpha.0", "typescript": "^3.7.3" } } diff --git a/examples/parsing-js/package.json b/examples/parsing-js/package.json index dc521335..37a8fe01 100644 --- a/examples/parsing-js/package.json +++ b/examples/parsing-js/package.json @@ -1,5 +1,6 @@ { "name": "@fast-csv/parse-js-examples", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv parsing examples", "scripts": { @@ -8,8 +9,8 @@ "example": "run-examples run" }, "dependencies": { - "example-runner": "^4.0.0", - "@fast-csv/parse": "^4.0.0", + "@fast-csv/parse": "^4.0.0-alpha.0", + "example-runner": "^4.0.0-alpha.0", "globby": "^10.0.1", "jest-diff": "^24.9.0" } diff --git a/examples/parsing-ts/package.json b/examples/parsing-ts/package.json index 4d9446dd..f8e2cfc3 100644 --- a/examples/parsing-ts/package.json +++ b/examples/parsing-ts/package.json @@ -1,5 +1,6 @@ { "name": "@fast-csv/parse-ts-examples", + "version": "4.0.0-alpha.0", "private": true, "description": "fast-csv parsing typescript examples", "scripts": { @@ -11,8 +12,8 @@ "compile": "tsc -p tsconfig.build.json" }, "dependencies": { - "example-runner": "^4.0.0", - "@fast-csv/parse": "^4.0.0", + "@fast-csv/parse": "^4.0.0-alpha.0", + "example-runner": "^4.0.0-alpha.0", "typescript": "^3.7.3" } } diff --git a/lerna.json b/lerna.json index 36e5e91a..463303f4 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,7 @@ { "packages": [ - "packages/*", - "examples/*" + "examples/*", + "packages/*" ], - "version": "4.0.0" + "version": "4.0.0-alpha.0" } diff --git a/package-lock.json b/package-lock.json index 3e9f2061..e1960eaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,7 @@ { "name": "fast-csv", - "version": "4.0.0", - "lockfileVersion": 1, "requires": true, + "lockfileVersion": 1, "dependencies": { "@babel/code-frame": { "version": "7.0.0", diff --git a/package.json b/package.json index 63a65f37..ad360871 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,5 @@ { "name": "fast-csv", - "version": "4.0.0", "private": true, "scripts": { "bootstrap": "lerna bootstrap --hoist", diff --git a/packages/fast-csv/package.json b/packages/fast-csv/package.json index 18916a86..e0705929 100644 --- a/packages/fast-csv/package.json +++ b/packages/fast-csv/package.json @@ -1,6 +1,6 @@ { "name": "fast-csv", - "version": "4.0.0", + "version": "4.0.0-alpha.0", "description": "CSV parser and writer", "main": "./build/src/index.js", "types": "./build/src/index.d.ts", @@ -31,14 +31,12 @@ "homepage": "http://c2fo.github.com/fast-csv/index.html", "author": "Doug Martin", "license": "MIT", - "devDependencies": { - }, "engines": { "node": ">=8.0.0" }, "dependencies": { - "@types/node": "^12.12.17", - "@fast-csv/parse": "4.0.0", - "@fast-csv/format": "4.0.0" + "@fast-csv/format": "^4.0.0-alpha.0", + "@fast-csv/parse": "^4.0.0-alpha.0", + "@types/node": "^12.12.17" } } diff --git a/packages/format/package.json b/packages/format/package.json index 9235ecb4..278014c5 100644 --- a/packages/format/package.json +++ b/packages/format/package.json @@ -1,6 +1,6 @@ { "name": "@fast-csv/format", - "version": "4.0.0", + "version": "4.0.0-alpha.0", "description": "fast-csv formatting module", "keywords": [ "csv", diff --git a/packages/parse/package.json b/packages/parse/package.json index 6efdd963..95416c6f 100644 --- a/packages/parse/package.json +++ b/packages/parse/package.json @@ -1,6 +1,6 @@ { "name": "@fast-csv/parse", - "version": "4.0.0", + "version": "4.0.0-alpha.0", "description": "fast-csv parsing package", "keywords": [ "csv",