@rushstack/lockfile-explorer
Version:
Rush Lockfile Explorer: The UI for solving version conflicts quickly in a large monorepo
123 lines • 4.13 kB
JavaScript
;
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBaseNameOf = getBaseNameOf;
exports.getParentOf = getParentOf;
exports.getAbsolute = getAbsolute;
exports.join = join;
/**
* For example, retrieves `d` from `/a/b/c/d`.
*/
function getBaseNameOf(importerPath) {
if (importerPath.length === 0) {
return '';
}
const index = importerPath.lastIndexOf('/');
if (index === importerPath.length - 1) {
throw new Error('Error: Path has a trailing slash');
}
if (index >= 0) {
return importerPath.substring(index + 1);
}
return importerPath;
}
/**
* For example, retrieves `/a/b/c` from `/a/b/c/d`.
*/
function getParentOf(importerPath) {
if (importerPath === '' || importerPath === '.' || importerPath === '/') {
throw new Error('Error: Path has no parent');
}
const index = importerPath.lastIndexOf('/');
if (index === importerPath.length - 1) {
throw new Error('Error: Path has a trailing slash');
}
if (index === 0) {
return '/';
}
if (index < 0) {
return '.';
}
return importerPath.substring(0, index);
}
/**
* Cheaply resolves a relative path against a base path, assuming the paths are delimited by `/`,
* and assuming the basePath is already in normal form. An error occurs if the relative path
* goes above the root folder.
*
* @example
* ```ts
* getAbsolutePath(`a/b/c`, `d/e`) === `a/b/c/d/e`
* getAbsolutePath(`/a/b/c`, `d/e`) === `/a/b/c/d/e`
* getAbsolutePath(`/a/b/c`, `/d/e`) === `/d/e`
* getAbsolutePath(`a/b/c`, `../../f`) === `a/f`
* getAbsolutePath(`a/b/c`, `.././/f`) === `a/b/f`
* getAbsolutePath(`a/b/c`, `../../..`) === `.`
* getAbsolutePath(`C:/a/b`, `../d`) === `C:/a/d`
* getAbsolutePath(`a/b/c`, `../../../..`) === ERROR
*
* // Degenerate cases:
* getAbsolutePath(`a/b/c/`, `d/`) === `a/b/c/d` // trailing slashes are discarded
* getAbsolutePath(`./../c`, `d`) === `./../c/d` // basePath assumed to be normal form
* getAbsolutePath(`C:\\`, `\\a`) === `C:\\/\\a` // backslashes not supported
* ```
*/
function getAbsolute(basePath, relativePath) {
let leadingSlash;
let stack;
// Discard intermediary slashes
const relativeParts = relativePath.split('/').filter((part) => part.length > 0);
if (relativePath.startsWith('/')) {
stack = [];
leadingSlash = true;
}
else {
// Discard intermediary slashes
stack = basePath.split('/').filter((part) => part.length > 0);
leadingSlash = basePath.startsWith('/');
}
for (const part of relativeParts) {
if (part === '.') {
// current directory, do nothing
continue;
}
else if (part === '..') {
if (stack.length === 0) {
throw new Error('getAbsolutePath(): relativePath goes above the root folder');
}
stack.pop();
}
else {
stack.push(part);
}
}
if (leadingSlash) {
return '/' + stack.join('/');
}
else {
return stack.length === 0 ? '.' : stack.join('/');
}
}
/**
* Returns the two parts joined by exactly one `/`, assuming the parts are already
* in normalized form. The `/` is not added if either part is an empty string.
*/
function join(leftPart, rightPart) {
if (leftPart.length === 0) {
return rightPart;
}
if (rightPart.length === 0) {
return leftPart;
}
const leftEndsWithSlash = leftPart[leftPart.length - 1] === '/';
const rightStartsWithSlash = rightPart[0] === '/';
if (leftEndsWithSlash && rightStartsWithSlash) {
return leftPart + rightPart.substring(1);
}
if (leftEndsWithSlash || rightStartsWithSlash) {
return leftPart + rightPart;
}
return leftPart + '/' + rightPart;
}
//# sourceMappingURL=lockfilePath.js.map