From b1aeecfadd505cba4dd7856f3bb1e051096b24c6 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Thu, 11 Jan 2024 17:02:30 +1100 Subject: [PATCH] docs(csv): complete documentation (#4163) --- csv/_io.ts | 34 ++++++++++++++++++++++------------ csv/csv_parse_stream.ts | 13 +++++++++---- csv/csv_stringify_stream.ts | 2 ++ csv/mod.ts | 2 +- csv/parse.ts | 27 ++++++++++++++++++++++++++- csv/stringify.ts | 20 +++++++++++++------- 6 files changed, 73 insertions(+), 25 deletions(-) diff --git a/csv/_io.ts b/csv/_io.ts index e8340d0a0..bc7af4a51 100644 --- a/csv/_io.ts +++ b/csv/_io.ts @@ -5,6 +5,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assert } from "../assert/assert.ts"; +/** Options for {@linkcode parseRecord}. */ export interface ReadOptions { /** Character which separates values. * @@ -223,6 +224,7 @@ export class ParseError extends SyntaxError { /** Column (rune index) where the error occurred */ column: number | null; + /** Constructs a new instance. */ constructor( start: number, line: number, @@ -268,22 +270,30 @@ export function convertRowToObject( return out; } -// deno-fmt-ignore +/** Options for {@linkcode parse} and {@linkcode CsvParseStream}. */ export type ParseResult = // If `columns` option is specified, the return type is Record type. T extends ParseOptions & { columns: readonly (infer C extends string)[] } ? RecordWithColumn[] - // If `skipFirstRow` option is specified, the return type is Record type. - : T extends ParseOptions & { skipFirstRow: true } - ? Record[] - // If `columns` and `skipFirstRow` option is _not_ specified, the return type is string[][]. - : T extends ParseOptions & { columns?: undefined; skipFirstRow?: false | undefined } - ? string[][] - // else, the return type is Record type or string[][]. - : Record[] | string[][]; + // If `skipFirstRow` option is specified, the return type is Record type. + : T extends ParseOptions & { skipFirstRow: true } + ? Record[] + // If `columns` and `skipFirstRow` option is _not_ specified, the return type is string[][]. + : T extends + ParseOptions & { columns?: undefined; skipFirstRow?: false | undefined } + ? string[][] + // else, the return type is Record type or string[][]. + : Record[] | string[][]; -// RecordWithColumn<"aaa"|"bbb"> => Record<"aaa"|"bbb", string> -// RecordWithColumn => Record -type RecordWithColumn = string extends C +/** + * Record type with column type. + * + * @example + * ``` + * type RecordWithColumn<"aaa"|"bbb"> => Record<"aaa"|"bbb", string> + * type RecordWithColumn => Record + * ``` + */ +export type RecordWithColumn = string extends C ? Record : Record; diff --git a/csv/csv_parse_stream.ts b/csv/csv_parse_stream.ts index 6c32d3102..cce67c3eb 100644 --- a/csv/csv_parse_stream.ts +++ b/csv/csv_parse_stream.ts @@ -11,6 +11,7 @@ import { } from "../csv/_io.ts"; import { TextDelimiterStream } from "../streams/text_delimiter_stream.ts"; +/** Options for {@linkcode CsvParseStream}. */ export interface CsvParseStreamOptions extends ReadOptions { /** * If you provide `skipFirstRow: true` and `columns`, the first line will be @@ -54,15 +55,16 @@ function stripLastCR(s: string): string { return s.endsWith("\r") ? s.slice(0, -1) : s; } -type RowType = T extends undefined ? string[] +/** Row return type. */ +export type RowType = T extends undefined ? string[] : ParseResult[number]; /** - * Read data from a CSV-encoded stream or file. - * Provides an auto/custom mapper for columns. + * Read data from a CSV-encoded stream or file. Provides an auto/custom mapper + * for columns. * * A `CsvParseStream` expects input conforming to - * [RFC 4180](https://rfc-editor.org/rfc/rfc4180.html). + * {@link https://tools.ietf.org/html/rfc4180 | RFC 4180}. * * @example * ```ts @@ -87,6 +89,7 @@ export class CsvParseStream< #headers: readonly string[] = []; + /** Construct a new instance. */ constructor(options?: T) { this.#options = { ...defaultReadOptions, @@ -167,10 +170,12 @@ export class CsvParseStream< } } + /** The instance's {@linkcode ReadableStream}. */ get readable(): ReadableStream> { return this.#readable as ReadableStream>; } + /** The instance's {@linkcode WritableStream}. */ get writable(): WritableStream { return this.#lines.writable; } diff --git a/csv/csv_stringify_stream.ts b/csv/csv_stringify_stream.ts index 4acf0c25a..90432b4c1 100644 --- a/csv/csv_stringify_stream.ts +++ b/csv/csv_stringify_stream.ts @@ -1,6 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { stringify } from "./stringify.ts"; +/** Options for {@linkcode CsvStringifyStream}. */ export interface CsvStringifyStreamOptions { /** * Delimiter used to separate values. @@ -43,6 +44,7 @@ export class CsvStringifyStream : Array, string > { + /** Construct a new instance. */ constructor(options?: TOptions) { const { separator, diff --git a/csv/mod.ts b/csv/mod.ts index 07c3834ca..a476f9ae1 100644 --- a/csv/mod.ts +++ b/csv/mod.ts @@ -4,7 +4,7 @@ /** Reads and writes comma-separated values (CSV) files. * * There are many kinds of CSV files; this module supports the format described - * in [RFC 4180](https://www.rfc-editor.org/rfc/rfc4180.html). + * in {@link https://tools.ietf.org/html/rfc4180 | RFC 4180}. * * A csv file contains zero or more records of one or more fields per record. * Each record is separated by the newline character. The final record may diff --git a/csv/parse.ts b/csv/parse.ts index e6c568419..539c9a9cb 100644 --- a/csv/parse.ts +++ b/csv/parse.ts @@ -10,10 +10,11 @@ import { ParseError, type ParseResult, type ReadOptions, + type RecordWithColumn, } from "./_io.ts"; import { assert } from "../assert/assert.ts"; -export { ParseError, type ParseResult, ReadOptions }; +export { ParseError, type ParseResult, ReadOptions, type RecordWithColumn }; const BYTE_ORDER_MARK = "\ufeff"; @@ -280,6 +281,7 @@ class Parser { } } +/** Options for {@linkcode parse}. */ export interface ParseOptions extends ReadOptions { /** * If you provide `skipFirstRow: true` and `columns`, the first line will be @@ -317,6 +319,29 @@ export interface ParseOptions extends ReadOptions { * If you provide `opt.skipFirstRow` or `opt.columns`, it returns `Record[]`. */ export function parse(input: string, opt?: undefined): string[][]; +/** + * Csv parse helper to manipulate data. + * Provides an auto/custom mapper for columns. + * + * @example + * ```ts + * import { parse } from "https://deno.land/std@$STD_VERSION/csv/parse.ts"; + * const string = "a,b,c\nd,e,f"; + * + * console.log( + * await parse(string, { + * skipFirstRow: false, + * }), + * ); + * // output: + * // [["a", "b", "c"], ["d", "e", "f"]] + * ``` + * + * @param input Input to parse. + * @param opt options of the parser. + * @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 function parse( input: string, opt: T, diff --git a/csv/stringify.ts b/csv/stringify.ts index 2656dd50b..0e19d1117 100644 --- a/csv/stringify.ts +++ b/csv/stringify.ts @@ -1,10 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. -type PropertyAccessor = number | string; -type ObjectWithStringPropertyKeys = Record; +/** Array index or record key corresponding to a value for a data object. */ +export type PropertyAccessor = number | string; /** + * Column information. + * * @param header Explicit column header name. If omitted, * the (final) property accessor is used for this value. * @@ -82,8 +84,9 @@ export type ColumnDetails = { export type Column = ColumnDetails | PropertyAccessor | PropertyAccessor[]; /** An object (plain or array) */ -export type DataItem = ObjectWithStringPropertyKeys | unknown[]; +export type DataItem = Record | unknown[]; +/** Options for {@linkcode stringify}. */ export type StringifyOptions = { /** Whether to include the row of headers or not. * @@ -165,8 +168,13 @@ function normalizeColumn(column: Column): NormalizedColumn { return { header, prop }; } +/** Error thrown in {@linkcode stringify}. */ export class StringifyError extends Error { - override readonly name = "StringifyError"; + /** Construct a new instance. */ + constructor(message?: string) { + super(message); + this.name = "StringifyError"; + } } /** @@ -193,7 +201,7 @@ function getValuesFromItem( ); } } // I think this assertion is safe. Confirm? - else value = (value as ObjectWithStringPropertyKeys)[prop]; + else value = (value as Record)[prop]; } values.push(value); @@ -273,8 +281,6 @@ function getValuesFromItem( * // Rick,70 * // Morty,14 * ``` - * - * @param options Output formatting options */ export function stringify( data: DataItem[],