@rushstack/node-core-library
Version:
Core libraries that every NodeJS toolchain project should use
1,101 lines (1,083 loc) • 158 kB
TypeScript
/**
* 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;
/**