Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "Add `FileSystem.createReadStream`, `FileSystem.createWriteStream`, and `FileSystem.createWriteStreamAsync` APIs for creating read and write filesystem streams.",
"type": "minor",
"packageName": "@rushstack/node-core-library"
}
],
"packageName": "@rushstack/node-core-library",
"email": "198982749+Copilot@users.noreply.github.com"
}
24 changes: 20 additions & 4 deletions common/reviews/api/node-core-library.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,15 @@ export class FileSystem {
static copyFilesAsync(options: IFileSystemCopyFilesAsyncOptions): Promise<void>;
static createHardLink(options: IFileSystemCreateLinkOptions): void;
static createHardLinkAsync(options: IFileSystemCreateLinkOptions): Promise<void>;
static createReadStream(filePath: string): FileSystemReadStream;
static createSymbolicLinkFile(options: IFileSystemCreateLinkOptions): void;
static createSymbolicLinkFileAsync(options: IFileSystemCreateLinkOptions): Promise<void>;
static createSymbolicLinkFolder(options: IFileSystemCreateLinkOptions): void;
static createSymbolicLinkFolderAsync(options: IFileSystemCreateLinkOptions): Promise<void>;
static createSymbolicLinkJunction(options: IFileSystemCreateLinkOptions): void;
static createSymbolicLinkJunctionAsync(options: IFileSystemCreateLinkOptions): Promise<void>;
static createWriteStream(filePath: string, options?: IFileSystemCreateWriteStreamOptions): FileSystemWriteStream;
static createWriteStreamAsync(filePath: string, options?: IFileSystemCreateWriteStreamOptions): Promise<FileSystemWriteStream>;
static deleteFile(filePath: string, options?: IFileSystemDeleteFileOptions): void;
static deleteFileAsync(filePath: string, options?: IFileSystemDeleteFileOptions): Promise<void>;
static deleteFolder(folderPath: string): void;
Expand Down Expand Up @@ -225,9 +228,15 @@ export type FileSystemCopyFilesAsyncFilter = (sourcePath: string, destinationPat
// @public
export type FileSystemCopyFilesFilter = (sourcePath: string, destinationPath: string) => boolean;

// @public
export type FileSystemReadStream = fs.ReadStream;

// @public
export type FileSystemStats = fs.Stats;

// @public
export type FileSystemWriteStream = fs.WriteStream;

// @public
export class FileWriter {
close(): void;
Expand Down Expand Up @@ -336,15 +345,18 @@ export interface IFileSystemCreateLinkOptions {
newLinkPath: string;
}

// @public
export interface IFileSystemCreateWriteStreamOptions extends IFileSystemWriteFileOptionsBase {
}

// @public
export interface IFileSystemDeleteFileOptions {
throwIfNotExists?: boolean;
}

// @public
export interface IFileSystemMoveOptions {
export interface IFileSystemMoveOptions extends IFileSystemWriteFileOptionsBase {
destinationPath: string;
ensureFolderExists?: boolean;
overwrite?: boolean;
sourcePath: string;
}
Expand All @@ -367,8 +379,7 @@ export interface IFileSystemUpdateTimeParameters {
}

// @public
export interface IFileSystemWriteBinaryFileOptions {
ensureFolderExists?: boolean;
export interface IFileSystemWriteBinaryFileOptions extends IFileSystemWriteFileOptionsBase {
}

// @public
Expand All @@ -377,6 +388,11 @@ export interface IFileSystemWriteFileOptions extends IFileSystemWriteBinaryFileO
encoding?: Encoding;
}

// @public (undocumented)
export interface IFileSystemWriteFileOptionsBase {
ensureFolderExists?: boolean;
}

// @public
export interface IFileWriterFlags {
append?: boolean;
Expand Down
109 changes: 95 additions & 14 deletions libraries/node-core-library/src/FileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ export type FileSystemStats = fs.Stats;
*/
export type FolderItem = fs.Dirent;

/**
* An alias for the Node.js `fs.ReadStream` object.
*
* @remarks
* This avoids the need to import the `fs` package when using the {@link FileSystem} API.
* @public
*/
export type FileSystemReadStream = fs.ReadStream;

/**
* An alias for the Node.js `fs.WriteStream` object.
*
* @remarks
* This avoids the need to import the `fs` package when using the {@link FileSystem} API.
* @public
*/
export type FileSystemWriteStream = fs.WriteStream;

// The PosixModeBits are intended to be used with bitwise operations.
/* eslint-disable no-bitwise */

Expand All @@ -44,17 +62,22 @@ export interface IFileSystemReadFolderOptions {
}

/**
* The options for {@link FileSystem.writeBuffersToFile}
* @public
*/
export interface IFileSystemWriteBinaryFileOptions {
export interface IFileSystemWriteFileOptionsBase {
/**
* If true, will ensure the folder is created before writing the file.
* @defaultValue false
*/
ensureFolderExists?: boolean;
}

/**
* The options for {@link FileSystem.writeBuffersToFile}
* @public
*/
export interface IFileSystemWriteBinaryFileOptions extends IFileSystemWriteFileOptionsBase {}

/**
* The options for {@link FileSystem.writeFile}
* @public
Expand Down Expand Up @@ -95,7 +118,7 @@ export interface IFileSystemReadFileOptions {
* The options for {@link FileSystem.move}
* @public
*/
export interface IFileSystemMoveOptions {
export interface IFileSystemMoveOptions extends IFileSystemWriteFileOptionsBase {
/**
* The path of the existing object to be moved.
* The path may be absolute or relative.
Expand All @@ -113,12 +136,6 @@ export interface IFileSystemMoveOptions {
* @defaultValue true
*/
overwrite?: boolean;

/**
* If true, will ensure the folder is created before writing the file.
* @defaultValue false
*/
ensureFolderExists?: boolean;
}

/**
Expand Down Expand Up @@ -258,6 +275,12 @@ export interface IFileSystemCopyFilesOptions extends IFileSystemCopyFilesAsyncOp
filter?: FileSystemCopyFilesFilter; // narrow the type to exclude FileSystemCopyFilesAsyncFilter
}

/**
* The options for {@link FileSystem.createWriteStream}
* @public
*/
export interface IFileSystemCreateWriteStreamOptions extends IFileSystemWriteFileOptionsBase {}

/**
* The options for {@link FileSystem.deleteFile}
* @public
Expand Down Expand Up @@ -750,10 +773,11 @@ export class FileSystem {
* 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.
* Throws an error if the folder doesn't exist, unless {@link IFileSystemWriteFileOptionsBase.ensureFolderExists}
* is set to `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`
* @param options - Optional settings that can change the behavior.
*/
public static writeFile(
filePath: string,
Expand Down Expand Up @@ -796,7 +820,8 @@ export class FileSystem {
* multiple sources.
*
* @remarks
* Throws an error if the folder doesn't exist, unless ensureFolder=true.
* Throws an error if the folder doesn't exist, unless {@link IFileSystemWriteFileOptionsBase.ensureFolderExists}
* is set to `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.
Expand Down Expand Up @@ -956,10 +981,11 @@ export class FileSystem {
* 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.
* Throws an error if the folder doesn't exist, unless {@link IFileSystemWriteFileOptionsBase.ensureFolderExists}
* is set to `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`
* @param options - Optional settings that can change the behavior.
*/
public static appendToFile(
filePath: string,
Expand Down Expand Up @@ -1237,6 +1263,61 @@ export class FileSystem {
});
}

/**
* Creates a readable stream for an existing file.
* Behind the scenes it uses `fs.createReadStream()`.
*
* @param filePath - The path to the file. The path may be absolute or relative.
* @returns A new readable stream for the file.
*/
public static createReadStream(filePath: string): FileSystemReadStream {
return FileSystem._wrapException(() => {
return fs.createReadStream(filePath);
});
}

/**
* Creates a writable stream for writing to a file.
* Behind the scenes it uses `fs.createWriteStream()`.
*
* @remarks
* Throws an error if the folder doesn't exist, unless {@link IFileSystemWriteFileOptionsBase.ensureFolderExists}
* is set to `true`.
* @param filePath - The path to the file. The path may be absolute or relative.
* @param options - Optional settings that can change the behavior.
* @returns A new writable stream for the file.
*/
public static createWriteStream(
filePath: string,
options?: IFileSystemCreateWriteStreamOptions
): FileSystemWriteStream {
return FileSystem._wrapException(() => {
if (options?.ensureFolderExists) {
const folderPath: string = nodeJsPath.dirname(filePath);
FileSystem.ensureFolder(folderPath);
}

return fs.createWriteStream(filePath);
});
}

/**
* An async version of {@link FileSystem.createWriteStream}.
*/
public static async createWriteStreamAsync(
filePath: string,
options?: IFileSystemCreateWriteStreamOptions
): Promise<FileSystemWriteStream> {
return await FileSystem._wrapExceptionAsync(async () => {
if (options?.ensureFolderExists) {
const folderPath: string = nodeJsPath.dirname(filePath);
await FileSystem.ensureFolderAsync(folderPath);
}

return fs.createWriteStream(filePath);
});
}

// ===============
// LINK OPERATIONS
// ===============
Expand Down
4 changes: 4 additions & 0 deletions libraries/node-core-library/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,19 @@ export { type IFileErrorOptions, type IFileErrorFormattingOptions, FileError } f
export {
AlreadyExistsBehavior,
FileSystem,
type IFileSystemWriteFileOptionsBase,
type FileSystemCopyFilesAsyncFilter,
type FileSystemCopyFilesFilter,
type FileSystemReadStream,
type FileSystemWriteStream,
type FolderItem,
type FileSystemStats,
type IFileSystemCopyFileBaseOptions,
type IFileSystemCopyFileOptions,
type IFileSystemCopyFilesAsyncOptions,
type IFileSystemCopyFilesOptions,
type IFileSystemCreateLinkOptions,
type IFileSystemCreateWriteStreamOptions,
type IFileSystemDeleteFileOptions,
type IFileSystemMoveOptions,
type IFileSystemReadFileOptions,
Expand Down
Loading