tabular-data-differ
Version:
A very efficient library for diffing two sorted streams of tabular data, such as CSV files.
185 lines (184 loc) • 6.95 kB
TypeScript
import { InputStream, InputStreamOptions, OutputStream, OutputStreamOptions, TextReader, TextWriter } from "./streams";
export declare const defaultStatusColumnName = "DIFF_STATUS";
export type CellValue = string | number | boolean | null;
export type SortDirection = 'ASC' | 'DESC';
export type ColumnComparer = (a: CellValue, b: CellValue) => number;
export type Column = {
name: string;
oldIndex: number;
newIndex: number;
comparer?: ColumnComparer;
sortDirection?: SortDirection;
};
export type Row = CellValue[];
export type RowComparer = (keys: Column[], a?: Row, b?: Row) => number;
export type RowNormalizer = (row?: Row) => Row | undefined;
export type RowFilter = (row: Row) => boolean;
export type RowDiffStatus = 'same' | 'added' | 'modified' | 'deleted';
export interface RowDiff {
delta: number;
status: RowDiffStatus;
oldRow?: Row;
newRow?: Row;
}
export type RowDiffFilter = (rowDiff: RowDiff) => boolean;
/**
* Shared option for some destination formats such as CSV or JSON.
*/
export type KeepOldValuesOptions = {
/**
* Specifies if the output should contain both the old and new values for each row.
*/
keepOldValues?: boolean;
};
export type CsvFormatReaderOptions = {
delimiter?: string;
} & InputStreamOptions;
export type CsvFormatWriterOptions = {
delimiter?: string;
statusColumnName?: string;
} & OutputStreamOptions & KeepOldValuesOptions;
export type JsonFormatReaderOptions = {} & InputStreamOptions;
export type JsonFormatWriterOptions = {} & OutputStreamOptions & KeepOldValuesOptions;
export type IterableFormatReaderOptions = {
provider: () => AsyncIterable<any>;
};
export interface FormatHeader {
columns: string[];
labels?: Record<string, string>;
}
export interface FormatReader {
open(): Promise<void>;
readHeader(): Promise<FormatHeader>;
readRow(): Promise<Row | undefined>;
close(): Promise<void>;
}
export declare class DiffStats {
totalComparisons: number;
totalChanges: number;
changePercent: number;
added: number;
deleted: number;
modified: number;
same: number;
add(rowDiff: RowDiff): void;
}
export interface FormatWriterOptions {
stream: OutputStream;
delimiter?: string;
keepOldValues?: boolean;
statusColumnName?: string;
}
export interface FormatFooter {
stats: DiffStats;
}
export interface FormatWriter {
open(): Promise<void>;
writeHeader(header: FormatHeader): Promise<void>;
writeDiff(rowDiff: RowDiff): Promise<void>;
writeFooter(footer: FormatFooter): Promise<void>;
close(): Promise<void>;
}
export type FormatWriterFactory = (options: FormatWriterOptions) => FormatWriter;
export declare class BufferedFormatReader implements FormatReader {
private reader;
private peekedRow;
private hasPeekedRow;
constructor(reader: FormatReader);
open(): Promise<void>;
readHeader(): Promise<FormatHeader>;
peekRow(): Promise<Row | undefined>;
readRow(): Promise<Row | undefined>;
close(): Promise<void>;
}
export declare abstract class StreamFormatReader implements FormatReader {
protected readonly stream: InputStream;
protected readonly encoding?: BufferEncoding;
constructor(options: InputStreamOptions);
open(): Promise<void>;
abstract readHeader(): Promise<FormatHeader>;
abstract readRow(): Promise<Row | undefined>;
close(): Promise<void>;
}
export declare abstract class TextFormatReader extends StreamFormatReader {
private _textReader?;
protected get textReader(): TextReader;
open(): Promise<void>;
close(): Promise<void>;
}
export declare abstract class StreamFormatWriter implements FormatWriter {
protected readonly stream: OutputStream;
protected readonly encoding?: BufferEncoding;
constructor(options: OutputStreamOptions);
open(): Promise<void>;
close(): Promise<void>;
abstract writeHeader(header: FormatHeader): Promise<void>;
abstract writeDiff(rowDiff: RowDiff): Promise<void>;
abstract writeFooter(footer: FormatFooter): Promise<void>;
}
export declare abstract class TextFormatWriter extends StreamFormatWriter {
private _textWriter?;
protected get textWriter(): TextWriter;
open(): Promise<void>;
close(): Promise<void>;
}
export declare class CsvFormatReader extends TextFormatReader {
private readonly delimiter;
constructor(options: CsvFormatReaderOptions);
readHeader(): Promise<FormatHeader>;
readRow(): Promise<Row | undefined>;
}
export declare class JsonFormatReader extends TextFormatReader {
private headerObj;
private columns;
constructor(options: JsonFormatReaderOptions);
open(): Promise<void>;
readHeader(): Promise<FormatHeader>;
readRow(): Promise<Row | undefined>;
}
export declare class IterableFormatReader implements FormatReader {
private headerObj;
private columns;
private iterable;
private iterator?;
constructor(options: IterableFormatReaderOptions);
open(): Promise<void>;
readHeader(): Promise<FormatHeader>;
readRow(): Promise<Row | undefined>;
close(): Promise<void>;
private nextItem;
}
export declare class CsvFormatWriter extends TextFormatWriter {
private readonly delimiter;
private readonly keepOldValues;
private readonly statusColumnName;
constructor(options: CsvFormatWriterOptions);
writeHeader(header: FormatHeader): Promise<void>;
writeDiff(rowDiff: RowDiff): Promise<void>;
writeFooter(footer: FormatFooter): Promise<void>;
}
export declare class JsonFormatWriter extends TextFormatWriter {
private readonly keepOldValues;
private rowCount;
constructor(options: JsonFormatWriterOptions);
writeHeader(header: FormatHeader): Promise<void>;
writeDiff(rowDiff: RowDiff): Promise<void>;
writeFooter(footer: FormatFooter): Promise<void>;
}
export declare class NullFormatWriter implements FormatWriter {
open(): Promise<void>;
writeHeader(header: FormatHeader): Promise<void>;
writeDiff(rowDiff: RowDiff): Promise<void>;
writeFooter(footer: FormatFooter): Promise<void>;
close(): Promise<void>;
}
export declare function parseJsonObj(line?: string): any;
export declare function convertJsonObjToRow(obj: any, columns: string[]): Row | undefined;
export declare function parseCsvLine(delimiter: string, line?: string): string[] | undefined;
export declare function serializeCsvField(value: CellValue): string;
export declare function serializeRowAsCsvLine(row: Row, delimiter?: string): string;
export declare function stringComparer(a: CellValue, b: CellValue): number;
export declare function numberComparer(a: CellValue, b: CellValue): number;
export declare function cellComparer(a: CellValue, b: CellValue): number;
export declare function defaultRowComparer(columns: Column[], a?: Row, b?: Row): number;
export declare function roundDecimals(value: number, decimals: number): number;