bidirectional-resolve
Version:
Resolve a package entry point to a file path (like require.resolve/import.meta.resolve) OR a file path to a package entry point
290 lines (289 loc) • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.resolveEntryPointsFromExportsTarget = resolveEntryPointsFromExportsTarget;
exports.resolveEntryPointsFromImportsTarget = resolveEntryPointsFromImportsTarget;
exports.resolveExportsTargetsFromEntryPoint = resolveExportsTargetsFromEntryPoint;
exports.resolveImportsTargetsFromEntryPoint = resolveImportsTargetsFromEntryPoint;
require("core-js/modules/es.array.push.js");
require("core-js/modules/es.iterator.constructor.js");
require("core-js/modules/es.iterator.every.js");
require("core-js/modules/es.iterator.filter.js");
require("core-js/modules/es.iterator.map.js");
require("core-js/modules/es.iterator.some.js");
var _nodeAssert = _interopRequireDefault(require("node:assert"));
var _escapeStringRegexp = _interopRequireDefault(require("escape-string-regexp~4"));
var _error = require("./error.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function resolveEntryPointsFromExportsTarget({
flattenedExports,
target,
conditions = [],
includeUnsafeFallbackTargets = false,
replaceSubpathAsterisks = true
}) {
return resolveEntryPointsFromTarget({
flattenedMap: flattenedExports,
wantedTarget: target,
wantedConditions: conditions,
shouldIncludeUnsafeFallbackTargets: includeUnsafeFallbackTargets,
shouldReplaceSubpathAsterisks: replaceSubpathAsterisks
});
}
function resolveExportsTargetsFromEntryPoint({
flattenedExports,
entryPoint,
conditions = [],
includeUnsafeFallbackTargets = false
}) {
return resolveTargetsFromEntryPoint({
flattenedMap: flattenedExports,
wantedSubpath: entryPoint,
wantedConditions: conditions,
shouldIncludeUnsafeFallbackTargets: includeUnsafeFallbackTargets
});
}
function resolveEntryPointsFromImportsTarget({
flattenedImports,
target,
conditions,
includeUnsafeFallbackTargets,
replaceSubpathAsterisks
}) {
return resolveEntryPointsFromTarget({
flattenedMap: flattenedImports,
wantedTarget: target,
wantedConditions: conditions,
shouldIncludeUnsafeFallbackTargets: includeUnsafeFallbackTargets,
shouldReplaceSubpathAsterisks: replaceSubpathAsterisks
});
}
function resolveImportsTargetsFromEntryPoint({
flattenedImports,
entryPoint,
conditions,
includeUnsafeFallbackTargets
}) {
return resolveTargetsFromEntryPoint({
flattenedMap: flattenedImports,
wantedSubpath: entryPoint,
wantedConditions: conditions,
shouldIncludeUnsafeFallbackTargets: includeUnsafeFallbackTargets
});
}
function resolveEntryPointsFromTarget({
flattenedMap,
wantedTarget,
wantedConditions = [],
shouldIncludeUnsafeFallbackTargets = false,
shouldReplaceSubpathAsterisks = true
}) {
let sawNonNullFallback = false;
const nonPatternSubpaths = [];
const nullTargetSubpaths = [];
const potentialEntryPoints = {
patterns: [],
nonPatterns: []
};
for (const {
subpath: seenSubpath,
target: seenTarget,
conditions: seenConditions,
excludedConditions,
isFallback,
isFirstNonNullFallback,
isLastFallback,
isDeadCondition
} of flattenedMap) {
const subpathDoesNotHaveMultipleAsterisks = !isAPattern(seenSubpath) || seenSubpath.indexOf('*') === seenSubpath.lastIndexOf('*');
if (subpathDoesNotHaveMultipleAsterisks) {
const isNotFallback = !isFallback;
if (isFirstNonNullFallback) {
sawNonNullFallback = true;
}
const shouldConsiderMapping = !isDeadCondition && excludedConditions.every(condition => !wantedConditions.includes(condition)) && (isNotFallback || isFirstNonNullFallback || !sawNonNullFallback && isLastFallback || shouldIncludeUnsafeFallbackTargets && seenTarget !== null);
if (isLastFallback) {
sawNonNullFallback = false;
}
if (shouldConsiderMapping) {
const isConditionsAMatch = isAConditionsMatch(seenConditions, wantedConditions);
const isTargetAnExactMatch = seenTarget === wantedTarget;
if (isConditionsAMatch) {
if (!isAPattern(seenSubpath)) {
nonPatternSubpaths.push({
subpath: seenSubpath,
target: seenTarget
});
}
const potentialEntryPoint = {
subpathActual: seenSubpath,
subpathWithAsterisksReplaced: seenSubpath
};
if (isTargetAnExactMatch) {
potentialEntryPoints.nonPatterns.push(potentialEntryPoint);
potentialEntryPoints.patterns = potentialEntryPoints.patterns.filter(entry => {
return !isAMatch(entry.subpathActual, seenSubpath);
});
} else if (seenTarget === null) {
nullTargetSubpaths.push(potentialEntryPoint);
} else if (wantedTarget !== null && isAMatch(seenTarget, wantedTarget)) {
const alreadyHasExactSubpath = potentialEntryPoints.nonPatterns.some(entry => isAMatch(seenSubpath, entry.subpathActual));
if (!alreadyHasExactSubpath) {
let alreadyHasBetterSubpathPattern = false;
potentialEntryPoints.patterns = potentialEntryPoints.patterns.filter(entry => {
if (isAMatch(seenSubpath, entry.subpathActual) || isAMatch(entry.subpathActual, seenSubpath)) {
if (patternKeyCompare(entry.subpathActual, seenSubpath) === 1) {
return false;
} else {
alreadyHasBetterSubpathPattern = true;
}
}
return true;
});
if (!alreadyHasBetterSubpathPattern) {
if (shouldReplaceSubpathAsterisks) {
potentialEntryPoint.subpathWithAsterisksReplaced = replaceAsterisksInPattern(seenSubpath, seenTarget, wantedTarget);
}
potentialEntryPoints.patterns.push(potentialEntryPoint);
}
}
}
}
}
}
}
const entryPoints = potentialEntryPoints.nonPatterns.map(({
subpathWithAsterisksReplaced
}) => subpathWithAsterisksReplaced);
for (const {
subpathActual,
subpathWithAsterisksReplaced
} of potentialEntryPoints.patterns) {
const losesToNullTargetSubpath = nullTargetSubpaths.some(({
subpathActual: nullSubpathActual
}) => {
return isAMatch(nullSubpathActual, subpathWithAsterisksReplaced) && patternKeyCompare(subpathActual, nullSubpathActual) === 1;
});
const isImplicitlyDead = nonPatternSubpaths.some(({
subpath,
target
}) => {
return subpathWithAsterisksReplaced === subpath && (target === null && wantedTarget !== null || target !== null && wantedTarget !== null && !isAMatch(target, wantedTarget));
});
if (!losesToNullTargetSubpath && !isImplicitlyDead) {
entryPoints.push(subpathWithAsterisksReplaced);
}
}
return entryPoints;
}
function resolveTargetsFromEntryPoint({
flattenedMap,
wantedSubpath,
wantedConditions = [],
shouldIncludeUnsafeFallbackTargets = false
}) {
let lastSeenSubpath = undefined;
let bestSubpathMatch = undefined;
for (const {
subpath: seenSubpath
} of flattenedMap) {
const isNotLastSeenSubpath = seenSubpath !== lastSeenSubpath;
const subpathDoesNotHaveMultipleAsterisks = !isAPattern(seenSubpath) || seenSubpath.indexOf('*') === seenSubpath.lastIndexOf('*');
if (isNotLastSeenSubpath && subpathDoesNotHaveMultipleAsterisks) {
lastSeenSubpath = seenSubpath;
const isSubpathAnExactMatch = seenSubpath === wantedSubpath;
if (isSubpathAnExactMatch) {
bestSubpathMatch = seenSubpath;
break;
} else if (isAMatch(seenSubpath, wantedSubpath) && (bestSubpathMatch === undefined || patternKeyCompare(bestSubpathMatch, seenSubpath) === 1)) {
bestSubpathMatch = seenSubpath;
}
}
}
if (bestSubpathMatch !== undefined) {
const bestSubpathTargets = [];
let sawFistConditionsMatch = false;
lastSeenSubpath = undefined;
for (const {
subpath: seenSubpath,
target: seenTarget,
conditions: seenConditions,
excludedConditions,
isFallback,
isFirstNonNullFallback,
isLastFallback,
isDeadCondition
} of flattenedMap) {
if (seenSubpath === bestSubpathMatch) {
lastSeenSubpath = bestSubpathMatch;
const isNotFallback = !isFallback;
const isConditionsAMatch = !isDeadCondition && isAConditionsMatch(seenConditions, wantedConditions) && excludedConditions.every(condition => !wantedConditions.includes(condition));
if (isConditionsAMatch) {
const isFirstMatchingFallback = !isNotFallback && !sawFistConditionsMatch;
sawFistConditionsMatch = true;
if (seenTarget !== null) {
if (isNotFallback) {
bestSubpathTargets.push(seenTarget);
break;
} else if (isFirstMatchingFallback || isFirstNonNullFallback || isLastFallback || shouldIncludeUnsafeFallbackTargets) {
bestSubpathTargets.push(seenTarget);
if (!shouldIncludeUnsafeFallbackTargets) {
break;
}
}
}
if (isLastFallback) {
break;
}
} else if (sawFistConditionsMatch && !shouldIncludeUnsafeFallbackTargets) {
break;
}
} else if (lastSeenSubpath !== undefined) {
break;
}
}
return bestSubpathTargets.map(target => {
return isAPattern(target) ? replaceAsterisksInPattern(target, bestSubpathMatch, wantedSubpath) : target;
});
}
return [];
}
function patternToRegExp(pattern) {
return new RegExp(`^${pattern.split('*').map(p => (0, _escapeStringRegexp.default)(p)).join('(.+)')}$`);
}
function isAMatch(maybePattern, path) {
if (isAPattern(maybePattern)) {
let firstMatch = undefined;
const matches = path.match(patternToRegExp(maybePattern))?.slice(1);
return !!matches?.every(match => {
return firstMatch === undefined ? firstMatch = match : match === firstMatch;
});
} else {
return maybePattern === path;
}
}
function isAPattern(maybePattern) {
return !!maybePattern.includes('*');
}
function isAConditionsMatch(seenConditions, wantedConditions) {
return seenConditions.every(condition => condition === 'default' || wantedConditions.includes(condition));
}
function replaceAsterisksInPattern(pattern, seenPath, wantedPath) {
const firstMatch = wantedPath.match(patternToRegExp(seenPath))?.[1];
(0, _nodeAssert.default)(firstMatch, _error.ErrorMessage.AssertionFailedWantedPathIsNotSeenPath());
return pattern.replaceAll('*', firstMatch);
}
function patternKeyCompare(keyA, keyB) {
const aPatternIndex = keyA.indexOf('*');
const bPatternIndex = keyB.indexOf('*');
const baseLengthA = aPatternIndex === -1 ? keyA.length : aPatternIndex + 1;
const baseLengthB = bPatternIndex === -1 ? keyB.length : bPatternIndex + 1;
if (baseLengthA > baseLengthB) return -1;
if (baseLengthB > baseLengthA) return 1;
if (aPatternIndex === -1) return 1;
if (bPatternIndex === -1) return -1;
if (keyA.length > keyB.length) return -1;
if (keyB.length > keyA.length) return 1;
return 0;
}