UNPKG

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
"use strict"; 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; }