507 lines
16 KiB
JavaScript
507 lines
16 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true,
|
|
});
|
|
exports.default = resolve;
|
|
var _FailedToResolveNameError = _interopRequireDefault(
|
|
require("./errors/FailedToResolveNameError"),
|
|
);
|
|
var _FailedToResolvePathError = _interopRequireDefault(
|
|
require("./errors/FailedToResolvePathError"),
|
|
);
|
|
var _formatFileCandidates = _interopRequireDefault(
|
|
require("./errors/formatFileCandidates"),
|
|
);
|
|
var _InvalidPackageConfigurationError = _interopRequireDefault(
|
|
require("./errors/InvalidPackageConfigurationError"),
|
|
);
|
|
var _InvalidPackageError = _interopRequireDefault(
|
|
require("./errors/InvalidPackageError"),
|
|
);
|
|
var _PackageImportNotResolvedError = _interopRequireDefault(
|
|
require("./errors/PackageImportNotResolvedError"),
|
|
);
|
|
var _PackagePathNotExportedError = _interopRequireDefault(
|
|
require("./errors/PackagePathNotExportedError"),
|
|
);
|
|
var _PackageExportsResolve = require("./PackageExportsResolve");
|
|
var _PackageImportsResolve = require("./PackageImportsResolve");
|
|
var _PackageResolve = require("./PackageResolve");
|
|
var _resolveAsset = _interopRequireDefault(require("./resolveAsset"));
|
|
var _isAssetFile = _interopRequireDefault(require("./utils/isAssetFile"));
|
|
var _path = _interopRequireDefault(require("path"));
|
|
function _interopRequireDefault(e) {
|
|
return e && e.__esModule ? e : { default: e };
|
|
}
|
|
function resolve(context, moduleName, platform) {
|
|
const resolveRequest = context.resolveRequest;
|
|
if (resolveRequest && resolveRequest !== resolve) {
|
|
return resolveRequest(
|
|
Object.freeze({
|
|
...context,
|
|
resolveRequest: resolve,
|
|
}),
|
|
moduleName,
|
|
platform,
|
|
);
|
|
}
|
|
if (isRelativeImport(moduleName) || _path.default.isAbsolute(moduleName)) {
|
|
const result = resolveModulePath(context, moduleName, platform);
|
|
if (result.type === "failed") {
|
|
throw new _FailedToResolvePathError.default(result.candidates);
|
|
}
|
|
return result.resolution;
|
|
} else if (isSubpathImport(moduleName)) {
|
|
const pkg = context.getPackageForModule(context.originModulePath);
|
|
const importsField = pkg?.packageJson.imports;
|
|
if (pkg == null) {
|
|
throw new _PackageImportNotResolvedError.default({
|
|
importSpecifier: moduleName,
|
|
reason: `Could not find a package.json file relative to module ${context.originModulePath}`,
|
|
});
|
|
} else if (importsField == null) {
|
|
throw new _PackageImportNotResolvedError.default({
|
|
importSpecifier: moduleName,
|
|
reason: `Missing field "imports" in package.json. Check package.json at: ${pkg.rootPath}`,
|
|
});
|
|
} else {
|
|
try {
|
|
const packageImportsResult = (0,
|
|
_PackageImportsResolve.resolvePackageTargetFromImports)(
|
|
context,
|
|
pkg.rootPath,
|
|
moduleName,
|
|
importsField,
|
|
platform,
|
|
);
|
|
if (packageImportsResult != null) {
|
|
return packageImportsResult;
|
|
}
|
|
} catch (e) {
|
|
if (e instanceof _PackageImportNotResolvedError.default) {
|
|
context.unstable_logWarning(
|
|
e.message +
|
|
" Falling back to file-based resolution. Consider updating the " +
|
|
'call site or checking there is a matching subpath inside "imports" of package.json.',
|
|
);
|
|
} else if (e instanceof _InvalidPackageConfigurationError.default) {
|
|
context.unstable_logWarning(
|
|
e.message + " Falling back to file-based resolution.",
|
|
);
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const realModuleName = (0, _PackageResolve.redirectModulePath)(
|
|
context,
|
|
moduleName,
|
|
);
|
|
if (realModuleName === false) {
|
|
return {
|
|
type: "empty",
|
|
};
|
|
}
|
|
const { originModulePath } = context;
|
|
const isDirectImport =
|
|
isRelativeImport(realModuleName) ||
|
|
_path.default.isAbsolute(realModuleName);
|
|
if (isDirectImport) {
|
|
const fromModuleParentIdx =
|
|
originModulePath.lastIndexOf("node_modules" + _path.default.sep) + 13;
|
|
const originModuleDir = originModulePath.slice(
|
|
0,
|
|
originModulePath.indexOf(_path.default.sep, fromModuleParentIdx),
|
|
);
|
|
const absPath = _path.default.join(originModuleDir, realModuleName);
|
|
const result = resolveModulePath(context, absPath, platform);
|
|
if (result.type === "failed") {
|
|
throw new _FailedToResolvePathError.default(result.candidates);
|
|
}
|
|
return result.resolution;
|
|
}
|
|
const parsedSpecifier = parseBareSpecifier(realModuleName);
|
|
if (context.allowHaste) {
|
|
if (parsedSpecifier.isSinglePart) {
|
|
const result = context.resolveHasteModule(parsedSpecifier.firstPart);
|
|
if (result != null) {
|
|
return {
|
|
type: "sourceFile",
|
|
filePath: result,
|
|
};
|
|
}
|
|
}
|
|
if (parsedSpecifier.isValidPackageName) {
|
|
const result = resolveHastePackage(context, parsedSpecifier, platform);
|
|
if (result.type === "resolved") {
|
|
return result.resolution;
|
|
}
|
|
}
|
|
}
|
|
const { disableHierarchicalLookup } = context;
|
|
const nodeModulesPaths = [];
|
|
let next = _path.default.dirname(originModulePath);
|
|
if (!disableHierarchicalLookup) {
|
|
let candidate;
|
|
do {
|
|
candidate = next;
|
|
const nodeModulesPath = candidate.endsWith(_path.default.sep)
|
|
? candidate + "node_modules"
|
|
: candidate + _path.default.sep + "node_modules";
|
|
nodeModulesPaths.push(nodeModulesPath);
|
|
next = _path.default.dirname(candidate);
|
|
} while (candidate !== next);
|
|
}
|
|
nodeModulesPaths.push(...context.nodeModulesPaths);
|
|
const extraPaths = [];
|
|
const { extraNodeModules } = context;
|
|
if (extraNodeModules && extraNodeModules[parsedSpecifier.packageName]) {
|
|
const newPackageName = extraNodeModules[parsedSpecifier.packageName];
|
|
extraPaths.push(
|
|
_path.default.join(newPackageName, parsedSpecifier.posixSubpath),
|
|
);
|
|
}
|
|
const allDirPaths = nodeModulesPaths
|
|
.map((nodeModulePath) => {
|
|
let lookupResult = null;
|
|
const mustBeDirectory =
|
|
parsedSpecifier.posixSubpath !== "." ||
|
|
parsedSpecifier.packageName.length > parsedSpecifier.firstPart.length
|
|
? nodeModulePath + _path.default.sep + parsedSpecifier.firstPart
|
|
: nodeModulePath;
|
|
lookupResult = context.fileSystemLookup(mustBeDirectory);
|
|
if (!lookupResult.exists || lookupResult.type !== "d") {
|
|
return null;
|
|
}
|
|
return _path.default.join(nodeModulePath, realModuleName);
|
|
})
|
|
.filter(Boolean)
|
|
.concat(extraPaths);
|
|
for (let i = 0; i < allDirPaths.length; ++i) {
|
|
const candidate = (0, _PackageResolve.redirectModulePath)(
|
|
context,
|
|
allDirPaths[i],
|
|
);
|
|
if (candidate === false) {
|
|
return {
|
|
type: "empty",
|
|
};
|
|
}
|
|
const result = resolvePackage(context, candidate, platform);
|
|
if (result.type === "resolved") {
|
|
return result.resolution;
|
|
}
|
|
}
|
|
throw new _FailedToResolveNameError.default(nodeModulesPaths, extraPaths);
|
|
}
|
|
function parseBareSpecifier(specifier) {
|
|
const normalized =
|
|
_path.default.sep === "/" ? specifier : specifier.replaceAll("\\", "/");
|
|
const firstSepIdx = normalized.indexOf("/");
|
|
if (normalized.startsWith("@") && firstSepIdx !== -1) {
|
|
const secondSepIdx = normalized.indexOf("/", firstSepIdx + 1);
|
|
if (secondSepIdx === -1) {
|
|
return {
|
|
isSinglePart: false,
|
|
isValidPackageName: true,
|
|
firstPart: normalized.slice(0, firstSepIdx),
|
|
normalizedSpecifier: normalized,
|
|
packageName: normalized,
|
|
posixSubpath: ".",
|
|
};
|
|
}
|
|
return {
|
|
isSinglePart: false,
|
|
isValidPackageName: true,
|
|
firstPart: normalized.slice(0, firstSepIdx),
|
|
normalizedSpecifier: normalized,
|
|
packageName: normalized.slice(0, secondSepIdx),
|
|
posixSubpath: "." + normalized.slice(secondSepIdx),
|
|
};
|
|
}
|
|
if (firstSepIdx === -1) {
|
|
return {
|
|
isSinglePart: true,
|
|
isValidPackageName: !normalized.startsWith("@"),
|
|
firstPart: normalized,
|
|
normalizedSpecifier: normalized,
|
|
packageName: normalized,
|
|
posixSubpath: ".",
|
|
};
|
|
}
|
|
const packageName = normalized.slice(0, firstSepIdx);
|
|
return {
|
|
isSinglePart: false,
|
|
isValidPackageName: true,
|
|
firstPart: packageName,
|
|
normalizedSpecifier: normalized,
|
|
packageName,
|
|
posixSubpath: "." + normalized.slice(firstSepIdx),
|
|
};
|
|
}
|
|
function resolveModulePath(context, toModuleName, platform) {
|
|
const modulePath = _path.default.isAbsolute(toModuleName)
|
|
? _path.default.sep === "/"
|
|
? toModuleName
|
|
: toModuleName.replaceAll("/", "\\")
|
|
: _path.default.join(
|
|
_path.default.dirname(context.originModulePath),
|
|
toModuleName,
|
|
);
|
|
const redirectedPath = (0, _PackageResolve.redirectModulePath)(
|
|
context,
|
|
modulePath,
|
|
);
|
|
if (redirectedPath === false) {
|
|
return resolvedAs({
|
|
type: "empty",
|
|
});
|
|
}
|
|
const dirPath = _path.default.dirname(redirectedPath);
|
|
const fileName = _path.default.basename(redirectedPath);
|
|
const fileResult = redirectedPath.endsWith(_path.default.sep)
|
|
? null
|
|
: resolveFile(context, dirPath, fileName, platform);
|
|
if (fileResult != null && fileResult.type === "resolved") {
|
|
return fileResult;
|
|
}
|
|
const dirResult = resolvePackageEntryPoint(context, redirectedPath, platform);
|
|
if (dirResult.type === "resolved") {
|
|
return dirResult;
|
|
}
|
|
return failedFor({
|
|
file: fileResult?.candidates ?? null,
|
|
dir: dirResult.candidates,
|
|
});
|
|
}
|
|
function resolveHastePackage(
|
|
context,
|
|
{ normalizedSpecifier: moduleName, packageName, posixSubpath: pathInModule },
|
|
platform,
|
|
) {
|
|
const packageJsonPath = context.resolveHastePackage(packageName);
|
|
if (packageJsonPath == null) {
|
|
return failedFor();
|
|
}
|
|
const potentialModulePath = _path.default.join(
|
|
packageJsonPath,
|
|
"..",
|
|
pathInModule,
|
|
);
|
|
const result = resolvePackage(context, potentialModulePath, platform);
|
|
if (result.type === "resolved") {
|
|
return result;
|
|
}
|
|
const { candidates } = result;
|
|
const opts = {
|
|
moduleName,
|
|
packageName,
|
|
pathInModule,
|
|
candidates,
|
|
};
|
|
throw new MissingFileInHastePackageError(opts);
|
|
}
|
|
class MissingFileInHastePackageError extends Error {
|
|
constructor(opts) {
|
|
super(
|
|
`While resolving module \`${opts.moduleName}\`, ` +
|
|
`the Haste package \`${opts.packageName}\` was found. However the ` +
|
|
`subpath \`${opts.pathInModule}\` could not be found within ` +
|
|
"the package. Indeed, none of these files exist:\n\n" +
|
|
[opts.candidates.file, opts.candidates.dir]
|
|
.filter(Boolean)
|
|
.map(
|
|
(candidates) =>
|
|
` * \`${(0, _formatFileCandidates.default)(candidates)}\``,
|
|
)
|
|
.join("\n"),
|
|
);
|
|
Object.assign(this, opts);
|
|
}
|
|
}
|
|
function resolvePackage(context, absoluteCandidatePath, platform) {
|
|
if (context.unstable_enablePackageExports) {
|
|
const pkg = context.getPackageForModule(absoluteCandidatePath);
|
|
const exportsField = pkg?.packageJson.exports;
|
|
if (pkg != null && exportsField != null) {
|
|
try {
|
|
const packageExportsResult = (0,
|
|
_PackageExportsResolve.resolvePackageTargetFromExports)(
|
|
context,
|
|
pkg.rootPath,
|
|
absoluteCandidatePath,
|
|
pkg.packageRelativePath,
|
|
exportsField,
|
|
platform,
|
|
);
|
|
if (packageExportsResult != null) {
|
|
return resolvedAs(packageExportsResult);
|
|
}
|
|
} catch (e) {
|
|
if (e instanceof _PackagePathNotExportedError.default) {
|
|
context.unstable_logWarning(
|
|
e.message +
|
|
" Falling back to file-based resolution. Consider updating the " +
|
|
"call site or asking the package maintainer(s) to expose this API.",
|
|
);
|
|
} else if (e instanceof _InvalidPackageConfigurationError.default) {
|
|
context.unstable_logWarning(
|
|
e.message + " Falling back to file-based resolution.",
|
|
);
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return resolveModulePath(context, absoluteCandidatePath, platform);
|
|
}
|
|
function resolvePackageEntryPoint(context, packagePath, platform) {
|
|
const dirLookup = context.fileSystemLookup(packagePath);
|
|
if (dirLookup.exists == false || dirLookup.type !== "d") {
|
|
return failedFor({
|
|
type: "sourceFile",
|
|
filePathPrefix: packagePath,
|
|
candidateExts: [],
|
|
});
|
|
}
|
|
const packageJsonPath = _path.default.join(packagePath, "package.json");
|
|
if (!context.doesFileExist(packageJsonPath)) {
|
|
return resolveFile(context, packagePath, "index", platform);
|
|
}
|
|
const packageInfo = {
|
|
rootPath: _path.default.dirname(packageJsonPath),
|
|
packageJson: context.getPackage(packageJsonPath) ?? {},
|
|
};
|
|
const mainModulePath = _path.default.join(
|
|
packageInfo.rootPath,
|
|
(0, _PackageResolve.getPackageEntryPoint)(context, packageInfo, platform),
|
|
);
|
|
const fileResult = resolveFile(
|
|
context,
|
|
_path.default.dirname(mainModulePath),
|
|
_path.default.basename(mainModulePath),
|
|
platform,
|
|
);
|
|
if (fileResult.type === "resolved") {
|
|
return fileResult;
|
|
}
|
|
const indexResult = resolveFile(context, mainModulePath, "index", platform);
|
|
if (indexResult.type !== "resolved") {
|
|
throw new _InvalidPackageError.default({
|
|
packageJsonPath,
|
|
mainModulePath,
|
|
fileCandidates: fileResult.candidates,
|
|
indexCandidates: indexResult.candidates,
|
|
});
|
|
}
|
|
return indexResult;
|
|
}
|
|
function resolveFile(context, dirPath, fileName, platform) {
|
|
if ((0, _isAssetFile.default)(fileName, context.assetExts)) {
|
|
const assetResolutions = (0, _resolveAsset.default)(
|
|
context,
|
|
_path.default.join(dirPath, fileName),
|
|
);
|
|
if (assetResolutions == null) {
|
|
return failedFor({
|
|
type: "asset",
|
|
name: fileName,
|
|
});
|
|
}
|
|
return resolvedAs(assetResolutions);
|
|
}
|
|
const candidateExts = [];
|
|
const filePathPrefix = _path.default.join(dirPath, fileName);
|
|
const sfContext = {
|
|
...context,
|
|
candidateExts,
|
|
filePathPrefix,
|
|
};
|
|
const sourceFileResolution = resolveSourceFile(sfContext, platform);
|
|
if (sourceFileResolution != null) {
|
|
if (typeof sourceFileResolution === "string") {
|
|
return resolvedAs({
|
|
type: "sourceFile",
|
|
filePath: sourceFileResolution,
|
|
});
|
|
}
|
|
return resolvedAs(sourceFileResolution);
|
|
}
|
|
return failedFor({
|
|
type: "sourceFile",
|
|
filePathPrefix,
|
|
candidateExts,
|
|
});
|
|
}
|
|
function resolveSourceFile(context, platform) {
|
|
let filePath = resolveSourceFileForAllExts(context, "");
|
|
if (filePath) {
|
|
return filePath;
|
|
}
|
|
const { sourceExts } = context;
|
|
for (let i = 0; i < sourceExts.length; i++) {
|
|
const ext = `.${sourceExts[i]}`;
|
|
filePath = resolveSourceFileForAllExts(context, ext, platform);
|
|
if (filePath != null) {
|
|
return filePath;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function resolveSourceFileForAllExts(context, sourceExt, platform) {
|
|
if (platform != null) {
|
|
const ext = `.${platform}${sourceExt}`;
|
|
const filePath = resolveSourceFileForExt(context, ext);
|
|
if (filePath) {
|
|
return filePath;
|
|
}
|
|
}
|
|
if (context.preferNativePlatform && sourceExt !== "") {
|
|
const filePath = resolveSourceFileForExt(context, `.native${sourceExt}`);
|
|
if (filePath) {
|
|
return filePath;
|
|
}
|
|
}
|
|
const filePath = resolveSourceFileForExt(context, sourceExt);
|
|
return filePath;
|
|
}
|
|
function resolveSourceFileForExt(context, extension) {
|
|
const filePath = `${context.filePathPrefix}${extension}`;
|
|
const redirectedPath =
|
|
extension !== ""
|
|
? (0, _PackageResolve.redirectModulePath)(context, filePath)
|
|
: filePath;
|
|
if (redirectedPath === false) {
|
|
return {
|
|
type: "empty",
|
|
};
|
|
}
|
|
const lookupResult = context.fileSystemLookup(redirectedPath);
|
|
if (lookupResult.exists && lookupResult.type === "f") {
|
|
return lookupResult.realPath;
|
|
}
|
|
context.candidateExts.push(extension);
|
|
return null;
|
|
}
|
|
function isRelativeImport(filePath) {
|
|
return /^[.][.]?(?:[/]|$)/.test(filePath);
|
|
}
|
|
function isSubpathImport(filePath) {
|
|
return filePath.startsWith("#");
|
|
}
|
|
function resolvedAs(resolution) {
|
|
return {
|
|
type: "resolved",
|
|
resolution,
|
|
};
|
|
}
|
|
function failedFor(candidates) {
|
|
return {
|
|
type: "failed",
|
|
candidates,
|
|
};
|
|
}
|