Skip to content

Commit

Permalink
move new inference feature to unstable-stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
kt3k committed Nov 13, 2024
1 parent 953f705 commit 0966c7c
Show file tree
Hide file tree
Showing 8 changed files with 427 additions and 58 deletions.
1 change: 1 addition & 0 deletions _tools/check_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const ENTRY_POINTS = [
"../crypto/mod.ts",
"../collections/mod.ts",
"../csv/mod.ts",
"../csv/unstable_stringify.ts",
"../data_structures/mod.ts",
"../data_structures/unstable_bidirectional_map.ts",
"../datetime/mod.ts",
Expand Down
3 changes: 2 additions & 1 deletion csv/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"./parse": "./parse.ts",
"./parse-stream": "./parse_stream.ts",
"./stringify": "./stringify.ts",
"./stringify-stream": "./stringify_stream.ts"
"./stringify-stream": "./stringify_stream.ts",
"./unstable-stringify": "./unstable_stringify.ts"
}
}
37 changes: 10 additions & 27 deletions csv/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ export type StringifyOptions = {
* column of output. This is also where you can provide an explicit header
* name for the column.
*
* @default {undefined}
* @default {[]}
*/
columns?: readonly Column[] | undefined;
columns?: readonly Column[];
/**
* Whether to add a
* {@link https://en.wikipedia.org/wiki/Byte_order_mark | byte-order mark} to the
Expand Down Expand Up @@ -250,14 +250,18 @@ function getValuesFromItem(
* @example Give an array of objects without specifying columns
* ```ts
* import { stringify } from "@std/csv/stringify";
* import { assertEquals } from "@std/assert/equals";
* import { assertThrows } from "@std/assert/throws";
*
* const data = [
* { name: "Rick", age: 70 },
* { name: "Morty", age: 14 },
* ];
*
* assertEquals(stringify(data), `name,age\r\nRick,70\r\nMorty,14\r\n`);
* assertThrows(
* () => stringify(data),
* TypeError,
* "No property accessor function was provided for object",
* );
* ```
*
* @example Give an array of objects and specify columns with `headers: false`
Expand Down Expand Up @@ -425,7 +429,7 @@ export function stringify(
data: readonly DataItem[],
options?: StringifyOptions,
): string {
const { headers = true, separator: sep = ",", columns, bom = false } =
const { headers = true, separator: sep = ",", columns = [], bom = false } =
options ?? {};

if (sep.includes(QUOTE) || sep.includes(CRLF)) {
Expand All @@ -437,12 +441,7 @@ export function stringify(
throw new TypeError(message);
}

if (columns && !Array.isArray(columns)) {
throw new TypeError("Invalid type: columns can only be an array");
}

const definedColumns = columns ?? inferColumns(data);
const normalizedColumns = definedColumns.map(normalizeColumn);
const normalizedColumns = columns.map(normalizeColumn);
let output = "";

if (bom) {
Expand All @@ -466,19 +465,3 @@ export function stringify(

return output;
}

/**
* Infers the columns from the first object element of the given array.
*/
function inferColumns(data: readonly DataItem[]): string[] {
const firstElement = data.at(0);
if (
firstElement &&
typeof firstElement === "object" &&
!Array.isArray(firstElement)
) {
return Object.keys(firstElement);
}

return [];
}
2 changes: 1 addition & 1 deletion csv/stringify_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
* @param options Options for the stream.
*/
constructor(options?: TOptions) {
const { separator, columns } = options ?? {};
const { separator, columns = [] } = options ?? {};

super(
{
Expand Down
12 changes: 5 additions & 7 deletions csv/stringify_stream_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Deno.test({
await assertRejects(
async () => await Array.fromAsync(readable),
TypeError,
"Invalid type: columns can only be an array",
"No property accessor function was provided for object",
);
});

Expand All @@ -90,12 +90,10 @@ Deno.test({
{ id: 3, name: "baz" },
// @ts-expect-error `columns` option is required
]).pipeThrough(new CsvStringifyStream());
const output = await Array.fromAsync(readable);
assertEquals(output, [
"1,foo\r\n",
"2,bar\r\n",
"3,baz\r\n",
]);
await assertRejects(
async () => await Array.fromAsync(readable),
TypeError,
);
});
},
});
36 changes: 14 additions & 22 deletions csv/stringify_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ Deno.test({
},
},
);

await t.step(
{
name: "Invalid data, no columns",
fn() {
const data = [{ a: 1 }, { a: 2 }];
assertThrows(
() => stringify(data),
TypeError,
"No property accessor function was provided for object",
);
},
},
);
await t.step(
{
name: "No data, no columns",
Expand Down Expand Up @@ -564,27 +578,5 @@ Deno.test({
});
},
});
await t.step(
{
name:
"Object array with no columns, should infer columns from the first array element",
fn() {
const data = [{ a: 1 }, { a: 2 }, { b: 3 }];
const output = `a${CRLF}1${CRLF}2${CRLF}${CRLF}`;
assertEquals(stringify(data), output);
},
},
);
await t.step(
{
name: "Object array with columns, shouldn't infer columns",
fn() {
const data = [{ a: 1 }, { a: 2 }, { b: 3 }];
const columns = ["a"];
const output = `a${CRLF}1${CRLF}2${CRLF}${CRLF}`;
assertEquals(stringify(data, { columns }), output);
},
},
);
},
});
Loading

0 comments on commit 0966c7c

Please sign in to comment.