Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(csv): add columns options type for array items #6363

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 48 additions & 60 deletions csv/unstable_stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,50 @@ export type ColumnDetails = {
*/
export type Column = ColumnDetails | PropertyAccessor | PropertyAccessor[];

/** An array of arrays */
export type ArrayItem = Readonly<unknown[]>;
/** An array of plain objects */
export type ObjectItem = Readonly<Record<string, unknown>>;
/** An object (plain or array) */
export type DataItem = Readonly<Record<string, unknown> | unknown[]>;
export type DataItem = ArrayItem | ObjectItem;

/** Options for {@linkcode stringify}. */
export type StringifyOptions = {
/** Options for {@linkcode stringify} with an array of of arrays as data. */
export type ArrayStringifyOptions = {
/** Whether to include the row of headers or not.
*
* @default {true}
*/
headers?: boolean;
/**
* Delimiter used to separate values. Examples:
* - `","` _comma_
* - `"\t"` _tab_
* - `"|"` _pipe_
* - etc.
*
* @default {","}
*/
separator?: string;
/**
* A list of instructions for how to target and transform the data for each
* column of output. This is also where you can provide an explicit header
* name for the column.
*
* @default {undefined}
*/
columns?: readonly number[] | undefined;
/**
* Whether to add a
* {@link https://en.wikipedia.org/wiki/Byte_order_mark | byte-order mark} to the
* beginning of the file content. Required by software such as MS Excel to
* properly display Unicode text.
*
* @default {false}
*/
bom?: boolean;
};
/** Options for {@linkcode stringify} with an array of of objects as data. */
export type ObjectStringifyOptions = {
/** Whether to include the row of headers or not.
*
* @default {true}
Expand Down Expand Up @@ -123,23 +162,12 @@ export type StringifyOptions = {
*/
bom?: boolean;
};
/** Options for {@linkcode stringify}. */
export type StringifyOptions = ArrayStringifyOptions | ObjectStringifyOptions;

/**
* Converts an array of objects into a CSV string.
*
* @example Default options
* ```ts
* import { stringify } from "@std/csv/unstable-stringify";
* import { assertEquals } from "@std/assert/equals";
*
* const data = [
* ["Rick", 70],
* ["Morty", 14],
* ];
*
* assertEquals(stringify(data), `Rick,70\r\nMorty,14\r\n`);
* ```
*
* @example Give an array of objects and specify columns
* ```ts
* import { stringify } from "@std/csv/unstable-stringify";
Expand Down Expand Up @@ -280,55 +308,15 @@ export type StringifyOptions = {
* );
* ```
*
* @example Give an array of string arrays and specify columns with renaming
* ```ts
* import { stringify } from "@std/csv/unstable-stringify";
* import { assertEquals } from "@std/assert/equals";
*
* const data = [
* ["Rick", 70],
* ["Morty", 14],
* ];
*
* const columns = [
* { prop: 0, header: "name" },
* { prop: 1, header: "age" },
* ];
*
* assertEquals(
* stringify(data, { columns }),
* `name,age\r\nRick,70\r\nMorty,14\r\n`,
* );
* ```
*
* @example Emit TSV (tab-separated values) with `separator: "\t"`
* ```ts
* import { stringify } from "@std/csv/unstable-stringify";
* import { assertEquals } from "@std/assert/equals";
*
* const data = [
* ["Rick", 70],
* ["Morty", 14],
* ];
*
* assertEquals(stringify(data, { separator: "\t" }), `Rick\t70\r\nMorty\t14\r\n`);
* ```
*
* @example Prepend a byte-order mark with `bom: true`
* ```ts
* import { stringify } from "@std/csv/unstable-stringify";
* import { assertEquals } from "@std/assert/equals";
*
* const data = [["Rick", 70]];
*
* assertEquals(stringify(data, { bom: true }), "\ufeffRick,70\r\n");
* ```
*
* @param data The source data to stringify. It's an array of items which are
* plain objects or arrays.
* @param options Options for the stringification.
* @returns A CSV string.
*/
export function stringify(
data: readonly ObjectItem[],
options?: ObjectStringifyOptions,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only expose ObjectStringifyOptions to the users. (ArrayStringifyOptions is only used in implementation signature, and not visible from the user)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need:

export function stringify(
  data: readonly ArrayItem[],
  options?: ArrayStringifyOptions,
): string;

BTW If we overload a function, the doc linter requires each overload (except implementation signature) having its own jsdoc.

): string;
export function stringify(
data: readonly DataItem[],
options?: StringifyOptions,
Expand Down
Loading