@rushstack/node-core-library
Advanced tools
Comparing version 3.20.0 to 3.21.0
@@ -5,2 +5,14 @@ { | ||
{ | ||
"version": "3.21.0", | ||
"tag": "@rushstack/node-core-library_v3.21.0", | ||
"date": "Thu, 21 May 2020 23:09:44 GMT", | ||
"comments": { | ||
"minor": [ | ||
{ | ||
"comment": "Create async versions of FileSystem and JsonFile APIs." | ||
} | ||
] | ||
} | ||
}, | ||
{ | ||
"version": "3.20.0", | ||
@@ -7,0 +19,0 @@ "tag": "@rushstack/node-core-library_v3.20.0", |
# Change Log - @rushstack/node-core-library | ||
This log was last generated on Thu, 21 May 2020 15:41:59 GMT and should not be manually modified. | ||
This log was last generated on Thu, 21 May 2020 23:09:44 GMT and should not be manually modified. | ||
## 3.21.0 | ||
Thu, 21 May 2020 23:09:44 GMT | ||
### Minor changes | ||
- Create async versions of FileSystem and JsonFile APIs. | ||
## 3.20.0 | ||
@@ -6,0 +13,0 @@ Thu, 21 May 2020 15:41:59 GMT |
@@ -174,2 +174,6 @@ /// <reference types="node" /> | ||
/** | ||
* An async version of {@link FileSystem.getStatistics}. | ||
*/ | ||
static getStatisticsAsync(path: string): Promise<fs.Stats>; | ||
/** | ||
* Updates the accessed and modified timestamps of the filesystem object referenced by path. | ||
@@ -183,2 +187,6 @@ * Behind the scenes it uses `fs.utimesSync()`. | ||
/** | ||
* 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. | ||
@@ -191,8 +199,21 @@ * Behind the scenes it uses `fs.chmodSync()`. | ||
/** | ||
* 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 | ||
@@ -211,2 +232,6 @@ * would be displayed by a command such as "ls -l" on a POSIX-like operating system. | ||
/** | ||
* An async version of {@link FileSystem.move}. | ||
*/ | ||
static moveAsync(options: IFileSystemMoveOptions): Promise<void>; | ||
/** | ||
* Recursively creates a folder at a given path. | ||
@@ -220,2 +245,6 @@ * Behind the scenes is uses `fs-extra.ensureDirSync()`. | ||
/** | ||
* An async version of {@link FileSystem.ensureFolder}. | ||
*/ | ||
static ensureFolderAsync(folderPath: string): Promise<void>; | ||
/** | ||
* Reads the contents of the folder, not including "." or "..". | ||
@@ -228,2 +257,6 @@ * Behind the scenes it uses `fs.readdirSync()`. | ||
/** | ||
* An async version of {@link FileSystem.readFolder}. | ||
*/ | ||
static readFolderAsync(folderPath: string, options?: IFileSystemReadFolderOptions): Promise<string[]>; | ||
/** | ||
* Deletes a folder, including all of its contents. | ||
@@ -237,2 +270,6 @@ * Behind the scenes is uses `fs-extra.removeSync()`. | ||
/** | ||
* 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. | ||
@@ -247,2 +284,6 @@ * Behind the scenes it uses `fs-extra.emptyDirSync()`. | ||
/** | ||
* 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. | ||
@@ -258,2 +299,6 @@ * Behind the scenes it uses `fs.writeFileSync()`. | ||
/** | ||
* An async version of {@link FileSystem.writeFile}. | ||
*/ | ||
static writeFileAsync(filePath: string, contents: string | Buffer, options?: IFileSystemWriteFileOptions): Promise<void>; | ||
/** | ||
* Writes a text string to a file on disk, appending to the file if it already exists. | ||
@@ -269,2 +314,6 @@ * Behind the scenes it uses `fs.appendFileSync()`. | ||
/** | ||
* 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. | ||
@@ -277,2 +326,6 @@ * Behind the scenes it uses `fs.readFileSync()`. | ||
/** | ||
* An async version of {@link FileSystem.readFile}. | ||
*/ | ||
static readFileAsync(filePath: string, options?: IFileSystemReadFileOptions): Promise<string>; | ||
/** | ||
* Reads the contents of a file into a buffer. | ||
@@ -284,2 +337,6 @@ * Behind the scenes is uses `fs.readFileSync()`. | ||
/** | ||
* An async version of {@link FileSystem.readFileToBuffer}. | ||
*/ | ||
static readFileToBufferAsync(filePath: string): Promise<Buffer>; | ||
/** | ||
* Copies a file from one location to another. | ||
@@ -291,2 +348,6 @@ * By default, destinationPath is overwritten if it already exists. | ||
/** | ||
* An async version of {@link FileSystem.copyFile}. | ||
*/ | ||
static copyFileAsync(options: IFileSystemCopyFileOptions): Promise<void>; | ||
/** | ||
* Deletes a file. Can optionally throw if the file doesn't exist. | ||
@@ -299,2 +360,6 @@ * Behind the scenes it uses `fs.unlinkSync()`. | ||
/** | ||
* 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. | ||
@@ -306,2 +371,6 @@ * Behind the scenes it uses `fs.lstatSync()`. | ||
/** | ||
* An async version of {@link FileSystem.getLinkStatistics}. | ||
*/ | ||
static getLinkStatisticsAsync(path: string): Promise<fs.Stats>; | ||
/** | ||
* Creates a Windows "directory junction". Behaves like `createSymbolicLinkToFile()` on other platforms. | ||
@@ -312,2 +381,6 @@ * Behind the scenes it uses `fs.symlinkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createSymbolicLinkJunction}. | ||
*/ | ||
static createSymbolicLinkJunctionAsync(options: IFileSystemCreateLinkOptions): Promise<void>; | ||
/** | ||
* Creates a symbolic link to a file (on Windows this requires elevated permissionsBits). | ||
@@ -318,2 +391,6 @@ * Behind the scenes it uses `fs.symlinkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createSymbolicLinkFile}. | ||
*/ | ||
static createSymbolicLinkFileAsync(options: IFileSystemCreateLinkOptions): Promise<void>; | ||
/** | ||
* Creates a symbolic link to a folder (on Windows this requires elevated permissionsBits). | ||
@@ -324,2 +401,6 @@ * Behind the scenes it uses `fs.symlinkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createSymbolicLinkFolder}. | ||
*/ | ||
static createSymbolicLinkFolderAsync(options: IFileSystemCreateLinkOptions): Promise<void>; | ||
/** | ||
* Creates a hard link. | ||
@@ -330,2 +411,6 @@ * Behind the scenes it uses `fs.linkSync()`. | ||
/** | ||
* 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. | ||
@@ -336,3 +421,12 @@ * Behind the scenes it uses `fs.realpathSync()`. | ||
static getRealPath(linkPath: string): string; | ||
/** | ||
* An async version of {@link FileSystem.getRealPath}. | ||
*/ | ||
static getRealPathAsync(linkPath: string): Promise<string>; | ||
/** | ||
* Returns true if the error provided indicates the file or folder | ||
* does not exist. | ||
*/ | ||
static isNotExistError(error: NodeJS.ErrnoException): boolean; | ||
} | ||
//# sourceMappingURL=FileSystem.d.ts.map |
"use strict"; | ||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. | ||
// See LICENSE in the project root for license information. | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const pathUtilities = require("path"); | ||
const nodeJsPath = require("path"); | ||
const fs = require("fs"); | ||
const fsx = require("fs-extra"); | ||
const Text_1 = require("./Text"); | ||
const MOVE_DEFAULT_OPTIONS = { | ||
overwrite: true, | ||
ensureFolderExists: false | ||
}; | ||
const READ_FOLDER_DEFAULT_OPTIONS = { | ||
absolutePaths: false | ||
}; | ||
const WRITE_FILE_DEFAULT_OPTIONS = { | ||
ensureFolderExists: false, | ||
convertLineEndings: undefined, | ||
encoding: "utf8" /* Utf8 */ | ||
}; | ||
const APPEND_TO_FILE_DEFAULT_OPTIONS = Object.assign({}, WRITE_FILE_DEFAULT_OPTIONS); | ||
const READ_FILE_DEFAULT_OPTIONS = { | ||
encoding: "utf8" /* Utf8 */, | ||
convertLineEndings: undefined | ||
}; | ||
const DELETE_FILE_DEFAULT_OPTIONS = { | ||
throwIfNotExists: false | ||
}; | ||
/** | ||
@@ -53,2 +81,8 @@ * The FileSystem API provides a complete set of recommended operations for interacting with the file system. | ||
/** | ||
* An async version of {@link FileSystem.getStatistics}. | ||
*/ | ||
static getStatisticsAsync(path) { | ||
return fsx.stat(path); | ||
} | ||
/** | ||
* Updates the accessed and modified timestamps of the filesystem object referenced by path. | ||
@@ -61,6 +95,13 @@ * Behind the scenes it uses `fs.utimesSync()`. | ||
static updateTimes(path, times) { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
fsx.utimesSync(path, times.accessedTime, times.modifiedTime); | ||
} | ||
/** | ||
* An async version of {@link FileSystem.updateTimes}. | ||
*/ | ||
static updateTimesAsync(path, times) { | ||
// This cast is needed because the fs-extra typings require both parameters | ||
// to have the same type (number or Date), whereas Node.js does not require that. | ||
return fsx.utimes(path, times.accessedTime, times.modifiedTime); | ||
} | ||
/** | ||
* Changes the permissions (i.e. file mode bits) for a filesystem object. | ||
@@ -75,5 +116,16 @@ * Behind the scenes it uses `fs.chmodSync()`. | ||
/** | ||
* An async version of {@link FileSystem.changePosixModeBits}. | ||
*/ | ||
static changePosixModeBitsAsync(path, mode) { | ||
return fsx.chmod(path, mode); | ||
} | ||
/** | ||
* 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. | ||
*/ | ||
@@ -84,2 +136,10 @@ static getPosixModeBits(path) { | ||
/** | ||
* An async version of {@link FileSystem.getPosixModeBits}. | ||
*/ | ||
static getPosixModeBitsAsync(path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return (yield FileSystem.getStatisticsAsync(path)).mode; | ||
}); | ||
} | ||
/** | ||
* Returns a 10-character string representation of a PosixModeBits value similar to what | ||
@@ -109,8 +169,44 @@ * would be displayed by a command such as "ls -l" on a POSIX-like operating system. | ||
static move(options) { | ||
options = Object.assign({ overwrite: true, ensureFolderExists: false }, options); | ||
if (options.ensureFolderExists) { | ||
FileSystem.ensureFolder(pathUtilities.basename(options.sourcePath)); | ||
options = Object.assign({}, MOVE_DEFAULT_OPTIONS, options); | ||
try { | ||
fsx.moveSync(options.sourcePath, options.destinationPath, { overwrite: options.overwrite }); | ||
} | ||
fsx.moveSync(options.sourcePath, options.destinationPath, { overwrite: options.overwrite }); | ||
catch (error) { | ||
if (options.ensureFolderExists) { | ||
if (!FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
const folderPath = nodeJsPath.dirname(options.destinationPath); | ||
FileSystem.ensureFolder(folderPath); | ||
fsx.moveSync(options.sourcePath, options.destinationPath, { overwrite: options.overwrite }); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
} | ||
/** | ||
* An async version of {@link FileSystem.move}. | ||
*/ | ||
static moveAsync(options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
options = Object.assign({}, MOVE_DEFAULT_OPTIONS, options); | ||
try { | ||
yield fsx.move(options.sourcePath, options.destinationPath, { overwrite: options.overwrite }); | ||
} | ||
catch (error) { | ||
if (options.ensureFolderExists) { | ||
if (!FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
const folderPath = nodeJsPath.dirname(options.destinationPath); | ||
yield FileSystem.ensureFolderAsync(nodeJsPath.dirname(folderPath)); | ||
yield fsx.move(options.sourcePath, options.destinationPath, { overwrite: options.overwrite }); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
}); | ||
} | ||
// =============== | ||
@@ -130,2 +226,8 @@ // FOLDER OPERATIONS | ||
/** | ||
* An async version of {@link FileSystem.ensureFolder}. | ||
*/ | ||
static ensureFolderAsync(folderPath) { | ||
return fsx.ensureDir(folderPath); | ||
} | ||
/** | ||
* Reads the contents of the folder, not including "." or "..". | ||
@@ -137,13 +239,51 @@ * Behind the scenes it uses `fs.readdirSync()`. | ||
static readFolder(folderPath, options) { | ||
options = Object.assign({ absolutePaths: false }, options); | ||
if (!FileSystem.exists(folderPath)) { | ||
throw new Error(`Folder does not exist: "${folderPath}"`); | ||
options = Object.assign({}, READ_FOLDER_DEFAULT_OPTIONS, options); | ||
let fileNames; | ||
try { | ||
// @todo: Update this to use Node 10's `withFileTypes: true` option when we drop support for Node 8 | ||
fileNames = fsx.readdirSync(folderPath); | ||
} | ||
const fileNames = fsx.readdirSync(folderPath); | ||
catch (e) { | ||
if (FileSystem.isNotExistError(e)) { | ||
throw new Error(`Folder does not exist: "${folderPath}"`); | ||
} | ||
else { | ||
throw e; | ||
} | ||
} | ||
if (options.absolutePaths) { | ||
return fileNames.map(fileName => pathUtilities.resolve(folderPath, fileName)); | ||
return fileNames.map(fileName => nodeJsPath.resolve(folderPath, fileName)); | ||
} | ||
return fileNames; | ||
else { | ||
return fileNames; | ||
} | ||
} | ||
/** | ||
* An async version of {@link FileSystem.readFolder}. | ||
*/ | ||
static readFolderAsync(folderPath, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
options = Object.assign({}, READ_FOLDER_DEFAULT_OPTIONS, options); | ||
let fileNames; | ||
try { | ||
// @todo: Update this to use Node 10's `withFileTypes: true` option when we drop support for Node 8 | ||
fileNames = yield fsx.readdir(folderPath); | ||
} | ||
catch (e) { | ||
if (FileSystem.isNotExistError(e)) { | ||
throw new Error(`Folder does not exist: "${folderPath}"`); | ||
} | ||
else { | ||
throw e; | ||
} | ||
} | ||
if (options.absolutePaths) { | ||
return fileNames.map(fileName => nodeJsPath.resolve(folderPath, fileName)); | ||
} | ||
else { | ||
return fileNames; | ||
} | ||
}); | ||
} | ||
/** | ||
* Deletes a folder, including all of its contents. | ||
@@ -159,2 +299,8 @@ * Behind the scenes is uses `fs-extra.removeSync()`. | ||
/** | ||
* An async version of {@link FileSystem.deleteFolder}. | ||
*/ | ||
static deleteFolderAsync(folderPath) { | ||
return fsx.remove(folderPath); | ||
} | ||
/** | ||
* Deletes the content of a folder, but not the folder itself. Also ensures the folder exists. | ||
@@ -170,2 +316,8 @@ * Behind the scenes it uses `fs-extra.emptyDirSync()`. | ||
} | ||
/** | ||
* An async version of {@link FileSystem.ensureEmptyFolder}. | ||
*/ | ||
static ensureEmptyFolderAsync(folderPath) { | ||
return fsx.emptyDir(folderPath); | ||
} | ||
// =============== | ||
@@ -184,13 +336,51 @@ // FILE OPERATIONS | ||
static writeFile(filePath, contents, options) { | ||
options = Object.assign({ ensureFolderExists: false, convertLineEndings: undefined, encoding: "utf8" /* Utf8 */ }, options); | ||
if (options.ensureFolderExists) { | ||
const folderPath = pathUtilities.dirname(filePath); | ||
FileSystem.ensureFolder(folderPath); | ||
} | ||
options = Object.assign({}, WRITE_FILE_DEFAULT_OPTIONS, options); | ||
if (options.convertLineEndings) { | ||
contents = Text_1.Text.convertTo(contents.toString(), options.convertLineEndings); | ||
} | ||
fsx.writeFileSync(filePath, contents, { encoding: options.encoding }); | ||
try { | ||
fsx.writeFileSync(filePath, contents, { encoding: options.encoding }); | ||
} | ||
catch (error) { | ||
if (options.ensureFolderExists) { | ||
if (!FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
const folderPath = nodeJsPath.dirname(filePath); | ||
FileSystem.ensureFolder(folderPath); | ||
fsx.writeFileSync(filePath, contents, { encoding: options.encoding }); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
} | ||
/** | ||
* An async version of {@link FileSystem.writeFile}. | ||
*/ | ||
static writeFileAsync(filePath, contents, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
options = Object.assign({}, WRITE_FILE_DEFAULT_OPTIONS, options); | ||
if (options.convertLineEndings) { | ||
contents = Text_1.Text.convertTo(contents.toString(), options.convertLineEndings); | ||
} | ||
try { | ||
yield fsx.writeFile(filePath, contents, { encoding: options.encoding }); | ||
} | ||
catch (error) { | ||
if (options.ensureFolderExists) { | ||
if (!FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
const folderPath = nodeJsPath.dirname(filePath); | ||
yield FileSystem.ensureFolderAsync(folderPath); | ||
yield fsx.writeFile(filePath, contents, { encoding: options.encoding }); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Writes a text string to a file on disk, appending to the file if it already exists. | ||
@@ -205,13 +395,51 @@ * Behind the scenes it uses `fs.appendFileSync()`. | ||
static appendToFile(filePath, contents, options) { | ||
options = Object.assign({ ensureFolderExists: false, convertLineEndings: undefined, encoding: "utf8" /* Utf8 */ }, options); | ||
if (options.ensureFolderExists) { | ||
const folderPath = pathUtilities.dirname(filePath); | ||
FileSystem.ensureFolder(folderPath); | ||
} | ||
options = Object.assign({}, APPEND_TO_FILE_DEFAULT_OPTIONS, options); | ||
if (options.convertLineEndings) { | ||
contents = Text_1.Text.convertTo(contents.toString(), options.convertLineEndings); | ||
} | ||
fsx.appendFileSync(filePath, contents, { encoding: options.encoding }); | ||
try { | ||
fsx.appendFileSync(filePath, contents, { encoding: options.encoding }); | ||
} | ||
catch (error) { | ||
if (options.ensureFolderExists) { | ||
if (!FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
const folderPath = nodeJsPath.dirname(filePath); | ||
FileSystem.ensureFolder(folderPath); | ||
fsx.appendFileSync(filePath, contents, { encoding: options.encoding }); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
} | ||
/** | ||
* An async version of {@link FileSystem.appendToFile}. | ||
*/ | ||
static appendToFileAsync(filePath, contents, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
options = Object.assign({}, APPEND_TO_FILE_DEFAULT_OPTIONS, options); | ||
if (options.convertLineEndings) { | ||
contents = Text_1.Text.convertTo(contents.toString(), options.convertLineEndings); | ||
} | ||
try { | ||
yield fsx.appendFile(filePath, contents, { encoding: options.encoding }); | ||
} | ||
catch (error) { | ||
if (options.ensureFolderExists) { | ||
if (!FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
const folderPath = nodeJsPath.dirname(filePath); | ||
yield FileSystem.ensureFolderAsync(folderPath); | ||
yield fsx.appendFile(filePath, contents, { encoding: options.encoding }); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Reads the contents of a file into a string. | ||
@@ -223,3 +451,3 @@ * Behind the scenes it uses `fs.readFileSync()`. | ||
static readFile(filePath, options) { | ||
options = Object.assign({ encoding: "utf8" /* Utf8 */, convertLineEndings: undefined }, options); | ||
options = Object.assign({}, READ_FILE_DEFAULT_OPTIONS, options); | ||
let contents = FileSystem.readFileToBuffer(filePath).toString(options.encoding); | ||
@@ -232,2 +460,15 @@ if (options.convertLineEndings) { | ||
/** | ||
* An async version of {@link FileSystem.readFile}. | ||
*/ | ||
static readFileAsync(filePath, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
options = Object.assign({}, READ_FILE_DEFAULT_OPTIONS, options); | ||
let contents = (yield FileSystem.readFileToBufferAsync(filePath)).toString(options.encoding); | ||
if (options.convertLineEndings) { | ||
contents = Text_1.Text.convertTo(contents, options.convertLineEndings); | ||
} | ||
return contents; | ||
}); | ||
} | ||
/** | ||
* Reads the contents of a file into a buffer. | ||
@@ -241,2 +482,8 @@ * Behind the scenes is uses `fs.readFileSync()`. | ||
/** | ||
* An async version of {@link FileSystem.readFileToBuffer}. | ||
*/ | ||
static readFileToBufferAsync(filePath) { | ||
return fsx.readFile(filePath); | ||
} | ||
/** | ||
* Copies a file from one location to another. | ||
@@ -250,2 +497,10 @@ * By default, destinationPath is overwritten if it already exists. | ||
/** | ||
* An async version of {@link FileSystem.copyFile}. | ||
*/ | ||
static copyFileAsync(options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield fsx.copy(options.sourcePath, options.destinationPath); | ||
}); | ||
} | ||
/** | ||
* Deletes a file. Can optionally throw if the file doesn't exist. | ||
@@ -257,14 +512,27 @@ * Behind the scenes it uses `fs.unlinkSync()`. | ||
static deleteFile(filePath, options) { | ||
options = Object.assign({ throwIfNotExists: false }, options); | ||
if (options.throwIfNotExists) { | ||
options = Object.assign({}, DELETE_FILE_DEFAULT_OPTIONS, options); | ||
try { | ||
fsx.unlinkSync(filePath); | ||
} | ||
else { | ||
catch (error) { | ||
if (options.throwIfNotExists || !FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
} | ||
} | ||
/** | ||
* An async version of {@link FileSystem.deleteFile}. | ||
*/ | ||
static deleteFileAsync(filePath, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
options = Object.assign({}, DELETE_FILE_DEFAULT_OPTIONS, options); | ||
try { | ||
fsx.unlinkSync(filePath); | ||
yield fsx.unlink(filePath); | ||
} | ||
catch (error) { | ||
/* no-op */ | ||
if (options.throwIfNotExists || !FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
@@ -283,2 +551,8 @@ // =============== | ||
/** | ||
* An async version of {@link FileSystem.getLinkStatistics}. | ||
*/ | ||
static getLinkStatisticsAsync(path) { | ||
return fsx.lstat(path); | ||
} | ||
/** | ||
* Creates a Windows "directory junction". Behaves like `createSymbolicLinkToFile()` on other platforms. | ||
@@ -292,2 +566,9 @@ * Behind the scenes it uses `fs.symlinkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createSymbolicLinkJunction}. | ||
*/ | ||
static createSymbolicLinkJunctionAsync(options) { | ||
// For directories, we use a Windows "junction". On POSIX operating systems, this produces a regular symlink. | ||
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'junction'); | ||
} | ||
/** | ||
* Creates a symbolic link to a file (on Windows this requires elevated permissionsBits). | ||
@@ -300,2 +581,8 @@ * Behind the scenes it uses `fs.symlinkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createSymbolicLinkFile}. | ||
*/ | ||
static createSymbolicLinkFileAsync(options) { | ||
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'file'); | ||
} | ||
/** | ||
* Creates a symbolic link to a folder (on Windows this requires elevated permissionsBits). | ||
@@ -308,2 +595,8 @@ * Behind the scenes it uses `fs.symlinkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createSymbolicLinkFolder}. | ||
*/ | ||
static createSymbolicLinkFolderAsync(options) { | ||
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'dir'); | ||
} | ||
/** | ||
* Creates a hard link. | ||
@@ -316,2 +609,8 @@ * Behind the scenes it uses `fs.linkSync()`. | ||
/** | ||
* An async version of {@link FileSystem.createHardLink}. | ||
*/ | ||
static createHardLinkAsync(options) { | ||
return fsx.link(options.linkTargetPath, options.newLinkPath); | ||
} | ||
/** | ||
* Follows a link to its destination and returns the absolute path to the final target of the link. | ||
@@ -324,4 +623,20 @@ * Behind the scenes it uses `fs.realpathSync()`. | ||
} | ||
/** | ||
* An async version of {@link FileSystem.getRealPath}. | ||
*/ | ||
static getRealPathAsync(linkPath) { | ||
return fsx.realpath(linkPath); | ||
} | ||
// =============== | ||
// UTILITY FUNCTIONS | ||
// =============== | ||
/** | ||
* Returns true if the error provided indicates the file or folder | ||
* does not exist. | ||
*/ | ||
static isNotExistError(error) { | ||
return error.code === 'ENOENT' || error.code === 'ENOTDIR'; | ||
} | ||
} | ||
exports.FileSystem = FileSystem; | ||
//# sourceMappingURL=FileSystem.js.map |
@@ -63,2 +63,6 @@ import { JsonSchema, IJsonSchemaErrorInfo, IJsonSchemaValidateOptions } from './JsonSchema'; | ||
/** | ||
* An async version of {@link JsonFile.load}. | ||
*/ | ||
static loadAsync(jsonFilename: string): Promise<JsonObject>; | ||
/** | ||
* Loads a JSON file and validate its schema. | ||
@@ -68,2 +72,6 @@ */ | ||
/** | ||
* An async version of {@link JsonFile.loadAndValidate}. | ||
*/ | ||
static loadAndValidateAsync(jsonFilename: string, jsonSchema: JsonSchema, options?: IJsonSchemaValidateOptions): Promise<JsonObject>; | ||
/** | ||
* Loads a JSON file and validate its schema, reporting errors using a callback | ||
@@ -75,2 +83,6 @@ * @remarks | ||
/** | ||
* An async version of {@link JsonFile.loadAndValidateWithCallback}. | ||
*/ | ||
static loadAndValidateWithCallbackAsync(jsonFilename: string, jsonSchema: JsonSchema, errorCallback: (errorInfo: IJsonSchemaErrorInfo) => void): Promise<JsonObject>; | ||
/** | ||
* Serializes the specified JSON object to a string buffer. | ||
@@ -98,2 +110,6 @@ * @param jsonObject - the object to be serialized | ||
/** | ||
* An async version of {@link JsonFile.loadAndValidateWithCallback}. | ||
*/ | ||
static saveAsync(jsonObject: JsonObject, jsonFilename: string, options?: IJsonFileSaveOptions): Promise<boolean>; | ||
/** | ||
* Used to validate a data structure before writing. Reports an error if there | ||
@@ -100,0 +116,0 @@ * are any undefined members. |
"use strict"; | ||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. | ||
// See LICENSE in the project root for license information. | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -9,2 +17,3 @@ const os = require("os"); | ||
const FileSystem_1 = require("./FileSystem"); | ||
const DEFAULT_ENCODING = 'utf8'; | ||
/** | ||
@@ -19,14 +28,35 @@ * Utilities for reading/writing JSON files. | ||
static load(jsonFilename) { | ||
if (!FileSystem_1.FileSystem.exists(jsonFilename)) { | ||
throw new Error(`Input file not found: ${jsonFilename}`); | ||
} | ||
const contents = FileSystem_1.FileSystem.readFile(jsonFilename); | ||
try { | ||
const contents = FileSystem_1.FileSystem.readFile(jsonFilename); | ||
return jju.parse(contents); | ||
} | ||
catch (error) { | ||
throw new Error(`Error reading "${jsonFilename}":` + os.EOL + ` ${error.message}`); | ||
if (FileSystem_1.FileSystem.isNotExistError(error)) { | ||
throw new Error(`Input file not found: ${jsonFilename}`); | ||
} | ||
else { | ||
throw new Error(`Error reading "${jsonFilename}":` + os.EOL + ` ${error.message}`); | ||
} | ||
} | ||
} | ||
/** | ||
* An async version of {@link JsonFile.load}. | ||
*/ | ||
static loadAsync(jsonFilename) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const contents = yield FileSystem_1.FileSystem.readFileAsync(jsonFilename); | ||
return jju.parse(contents); | ||
} | ||
catch (error) { | ||
if (FileSystem_1.FileSystem.isNotExistError(error)) { | ||
throw new Error(`Input file not found: ${jsonFilename}`); | ||
} | ||
else { | ||
throw new Error(`Error reading "${jsonFilename}":` + os.EOL + ` ${error.message}`); | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Loads a JSON file and validate its schema. | ||
@@ -40,2 +70,12 @@ */ | ||
/** | ||
* An async version of {@link JsonFile.loadAndValidate}. | ||
*/ | ||
static loadAndValidateAsync(jsonFilename, jsonSchema, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const jsonObject = yield JsonFile.loadAsync(jsonFilename); | ||
jsonSchema.validateObject(jsonObject, jsonFilename, options); | ||
return jsonObject; | ||
}); | ||
} | ||
/** | ||
* Loads a JSON file and validate its schema, reporting errors using a callback | ||
@@ -51,2 +91,12 @@ * @remarks | ||
/** | ||
* An async version of {@link JsonFile.loadAndValidateWithCallback}. | ||
*/ | ||
static loadAndValidateWithCallbackAsync(jsonFilename, jsonSchema, errorCallback) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const jsonObject = yield JsonFile.loadAsync(jsonFilename); | ||
jsonSchema.validateObjectWithCallback(jsonObject, errorCallback); | ||
return jsonObject; | ||
}); | ||
} | ||
/** | ||
* Serializes the specified JSON object to a string buffer. | ||
@@ -109,10 +159,9 @@ * @param jsonObject - the object to be serialized | ||
if (options.updateExistingFile || options.onlyIfChanged) { | ||
if (FileSystem_1.FileSystem.exists(jsonFilename)) { | ||
try { | ||
oldBuffer = FileSystem_1.FileSystem.readFileToBuffer(jsonFilename); | ||
try { | ||
oldBuffer = FileSystem_1.FileSystem.readFileToBuffer(jsonFilename); | ||
} | ||
catch (error) { | ||
if (!FileSystem_1.FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
catch (error) { | ||
// Ignore this error, and try writing a new file. If that fails, then we should report that | ||
// error instead. | ||
} | ||
} | ||
@@ -122,6 +171,6 @@ } | ||
if (options.updateExistingFile && oldBuffer) { | ||
jsonToUpdate = oldBuffer.toString(); | ||
jsonToUpdate = oldBuffer.toString(DEFAULT_ENCODING); | ||
} | ||
const newJson = JsonFile.updateString(jsonToUpdate, jsonObject, options); | ||
const newBuffer = Buffer.from(newJson); // utf8 encoding happens here | ||
const newBuffer = Buffer.from(newJson, DEFAULT_ENCODING); | ||
if (options.onlyIfChanged) { | ||
@@ -134,3 +183,3 @@ // Has the file changed? | ||
} | ||
FileSystem_1.FileSystem.writeFile(jsonFilename, newBuffer.toString(), { | ||
FileSystem_1.FileSystem.writeFile(jsonFilename, newBuffer.toString(DEFAULT_ENCODING), { | ||
ensureFolderExists: options.ensureFolderExists | ||
@@ -151,6 +200,54 @@ }); | ||
/** | ||
* An async version of {@link JsonFile.loadAndValidateWithCallback}. | ||
*/ | ||
static saveAsync(jsonObject, jsonFilename, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!options) { | ||
options = {}; | ||
} | ||
// Do we need to read the previous file contents? | ||
let oldBuffer = undefined; | ||
if (options.updateExistingFile || options.onlyIfChanged) { | ||
try { | ||
oldBuffer = yield FileSystem_1.FileSystem.readFileToBufferAsync(jsonFilename); | ||
} | ||
catch (error) { | ||
if (!FileSystem_1.FileSystem.isNotExistError(error)) { | ||
throw error; | ||
} | ||
} | ||
} | ||
let jsonToUpdate = ''; | ||
if (options.updateExistingFile && oldBuffer) { | ||
jsonToUpdate = oldBuffer.toString(DEFAULT_ENCODING); | ||
} | ||
const newJson = JsonFile.updateString(jsonToUpdate, jsonObject, options); | ||
const newBuffer = Buffer.from(newJson, DEFAULT_ENCODING); | ||
if (options.onlyIfChanged) { | ||
// Has the file changed? | ||
if (oldBuffer && Buffer.compare(newBuffer, oldBuffer) === 0) { | ||
// Nothing has changed, so don't touch the file | ||
return false; | ||
} | ||
} | ||
yield FileSystem_1.FileSystem.writeFileAsync(jsonFilename, newBuffer.toString(DEFAULT_ENCODING), { | ||
ensureFolderExists: options.ensureFolderExists | ||
}); | ||
// TEST CODE: Used to verify that onlyIfChanged isn't broken by a hidden transformation during saving. | ||
/* | ||
const oldBuffer2: Buffer = await FileSystem.readFileToBufferAsync(jsonFilename); | ||
if (Buffer.compare(buffer, oldBuffer2) !== 0) { | ||
console.log('new:' + buffer.toString('hex')); | ||
console.log('old:' + oldBuffer2.toString('hex')); | ||
throw new Error('onlyIfChanged logic is broken'); | ||
} | ||
*/ | ||
return true; | ||
}); | ||
} | ||
/** | ||
* Used to validate a data structure before writing. Reports an error if there | ||
* are any undefined members. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
static validateNoUndefinedMembers(jsonObject) { | ||
@@ -157,0 +254,0 @@ return JsonFile._validateNoUndefinedMembers(jsonObject, []); |
{ | ||
"name": "@rushstack/node-core-library", | ||
"version": "3.20.0", | ||
"version": "3.21.0", | ||
"description": "Core libraries that every NodeJS toolchain project should use", | ||
@@ -27,3 +27,3 @@ "main": "lib/index.js", | ||
"@rushstack/eslint-config": "0.5.7", | ||
"@types/fs-extra": "5.0.4", | ||
"@types/fs-extra": "7.0.0", | ||
"@types/jest": "25.2.1", | ||
@@ -30,0 +30,0 @@ "@types/jju": "1.4.1", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
676583
9262