docs(csv): improve API docs (#4920)

Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com>
This commit is contained in:
Yoshiya Hinosawa 2024-06-03 12:32:09 +09:00 committed by GitHub
parent 44bc90065b
commit 3db62b0017
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 231 additions and 60 deletions

View File

@ -33,6 +33,7 @@ const ENTRY_POINTS = [
"../cli/mod.ts",
"../crypto/mod.ts",
"../collections/mod.ts",
"../csv/mod.ts",
"../data_structures/mod.ts",
"../datetime/mod.ts",
"../encoding/mod.ts",

View File

@ -215,16 +215,88 @@ function runeCount(s: string): number {
/**
* A ParseError is returned for parsing errors.
* Line numbers are 1-indexed and columns are 0-indexed.
*
* @example Usage
* ```ts
* import { parse, ParseError } from "@std/csv/parse";
*
* try {
* parse(`a "word","b"`);
* } catch (error) {
* if (error instanceof ParseError) {
* console.error(error.message);
* }
* }
* ```
*/
export class ParseError extends SyntaxError {
/** Line where the record starts*/
/**
* Line where the record starts.
*
* @example Usage
* ```ts
* import { parse, ParseError } from "@std/csv/parse";
*
* try {
* parse(`a "word","b"`);
* } catch (error) {
* if (error instanceof ParseError) {
* console.error(error.startLine);
* }
* }
* ```
*/
startLine: number;
/** Line where the error occurred */
/**
* Line where the error occurred.
*
* @example Usage
* ```ts
* import { parse, ParseError } from "@std/csv/parse";
*
* try {
* parse(`a "word","b"`);
* } catch (error) {
* if (error instanceof ParseError) {
* console.error(error.line);
* }
* }
* ```
*/
line: number;
/** Column (rune index) where the error occurred */
/**
* Column (rune index) where the error occurred.
*
* @example Usage
* ```ts
* import { parse, ParseError } from "@std/csv/parse";
*
* try {
* parse(`a "word","b"`);
* } catch (error) {
* if (error instanceof ParseError) {
* console.error(error.column);
* }
* }
* ```
*/
column: number | null;
/** Constructs a new instance. */
/**
* Constructs a new instance.
*
* @example Usage
* ```ts no-eval
* import { ParseError } from "@std/csv/parse";
*
* throw new ParseError(1, 2, 3, "error message");
* ```
*
* @param start Line where the record starts
* @param line Line where the error occurred
* @param column Column The index where the error occurred
* @param message Error message
*/
constructor(
start: number,
line: number,

View File

@ -66,14 +66,20 @@ export type RowType<T> = T extends undefined ? string[]
* A `CsvParseStream` expects input conforming to
* {@link https://www.rfc-editor.org/rfc/rfc4180.html | RFC 4180}.
*
* @example
* @example Usage
* ```ts
* import { CsvParseStream } from "@std/csv/csv-parse-stream";
* const res = await fetch("https://example.com/data.csv");
* const parts = res.body!
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new CsvParseStream());
*
* const source = ReadableStream.from([
* "name,age",
* "Alice,34",
* "Bob,24",
* "Charlie,45",
* ]);
* const parts = source.pipeThrough(new CsvParseStream());
* ```
*
* @typeParam T The type of options for the stream.
*/
export class CsvParseStream<
const T extends CsvParseStreamOptions | undefined = undefined,
@ -89,7 +95,23 @@ export class CsvParseStream<
#headers: readonly string[] = [];
/** Construct a new instance. */
/** Construct a new instance.
*
* @example Usage
* ```ts
* import { CsvParseStream } from "@std/csv/csv-parse-stream";
*
* const source = ReadableStream.from([
* "name,age",
* "Alice,34",
* "Bob,24",
* "Charlie,45",
* ]);
* const parts = source.pipeThrough(new CsvParseStream());
* ```
*
* @param options Options for the stream.
*/
constructor(options?: T) {
this.#options = {
...defaultReadOptions,
@ -170,12 +192,54 @@ export class CsvParseStream<
}
}
/** The instance's {@linkcode ReadableStream}. */
/**
* The instance's {@linkcode ReadableStream}.
*
* @example Usage
* ```ts
* import { CsvParseStream } from "@std/csv/csv-parse-stream";
*
* const source = ReadableStream.from([
* "name,age",
* "Alice,34",
* "Bob,24",
* "Charlie,45",
* ]);
* const parseStream = new CsvParseStream();
* const parts = source.pipeTo(parseStream.writable);
* for await (const part of parseStream.readable) {
* console.log(part);
* }
* ```
*
* @returns The instance's {@linkcode ReadableStream}.
*/
get readable(): ReadableStream<RowType<T>> {
return this.#readable as ReadableStream<RowType<T>>;
}
/** The instance's {@linkcode WritableStream}. */
/**
* The instance's {@linkcode WritableStream}.
*
* @example Usage
* ```ts
* import { CsvParseStream } from "@std/csv/csv-parse-stream";
*
* const source = ReadableStream.from([
* "name,age",
* "Alice,34",
* "Bob,24",
* "Charlie,45",
* ]);
* const parseStream = new CsvParseStream();
* const parts = source.pipeTo(parseStream.writable);
* for await (const part of parseStream.readable) {
* console.log(part);
* }
* ```
*
* @returns The instance's {@linkcode WritableStream}.
*/
get writable(): WritableStream<string> {
return this.#lines.writable;
}

View File

@ -22,11 +22,13 @@ export interface CsvStringifyStreamOptions {
/**
* Convert each chunk to a CSV record.
*
* @example
* @example Usage
* ```ts
* import { CsvStringifyStream } from "@std/csv/csv-stringify-stream";
*
* const file = await Deno.open("data.csv", { create: true, write: true });
* const path = await Deno.makeTempFile();
*
* const file = await Deno.open(path, { create: true, write: true });
* const readable = ReadableStream.from([
* { id: 1, name: "one" },
* { id: 2, name: "two" },
@ -37,7 +39,9 @@ export interface CsvStringifyStreamOptions {
* .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] }))
* .pipeThrough(new TextEncoderStream())
* .pipeTo(file.writable);
* ````
* ```
*
* @typeParam TOptions The type of options for the stream.
*/
export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
extends TransformStream<
@ -45,7 +49,30 @@ export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
: Array<unknown>,
string
> {
/** Construct a new instance. */
/**
* Construct a new instance.
*
* @example Usage
* ```ts
* import { CsvStringifyStream } from "@std/csv/csv-stringify-stream";
*
* const path = await Deno.makeTempFile();
*
* const file = await Deno.open(path, { create: true, write: true });
* const readable = ReadableStream.from([
* { id: 1, name: "one" },
* { id: 2, name: "two" },
* { id: 3, name: "three" },
* ]);
*
* await readable
* .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] }))
* .pipeThrough(new TextEncoderStream())
* .pipeTo(file.writable);
* ```
*
* @param options Options for the stream.
*/
constructor(options?: TOptions) {
const {
separator,

View File

@ -304,45 +304,39 @@ export interface ParseOptions extends ReadOptions {
* Csv parse helper to manipulate data.
* Provides an auto/custom mapper for columns.
*
* @example
* @example Usage
* ```ts
* import { parse } from "@std/csv/parse";
* import { assertEquals } from "@std/assert/assert-equals";
*
* const string = "a,b,c\nd,e,f";
*
* console.log(
* await parse(string, {
* skipFirstRow: false,
* }),
* );
* // output:
* // [["a", "b", "c"], ["d", "e", "f"]]
* assertEquals(parse(string), [["a", "b", "c"], ["d", "e", "f"]]);
* ```
*
* @param input Input to parse.
* @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<string, unknown>[]`.
* @param input The input to parse.
* @returns The parsed data.
*/
export function parse(input: string): string[][];
/**
* Csv parse helper to manipulate data.
* Provides an auto/custom mapper for columns.
*
* @example
* @example Usage
* ```ts
* import { parse } from "@std/csv/parse";
* import { assertEquals } from "@std/assert/assert-equals";
*
* const string = "a,b,c\nd,e,f";
*
* console.log(
* await parse(string, {
* skipFirstRow: false,
* }),
* );
* // output:
* // [["a", "b", "c"], ["d", "e", "f"]]
* assertEquals(parse(string, { skipFirstRow: false }), [["a", "b", "c"], ["d", "e", "f"]]);
* assertEquals(parse(string, { skipFirstRow: true }), [{ a: "d", b: "e", c: "f" }]);
* assertEquals(parse(string, { columns: ["x", "y", "z"] }), [{ x: "a", y: "b", z: "c" }, { x: "d", y: "e", z: "f" }]);
* ```
*
* @param input Input to parse.
* @param opt options of the parser.
* @typeParam T The options' type for parsing.
* @param input The input to parse.
* @param opt The options for parsing.
* @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<string, unknown>[]`.
*/

View File

@ -168,9 +168,35 @@ function normalizeColumn(column: Column): NormalizedColumn {
return { header, prop };
}
/** Error thrown in {@linkcode stringify}. */
/**
* Error thrown in {@linkcode stringify}.
*
* @example Usage
* ```ts
* import { stringify, StringifyError } from "@std/csv/stringify";
*
* try {
* stringify([{ a: 1 }, { a: 2 }], { separator: "\r\n" });
* } catch (error) {
* if (error instanceof StringifyError) {
* console.error(error.message);
* }
* }
* ```
*/
export class StringifyError extends Error {
/** Construct a new instance. */
/**
* Construct a new instance.
*
* @example Usage
* ```ts no-eval
* import { StringifyError } from "@std/csv/stringify";
*
* throw new StringifyError("An error occurred");
* ```
*
* @param message The error message.
*/
constructor(message?: string) {
super(message);
this.name = "StringifyError";
@ -222,29 +248,15 @@ function getValuesFromItem(
}
/**
* Write data using CSV encoding.
* Converts an array of objects into a CSV string.
*
* @param data The source data to stringify. It's an array of items which are
* plain objects or arrays.
*
* `DataItem: Record<string, unknown> | unknown[]`
*
* ```ts
* const data = [
* {
* name: "Deno",
* repo: { org: "denoland", name: "deno" },
* runsOn: ["Rust", "TypeScript"],
* },
* ];
* ```
*
* @example
* @example Usage
* ```ts
* import {
* Column,
* stringify,
* } from "@std/csv/stringify";
* import { assertEquals } from "@std/assert/assert-equals";
*
* type Character = {
* age: number;
@ -276,11 +288,12 @@ function getValuesFromItem(
* "age",
* ];
*
* console.log(stringify(data, { columns }));
* // first,age
* // Rick,70
* // Morty,14
* assertEquals(stringify(data, { columns }), `first,age\r\nRick,70\r\nMorty,14\r\n`);
* ```
*
* @param data The source data to stringify. It's an array of items which are
* plain objects or arrays.
* @returns A CSV string.
*/
export function stringify(
data: DataItem[],