UNPKG

update-file-content

Version:

Utility for executing RegEx replacement on files, powered by stream.

391 lines (364 loc) 11.6 kB
/// <reference types="node" /> import { Writable, Readable } from "stream"; type GlobalLimit = number; type LocalLimit = number; interface BasicReplaceOption { /** * Correspondence: String.prototype.replace's 2nd argument. * * Replaces the according text for a given match, a string or * a function that returns the replacement text can be passed. * * Special replacement patterns (parenthesized capture group placeholders) * are well supported. * * For a partial replacement, $& (also the 1st supplied value to replace * function) and $1 (the 2nd param passed) always have the same value, * supplying the matched substring in the parenthesized capture group * you specified. */ replacement?: string | ((wholeMatch: string, ...args: string[]) => string); /** * Perform a full replacement or not. * * A RegExp search without capture groups or a search in string will be * treated as a full replacement silently. */ isFullReplacement?: Boolean; /** * Only valid for a string replacement. * * Disable placeholders in replacement or not. Processed result shall be * exactly the same as the string replacement if set to true. * * Default: false */ disablePlaceholders?: Boolean; /** * Apply restriction on certain search's maximum executed times. * * Upon reaching the limit, if option `truncate` is falsy (false by default), * underlying transform stream will become a transparent passThrough stream. * * Default: Infinity. 0 is considered as Infinity for this option. */ limit?: LocalLimit; /** * Observe a certain search's executed times, remove that search right * after upper limit reached. * * Default: Infinity. 0 is considered as Infinity for this option. */ maxTimes?: number; } interface SearchAndReplaceOption extends BasicReplaceOption { /** * Correspondence: `String.prototype.replaceAll`'s 1st argument. * * Accepts a literal string or a RegExp object. * * Will replace all occurrences by converting input into a global RegExp * object, which means that the according replacement might be invoked * multiple times for each full match to be replaced. * * Every `search` and `replacement` not arranged in pairs is silently * discarded in `options`, while in `options.replace` that will result in * an error thrown. */ search?: string | RegExp; } interface MatchAndReplaceOption extends BasicReplaceOption { /** * Alias for options.search. * * Correspondence: `String.prototype.replaceAll`'s 1st argument. * * Accepts a literal string or a RegExp object. * * Will replace all occurrences by converting input into a global RegExp * object, which means that the according replacement might be invoked * multiple times for each full match to be replaced. * * Every `match` and `replacement` not arranged in pairs is silently * discarded in `options`, while in `options.replace` that will result in * an error thrown. */ match?: string | RegExp; } interface MultipleReplacementOption { /** * Apply restriction on the maximum count of every search's executed times. * * Upon reaching the limit, if option `truncate` is falsy (false by default), * underlying transform stream will become a transparent passThrough stream. * * Default: Infinity. 0 is considered as Infinity for this option. */ limit?: GlobalLimit; /** * Should be an array of { [ "match" | "search" ], "replacement" } pairs. * * Possible `search|match` and `replacement` pair in `options` scope will be * prepended to `options.replace` array, if both exist. */ replace?: Array<SearchAndReplaceOption | MatchAndReplaceOption>; } // An interface can only extend an object type or intersection of object types with statically known members. type ReplaceOptions = MultipleReplacementOption & MatchAndReplaceOption & SearchAndReplaceOption; interface BasicOptions extends ReplaceOptions { /** * Correspondence: String.prototype.split's 1nd argument. * * Accepts a literal string or a RegExp object. * * Used by underlying transform stream to split upstream data into separate * to-be-processed parts. * * String.prototype.split will implicitly call `toString` on non-string & * non-regex & non-void values. * * Specify `null` or `undefined` to process upstream data as a whole. * * Default: /(?<=\r?\n)/. Line endings following lines. */ separator?: string | RegExp | null; /** * Correspondence: String.prototype.join's 1nd argument, though a function * is also acceptable. * * You can specify a literal string or a function that returns the post-processed * part. * * Example function for appending a CRLF: part => part.concat("\r\n"); * * Default: part => part */ join?: string | ((part: string) => string) | null; /** * Correspondence: encoding of Node.js Buffer. * * If specified, then processed and joined strings will be encoded to buffers * with that encoding. * * Node.js currently supportes following options: * "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex" * Default: "utf8". */ encoding?: BufferEncoding; /** * Correspondence: encodings of WHATWG Encoding Standard TextDecoder. * * Accept a specific character encoding, like utf-8, iso-8859-2, koi8, cp1261, * gbk, etc for decoding the input raw buffer. * * This option only makes sense when no encoding is assigned and stream data are * passed as Buffer objects (that is, haven't done something like * readable.setEncoding('utf8')); * * Example: updateFileContent({ * from: createReadStream("gbk.txt"), * to: createWriteStream("utf8.txt"), * decodeBuffers: "gbk" * }); * * Some encodings are only available for Node embedded the entire ICU (full-icu). * See https://nodejs.org/api/util.html#util_class_util_textdecoder. * * Default: "utf8". */ decodeBuffers?: string; /** * Truncating the rest or not when limits reached. * * Default: false. */ truncate?: Boolean; /** * The maximum size of the line buffer. * * A line buffer is the buffer used for buffering the last incomplete substring * when dividing chunks (typically 64 KiB) by options.separator. * * Default: Infinity. */ maxLength?: number; /** * Correspondence: readableObjectMode option of Node.js stream.Transform * * Options writableObjectMode and objectMode are not supported. * * Default: Infinity. */ readableObjectMode?: boolean; /** * A post-processing function that consumes transformed strings and returns a * string or a Buffer. This option has higher priority over option `join`. * * If readableObjectMode is enabled, any object accepted by Node.js objectMode * streams can be returned. */ postProcessing: (part: string, isLastPart: boolean) => any } type WritableOrVoid = Writable | void; // updateFileContent - file interface UpdateFileOptions extends BasicOptions { /** * Path to the file. */ file: string; /** * Correspondence: fs.read's 4th argument - position * * The location where to begin reading data from the file. * * Default: 0 */ readStart?: number; /** * Correspondence: fs.write's 4th argument - position * * The offset from the beginning of the file where the substituted data should be written. * * writeStart should be smaller or equal to readStart. * * Default: 0 */ writeStart?: number; } // updateFileContent - TransformReadable interface TransformReadableOptions<T> extends BasicOptions { /** * A Readable stream. */ from: Readable; /** * A Writable stream. */ to: T; } interface TransformReadableOptionsAlias<T> extends BasicOptions { /** * Alias of `from`. */ readableStream: Readable; /** * Alias of `to`. */ writableStream: T; } /** * update file content, or transform/transcode/truncate streams * * P.S. TS doesn't support overloading functions with same * number of parameters, so a huge union is there 😀 */ export declare function updateFileContent<T extends WritableOrVoid>( options: UpdateFileOptions | TransformReadableOptions<T> | TransformReadableOptionsAlias<T> ): Promise<T>; // updateFiles - files interface UpdateFilesOptions extends BasicOptions { /** * A array of filepaths. */ files: string[]; /** * Correspondence: fs.read's 4th argument - position * * The location where to begin reading data from the file. * * Applies to all files. * * Default: 0 */ readStart?: number; /** * Correspondence: fs.write's 4th argument - position * * The offset from the beginning of the file where the substituted data should be written. * * Applies to all files. * * writeStart should be smaller or equal to readStart. * * Default: 0 */ writeStart?: number; } // updateFiles - readables -> writable interface MultipleReadablesToWritableOptions<T> extends BasicOptions { /** * An array of Readable streams. */ from: Array<Readable>; /** * A Writable stream. */ to: T; /** * Concatenate results of transformed Readables with the input value. * * Accepts a literal string or a Buffer. * * Default: "" */ contentJoin: string | Buffer; } interface MultipleReadablesToWritableOptionsAlias<T> extends BasicOptions { /** * Alias of `from`. * An array of Readable streams */ readableStreams: Array<Readable>; /** * Alias of `to`. * A Writable stream. */ writableStream: T; /** * Concatenate results of transformed Readables with the input value. * * Accepts a literal string or a Buffer. * * option.encoding will be passed along with contentJoin to Writable.write * * Default: "" */ contentJoin: string | Buffer; } // updateFiles - readable -> writables interface ReadableToMultipleWritablesOptions<T> extends BasicOptions { /** * A Readable stream source. */ from: Readable; /** * An array of Writable streams, preferably being the same type. */ to: Array<T>; } interface ReadableToMultipleWritablesOptionsAlias<T> extends BasicOptions { /** * Alias of `from`. * A Readable stream source. */ readableStream: Readable; /** * Alias of `to`. * An array of Writable streams, preferably being the same type. */ writableStreams: Array<T>; } /** * update files, or transform streams and pipe/tee/combine them here and there. * * `from` `to` cannot be arrays at the same time. * * P.S. TS doesn't support overloading functions with same * number of parameters, so a huge union is there 😀 */ export declare function updateFiles<T extends WritableOrVoid>( options: UpdateFilesOptions | MultipleReadablesToWritableOptionsAlias<T> | MultipleReadablesToWritableOptions<T> | ReadableToMultipleWritablesOptions<T> | ReadableToMultipleWritablesOptionsAlias<T> ): Promise< T[] | T >;