polen
Version:
A framework for delightful GraphQL developer portals
126 lines • 4.53 kB
JavaScript
import { Path } from '@wollybeard/kit';
/**
* Special key added to path objects to reference the directory itself
*/
export const DIR_KEY = `$`;
export function create(paths, base) {
const relative = processRelativePaths(paths, []);
if (!base) {
return relative;
}
// Normalize base path - trim spaces, collapse multiple slashes, remove trailing
const trimmedBase = base.trim();
// Collapse multiple slashes to single, then remove trailing (unless it's just "/")
const collapsedBase = trimmedBase.replace(/\/+/g, `/`);
const normalizedBase = collapsedBase === `/` ? `/` : collapsedBase.replace(/\/$/, ``);
const rooted = processRootedPaths(paths, []);
const absolute = processAbsolutePaths(paths, normalizedBase, []);
return {
relative: relative,
rooted: rooted,
absolute: absolute,
base: normalizedBase,
};
}
/**
* Create a new PathMap with a different base path
*
* @param pathMap - Existing PathMap or RelativePathMap
* @param base - New base path
* @returns New PathMap with updated absolute paths
*
* @example
* ```ts
* const dev = PathMap.create(paths, '/dev')
* const prod = PathMap.rebase(dev, '/prod')
*
* prod.absolute.src.lib.utils // '/prod/src/lib/utils.ts'
* ```
*/
export const rebase = (pathMap, base) => {
// Extract the input structure from the relative paths
const input = extractInput(pathMap);
return create(input, base);
};
// Helper to process paths for relative variant (local to parent)
const processRelativePaths = (input, currentPath) => {
const result = {};
// Add $ property for directory (just the last segment)
if (currentPath.length > 0) {
result[DIR_KEY] = currentPath[currentPath.length - 1];
}
else {
result[DIR_KEY] = `.`;
}
for (const [key, value] of Object.entries(input)) {
if (typeof value === `string`) {
result[key] = value;
}
else {
result[key] = processRelativePaths(value, [...currentPath, key]);
}
}
return result;
};
// Helper to process paths for rooted variant (from PathMap root)
const processRootedPaths = (input, currentPath) => {
const result = {};
// Add $ property for directory (full path from root)
result[DIR_KEY] = currentPath.length > 0 ? currentPath.join(`/`) : `.`;
for (const [key, value] of Object.entries(input)) {
if (typeof value === `string`) {
// File: join current path with filename
result[key] = currentPath.length > 0
? `${currentPath.join(`/`)}/${value}`
: value;
}
else {
result[key] = processRootedPaths(value, [...currentPath, key]);
}
}
return result;
};
// Helper to process paths for absolute variant
const processAbsolutePaths = (input, base, currentPath) => {
const result = {};
// Normalize base to not end with slash unless it's root
const normalizedBase = base === `/` ? base : base.replace(/\/$/, ``);
// Add $ property for directory
const relativePath = currentPath.length > 0 ? currentPath.join(`/`) : ``;
result[DIR_KEY] = relativePath ? Path.join(normalizedBase, relativePath) : normalizedBase;
for (const [key, value] of Object.entries(input)) {
if (typeof value === `string`) {
// File: join base + current path + filename
const fullPath = currentPath.length > 0
? Path.join(normalizedBase, ...currentPath, value)
: Path.join(normalizedBase, value);
result[key] = fullPath;
}
else {
result[key] = processAbsolutePaths(value, normalizedBase, [...currentPath, key]);
}
}
return result;
};
// Helper to extract input structure from processed paths
const extractInput = (pathMap) => {
const input = {};
// Get the source - could be relative from PathMap or the whole thing for RelativePathMap
const source = `relative` in pathMap ? pathMap.relative : pathMap;
function extract(processed, target) {
for (const [key, value] of Object.entries(processed)) {
if (key === DIR_KEY)
continue;
if (typeof value === `string`) {
target[key] = value;
}
else {
target[key] = {};
extract(value, target[key]);
}
}
}
extract(source, input);
return input;
};
//# sourceMappingURL=path-map.js.map