@tsed/cli
Version:
CLI to bootstrap your Ts.ED project
74 lines (73 loc) • 3.05 kB
JavaScript
import { homedir } from "node:os";
import { basename, relative, resolve } from "node:path";
const GLOBAL_MODULE_MARKER = "/node_modules/";
function toPosixPath(pathname) {
return pathname.replace(/\\/g, "/");
}
function normalizePath(pathname) {
return toPosixPath(resolve(pathname));
}
function isSubPath(pathname, parentPath) {
return pathname === parentPath || pathname.startsWith(`${parentPath}/`);
}
function splitPathAndLocation(pathname) {
const match = pathname.match(/^(.*?)(:\d+(?::\d+)?)?$/);
return {
path: match?.[1] || pathname,
location: match?.[2] || ""
};
}
function getGlobalModulePath(absolutePath, absolutePathForCompare) {
const index = absolutePathForCompare.indexOf(GLOBAL_MODULE_MARKER);
if (index === -1) {
return;
}
const pathAfterNodeModules = absolutePath.slice(index + GLOBAL_MODULE_MARKER.length);
const segments = pathAfterNodeModules.split("/").filter(Boolean);
if (!segments.length) {
return;
}
const isScoped = segments[0].startsWith("@");
const moduleName = isScoped ? segments.slice(0, 2).join("/") : segments[0];
if (!moduleName || (isScoped && segments.length < 2)) {
return;
}
const suffixSegments = segments.slice(isScoped ? 2 : 1);
const suffix = suffixSegments.length ? `/${suffixSegments.join("/")}` : "";
return `<global>/${moduleName}${suffix}`;
}
function anonymizeAbsolutePath(pathname, cwd, home) {
const absolutePath = normalizePath(pathname);
const absolutePathForCompare = absolutePath.toLowerCase();
const cwdForCompare = cwd.toLowerCase();
const homeForCompare = home.toLowerCase();
if (isSubPath(absolutePathForCompare, cwdForCompare)) {
const relativePath = toPosixPath(relative(cwd, absolutePath));
return relativePath ? `<cwd>/${relativePath}` : "<cwd>";
}
const globalModulePath = getGlobalModulePath(absolutePath, absolutePathForCompare);
if (globalModulePath) {
return globalModulePath;
}
if (isSubPath(absolutePathForCompare, homeForCompare)) {
return `~/${toPosixPath(relative(home, absolutePath))}`;
}
return `<external>/${basename(absolutePath)}`;
}
function anonymizeTokenWithContext(token, cwd, home) {
const { path, location } = splitPathAndLocation(token);
return `${anonymizeAbsolutePath(path, cwd, home)}${location}`;
}
function toPathFromFileUrl(token) {
const decodedPath = decodeURIComponent(token.replace(/^file:\/\//, ""));
return decodedPath.replace(/^\/([A-Za-z]:[\\/])/, "$1");
}
export function anonymizePaths(stack, options = {}) {
const cwd = normalizePath(options.cwd || process.cwd());
const home = normalizePath(options.home || homedir());
return stack
.replace(/file:\/\/\/[^\s)]+/g, (token) => anonymizeTokenWithContext(toPathFromFileUrl(token), cwd, home))
.replace(/(^|[\s(])((?:[A-Za-z]:\\|\/)[^\s)]+)/g, (_full, prefix, token) => {
return `${prefix}${anonymizeTokenWithContext(token, cwd, home)}`;
});
}