@rushstack/node-core-library
Advanced tools
Comparing version
# Change Log - @rushstack/node-core-library | ||
This log was last generated on Fri, 22 Nov 2024 01:10:43 GMT and should not be manually modified. | ||
This log was last generated on Sat, 14 Dec 2024 01:11:07 GMT and should not be manually modified. | ||
## 5.10.1 | ||
Sat, 14 Dec 2024 01:11:07 GMT | ||
### Patches | ||
- Fix handling of trailing slashes and relative paths in RealNodeModulePath to match semantics of `fs.realpathSync.native`. | ||
## 5.10.0 | ||
@@ -6,0 +13,0 @@ Fri, 22 Nov 2024 01:10:43 GMT |
@@ -8,5 +8,5 @@ // This file is read by tools that parse documentation comments conforming to the TSDoc standard. | ||
"packageName": "@microsoft/api-extractor", | ||
"packageVersion": "7.47.9" | ||
"packageVersion": "7.48.0" | ||
} | ||
] | ||
} |
@@ -10,4 +10,4 @@ /// <reference types="node" /> | ||
export interface IRealNodeModulePathResolverOptions { | ||
fs: Pick<typeof nodeFs, 'lstatSync' | 'readlinkSync'>; | ||
path: Pick<typeof nodePath, 'isAbsolute' | 'normalize' | 'resolve' | 'sep'>; | ||
fs?: Partial<Pick<typeof nodeFs, 'lstatSync' | 'readlinkSync'>>; | ||
path?: Partial<Pick<typeof nodePath, 'isAbsolute' | 'join' | 'resolve' | 'sep'>>; | ||
} | ||
@@ -39,2 +39,3 @@ /** | ||
private readonly _fs; | ||
private readonly _path; | ||
constructor(options?: IRealNodeModulePathResolverOptions); | ||
@@ -41,0 +42,0 @@ /** |
@@ -46,12 +46,17 @@ "use strict"; | ||
class RealNodeModulePathResolver { | ||
constructor(options = { | ||
fs: nodeFs, | ||
path: nodePath | ||
}) { | ||
constructor(options = {}) { | ||
const { fs: { lstatSync = nodeFs.lstatSync, readlinkSync = nodeFs.readlinkSync } = nodeFs, path: { isAbsolute = nodePath.isAbsolute, join = nodePath.join, resolve = nodePath.resolve, sep = nodePath.sep } = nodePath } = options; | ||
const cache = (this._cache = new Map()); | ||
const { path, fs } = options; | ||
const { sep: pathSeparator } = path; | ||
this._fs = fs; | ||
const nodeModulesToken = `${pathSeparator}node_modules${pathSeparator}`; | ||
const tryReadLink = this._tryReadLink.bind(this); | ||
this._fs = { | ||
lstatSync, | ||
readlinkSync | ||
}; | ||
this._path = { | ||
isAbsolute, | ||
join, | ||
resolve, | ||
sep | ||
}; | ||
const nodeModulesToken = `${sep}node_modules${sep}`; | ||
const self = this; | ||
function realNodeModulePathInternal(input) { | ||
@@ -66,3 +71,3 @@ // Find the last node_modules path segment | ||
let linkStart = nodeModulesIndex + nodeModulesToken.length - 1; | ||
let linkEnd = input.indexOf(pathSeparator, linkStart + 1); | ||
let linkEnd = input.indexOf(sep, linkStart + 1); | ||
// If the path segment starts with a '@', then it is a scoped package | ||
@@ -75,6 +80,8 @@ const isScoped = input.charAt(linkStart + 1) === '@'; | ||
// and preserve the rest of the path | ||
return `${realNodeModulePathInternal(input.slice(0, nodeModulesIndex))}${input.slice(nodeModulesIndex)}`; | ||
return join(realNodeModulePathInternal(input.slice(0, nodeModulesIndex)), input.slice(nodeModulesIndex + 1), | ||
// Joining to `.` will clean up any extraneous trailing slashes | ||
'.'); | ||
} | ||
linkStart = linkEnd; | ||
linkEnd = input.indexOf(pathSeparator, linkStart + 1); | ||
linkEnd = input.indexOf(sep, linkStart + 1); | ||
} | ||
@@ -87,4 +94,4 @@ // No trailing separator, so the link is the last path segment | ||
// Check if the link is a symlink | ||
const linkTarget = tryReadLink(linkCandidate); | ||
if (linkTarget && path.isAbsolute(linkTarget)) { | ||
const linkTarget = self._tryReadLink(linkCandidate); | ||
if (linkTarget && isAbsolute(linkTarget)) { | ||
// Absolute path, combine the link target with any remaining path segments | ||
@@ -94,3 +101,4 @@ // Cache the resolution to avoid the readlink call in subsequent calls | ||
cache.set(linkTarget, linkTarget); | ||
return `${linkTarget}${input.slice(linkEnd)}`; | ||
// Joining to `.` will clean up any extraneous trailing slashes | ||
return join(linkTarget, input.slice(linkEnd + 1), '.'); | ||
} | ||
@@ -103,14 +111,16 @@ // Relative path or does not exist | ||
// Relative path in symbolic link. Should be resolved relative to real path of base path. | ||
const resolvedTarget = path.resolve(`${realpathBeforeNodeModules}${input.slice(nodeModulesIndex, linkStart)}`, linkTarget); | ||
const resolvedTarget = resolve(realpathBeforeNodeModules, input.slice(nodeModulesIndex + 1, linkStart), linkTarget); | ||
// Cache the result of the combined resolution to avoid the readlink call in subsequent calls | ||
cache.set(linkCandidate, resolvedTarget); | ||
cache.set(resolvedTarget, resolvedTarget); | ||
return `${resolvedTarget}${input.slice(linkEnd)}`; | ||
// Joining to `.` will clean up any extraneous trailing slashes | ||
return join(resolvedTarget, input.slice(linkEnd + 1), '.'); | ||
} | ||
// No symlink, so just return the real path before the last node_modules combined with the | ||
// subsequent path segments | ||
return `${realpathBeforeNodeModules}${input.slice(nodeModulesIndex)}`; | ||
// Joining to `.` will clean up any extraneous trailing slashes | ||
return join(realpathBeforeNodeModules, input.slice(nodeModulesIndex + 1), '.'); | ||
} | ||
this.realNodeModulePath = (input) => { | ||
return realNodeModulePathInternal(path.normalize(input)); | ||
return realNodeModulePathInternal(resolve(input)); | ||
}; | ||
@@ -140,3 +150,5 @@ } | ||
if (stat.isSymbolicLink()) { | ||
return this._fs.readlinkSync(link, 'utf8'); | ||
// path.join(x, '.') will trim trailing slashes, if applicable | ||
const result = this._path.join(this._fs.readlinkSync(link, 'utf8'), '.'); | ||
return result; | ||
} | ||
@@ -143,0 +155,0 @@ } |
{ | ||
"name": "@rushstack/node-core-library", | ||
"version": "5.10.0", | ||
"version": "5.10.1", | ||
"description": "Core libraries that every NodeJS toolchain project should use", | ||
@@ -24,4 +24,4 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"@rushstack/heft": "0.67.2", | ||
"@rushstack/heft-node-rig": "2.6.31", | ||
"@rushstack/heft": "0.68.10", | ||
"@rushstack/heft-node-rig": "2.6.44", | ||
"@types/fs-extra": "7.0.0", | ||
@@ -28,0 +28,0 @@ "@types/heft-jest": "1.0.1", |
Sorry, the diff of this file is too big to display
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
1230098
0.22%17364
0.15%