From dd784241e14d8e43fbe64dce5a066afea29b7d51 Mon Sep 17 00:00:00 2001 From: Andrew Mitchell Date: Fri, 17 Dec 2021 19:00:20 -0500 Subject: [PATCH 1/6] Adds a return type to csv's parse and removes a custom parse option from the args --- encoding/csv.ts | 43 +++----------------------------- encoding/csv_test.ts | 59 +++----------------------------------------- 2 files changed, 7 insertions(+), 95 deletions(-) diff --git a/encoding/csv.ts b/encoding/csv.ts index 33e1d346b4f5..c158ee098901 100644 --- a/encoding/csv.ts +++ b/encoding/csv.ts @@ -361,44 +361,22 @@ export interface ParseOptions extends ReadOptions { * If you provide `string[]` or `ColumnOptions[]`, those names will be used for header definition. */ columns?: string[] | ColumnOptions[]; - - /** Parse function for rows. - * Example: - * ```ts - * import { parse } from "./csv.ts"; - * const r = await parse('a,b,c\ne,f,g\n', { - * columns: ["this", "is", "sparta"], - * parse: (_e: unknown) => { - * const e = _e as { this: unknown, is: unknown, sparta: unknown }; - * return { super: e.this, street: e.is, fighter: e.sparta }; - * } - * }); - * // output - * // [ - * // { super: "a", street: "b", fighter: "c" }, - * // { super: "e", street: "f", fighter: "g" } - * // ] - * ``` - */ - parse?: (input: unknown) => unknown; } /** * Csv parse helper to manipulate data. - * Provides an auto/custom mapper for columns and parse function - * for columns and rows. + * Provides an auto/custom mapper for columns for columns and rows. * @param input Input to parse. Can be a string or BufReader. * @param opt options of the parser. * @returns If you don't provide `opt.skipFirstRow`, `opt.parse`, and `opt.columns`, it returns `string[][]`. * If you provide `opt.skipFirstRow` or `opt.columns` but not `opt.parse`, it returns `object[]`. - * If you provide `opt.parse`, it returns an array where each element is the value returned from `opt.parse`. */ export async function parse( input: string | BufReader, opt: ParseOptions = { skipFirstRow: false, }, -): Promise { +): Promise[]> { let r: string[][]; if (input instanceof BufReader) { r = await readMatrix(input, opt); @@ -436,7 +414,7 @@ export async function parse( ); } } - return r.map((e): unknown => { + return r.map((e) => { if (e.length !== headers.length) { throw `Error number of fields line:${i}`; } @@ -444,23 +422,10 @@ export async function parse( const out: Record = {}; for (let j = 0; j < e.length; j++) { const h = headers[j]; - if (h.parse) { - out[h.name] = h.parse(e[j]); - } else { - out[h.name] = e[j]; - } - } - if (opt.parse) { - return opt.parse(out); + out[h.name] = e[j]; } return out; }); } - if (opt.parse) { - return r.map((e: string[]): unknown => { - assert(opt.parse, "opt.parse must be set"); - return opt.parse(e); - }); - } return r; } diff --git a/encoding/csv_test.ts b/encoding/csv_test.ts index 8c64d274ad9e..7550192c1cd0 100644 --- a/encoding/csv_test.ts +++ b/encoding/csv_test.ts @@ -549,58 +549,6 @@ const parseTestCases = [ { this: "e", is: "f", sparta: "g" }, ], }, - { - name: "header mapping parse entry", - in: "a,b,c\ne,f,g\n", - columns: [ - { - name: "this", - parse: (e: string): string => { - return `b${e}$$`; - }, - }, - { - name: "is", - parse: (e: string): number => { - return e.length; - }, - }, - { - name: "sparta", - parse: (e: string): unknown => { - return { bim: `boom-${e}` }; - }, - }, - ], - result: [ - { this: "ba$$", is: 1, sparta: { bim: `boom-c` } }, - { this: "be$$", is: 1, sparta: { bim: `boom-g` } }, - ], - }, - { - name: "multiline parse", - in: "a,b,c\ne,f,g\n", - parse: (e: string[]): unknown => { - return { super: e[0], street: e[1], fighter: e[2] }; - }, - skipFirstRow: false, - result: [ - { super: "a", street: "b", fighter: "c" }, - { super: "e", street: "f", fighter: "g" }, - ], - }, - { - name: "header mapping object parseline", - in: "a,b,c\ne,f,g\n", - columns: [{ name: "this" }, { name: "is" }, { name: "sparta" }], - parse: (e: Record): unknown => { - return { super: e.this, street: e.is, fighter: e.sparta }; - }, - result: [ - { super: "a", street: "b", fighter: "c" }, - { super: "e", street: "f", fighter: "g" }, - ], - }, { name: "provides both opts.skipFirstRow and opts.columns", in: "a,b,1\nc,d,2\ne,f,3", @@ -608,11 +556,11 @@ const parseTestCases = [ columns: [ { name: "foo" }, { name: "bar" }, - { name: "baz", parse: (e: string) => Number(e) }, + { name: "baz" }, ], result: [ - { foo: "c", bar: "d", baz: 2 }, - { foo: "e", bar: "f", baz: 3 }, + { foo: "c", bar: "d", baz: "2" }, + { foo: "e", bar: "f", baz: "3" }, ], }, ]; @@ -624,7 +572,6 @@ for (const testCase of parseTestCases) { const r = await parse(testCase.in, { skipFirstRow: testCase.skipFirstRow, columns: testCase.columns, - parse: testCase.parse as (input: unknown) => unknown, }); assertEquals(r, testCase.result); }, From ae8253ee0c3ffe4d99e8d5cf1b2056079d3befa1 Mon Sep 17 00:00:00 2001 From: Andrew Mitchell Date: Fri, 17 Dec 2021 19:19:30 -0500 Subject: [PATCH 2/6] Removes references to parse option from jsdoc --- encoding/csv.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/encoding/csv.ts b/encoding/csv.ts index c158ee098901..1d865b658600 100644 --- a/encoding/csv.ts +++ b/encoding/csv.ts @@ -365,11 +365,11 @@ export interface ParseOptions extends ReadOptions { /** * Csv parse helper to manipulate data. - * Provides an auto/custom mapper for columns for columns and rows. + * Provides an auto/custom mapper for columns. * @param input Input to parse. Can be a string or BufReader. * @param opt options of the parser. - * @returns If you don't provide `opt.skipFirstRow`, `opt.parse`, and `opt.columns`, it returns `string[][]`. - * If you provide `opt.skipFirstRow` or `opt.columns` but not `opt.parse`, it returns `object[]`. + * @returns If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns `string[][]`. + * If you provide `opt.skipFirstRow` or `opt.columns`, it returns `Record[]`. */ export async function parse( input: string | BufReader, From 6837d3f03c6620b11748def125e865a788b6985b Mon Sep 17 00:00:00 2001 From: Andrew Mitchell Date: Fri, 17 Dec 2021 19:20:46 -0500 Subject: [PATCH 3/6] Removes unnecessary variable declaration in csv's parse --- encoding/csv.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/encoding/csv.ts b/encoding/csv.ts index 1d865b658600..cfb31697eb79 100644 --- a/encoding/csv.ts +++ b/encoding/csv.ts @@ -421,8 +421,7 @@ export async function parse( i++; const out: Record = {}; for (let j = 0; j < e.length; j++) { - const h = headers[j]; - out[h.name] = e[j]; + out[headers[j].name] = e[j]; } return out; }); From 6452c7fea56e25038b077438079b410a8aacd2ce Mon Sep 17 00:00:00 2001 From: Andrew Mitchell Date: Fri, 17 Dec 2021 21:17:02 -0500 Subject: [PATCH 4/6] Remove parse option from columns for csv's parse function --- encoding/csv.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/encoding/csv.ts b/encoding/csv.ts index cfb31697eb79..259ba01504d8 100644 --- a/encoding/csv.ts +++ b/encoding/csv.ts @@ -334,20 +334,12 @@ export async function readMatrix( * Parse the CSV string/buffer with the options provided. * * ColumnOptions provides the column definition - * and the parse function for each entry of the - * column. */ export interface ColumnOptions { /** * Name of the column to be used as property */ name: string; - /** - * Parse function for the column. - * This is executed on each entry of the header. - * This can be combined with the Parse function of the rows. - */ - parse?: (input: string) => unknown; } export interface ParseOptions extends ReadOptions { @@ -414,6 +406,7 @@ export async function parse( ); } } + return r.map((e) => { if (e.length !== headers.length) { throw `Error number of fields line:${i}`; From ec91cb86611d674fc52ae0b67eca786abbeed9d9 Mon Sep 17 00:00:00 2001 From: Andrew Mitchell Date: Tue, 21 Dec 2021 22:29:50 -0500 Subject: [PATCH 5/6] Add function overloads to csv's parse function --- encoding/README.md | 7 ++----- encoding/csv.ts | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/encoding/README.md b/encoding/README.md index 82b032e1f0dc..f85cbc298dab 100644 --- a/encoding/README.md +++ b/encoding/README.md @@ -57,18 +57,15 @@ function is as follows: `columns`, the first line will be skipped. If you provide `skipFirstRow: true` but not `columns`, the first line will be skipped and used as header definitions. -- **`columns: string[] | HeaderOptions[];`**: If you provide `string[]` or +- **`columns: string[] | ColumnOptions[];`**: If you provide `string[]` or `ColumnOptions[]`, those names will be used for header definition. - **`parse?: (input: unknown) => unknown;`**: Parse function for the row, which will be executed after parsing of all columns. Therefore if you don't provide `skipFirstRow`, `columns`, and `parse` function, input will be `string[]`. -##### `HeaderOptions` +##### `ColumnOptions` - **`name: string;`**: Name of the header to be used as property. -- **`parse?: (input: string) => unknown;`**: Parse function for the column. This - is executed on each entry of the header. This can be combined with the Parse - function of the rows. ##### `ReadOptions` diff --git a/encoding/csv.ts b/encoding/csv.ts index 259ba01504d8..4419cca76f13 100644 --- a/encoding/csv.ts +++ b/encoding/csv.ts @@ -334,6 +334,8 @@ export async function readMatrix( * Parse the CSV string/buffer with the options provided. * * ColumnOptions provides the column definition + * and the parse function for each entry of the + * column. */ export interface ColumnOptions { /** @@ -363,6 +365,29 @@ export interface ParseOptions extends ReadOptions { * @returns If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns `string[][]`. * If you provide `opt.skipFirstRow` or `opt.columns`, it returns `Record[]`. */ +export async function parse( + input: string | BufReader, +): Promise; +export async function parse( + input: string | BufReader, + opt: Omit, +): Promise; +export async function parse( + input: string | BufReader, + opt: Omit & { + columns: string[] | ColumnOptions[]; + }, +): Promise[]>; +export async function parse( + input: string | BufReader, + opt: Omit & { + skipFirstRow: true; + }, +): Promise[]>; +export async function parse( + input: string | BufReader, + opt: ParseOptions, +): Promise[]>; export async function parse( input: string | BufReader, opt: ParseOptions = { From fd9e89f500f1824c6367c015e60008bf847d1b18 Mon Sep 17 00:00:00 2001 From: Andrew Mitchell Date: Tue, 21 Dec 2021 22:36:58 -0500 Subject: [PATCH 6/6] Reconciles readme for csv's parse with current function state --- encoding/README.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/encoding/README.md b/encoding/README.md index f85cbc298dab..4174c1828513 100644 --- a/encoding/README.md +++ b/encoding/README.md @@ -44,12 +44,10 @@ Parse the CSV from the `reader` with the options provided and return Parse the CSV string/buffer with the options provided. The result of this function is as follows: -- If you don't provide `opt.skipFirstRow`, `opt.parse`, and `opt.columns`, it - returns `string[][]`. -- If you provide `opt.skipFirstRow` or `opt.columns` but not `opt.parse`, it - returns `object[]`. -- If you provide `opt.parse`, it returns an array where each element is the - value returned from `opt.parse`. +- If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns + `string[][]`. +- If you provide `opt.skipFirstRow` or `opt.columns` it returns + `Record[]`. ##### `ParseOptions` @@ -59,9 +57,6 @@ function is as follows: definitions. - **`columns: string[] | ColumnOptions[];`**: If you provide `string[]` or `ColumnOptions[]`, those names will be used for header definition. -- **`parse?: (input: unknown) => unknown;`**: Parse function for the row, which - will be executed after parsing of all columns. Therefore if you don't provide - `skipFirstRow`, `columns`, and `parse` function, input will be `string[]`. ##### `ColumnOptions`