Socket
Socket
Sign inDemoInstall

@rushstack/node-core-library

Package Overview
Dependencies
Maintainers
2
Versions
136
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rushstack/node-core-library - npm Package Compare versions

Comparing version 3.40.0 to 3.40.1

12

CHANGELOG.json

@@ -5,2 +5,14 @@ {

{
"version": "3.40.1",
"tag": "@rushstack/node-core-library_v3.40.1",
"date": "Mon, 13 Sep 2021 15:07:05 GMT",
"comments": {
"patch": [
{
"comment": "Add support for AlreadyExistsBehavior in symlink and junction scenarios"
}
]
}
},
{
"version": "3.40.0",

@@ -7,0 +19,0 @@ "tag": "@rushstack/node-core-library_v3.40.0",

9

CHANGELOG.md
# Change Log - @rushstack/node-core-library
This log was last generated on Wed, 11 Aug 2021 00:07:21 GMT and should not be manually modified.
This log was last generated on Mon, 13 Sep 2021 15:07:05 GMT and should not be manually modified.
## 3.40.1
Mon, 13 Sep 2021 15:07:05 GMT
### Patches
- Add support for AlreadyExistsBehavior in symlink and junction scenarios
## 3.40.0

@@ -6,0 +13,0 @@ Wed, 11 Aug 2021 00:07:21 GMT

61

lib/FileSystem.d.ts

@@ -97,3 +97,3 @@ /// <reference types="node" />

/**
* Specifies what to do if the target object already exists.
* Specifies what to do if the destination path already exists.
* @defaultValue {@link AlreadyExistsBehavior.Overwrite}

@@ -115,4 +115,12 @@ */

/**
* Specifies the behavior of {@link FileSystem.copyFiles} in a situation where the target object
* already exists.
* 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

@@ -122,12 +130,20 @@ */

/**
* If the destination object exists, overwrite it.
* This is the default behavior for {@link FileSystem.copyFiles}.
* 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 destination object exists, report an error.
* If the output file path already exists, the operation will fail, and an error
* will be reported.
*/
Error = "error",
/**
* If the destination object exists, skip it and continue the operation.
* If the output file path already exists, skip this item, and continue the operation.
*/

@@ -166,3 +182,8 @@ Ignore = "ignore"

/**
* Specifies what to do if the target object already exists.
* Specifies what to do if a destination path already exists.
*
* @remarks
* This setting is applied individually for each file being copied.
* For example, `AlreadyExistsBehavior.Overwrite` will not recursively delete a folder
* whose path corresponds to an individual file that is being copied to that location.
*/

@@ -223,11 +244,12 @@ alreadyExistsBehavior?: AlreadyExistsBehavior;

/**
* The existing path that the symbolic link will point to.
* The newly created symbolic link will point to `linkTargetPath` as its target.
*/
linkTargetPath: string;
/**
* The new path for the new symlink link to be created.
* The newly created symbolic link will have this path.
*/
newLinkPath: string;
/**
* Specifies what to do if the target object already exists. Defaults to `AlreadyExistsBehavior.Error`.
* Specifies what to do if the path to create already exists.
* The default is `AlreadyExistsBehavior.Error`.
*/

@@ -546,17 +568,28 @@ alreadyExistsBehavior?: AlreadyExistsBehavior;

/**
* Returns true if the error provided indicates the file or folder does not exist.
* 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 provided indicates the file does not exist.
* Returns true if the error object indicates the file does not exist (`ENOENT`).
*/
static isFileDoesNotExistError(error: Error): boolean;
/**
* Returns true if the error provided indicates the folder does not exist.
* Returns true if the error object indicates the folder does not exist (`ENOTDIR`).
*/
static isFolderDoesNotExistError(error: Error): boolean;
/**
* Returns true if the error object indicates that the `unlink` system call failed
* due to a permissions issue (`EPERM`).
*/
static isUnlinkNotPermittedError(error: Error): boolean;
/**
* Detects if the provided error object is a `NodeJS.ErrnoException`
*/
static isErrnoException(error: Error): error is NodeJS.ErrnoException;
private static _handleLink;
private static _handleLinkAsync;
private static _wrapException;

@@ -563,0 +596,0 @@ private static _wrapExceptionAsync;

@@ -682,4 +682,6 @@ "use strict";

FileSystem._wrapException(() => {
// For directories, we use a Windows "junction". On POSIX operating systems, this produces a regular symlink.
fsx.symlinkSync(options.linkTargetPath, options.newLinkPath, 'junction');
return FileSystem._handleLink(() => {
// For directories, we use a Windows "junction". On POSIX operating systems, this produces a regular symlink.
return fsx.symlinkSync(options.linkTargetPath, options.newLinkPath, 'junction');
}, options);
});

@@ -692,4 +694,6 @@ }

await FileSystem._wrapExceptionAsync(() => {
// For directories, we use a Windows "junction". On POSIX operating systems, this produces a regular symlink.
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'junction');
return FileSystem._handleLinkAsync(() => {
// For directories, we use a Windows "junction". On POSIX operating systems, this produces a regular symlink.
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'junction');
}, options);
});

@@ -703,3 +707,5 @@ }

FileSystem._wrapException(() => {
fsx.symlinkSync(options.linkTargetPath, options.newLinkPath, 'file');
return FileSystem._handleLink(() => {
return fsx.symlinkSync(options.linkTargetPath, options.newLinkPath, 'file');
}, options);
});

@@ -712,3 +718,5 @@ }

await FileSystem._wrapExceptionAsync(() => {
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'file');
return FileSystem._handleLinkAsync(() => {
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'file');
}, options);
});

@@ -722,3 +730,5 @@ }

FileSystem._wrapException(() => {
fsx.symlinkSync(options.linkTargetPath, options.newLinkPath, 'dir');
return FileSystem._handleLink(() => {
return fsx.symlinkSync(options.linkTargetPath, options.newLinkPath, 'dir');
}, options);
});

@@ -731,3 +741,5 @@ }

await FileSystem._wrapExceptionAsync(() => {
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'dir');
return FileSystem._handleLinkAsync(() => {
return fsx.symlink(options.linkTargetPath, options.newLinkPath, 'dir');
}, options);
});

@@ -741,29 +753,5 @@ }

FileSystem._wrapException(() => {
try {
fsx.linkSync(options.linkTargetPath, options.newLinkPath);
}
catch (error) {
if (error.code === 'EEXIST') {
switch (options.alreadyExistsBehavior) {
case "ignore" /* Ignore */:
return;
case "overwrite" /* Overwrite */:
this.deleteFile(options.newLinkPath);
break;
case "error" /* Error */:
default:
throw error;
}
}
else {
const linkTargetExists = FileSystem.exists(options.linkTargetPath);
if (FileSystem.isNotExistError(error) && linkTargetExists) {
this.ensureFolder(nodeJsPath.dirname(options.newLinkPath));
this.createHardLink(options);
}
else {
throw error;
}
}
}
return FileSystem._handleLink(() => {
return fsx.linkSync(options.linkTargetPath, options.newLinkPath);
}, Object.assign(Object.assign({}, options), { linkTargetMustExist: true }));
});

@@ -775,30 +763,6 @@ }

static async createHardLinkAsync(options) {
await FileSystem._wrapExceptionAsync(async () => {
try {
await fsx.link(options.linkTargetPath, options.newLinkPath);
}
catch (error) {
if (error.code === 'EEXIST') {
switch (options.alreadyExistsBehavior) {
case "ignore" /* Ignore */:
return;
case "overwrite" /* Overwrite */:
await this.deleteFileAsync(options.newLinkPath);
break;
case "error" /* Error */:
default:
throw error;
}
}
else {
const linkTargetExists = await FileSystem.exists(options.linkTargetPath);
if (FileSystem.isNotExistError(error) && linkTargetExists) {
await this.ensureFolderAsync(nodeJsPath.dirname(options.newLinkPath));
await this.createHardLinkAsync(options);
}
else {
throw error;
}
}
}
await FileSystem._wrapExceptionAsync(() => {
return FileSystem._handleLinkAsync(() => {
return fsx.link(options.linkTargetPath, options.newLinkPath);
}, Object.assign(Object.assign({}, options), { linkTargetMustExist: true }));
});

@@ -828,4 +792,10 @@ }

/**
* Returns true if the error provided indicates the file or folder does not exist.
* Returns true if the error object indicates the file or folder already exists (`EEXIST`).
*/
static isExistError(error) {
return FileSystem.isErrnoException(error) && error.code === 'EEXIST';
}
/**
* Returns true if the error object indicates the file or folder does not exist (`ENOENT` or `ENOTDIR`)
*/
static isNotExistError(error) {

@@ -835,3 +805,3 @@ return FileSystem.isFileDoesNotExistError(error) || FileSystem.isFolderDoesNotExistError(error);

/**
* Returns true if the error provided indicates the file does not exist.
* Returns true if the error object indicates the file does not exist (`ENOENT`).
*/

@@ -842,3 +812,3 @@ static isFileDoesNotExistError(error) {

/**
* Returns true if the error provided indicates the folder does not exist.
* Returns true if the error object indicates the folder does not exist (`ENOTDIR`).
*/

@@ -849,2 +819,9 @@ static isFolderDoesNotExistError(error) {

/**
* Returns true if the error object indicates that the `unlink` system call failed
* due to a permissions issue (`EPERM`).
*/
static isUnlinkNotPermittedError(error) {
return FileSystem.isErrnoException(error) && error.code === 'EPERM' && error.syscall === 'unlink';
}
/**
* Detects if the provided error object is a `NodeJS.ErrnoException`

@@ -859,2 +836,76 @@ */

}
static _handleLink(linkFn, options) {
try {
linkFn();
}
catch (error) {
if (FileSystem.isExistError(error)) {
// Link exists, handle it
switch (options.alreadyExistsBehavior) {
case "ignore" /* Ignore */:
break;
case "overwrite" /* Overwrite */:
// fsx.linkSync does not allow overwriting so we must manually delete. If it's
// a folder, it will throw an error.
this.deleteFile(options.newLinkPath);
linkFn();
break;
case "error" /* Error */:
default:
throw error;
}
}
else {
// When attempting to create a link in a directory that does not exist, an ENOENT
// or ENOTDIR error is thrown, so we should ensure the directory exists before
// retrying. There are also cases where the target file must exist, so validate in
// those cases to avoid confusing the missing directory with the missing target file.
if (FileSystem.isNotExistError(error) &&
(!options.linkTargetMustExist || FileSystem.exists(options.linkTargetPath))) {
this.ensureFolder(nodeJsPath.dirname(options.newLinkPath));
linkFn();
}
else {
throw error;
}
}
}
}
static async _handleLinkAsync(linkFn, options) {
try {
await linkFn();
}
catch (error) {
if (FileSystem.isExistError(error)) {
// Link exists, handle it
switch (options.alreadyExistsBehavior) {
case "ignore" /* Ignore */:
break;
case "overwrite" /* Overwrite */:
// fsx.linkSync does not allow overwriting so we must manually delete. If it's
// a folder, it will throw an error.
await this.deleteFileAsync(options.newLinkPath);
await linkFn();
break;
case "error" /* Error */:
default:
throw error;
}
}
else {
// When attempting to create a link in a directory that does not exist, an ENOENT
// or ENOTDIR error is thrown, so we should ensure the directory exists before
// retrying. There are also cases where the target file must exist, so validate in
// those cases to avoid confusing the missing directory with the missing target file.
if (FileSystem.isNotExistError(error) &&
(!options.linkTargetMustExist || (await FileSystem.existsAsync(options.linkTargetPath)))) {
await this.ensureFolderAsync(nodeJsPath.dirname(options.newLinkPath));
await linkFn();
}
else {
throw error;
}
}
}
}
static _wrapException(fn) {

@@ -888,2 +939,13 @@ try {

}
else if (FileSystem.isExistError(error)) {
// Oddly, the typing does not include the `dest` property even though the documentation
// indicates it is there: https://nodejs.org/docs/latest-v10.x/api/errors.html#errors_error_dest
const extendedError = error;
// eslint-disable-line @typescript-eslint/no-use-before-define
error.message = `File or folder already exists: ${extendedError.dest}\n${error.message}`;
}
else if (FileSystem.isUnlinkNotPermittedError(error)) {
// eslint-disable-line @typescript-eslint/no-use-before-define
error.message = `File or folder could not be deleted: ${error.path}\n${error.message}`;
}
}

@@ -890,0 +952,0 @@ }

{
"name": "@rushstack/node-core-library",
"version": "3.40.0",
"version": "3.40.1",
"description": "Core libraries that every NodeJS toolchain project should use",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc