@rushstack/node-core-library
Advanced tools
Comparing version 3.55.2 to 3.56.0
@@ -82,2 +82,22 @@ /** | ||
} | ||
/** | ||
* 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; | ||
} | ||
//# sourceMappingURL=Async.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 __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } | ||
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var g = generator.apply(thisArg, _arguments || []), i, q = []; | ||
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; | ||
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } | ||
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } | ||
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } | ||
function fulfill(value) { resume("next", value); } | ||
function reject(value) { resume("throw", value); } | ||
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Async = void 0; | ||
exports.AsyncQueue = exports.Async = void 0; | ||
/** | ||
@@ -141,2 +153,66 @@ * Utilities for parallel asynchronous operations, for use with the system `Promise` APIs. | ||
exports.Async = Async; | ||
function getSignal() { | ||
let resolver; | ||
const promise = new Promise((resolve) => { | ||
resolver = resolve; | ||
}); | ||
return [promise, resolver]; | ||
} | ||
/** | ||
* 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 | ||
*/ | ||
class AsyncQueue { | ||
constructor(iterable) { | ||
this._queue = iterable ? Array.from(iterable) : []; | ||
const [promise, resolver] = getSignal(); | ||
this._onPushSignal = promise; | ||
this._onPushResolve = resolver; | ||
} | ||
[Symbol.asyncIterator]() { | ||
return __asyncGenerator(this, arguments, function* _a() { | ||
let activeIterations = 0; | ||
let [callbackSignal, callbackResolve] = getSignal(); | ||
const callback = () => { | ||
if (--activeIterations === 0) { | ||
// Resolve whatever the latest callback promise is and create a new one | ||
callbackResolve(); | ||
const [newCallbackSignal, newCallbackResolve] = getSignal(); | ||
callbackSignal = newCallbackSignal; | ||
callbackResolve = newCallbackResolve; | ||
} | ||
}; | ||
let position = 0; | ||
while (this._queue.length > position || activeIterations > 0) { | ||
if (this._queue.length > position) { | ||
activeIterations++; | ||
yield yield __await([this._queue[position++], callback]); | ||
} | ||
else { | ||
// On push, the item will be added to the queue and the onPushSignal will be resolved. | ||
// On calling the callback, active iterations will be decremented by the callback and the | ||
// callbackSignal will be resolved. This means that the loop will continue if there are | ||
// active iterations or if there are items in the queue that haven't been yielded yet. | ||
yield __await(Promise.race([this._onPushSignal, callbackSignal])); | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Adds an item to the queue. | ||
* | ||
* @param item - The item to push into the queue. | ||
*/ | ||
push(item) { | ||
this._queue.push(item); | ||
this._onPushResolve(); | ||
const [onPushSignal, onPushResolve] = getSignal(); | ||
this._onPushSignal = onPushSignal; | ||
this._onPushResolve = onPushResolve; | ||
} | ||
} | ||
exports.AsyncQueue = AsyncQueue; | ||
//# sourceMappingURL=Async.js.map |
@@ -509,3 +509,3 @@ /// <reference types="node" /> | ||
*/ | ||
static copyFilesAsync(options: IFileSystemCopyFilesOptions): Promise<void>; | ||
static copyFilesAsync(options: IFileSystemCopyFilesAsyncOptions): Promise<void>; | ||
/** | ||
@@ -512,0 +512,0 @@ * Deletes a file. Can optionally throw if the file doesn't exist. |
@@ -46,4 +46,28 @@ /** | ||
allowSelfReference?: boolean; | ||
/** | ||
* A function used to resolve the realpath of a provided file path. | ||
* | ||
* @remarks | ||
* This is used to resolve symlinks and other non-standard file paths. By default, this uses the | ||
* {@link FileSystem.getRealPath} function. However, it can be overridden to use a custom implementation | ||
* which may be faster, more accurate, or provide support for additional non-standard file paths. | ||
*/ | ||
getRealPath?: (filePath: string) => string; | ||
} | ||
/** | ||
* Common options shared by {@link IImportResolveModuleAsyncOptions} and {@link IImportResolvePackageAsyncOptions} | ||
* @public | ||
*/ | ||
export interface IImportResolveAsyncOptions extends IImportResolveOptions { | ||
/** | ||
* A function used to resolve the realpath of a provided file path. | ||
* | ||
* @remarks | ||
* This is used to resolve symlinks and other non-standard file paths. By default, this uses the | ||
* {@link FileSystem.getRealPath} function. However, it can be overridden to use a custom implementation | ||
* which may be faster, more accurate, or provide support for additional non-standard file paths. | ||
*/ | ||
getRealPathAsync?: (filePath: string) => Promise<string>; | ||
} | ||
/** | ||
* Options for {@link Import.resolveModule} | ||
@@ -60,2 +84,13 @@ * @public | ||
/** | ||
* Options for {@link Import.resolveModuleAsync} | ||
* @public | ||
*/ | ||
export interface IImportResolveModuleAsyncOptions extends IImportResolveAsyncOptions { | ||
/** | ||
* The module identifier to resolve. For example "\@rushstack/node-core-library" or | ||
* "\@rushstack/node-core-library/lib/index.js" | ||
*/ | ||
modulePath: string; | ||
} | ||
/** | ||
* Options for {@link Import.resolvePackage} | ||
@@ -71,2 +106,12 @@ * @public | ||
/** | ||
* Options for {@link Import.resolvePackageAsync} | ||
* @public | ||
*/ | ||
export interface IImportResolvePackageAsyncOptions extends IImportResolveAsyncOptions { | ||
/** | ||
* The package name to resolve. For example "\@rushstack/node-core-library" | ||
*/ | ||
packageName: string; | ||
} | ||
/** | ||
* Helpers for resolving and importing Node.js modules. | ||
@@ -175,2 +220,6 @@ * @public | ||
/** | ||
* Async version of {@link Import.resolveModule}. | ||
*/ | ||
static resolveModuleAsync(options: IImportResolveModuleAsyncOptions): Promise<string>; | ||
/** | ||
* Performs module resolution to determine the folder where a package is installed. | ||
@@ -196,4 +245,8 @@ * | ||
static resolvePackage(options: IImportResolvePackageOptions): string; | ||
/** | ||
* Async version of {@link Import.resolvePackage}. | ||
*/ | ||
static resolvePackageAsync(options: IImportResolvePackageAsyncOptions): Promise<string>; | ||
private static _getPackageName; | ||
} | ||
//# sourceMappingURL=Import.d.ts.map |
@@ -147,7 +147,7 @@ "use strict"; | ||
static resolveModule(options) { | ||
const { modulePath, baseFolderPath, includeSystemModules, allowSelfReference } = options; | ||
const { modulePath, baseFolderPath, includeSystemModules, allowSelfReference, getRealPath } = options; | ||
if (path.isAbsolute(modulePath)) { | ||
return modulePath; | ||
} | ||
const normalizedRootPath = FileSystem_1.FileSystem.getRealPath(baseFolderPath); | ||
const normalizedRootPath = (getRealPath || FileSystem_1.FileSystem.getRealPath)(baseFolderPath); | ||
if (modulePath.startsWith('.')) { | ||
@@ -157,9 +157,14 @@ // This looks like a conventional relative path | ||
} | ||
if (includeSystemModules === true && Import._builtInModules.has(modulePath)) { | ||
return modulePath; | ||
// Built-in modules do not have a scope, so if there is a slash, then we need to check | ||
// against the first path segment | ||
const slashIndex = modulePath.indexOf('/'); | ||
const moduleName = slashIndex === -1 ? modulePath : modulePath.slice(0, slashIndex); | ||
if (!includeSystemModules && Import._builtInModules.has(moduleName)) { | ||
throw new Error(`Cannot find module "${modulePath}" from "${options.baseFolderPath}".`); | ||
} | ||
if (allowSelfReference === true) { | ||
const ownPackage = Import._getPackageName(baseFolderPath); | ||
if (ownPackage && modulePath.startsWith(ownPackage.packageName)) { | ||
const packagePath = modulePath.substr(ownPackage.packageName.length + 1); | ||
if (ownPackage && | ||
(modulePath === ownPackage.packageName || modulePath.startsWith(`${ownPackage.packageName}/`))) { | ||
const packagePath = modulePath.slice(ownPackage.packageName.length + 1); | ||
return path.resolve(ownPackage.packageRootPath, packagePath); | ||
@@ -169,7 +174,6 @@ } | ||
try { | ||
return Resolve.sync( | ||
// Append a slash to the package name to ensure `resolve.sync` doesn't attempt to return a system package | ||
includeSystemModules !== true && modulePath.indexOf('/') === -1 ? `${modulePath}/` : modulePath, { | ||
return Resolve.sync(modulePath, { | ||
basedir: normalizedRootPath, | ||
preserveSymlinks: false | ||
preserveSymlinks: false, | ||
realpathSync: getRealPath | ||
}); | ||
@@ -182,2 +186,71 @@ } | ||
/** | ||
* Async version of {@link Import.resolveModule}. | ||
*/ | ||
static async resolveModuleAsync(options) { | ||
const { modulePath, baseFolderPath, includeSystemModules, allowSelfReference, getRealPath, getRealPathAsync } = options; | ||
if (path.isAbsolute(modulePath)) { | ||
return modulePath; | ||
} | ||
const normalizedRootPath = await (getRealPathAsync || getRealPath || FileSystem_1.FileSystem.getRealPathAsync)(baseFolderPath); | ||
if (modulePath.startsWith('.')) { | ||
// This looks like a conventional relative path | ||
return path.resolve(normalizedRootPath, modulePath); | ||
} | ||
// Built-in modules do not have a scope, so if there is a slash, then we need to check | ||
// against the first path segment | ||
const slashIndex = modulePath.indexOf('/'); | ||
const moduleName = slashIndex === -1 ? modulePath : modulePath.slice(0, slashIndex); | ||
if (!includeSystemModules && Import._builtInModules.has(moduleName)) { | ||
throw new Error(`Cannot find module "${modulePath}" from "${options.baseFolderPath}".`); | ||
} | ||
if (allowSelfReference === true) { | ||
const ownPackage = Import._getPackageName(baseFolderPath); | ||
if (ownPackage && | ||
(modulePath === ownPackage.packageName || modulePath.startsWith(`${ownPackage.packageName}/`))) { | ||
const packagePath = modulePath.slice(ownPackage.packageName.length + 1); | ||
return path.resolve(ownPackage.packageRootPath, packagePath); | ||
} | ||
} | ||
try { | ||
const resolvePromise = new Promise((resolve, reject) => { | ||
const realPathFn = getRealPathAsync || getRealPath | ||
? (filePath, callback) => { | ||
if (getRealPathAsync) { | ||
getRealPathAsync(filePath) | ||
.then((resolvedPath) => callback(null, resolvedPath)) | ||
.catch((error) => callback(error)); | ||
} | ||
else { | ||
try { | ||
const resolvedPath = getRealPath(filePath); | ||
callback(null, resolvedPath); | ||
} | ||
catch (error) { | ||
callback(error); | ||
} | ||
} | ||
} | ||
: undefined; | ||
Resolve.default(modulePath, { | ||
basedir: normalizedRootPath, | ||
preserveSymlinks: false, | ||
realpath: realPathFn | ||
}, (error, resolvedPath) => { | ||
if (error) { | ||
reject(error); | ||
} | ||
else { | ||
// Resolve docs state that either an error will be returned, or the resolved path. | ||
// In this case, the resolved path should always be populated. | ||
resolve(resolvedPath); | ||
} | ||
}); | ||
}); | ||
return await resolvePromise; | ||
} | ||
catch (e) { | ||
throw new Error(`Cannot find module "${modulePath}" from "${options.baseFolderPath}".`); | ||
} | ||
} | ||
/** | ||
* Performs module resolution to determine the folder where a package is installed. | ||
@@ -203,7 +276,7 @@ * | ||
static resolvePackage(options) { | ||
const { packageName, includeSystemModules, baseFolderPath, allowSelfReference } = options; | ||
const { packageName, includeSystemModules, baseFolderPath, allowSelfReference, getRealPath } = options; | ||
if (includeSystemModules && Import._builtInModules.has(packageName)) { | ||
return packageName; | ||
} | ||
const normalizedRootPath = FileSystem_1.FileSystem.getRealPath(baseFolderPath); | ||
const normalizedRootPath = (getRealPath || FileSystem_1.FileSystem.getRealPath)(baseFolderPath); | ||
if (allowSelfReference) { | ||
@@ -228,3 +301,4 @@ const ownPackage = Import._getPackageName(baseFolderPath); | ||
return pkg; | ||
} | ||
}, | ||
realpathSync: getRealPath | ||
}); | ||
@@ -238,2 +312,71 @@ const packagePath = path.dirname(resolvedPath); | ||
} | ||
/** | ||
* Async version of {@link Import.resolvePackage}. | ||
*/ | ||
static async resolvePackageAsync(options) { | ||
const { packageName, includeSystemModules, baseFolderPath, allowSelfReference, getRealPath, getRealPathAsync } = options; | ||
if (includeSystemModules && Import._builtInModules.has(packageName)) { | ||
return packageName; | ||
} | ||
const normalizedRootPath = await (getRealPathAsync || getRealPath || FileSystem_1.FileSystem.getRealPathAsync)(baseFolderPath); | ||
if (allowSelfReference) { | ||
const ownPackage = Import._getPackageName(baseFolderPath); | ||
if (ownPackage && ownPackage.packageName === packageName) { | ||
return ownPackage.packageRootPath; | ||
} | ||
} | ||
PackageName_1.PackageName.parse(packageName); // Ensure the package name is valid and doesn't contain a path | ||
try { | ||
const resolvePromise = new Promise((resolve, reject) => { | ||
const realPathFn = getRealPathAsync || getRealPath | ||
? (filePath, callback) => { | ||
if (getRealPathAsync) { | ||
getRealPathAsync(filePath) | ||
.then((resolvedPath) => callback(null, resolvedPath)) | ||
.catch((error) => callback(error)); | ||
} | ||
else { | ||
try { | ||
const resolvedPath = getRealPath(filePath); | ||
callback(null, resolvedPath); | ||
} | ||
catch (error) { | ||
callback(error); | ||
} | ||
} | ||
} | ||
: undefined; | ||
Resolve.default( | ||
// Append a slash to the package name to ensure `resolve` doesn't attempt to return a system package | ||
`${packageName}/`, { | ||
basedir: normalizedRootPath, | ||
preserveSymlinks: false, | ||
packageFilter: (pkg, pkgFile, dir) => { | ||
// Hardwire "main" to point to a file that is guaranteed to exist. | ||
// This helps resolve packages such as @types/node that have no entry point. | ||
// And then we can use path.dirname() below to locate the package folder, | ||
// even if the real entry point was in an subfolder with arbitrary nesting. | ||
pkg.main = 'package.json'; | ||
return pkg; | ||
}, | ||
realpath: realPathFn | ||
}, (error, resolvedPath) => { | ||
if (error) { | ||
reject(error); | ||
} | ||
else { | ||
// Resolve docs state that either an error will be returned, or the resolved path. | ||
// In this case, the resolved path should always be populated. | ||
resolve(resolvedPath); | ||
} | ||
}); | ||
}); | ||
const resolvedPath = await resolvePromise; | ||
const packagePath = path.dirname(resolvedPath); | ||
return packagePath; | ||
} | ||
catch (_a) { | ||
throw new Error(`Cannot find package "${packageName}" from "${baseFolderPath}".`); | ||
} | ||
} | ||
static _getPackageName(rootPath) { | ||
@@ -240,0 +383,0 @@ const packageJsonPath = PackageJsonLookup_1.PackageJsonLookup.instance.tryGetPackageJsonFilePathFor(rootPath); |
@@ -8,3 +8,3 @@ /** | ||
export { AnsiEscape, IAnsiEscapeConvertForTestsOptions } from './Terminal/AnsiEscape'; | ||
export { Async, IAsyncParallelismOptions, IRunWithRetriesOptions } from './Async'; | ||
export { Async, AsyncQueue, IAsyncParallelismOptions, IRunWithRetriesOptions } from './Async'; | ||
export { Brand } from './PrimitiveTypes'; | ||
@@ -17,3 +17,3 @@ export { FileConstants, FolderConstants } from './Constants'; | ||
export { INodePackageJson, IPackageJson, IPackageJsonDependencyTable, IPackageJsonScriptTable, IPackageJsonRepository, IPeerDependenciesMetaTable } from './IPackageJson'; | ||
export { Import, IImportResolveOptions, IImportResolveModuleOptions, IImportResolvePackageOptions } from './Import'; | ||
export { Import, IImportResolveOptions, IImportResolveAsyncOptions, IImportResolveModuleOptions, IImportResolveModuleAsyncOptions, IImportResolvePackageOptions, IImportResolvePackageAsyncOptions } from './Import'; | ||
export { InternalError } from './InternalError'; | ||
@@ -20,0 +20,0 @@ export { JsonObject, JsonNull, JsonSyntax, IJsonFileParseOptions, IJsonFileLoadAndValidateOptions, IJsonFileStringifyOptions, IJsonFileSaveOptions, JsonFile } from './JsonFile'; |
@@ -5,3 +5,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TypeUuid = exports.StringBufferTerminalProvider = exports.ConsoleTerminalProvider = exports.TerminalProviderSeverity = exports.TextAttribute = exports.ColorValue = exports.Colors = exports.Terminal = exports.SubprocessTerminator = exports.StringBuilder = exports.LegacyAdapters = exports.FileWriter = exports.FileSystem = exports.AlreadyExistsBehavior = exports.Sort = exports.NewlineKind = exports.Text = exports.Encoding = exports.Path = exports.PackageNameParser = exports.PackageName = exports.PackageJsonLookup = exports.ProtectableMap = exports.PosixModeBits = exports.MapExtensions = exports.LockFile = exports.JsonSchema = exports.JsonFile = exports.JsonSyntax = exports.InternalError = exports.Import = exports.FileError = exports.Executable = exports.EnvironmentMap = exports.Enum = exports.FolderConstants = exports.FileConstants = exports.Async = exports.AnsiEscape = exports.AlreadyReportedError = void 0; | ||
exports.TypeUuid = exports.StringBufferTerminalProvider = exports.ConsoleTerminalProvider = exports.TerminalProviderSeverity = exports.TextAttribute = exports.ColorValue = exports.Colors = exports.Terminal = exports.SubprocessTerminator = exports.StringBuilder = exports.LegacyAdapters = exports.FileWriter = exports.FileSystem = exports.AlreadyExistsBehavior = exports.Sort = exports.NewlineKind = exports.Text = exports.Encoding = exports.Path = exports.PackageNameParser = exports.PackageName = exports.PackageJsonLookup = exports.ProtectableMap = exports.PosixModeBits = exports.MapExtensions = exports.LockFile = exports.JsonSchema = exports.JsonFile = exports.JsonSyntax = exports.InternalError = exports.Import = exports.FileError = exports.Executable = exports.EnvironmentMap = exports.Enum = exports.FolderConstants = exports.FileConstants = exports.AsyncQueue = exports.Async = exports.AnsiEscape = exports.AlreadyReportedError = void 0; | ||
/** | ||
@@ -18,2 +18,3 @@ * Core libraries that every NodeJS toolchain project should use. | ||
Object.defineProperty(exports, "Async", { enumerable: true, get: function () { return Async_1.Async; } }); | ||
Object.defineProperty(exports, "AsyncQueue", { enumerable: true, get: function () { return Async_1.AsyncQueue; } }); | ||
var Constants_1 = require("./Constants"); | ||
@@ -20,0 +21,0 @@ Object.defineProperty(exports, "FileConstants", { enumerable: true, get: function () { return Constants_1.FileConstants; } }); |
{ | ||
"name": "@rushstack/node-core-library", | ||
"version": "3.55.2", | ||
"version": "3.56.0", | ||
"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
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
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
1071540
13987