UNPKG

@rushstack/node-core-library

Version:

Core libraries that every NodeJS toolchain project should use

1,101 lines (1,083 loc) 158 kB
/** * Core libraries that every NodeJS toolchain project should use. * * @packageDocumentation */ /// <reference types="node" /> import * as child_process from 'child_process'; import * as nodeFs from 'fs'; import * as nodePath from 'path'; /** * Specifies the behavior of APIs such as {@link FileSystem.copyFile} or * {@link FileSystem.createSymbolicLinkFile} when the output file path already exists. * * @remarks * For {@link FileSystem.copyFile} and related APIs, the "output file path" is * {@link IFileSystemCopyFileOptions.destinationPath}. * * For {@link FileSystem.createSymbolicLinkFile} and related APIs, the "output file path" is * {@link IFileSystemCreateLinkOptions.newLinkPath}. * * @public */ export declare enum AlreadyExistsBehavior { /** * If the output file path already exists, try to overwrite the existing object. * * @remarks * If overwriting the object would require recursively deleting a folder tree, * then the operation will fail. As an example, suppose {@link FileSystem.copyFile} * is copying a single file `/a/b/c` to the destination path `/d/e`, and `/d/e` is a * nonempty folder. In this situation, an error will be reported; specifying * `AlreadyExistsBehavior.Overwrite` does not help. Empty folders can be overwritten * depending on the details of the implementation. */ Overwrite = "overwrite", /** * If the output file path already exists, the operation will fail, and an error * will be reported. */ Error = "error", /** * If the output file path already exists, skip this item, and continue the operation. */ Ignore = "ignore" } /** * This exception can be thrown to indicate that an operation failed and an error message has already * been reported appropriately. Thus, the catch handler does not have responsibility for reporting * the error. * * @remarks * For example, suppose a tool writes interactive output to `console.log()`. When an exception is thrown, * the `catch` handler will typically provide simplistic reporting such as this: * * ```ts * catch (error) { * console.log("ERROR: " + error.message); * } * ``` * * Suppose that the code performing the operation normally prints rich output to the console. It may be able to * present an error message more nicely (for example, as part of a table, or structured log format). Throwing * `AlreadyReportedError` provides a way to use exception handling to abort the operation, but instruct the `catch` * handler not to print an error a second time: * * ```ts * catch (error) { * if (error instanceof AlreadyReportedError) { * return; * } * console.log("ERROR: " + error.message); * } * ``` * * @public */ export declare class AlreadyReportedError extends Error { constructor(); static [Symbol.hasInstance](instance: object): boolean; } /** * Utilities for parallel asynchronous operations, for use with the system `Promise` APIs. * * @public */ export declare class Async { /** * Given an input array and a `callback` function, invoke the callback to start a * promise for each element in the array. Returns an array containing the results. * * @remarks * This API is similar to the system `Array#map`, except that the loop is asynchronous, * and the maximum number of concurrent promises can be throttled * using {@link IAsyncParallelismOptions.concurrency}. * * If `callback` throws a synchronous exception, or if it returns a promise that rejects, * then the loop stops immediately. Any remaining array items will be skipped, and * overall operation will reject with the first error that was encountered. * * @param iterable - the array of inputs for the callback function * @param callback - a function that starts an asynchronous promise for an element * from the array * @param options - options for customizing the control flow * @returns an array containing the result for each callback, in the same order * as the original input `array` */ static mapAsync<TEntry, TRetVal>(iterable: Iterable<TEntry> | AsyncIterable<TEntry>, callback: (entry: TEntry, arrayIndex: number) => Promise<TRetVal>, options?: (IAsyncParallelismOptions & { weighted?: false; }) | undefined): Promise<TRetVal[]>; /** * Given an input array and a `callback` function, invoke the callback to start a * promise for each element in the array. Returns an array containing the results. * * @remarks * This API is similar to the system `Array#map`, except that the loop is asynchronous, * and the maximum number of concurrent units can be throttled * using {@link IAsyncParallelismOptions.concurrency}. Using the {@link IAsyncParallelismOptions.weighted} * option, the weight of each operation can be specified, which determines how many concurrent units it takes up. * * If `callback` throws a synchronous exception, or if it returns a promise that rejects, * then the loop stops immediately. Any remaining array items will be skipped, and * overall operation will reject with the first error that was encountered. * * @param iterable - the array of inputs for the callback function * @param callback - a function that starts an asynchronous promise for an element * from the array * @param options - options for customizing the control flow * @returns an array containing the result for each callback, in the same order * as the original input `array` */ static mapAsync<TEntry extends IWeighted, TRetVal>(iterable: Iterable<TEntry> | AsyncIterable<TEntry>, callback: (entry: TEntry, arrayIndex: number) => Promise<TRetVal>, options: IAsyncParallelismOptions & { weighted: true; }): Promise<TRetVal[]>; private static _forEachWeightedAsync; /** * Given an input array and a `callback` function, invoke the callback to start a * promise for each element in the array. * * @remarks * This API is similar to the system `Array#forEach`, except that the loop is asynchronous, * and the maximum number of concurrent promises can be throttled * using {@link IAsyncParallelismOptions.concurrency}. * * If `callback` throws a synchronous exception, or if it returns a promise that rejects, * then the loop stops immediately. Any remaining array items will be skipped, and * overall operation will reject with the first error that was encountered. * * @param iterable - the array of inputs for the callback function * @param callback - a function that starts an asynchronous promise for an element * from the array * @param options - options for customizing the control flow */ static forEachAsync<TEntry>(iterable: Iterable<TEntry> | AsyncIterable<TEntry>, callback: (entry: TEntry, arrayIndex: number) => Promise<void>, options?: (IAsyncParallelismOptions & { weighted?: false; }) | undefined): Promise<void>; /** * Given an input array and a `callback` function, invoke the callback to start a * promise for each element in the array. * * @remarks * This API is similar to the other `Array#forEachAsync`, except that each item can have * a weight that determines how many concurrent operations are allowed. The unweighted * `Array#forEachAsync` is a special case of this method where weight = 1 for all items. * * The maximum number of concurrent operations can still be throttled using * {@link IAsyncParallelismOptions.concurrency}, however it no longer determines the * maximum number of operations that can be in progress at once. Instead, it determines the * number of concurrency units that can be in progress at once. The weight of each operation * determines how many concurrency units it takes up. For example, if the concurrency is 2 * and the first operation has a weight of 2, then only one more operation can be in progress. * * If `callback` throws a synchronous exception, or if it returns a promise that rejects, * then the loop stops immediately. Any remaining array items will be skipped, and * overall operation will reject with the first error that was encountered. * * @param iterable - the array of inputs for the callback function * @param callback - a function that starts an asynchronous promise for an element * from the array * @param options - options for customizing the control flow */ static forEachAsync<TEntry extends IWeighted>(iterable: Iterable<TEntry> | AsyncIterable<TEntry>, callback: (entry: TEntry, arrayIndex: number) => Promise<void>, options: IAsyncParallelismOptions & { weighted: true; }): Promise<void>; /** * Return a promise that resolves after the specified number of milliseconds. */ static sleepAsync(ms: number): Promise<void>; /** * Executes an async function and optionally retries it if it fails. */ static runWithRetriesAsync<TResult>({ action, maxRetries, retryDelayMs }: IRunWithRetriesOptions<TResult>): Promise<TResult>; /** * Ensures that the argument is a valid {@link IWeighted}, with a `weight` argument that * is a positive integer or 0. */ static validateWeightedIterable(operation: IWeighted): void; /** * Returns a Signal, a.k.a. a "deferred promise". */ static getSignal(): [Promise<void>, () => void, (err: Error) => void]; } /** * A queue that allows for asynchronous iteration. During iteration, the queue will wait until * the next item is pushed into the queue before yielding. If instead all queue items are consumed * and all callbacks have been called, the queue will return. * * @public */ export declare class AsyncQueue<T> implements AsyncIterable<[T, () => void]> { private _queue; private _onPushSignal; private _onPushResolve; constructor(iterable?: Iterable<T>); [Symbol.asyncIterator](): AsyncIterableIterator<[T, () => void]>; /** * Adds an item to the queue. * * @param item - The item to push into the queue. */ push(item: T): void; } /** * A "branded type" is a primitive type with a compile-type key that makes it incompatible with other * aliases for the primitive type. * * @remarks * * Example usage: * * ```ts * // PhoneNumber is a branded type based on the "string" primitive. * type PhoneNumber = Brand<string, 'PhoneNumber'>; * * function createPhoneNumber(input: string): PhoneNumber { * if (!/\d+(\-\d+)+/.test(input)) { * throw new Error('Invalid phone number: ' + JSON.stringify(input)); * } * return input as PhoneNumber; * } * * const p1: PhoneNumber = createPhoneNumber('123-456-7890'); * * // PhoneNumber is a string and can be used as one: * const p2: string = p1; * * // But an arbitrary string cannot be implicitly type cast as PhoneNumber. * // ERROR: Type 'string' is not assignable to type 'PhoneNumber' * const p3: PhoneNumber = '123-456-7890'; * ``` * * For more information about this pattern, see {@link * https://github.com/Microsoft/TypeScript/blob/7b48a182c05ea4dea81bab73ecbbe9e013a79e99/src/compiler/types.ts#L693-L698 * | this comment} explaining the TypeScript compiler's introduction of this pattern, and * {@link https://spin.atomicobject.com/2018/01/15/typescript-flexible-nominal-typing/ | this article} * explaining the technique in depth. * * @public */ export declare type Brand<T, BrandTag extends string> = T & { __brand: BrandTag; }; /** * The allowed types of encodings, as supported by Node.js * @public */ export declare enum Encoding { Utf8 = "utf8" } /** * A helper for looking up TypeScript `enum` keys/values. * * @remarks * TypeScript enums implement a lookup table for mapping between their keys and values: * * ```ts * enum Colors { * Red = 1 * } * * // Prints "Red" * console.log(Colors[1]); * * // Prints "1" * console.log(Colors["Red]); * ``` * * However the compiler's "noImplicitAny" validation has trouble with these mappings, because * there are so many possible types for the map elements: * * ```ts * function f(s: string): Colors | undefined { * // (TS 7015) Element implicitly has an 'any' type because * // index expression is not of type 'number'. * return Colors[s]; * } * ``` * * The `Enum` helper provides a more specific, strongly typed way to access members: * * ```ts * function f(s: string): Colors | undefined { * return Enum.tryGetValueByKey(Colors, s); * } * ``` * * @public */ export declare class Enum { private constructor(); /** * Returns an enum value, given its key. Returns `undefined` if no matching key is found. * * @example * * Example usage: * ```ts * enum Colors { * Red = 1 * } * * // Prints "1" * console.log(Enum.tryGetValueByKey(Colors, "Red")); * * // Prints "undefined" * console.log(Enum.tryGetValueByKey(Colors, "Black")); * ``` */ static tryGetValueByKey<TEnumValue>(enumObject: { [key: string]: TEnumValue | string; [key: number]: TEnumValue | string; }, key: string): TEnumValue | undefined; /** * This API is similar to {@link Enum.tryGetValueByKey}, except that it throws an exception * if the key is undefined. */ static getValueByKey<TEnumValue>(enumObject: { [key: string]: TEnumValue | string; [key: number]: TEnumValue | string; }, key: string): TEnumValue; /** * Returns an enum string key, given its numeric value. Returns `undefined` if no matching value * is found. * * @remarks * The TypeScript compiler only creates a reverse mapping for enum members whose value is numeric. * For example: * * ```ts * enum E { * A = 1, * B = 'c' * } * * // Prints "A" * console.log(E[1]); * * // Prints "undefined" * console.log(E["c"]); * ``` * * @example * * Example usage: * ```ts * enum Colors { * Red = 1, * Blue = 'blue' * } * * // Prints "Red" * console.log(Enum.tryGetKeyByNumber(Colors, 1)); * * // Prints "undefined" * console.log(Enum.tryGetKeyByNumber(Colors, -1)); * ``` */ static tryGetKeyByNumber<TEnumValue, TEnumObject extends { [key: string]: TEnumValue; }>(enumObject: TEnumObject, value: number): keyof typeof enumObject | undefined; /** * This API is similar to {@link Enum.tryGetKeyByNumber}, except that it throws an exception * if the key is undefined. */ static getKeyByNumber<TEnumValue, TEnumObject extends { [key: string]: TEnumValue; }>(enumObject: TEnumObject, value: number): keyof typeof enumObject; } /** * A map data structure that stores process environment variables. On Windows * operating system, the variable names are case-insensitive. * @public */ export declare class EnvironmentMap { private readonly _map; /** * Whether the environment variable names are case-sensitive. * * @remarks * On Windows operating system, environment variables are case-insensitive. * The map will preserve the variable name casing from the most recent assignment operation. */ readonly caseSensitive: boolean; constructor(environmentObject?: Record<string, string | undefined>); /** * Clears all entries, resulting in an empty map. */ clear(): void; /** * Assigns the variable to the specified value. A previous value will be overwritten. * * @remarks * The value can be an empty string. To completely remove the entry, use * {@link EnvironmentMap.unset} instead. */ set(name: string, value: string): void; /** * Removes the key from the map, if present. */ unset(name: string): void; /** * Returns the value of the specified variable, or `undefined` if the map does not contain that name. */ get(name: string): string | undefined; /** * Returns the map keys, which are environment variable names. */ names(): IterableIterator<string>; /** * Returns the map entries. */ entries(): IterableIterator<IEnvironmentEntry>; /** * Adds each entry from `environmentMap` to this map. */ mergeFrom(environmentMap: EnvironmentMap): void; /** * Merges entries from a plain JavaScript object, such as would be used with the `process.env` API. */ mergeFromObject(environmentObject?: Record<string, string | undefined>): void; /** * Returns the keys as a plain JavaScript object similar to the object returned by the `process.env` API. */ toObject(): Record<string, string>; } /** * The Executable class provides a safe, portable, recommended solution for tools that need * to launch child processes. * * @remarks * The NodeJS child_process API provides a solution for launching child processes, however * its design encourages reliance on the operating system shell for certain features. * Invoking the OS shell is not safe, not portable, and generally not recommended: * * - Different shells have different behavior and command-line syntax, and which shell you * will get with NodeJS is unpredictable. There is no universal shell guaranteed to be * available on all platforms. * * - If a command parameter contains symbol characters, a shell may interpret them, which * can introduce a security vulnerability * * - Each shell has different rules for escaping these symbols. On Windows, the default * shell is incapable of escaping certain character sequences. * * The Executable API provides a pure JavaScript implementation of primitive shell-like * functionality for searching the default PATH, appending default file extensions on Windows, * and executing a file that may contain a POSIX shebang. This primitive functionality * is sufficient (and recommended) for most tooling scenarios. * * If you need additional shell features such as wildcard globbing, environment variable * expansion, piping, or built-in commands, then we recommend to use the `@microsoft/rushell` * library instead. Rushell is a pure JavaScript shell with a standard syntax that is * guaranteed to work consistently across all platforms. * * @public */ export declare class Executable { /** * Synchronously create a child process and optionally capture its output. * * @remarks * This function is similar to child_process.spawnSync(). The main differences are: * * - It does not invoke the OS shell unless the executable file is a shell script. * - Command-line arguments containing special characters are more accurately passed * through to the child process. * - If the filename is missing a path, then the shell's default PATH will be searched. * - If the filename is missing a file extension, then Windows default file extensions * will be searched. * * @param filename - The name of the executable file. This string must not contain any * command-line arguments. If the name contains any path delimiters, then the shell's * default PATH will not be searched. * @param args - The command-line arguments to be passed to the process. * @param options - Additional options * @returns the same data type as returned by the NodeJS child_process.spawnSync() API * * @privateRemarks * * NOTE: The NodeJS spawnSync() returns SpawnSyncReturns<string> or SpawnSyncReturns<Buffer> * polymorphically based on the options.encoding parameter value. This is a fairly confusing * design. In most cases, developers want string with the default encoding. If/when someone * wants binary output or a non-default text encoding, we will introduce a separate API function * with a name like "spawnWithBufferSync". */ static spawnSync(filename: string, args: string[], options?: IExecutableSpawnSyncOptions): child_process.SpawnSyncReturns<string>; /** * Start a child process. * * @remarks * This function is similar to child_process.spawn(). The main differences are: * * - It does not invoke the OS shell unless the executable file is a shell script. * - Command-line arguments containing special characters are more accurately passed * through to the child process. * - If the filename is missing a path, then the shell's default PATH will be searched. * - If the filename is missing a file extension, then Windows default file extensions * will be searched. * * This command is asynchronous, but it does not return a `Promise`. Instead it returns * a Node.js `ChildProcess` supporting event notifications. * * @param filename - The name of the executable file. This string must not contain any * command-line arguments. If the name contains any path delimiters, then the shell's * default PATH will not be searched. * @param args - The command-line arguments to be passed to the process. * @param options - Additional options * @returns the same data type as returned by the NodeJS child_process.spawnSync() API */ static spawn(filename: string, args: string[], options?: IExecutableSpawnOptions): child_process.ChildProcess; /** {@inheritDoc Executable.(waitForExitAsync:3)} */ static waitForExitAsync(childProcess: child_process.ChildProcess, options: IWaitForExitWithStringOptions): Promise<IWaitForExitResult<string>>; /** {@inheritDoc Executable.(waitForExitAsync:3)} */ static waitForExitAsync(childProcess: child_process.ChildProcess, options: IWaitForExitWithBufferOptions): Promise<IWaitForExitResult<Buffer>>; /** * Wait for a child process to exit and return the result. * * @param childProcess - The child process to wait for. * @param options - Options for waiting for the process to exit. */ static waitForExitAsync(childProcess: child_process.ChildProcess, options?: IWaitForExitOptions): Promise<IWaitForExitResult<never>>; /** * Get the list of processes currently running on the system, keyed by the process ID. * * @remarks The underlying implementation depends on the operating system: * - On Windows, this uses the `wmic.exe` utility. * - On Unix, this uses the `ps` utility. */ static getProcessInfoByIdAsync(): Promise<Map<number, IProcessInfo>>; /** * {@inheritDoc Executable.getProcessInfoByIdAsync} */ static getProcessInfoById(): Map<number, IProcessInfo>; /** * Get the list of processes currently running on the system, keyed by the process name. All processes * with the same name will be grouped. * * @remarks The underlying implementation depends on the operating system: * - On Windows, this uses the `wmic.exe` utility. * - On Unix, this uses the `ps` utility. */ static getProcessInfoByNameAsync(): Promise<Map<string, IProcessInfo[]>>; /** * {@inheritDoc Executable.getProcessInfoByNameAsync} */ static getProcessInfoByName(): Map<string, IProcessInfo[]>; private static _buildCommandLineFixup; /** * Given a filename, this determines the absolute path of the executable file that would * be executed by a shell: * * - If the filename is missing a path, then the shell's default PATH will be searched. * - If the filename is missing a file extension, then Windows default file extensions * will be searched. * * @remarks * * @param filename - The name of the executable file. This string must not contain any * command-line arguments. If the name contains any path delimiters, then the shell's * default PATH will not be searched. * @param options - optional other parameters * @returns the absolute path of the executable, or undefined if it was not found */ static tryResolve(filename: string, options?: IExecutableResolveOptions): string | undefined; private static _tryResolve; private static _tryResolveFileExtension; private static _buildEnvironmentMap; /** * This is used when searching the shell PATH for an executable, to determine * whether a match should be skipped or not. If it returns true, this does not * guarantee that the file can be successfully executed. */ private static _canExecute; /** * Returns the list of folders where we will search for an executable, * based on the PATH environment variable. */ private static _getSearchFolders; private static _getExecutableContext; /** * Given an input string containing special symbol characters, this inserts the "^" escape * character to ensure the symbols are interpreted literally by the Windows shell. */ private static _getEscapedForWindowsShell; /** * Checks for characters that are unsafe to pass to a Windows batch file * due to the way that cmd.exe implements escaping. */ private static _validateArgsForWindowsShell; } /** * Types for {@link IExecutableSpawnSyncOptions.stdio} * and {@link IExecutableSpawnOptions.stdio} * @public */ export declare type ExecutableStdioMapping = 'pipe' | 'ignore' | 'inherit' | ExecutableStdioStreamMapping[]; /** * Typings for one of the streams inside IExecutableSpawnSyncOptions.stdio. * @public */ export declare type ExecutableStdioStreamMapping = 'pipe' | 'ignore' | 'inherit' | NodeJS.WritableStream | NodeJS.ReadableStream | number | undefined; /** * String constants for common filenames and parts of filenames. * * @public */ export declare const FileConstants: { /** * "package.json" - the configuration file that defines an NPM package */ readonly PackageJson: "package.json"; }; /** * An `Error` subclass that should be thrown to report an unexpected state that specifically references * a location in a file. * * @remarks The file path provided to the FileError constructor is expected to exist on disk. FileError * should not be used for reporting errors that are not in reference to an existing file. * * @public */ export declare class FileError extends Error { /** @internal */ static _sanitizedEnvironmentVariable: string | undefined; /** @internal */ static _environmentVariableIsAbsolutePath: boolean; private static _environmentVariableBasePathFnMap; /** {@inheritdoc IFileErrorOptions.absolutePath} */ readonly absolutePath: string; /** {@inheritdoc IFileErrorOptions.projectFolder} */ readonly projectFolder: string; /** {@inheritdoc IFileErrorOptions.line} */ readonly line: number | undefined; /** {@inheritdoc IFileErrorOptions.column} */ readonly column: number | undefined; /** * Constructs a new instance of the {@link FileError} class. * * @param message - A message describing the error. * @param options - Options for the error. */ constructor(message: string, options: IFileErrorOptions); /** * Get the Unix-formatted the error message. * * @override */ toString(): string; /** * Get the formatted error message. * * @param options - Options for the error message format. */ getFormattedErrorMessage(options?: IFileErrorFormattingOptions): string; private _evaluateBaseFolder; static [Symbol.hasInstance](instance: object): boolean; } /** * The format that the FileError message should conform to. The supported formats are: * - Unix: `<path>:<line>:<column> - <message>` * - VisualStudio: `<path>(<line>,<column>) - <message>` * * @public */ export declare type FileLocationStyle = 'Unix' | 'VisualStudio'; /** * The FileSystem API provides a complete set of recommended operations for interacting with the file system. * * @remarks * We recommend to use this instead of the native `fs` API, because `fs` is a minimal set of low-level * primitives that must be mapped for each supported operating system. The FileSystem API takes a * philosophical approach of providing "one obvious way" to do each operation. We also prefer synchronous * operations except in cases where there would be a clear performance benefit for using async, since synchronous * code is much easier to read and debug. Also, indiscriminate parallelism has been seen to actually worsen * performance, versus improving it. * * Note that in the documentation, we refer to "filesystem objects", this can be a * file, folder, symbolic link, hard link, directory junction, etc. * * @public */ export declare class FileSystem { /** * Returns true if the path exists on disk. * Behind the scenes it uses `fs.existsSync()`. * @remarks * There is a debate about the fact that after `fs.existsSync()` returns true, * the file might be deleted before fs.readSync() is called, which would imply that everybody * should catch a `readSync()` exception, and nobody should ever use `fs.existsSync()`. * We find this to be unpersuasive, since "unexceptional exceptions" really hinder the * break-on-exception debugging experience. Also, throwing/catching is generally slow. * @param path - The absolute or relative path to the filesystem object. */ static exists(path: string): boolean; /** * An async version of {@link FileSystem.exists}. */ static existsAsync(path: string): Promise<boolean>; /** * Gets the statistics for a particular filesystem object. * If the path is a link, this function follows the link and returns statistics about the link target. * Behind the scenes it uses `fs.statSync()`. * @param path - The absolute or relative path to the filesystem object. */ static getStatistics(path: string): FileSystemStats; /** * An async version of {@link FileSystem.getStatistics}. */ static getStatisticsAsync(path: string): Promise<FileSystemStats>; /** * Updates the accessed and modified timestamps of the filesystem object referenced by path. * Behind the scenes it uses `fs.utimesSync()`. * The caller should specify both times in the `times` parameter. * @param path - The path of the file that should be modified. * @param times - The times that the object should be updated to reflect. */ static updateTimes(path: string, times: IFileSystemUpdateTimeParameters): void; /** * An async version of {@link FileSystem.updateTimes}. */ static updateTimesAsync(path: string, times: IFileSystemUpdateTimeParameters): Promise<void>; /** * Changes the permissions (i.e. file mode bits) for a filesystem object. * Behind the scenes it uses `fs.chmodSync()`. * @param path - The absolute or relative path to the object that should be updated. * @param modeBits - POSIX-style file mode bits specified using the {@link PosixModeBits} enum */ static changePosixModeBits(path: string, modeBits: PosixModeBits): void; /** * An async version of {@link FileSystem.changePosixModeBits}. */ static changePosixModeBitsAsync(path: string, mode: PosixModeBits): Promise<void>; /** * Retrieves the permissions (i.e. file mode bits) for a filesystem object. * Behind the scenes it uses `fs.chmodSync()`. * @param path - The absolute or relative path to the object that should be updated. * * @remarks * This calls {@link FileSystem.getStatistics} to get the POSIX mode bits. * If statistics in addition to the mode bits are needed, it is more efficient * to call {@link FileSystem.getStatistics} directly instead. */ static getPosixModeBits(path: string): PosixModeBits; /** * An async version of {@link FileSystem.getPosixModeBits}. */ static getPosixModeBitsAsync(path: string): Promise<PosixModeBits>; /** * Returns a 10-character string representation of a PosixModeBits value similar to what * would be displayed by a command such as "ls -l" on a POSIX-like operating system. * @remarks * For example, `PosixModeBits.AllRead | PosixModeBits.AllWrite` would be formatted as "-rw-rw-rw-". * @param modeBits - POSIX-style file mode bits specified using the {@link PosixModeBits} enum */ static formatPosixModeBits(modeBits: PosixModeBits): string; /** * Moves a file. The folder must exist, unless the `ensureFolderExists` option is provided. * Behind the scenes it uses `fs-extra.moveSync()` */ static move(options: IFileSystemMoveOptions): void; /** * An async version of {@link FileSystem.move}. */ static moveAsync(options: IFileSystemMoveOptions): Promise<void>; /** * Recursively creates a folder at a given path. * Behind the scenes is uses `fs-extra.ensureDirSync()`. * @remarks * Throws an exception if anything in the folderPath is not a folder. * @param folderPath - The absolute or relative path of the folder which should be created. */ static ensureFolder(folderPath: string): void; /** * An async version of {@link FileSystem.ensureFolder}. */ static ensureFolderAsync(folderPath: string): Promise<void>; /** * Reads the names of folder entries, not including "." or "..". * Behind the scenes it uses `fs.readdirSync()`. * @param folderPath - The absolute or relative path to the folder which should be read. * @param options - Optional settings that can change the behavior. Type: `IReadFolderOptions` */ static readFolderItemNames(folderPath: string, options?: IFileSystemReadFolderOptions): string[]; /** * An async version of {@link FileSystem.readFolderItemNames}. */ static readFolderItemNamesAsync(folderPath: string, options?: IFileSystemReadFolderOptions): Promise<string[]>; /** * Reads the contents of the folder, not including "." or "..", returning objects including the * entry names and types. * Behind the scenes it uses `fs.readdirSync()`. * @param folderPath - The absolute or relative path to the folder which should be read. * @param options - Optional settings that can change the behavior. Type: `IReadFolderOptions` */ static readFolderItems(folderPath: string, options?: IFileSystemReadFolderOptions): FolderItem[]; /** * An async version of {@link FileSystem.readFolderItems}. */ static readFolderItemsAsync(folderPath: string, options?: IFileSystemReadFolderOptions): Promise<FolderItem[]>; /** * Deletes a folder, including all of its contents. * Behind the scenes is uses `fs-extra.removeSync()`. * @remarks * Does not throw if the folderPath does not exist. * @param folderPath - The absolute or relative path to the folder which should be deleted. */ static deleteFolder(folderPath: string): void; /** * An async version of {@link FileSystem.deleteFolder}. */ static deleteFolderAsync(folderPath: string): Promise<void>; /** * Deletes the content of a folder, but not the folder itself. Also ensures the folder exists. * Behind the scenes it uses `fs-extra.emptyDirSync()`. * @remarks * This is a workaround for a common race condition, where the virus scanner holds a lock on the folder * for a brief period after it was deleted, causing EBUSY errors for any code that tries to recreate the folder. * @param folderPath - The absolute or relative path to the folder which should have its contents deleted. */ static ensureEmptyFolder(folderPath: string): void; /** * An async version of {@link FileSystem.ensureEmptyFolder}. */ static ensureEmptyFolderAsync(folderPath: string): Promise<void>; /** * Writes a text string to a file on disk, overwriting the file if it already exists. * Behind the scenes it uses `fs.writeFileSync()`. * @remarks * Throws an error if the folder doesn't exist, unless ensureFolder=true. * @param filePath - The absolute or relative path of the file. * @param contents - The text that should be written to the file. * @param options - Optional settings that can change the behavior. Type: `IWriteFileOptions` */ static writeFile(filePath: string, contents: string | Buffer, options?: IFileSystemWriteFileOptions): void; /** * Writes the contents of multiple Uint8Arrays to a file on disk, overwriting the file if it already exists. * Behind the scenes it uses `fs.writevSync()`. * * This API is useful for writing large files efficiently, especially if the input is being concatenated from * multiple sources. * * @remarks * Throws an error if the folder doesn't exist, unless ensureFolder=true. * @param filePath - The absolute or relative path of the file. * @param contents - The content that should be written to the file. * @param options - Optional settings that can change the behavior. */ static writeBuffersToFile(filePath: string, contents: ReadonlyArray<Uint8Array>, options?: IFileSystemWriteBinaryFileOptions): void; /** * An async version of {@link FileSystem.writeFile}. */ static writeFileAsync(filePath: string, contents: string | Buffer, options?: IFileSystemWriteFileOptions): Promise<void>; /** * An async version of {@link FileSystem.writeBuffersToFile}. */ static writeBuffersToFileAsync(filePath: string, contents: ReadonlyArray<Uint8Array>, options?: IFileSystemWriteBinaryFileOptions): Promise<void>; /** * Writes a text string to a file on disk, appending to the file if it already exists. * Behind the scenes it uses `fs.appendFileSync()`. * @remarks * Throws an error if the folder doesn't exist, unless ensureFolder=true. * @param filePath - The absolute or relative path of the file. * @param contents - The text that should be written to the file. * @param options - Optional settings that can change the behavior. Type: `IWriteFileOptions` */ static appendToFile(filePath: string, contents: string | Buffer, options?: IFileSystemWriteFileOptions): void; /** * An async version of {@link FileSystem.appendToFile}. */ static appendToFileAsync(filePath: string, contents: string | Buffer, options?: IFileSystemWriteFileOptions): Promise<void>; /** * Reads the contents of a file into a string. * Behind the scenes it uses `fs.readFileSync()`. * @param filePath - The relative or absolute path to the file whose contents should be read. * @param options - Optional settings that can change the behavior. Type: `IReadFileOptions` */ static readFile(filePath: string, options?: IFileSystemReadFileOptions): string; /** * An async version of {@link FileSystem.readFile}. */ static readFileAsync(filePath: string, options?: IFileSystemReadFileOptions): Promise<string>; /** * Reads the contents of a file into a buffer. * Behind the scenes is uses `fs.readFileSync()`. * @param filePath - The relative or absolute path to the file whose contents should be read. */ static readFileToBuffer(filePath: string): Buffer; /** * An async version of {@link FileSystem.readFileToBuffer}. */ static readFileToBufferAsync(filePath: string): Promise<Buffer>; /** * Copies a single file from one location to another. * By default, destinationPath is overwritten if it already exists. * * @remarks * The `copyFile()` API cannot be used to copy folders. It copies at most one file. * Use {@link FileSystem.copyFiles} if you need to recursively copy a tree of folders. * * The implementation is based on `copySync()` from the `fs-extra` package. */ static copyFile(options: IFileSystemCopyFileOptions): void; /** * An async version of {@link FileSystem.copyFile}. */ static copyFileAsync(options: IFileSystemCopyFileOptions): Promise<void>; /** * Copies a file or folder from one location to another, recursively copying any folder contents. * By default, destinationPath is overwritten if it already exists. * * @remarks * If you only intend to copy a single file, it is recommended to use {@link FileSystem.copyFile} * instead to more clearly communicate the intended operation. * * The implementation is based on `copySync()` from the `fs-extra` package. */ static copyFiles(options: IFileSystemCopyFilesOptions): void; /** * An async version of {@link FileSystem.copyFiles}. */ static copyFilesAsync(options: IFileSystemCopyFilesAsyncOptions): Promise<void>; /** * Deletes a file. Can optionally throw if the file doesn't exist. * Behind the scenes it uses `fs.unlinkSync()`. * @param filePath - The absolute or relative path to the file that should be deleted. * @param options - Optional settings that can change the behavior. Type: `IDeleteFileOptions` */ static deleteFile(filePath: string, options?: IFileSystemDeleteFileOptions): void; /** * An async version of {@link FileSystem.deleteFile}. */ static deleteFileAsync(filePath: string, options?: IFileSystemDeleteFileOptions): Promise<void>; /** * Gets the statistics of a filesystem object. Does NOT follow the link to its target. * Behind the scenes it uses `fs.lstatSync()`. * @param path - The absolute or relative path to the filesystem object. */ static getLinkStatistics(path: string): FileSystemStats; /** * An async version of {@link FileSystem.getLinkStatistics}. */ static getLinkStatisticsAsync(path: string): Promise<FileSystemStats>; /** * If `path` refers to a symbolic link, this returns the path of the link target, which may be * an absolute or relative path. * * @remarks * If `path` refers to a filesystem object that is not a symbolic link, then an `ErrnoException` is thrown * with code 'UNKNOWN'. If `path` does not exist, then an `ErrnoException` is thrown with code `ENOENT`. * * @param path - The absolute or relative path to the symbolic link. * @returns the path of the link target */ static readLink(path: string): string; /** * An async version of {@link FileSystem.readLink}. */ static readLinkAsync(path: string): Promise<string>; /** * Creates an NTFS "directory junction" on Windows operating systems; for other operating systems, it * creates a regular symbolic link. The link target must be a folder, not a file. * Behind the scenes it uses `fs.symlinkSync()`. * * @remarks * For security reasons, Windows operating systems by default require administrator elevation to create * symbolic links. As a result, on Windows it's generally recommended for Node.js tools to use hard links * (for files) or NTFS directory junctions (for folders), since regular users are allowed to create them. * Hard links and junctions are less vulnerable to symlink attacks because they cannot reference a network share, * and their target must exist at the time of link creation. Non-Windows operating systems generally don't * restrict symlink creation, and as such are more vulnerable to symlink attacks. Note that Windows can be * configured to permit regular users to create symlinks, for example by enabling Windows 10 "developer mode." * * A directory junction requires the link source and target to both be located on local disk volumes; * if not, use a symbolic link instead. */ static createSymbolicLinkJunction(options: IFileSystemCreateLinkOptions): void; /** * An async version of {@link FileSystem.createSymbolicLinkJunction}. */ static createSymbolicLinkJunctionAsync(options: IFileSystemCreateLinkOptions): Promise<void>; /** * Creates a symbolic link to a file. On Windows operating systems, this may require administrator elevation. * Behind the scenes it uses `fs.symlinkSync()`. * * @remarks * To avoid administrator elevation on Windows, use {@link FileSystem.createHardLink} instead. * * On Windows operating systems, the NTFS file system distinguishes file symlinks versus directory symlinks: * If the target is not the correct type, the symlink will be created successfully, but will fail to resolve. * Other operating systems do not make this distinction, in which case {@link FileSystem.createSymbolicLinkFile} * and {@link FileSystem.createSymbolicLinkFolder} can be used interchangeably, but doing so will make your * tool incompatible with Windows. */ static createSymbolicLinkFile(options: IFileSystemCreateLinkOptions): void; /** * An async version of {@link FileSystem.createSymbolicLinkFile}. */ static createSymbolicLinkFileAsync(options: IFileSystemCreateLinkOptions): Promise<void>; /** * Creates a symbolic link to a folder. On Windows operating systems, this may require administrator elevation. * Behind the scenes it uses `fs.symlinkSync()`. * * @remarks * To avoid administrator elevation on Windows, use {@link FileSystem.createSymbolicLinkJunction} instead. * * On Windows operating systems, the NTFS file system distinguishes file symlinks versus directory symlinks: * If the target is not the correct type, the symlink will be created successfully, but will fail to resolve. * Other operating systems do not make this distinction, in which case {@link FileSystem.createSymbolicLinkFile} * and {@link FileSystem.createSymbolicLinkFolder} can be used interchangeably, but doing so will make your * tool incompatible with Windows. */ static createSymbolicLinkFolder(options: IFileSystemCreateLinkOptions): void; /** * An async version of {@link FileSystem.createSymbolicLinkFolder}. */ static createSymbolicLinkFolderAsync(options: IFileSystemCreateLinkOptions): Promise<void>; /** * Creates a hard link. The link target must be a file, not a folder. * Behind the scenes it uses `fs.linkSync()`. * * @remarks * For security reasons, Windows operating systems by default require administrator elevation to create * symbolic links. As a result, on Windows it's generally recommended for Node.js tools to use hard links * (for files) or NTFS directory junctions (for folders), since regular users are allowed to create them. * Hard links and junctions are less vulnerable to symlink attacks because they cannot reference a network share, * and their target must exist at the time of link creation. Non-Windows operating systems generally don't * restrict symlink creation, and as such are more vulnerable to symlink attacks. Note that Windows can be * configured to permit regular users to create symlinks, for example by enabling Windows 10 "developer mode." * * A hard link requires the link source and target to both be located on same disk volume; * if not, use a symbolic link instead. */ static createHardLink(options: IFileSystemCreateLinkOptions): void; /** * An async version of {@link FileSystem.createHardLink}. */ static createHardLinkAsync(options: IFileSystemCreateLinkOptions): Promise<void>; /** * Follows a link to its destination and returns the absolute path to the final target of the link. * Behind the scenes it uses `fs.realpathSync()`. * @param linkPath - The path to the link. */ static getRealPath(linkPath: string): string; /** * An async version of {@link FileSystem.getRealPath}. */ static getRealPathAsync(linkPath: string): Promise<string>; /** * Returns true if the error object indicates the file or folder already exists (`EEXIST`). */ static isExistError(error: Error): boolean; /** * Returns true if the error object indicates the file or folder does not exist (`ENOENT` or `ENOTDIR`) */ static isNotExistError(error: Error): boolean; /** * Returns true if the error object indicates the file does not exist (`ENOENT`). */ static isFileDoesNotExistError(error: Error): boolean; /** * Returns true if the error object indicates the folder does not exist (`ENOTDIR`). */ static isFolderDoesNotExistError(error: Error): boolean; /**