UNPKG

easy-cli-framework

Version:

A framework for building CLI applications that are robust and easy to maintain. Supports theming, configuration files, interactive prompts, and more.

204 lines (203 loc) 7.16 kB
import { EasyCLITheme } from '../themes'; /** * A mapping for a CSV field to a field in an object. * @template TType The type of the field after transformation. * * @interface CsvFieldMapping * * @property {string[]} aliases The aliases for the field in the CSV. * @property {boolean} required If the field is required or not. * @property {function} transform The function to transform the value from the CSV. (Default: value => value) * @property {boolean} allowEmpty If the field can be empty or not. (Default: false) * @property {TType} defaultValue The default value for the field. (Default: undefined) */ export type CsvFieldMapping<TType = any> = { aliases: string[]; required: boolean; transform?: (value: string) => any | Promise<any>; allowEmpty?: boolean; defaultValue?: TType; }; /** * A mapping of fields in an object to their CSV field mappings. * * @interface CsvFieldMappings * * @template TObject The object type to map to. * * @property {keyof TObject} The name of the field in the object. * @property {CsvFieldMapping<TObject[keyof TObject]>} The rules for mapping the field. * */ export type CsvFieldMappings<TObject> = Record<keyof TObject, CsvFieldMapping<TObject[keyof TObject]>>; /** * A mapping of CSV columns to their object fields that they map to. * * @interface ObjectDataMapper * * @template TObject The output object type. * @template TFileObject The CSV file object type. * * @property {keyof TFileObject} The column in the CSV file. * @property {keyof TObject[]} The fields in the object that the column maps to. * * @example * ```typescript * { * 'Username': ['username'], * 'Identifier': ['id'], * 'First name': ['firstName', 'firstInital'], * } * ``` */ export type ObjectDataMapper<TObject, TFileObject> = Record<keyof TFileObject, (keyof TObject)[]>; /** * The settings for the CSV Mapper instance. * * @interface CsvMapperOptions * * @property {CsvFieldMappings<TObject>} mappings The field mappings for the CSV file. * @property {boolean} interactive If it should interactively ask for other field mappings. (Default: false) * @property {boolean} discardOriginalFields If it should discard any fields that are not mapped or not. If false, will store them with their name from the CSV. (Default: true) * @property {EasyCLITheme} theme The theme to use for the prompts. * @property {boolean} validate If it should validate the data against the mappings. (Default: true) * * @example * ```typescript * { * mappings: { * username: { * aliases: ['Username'], * required: true, * transform: value => value, * }, * ... * }, * interactive?: true, // If it should interactively ask for other field mappings. (Default: false) * discardOriginalFields?: true, // If it should discard any fields that are not mapped or not. If false, will store them with their name from the CSV along with the mapped fields (Default: true) * theme?: EasyCLITheme | null, // The theme to use for the prompts. * validate?: true, // If it should validate the data against the mapping rules, if errors are detected it will throw an error (Default: true) * } * ``` */ export type CsvMapperOptions<TObject extends Record<string, any>> = { interactive?: boolean; discardOriginalFields?: boolean; mappings: CsvFieldMappings<TObject>; theme?: EasyCLITheme | null; validate?: boolean; }; export declare class CSVMapper<TObject extends Record<string, any> = Record<string, any>, TFileObject extends Record<string, any> = Record<string, any>> { private mappings; private interactive; private discardOriginalFields; private theme; private validate; /** * Create a new CSV Mapper instance. * * @param options The options for the CSV Mapper. * @returns {CSVMapper<TObject, TFileObject>} A new CSV Mapper instance. * * @example * const csvProcessor = new CSVMapper({ * mappings: { * username: { * aliases: ['Username'], * required: true, * transform: value => value, * }, * id: { * aliases: ['Identifier'], * required: true, * transform: value => parseInt(value), * }, * lastName: { * aliases: [], * required: true, * transform: value => value, * }, * firstName: { * aliases: ['First name', 'First Name'], * required: true, * transform: value => value, * }, * firstInital: { * aliases: ['First name', 'First Name'], * required: true, * transform: value => value[0], * }, * }, * interactive: true, * }); */ constructor(options: CsvMapperOptions<TObject>); /** * Read a CSV file and parse it into an array of objects. * * @param path The path to the CSV file to read. * @throws {Error} If the file is not found or there is an error reading the file. * * @returns The parsed CSV file as an array of objects. */ private readFile; /** * Prompt the user for missing fields in the mappings. * * @param missingFields What fields are missing from the mappings * @param unmappedColumns What columns are not mapped * * @returns Additional mappings for the CSV columns */ private promptMissingFields; /** * Process a CSV file and return the data as an array of transformed objects. * * @param path The path to the CSV file to process * * @throws {Error} If there are validation errors in the CSV file and the validate option is set to true. * * @returns {Promise<TObject[]>} The data from the CSV file as an array of transformed objects * * @example * ```typescript * const csvProcessor = new CSVMapper({...}); * const data = await csvProcessor.processFile('./username.csv'); * ``` */ processFile: (path: string) => Promise<TObject[]>; /** * Validation for the CSV file, comparing the fields to the mappings. * * @param rows The rows to validate * @param fieldMap The field map to use for validation * * @throws {Error} If there are validation errors in the CSV file */ private validateData; /** * Transforn a row from the CSV file into the correct output. * * @param row The row data to transform * @param fieldMapping How to map the fields from the CSV to the object * * @returns {Promise<TObject>} A normalized row object */ private transformRow; /** * Build a field map from the columns found in the CSV file. * * @param {(keyof TFileObject)[]} columns The columns found in the CSV file * * @returns {ObjectDataMapper<TObject, TFileObject>} A field map that maps the CSV columns to the object fields */ private buildFieldMap; /** * Find the mapped field for a CSV column. * * @param {keyof TFileObject} field The field to find the mapped field for * * @returns {(keyof TObject[])} The mapped fields for the CSV column */ private findMappedField; }