/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
*/
"use strict";
const AssetResolutionCache = require("../../node-haste/AssetResolutionCache");
const DependencyGraphHelpers = require("../../node-haste/DependencyGraph/DependencyGraphHelpers");
const FilesByDirNameIndex = require("../../node-haste/FilesByDirNameIndex");
const HasteFS = require("./HasteFS");
const Module = require("./Module");
const ModuleCache = require("./ModuleCache");
const defaults = require("metro-config/src/defaults/defaults");
const parsePlatformFilePath = require("../../node-haste/lib/parsePlatformFilePath");
const path = require("path");
const _require = require("../../node-haste/DependencyGraph/ModuleResolution"),
ModuleResolver = _require.ModuleResolver;
const _require2 = require("jest-haste-map"),
ModuleMap = _require2.ModuleMap;
const platforms = new Set(defaults.platforms);
const GENERIC_PLATFORM = "g";
const PACKAGE_JSON = path.sep + "package.json";
const NULL_MODULE = {
path: "/",
getPackage() {},
isHaste() {
throw new Error("not implemented");
},
getName() {
throw new Error("not implemented");
}
}; // This function maps the ModuleGraph data structure to jest-haste-map's ModuleMap
const createModuleMap = _ref => {
let files = _ref.files,
helpers = _ref.helpers,
moduleCache = _ref.moduleCache,
sourceExts = _ref.sourceExts;
const map = new Map();
files.forEach(filePath => {
if (helpers.isNodeModulesDir(filePath)) {
return;
}
let id;
let module;
if (filePath.endsWith(PACKAGE_JSON)) {
module = moduleCache.getPackage(filePath);
id = module.data.name;
} else if (sourceExts.indexOf(path.extname(filePath).substr(1)) !== -1) {
module = moduleCache.getModule(filePath);
id = module.name;
}
if (!(id && module && module.isHaste())) {
return;
}
const mapModule = map.get(id) || Object.create(null);
const platform =
parsePlatformFilePath(filePath, platforms).platform || GENERIC_PLATFORM;
const existingModule = mapModule[platform]; // 0 = Module, 1 = Package in jest-haste-map
mapModule[platform] = [filePath, module.type === "Package" ? 1 : 0];
if (existingModule && existingModule[0] !== filePath) {
throw new Error(
[
"@providesModule naming collision:",
` Duplicate module name: \`${id}\``,
` Paths: \`${filePath}\` collides with \`${existingModule[0]}\``,
"",
"This error is caused by a @providesModule declaration " +
"with the same name across two different files."
].join("\n")
);
}
map.set(id, mapModule);
});
return map;
};
exports.createResolveFn = function(options) {
const allowPnp = options.allowPnp,
assetExts = options.assetExts,
extraNodeModules = options.extraNodeModules,
transformedFiles = options.transformedFiles,
sourceExts = options.sourceExts,
platform = options.platform;
const files = Object.keys(transformedFiles);
function getTransformedFile(path) {
const result = transformedFiles[path];
if (!result) {
throw new Error(`"${path} does not exist`);
}
return result;
}
const helpers = new DependencyGraphHelpers({
assetExts,
providesModuleNodeModules: defaults.providesModuleNodeModules
});
const hasteFS = new HasteFS(files);
const moduleCache = new ModuleCache(
filePath => hasteFS.closest(filePath, "package.json"),
getTransformedFile
);
const filesByDirNameIndex = new FilesByDirNameIndex(files);
const assetResolutionCache = new AssetResolutionCache({
assetExtensions: new Set(assetExts),
getDirFiles: dirPath => filesByDirNameIndex.getAllFiles(dirPath),
platforms
});
const moduleResolver = new ModuleResolver({
allowPnp,
dirExists: filePath => hasteFS.dirExists(filePath),
doesFileExist: filePath => hasteFS.exists(filePath),
extraNodeModules,
isAssetFile: filePath => helpers.isAssetFile(filePath),
mainFields: options.mainFields,
moduleCache,
moduleMap: new ModuleMap({
duplicates: new Map(),
map: createModuleMap({
files,
helpers,
moduleCache,
sourceExts
}),
mocks: new Map(),
rootDir: ""
}),
preferNativePlatform: true,
resolveAsset: (dirPath, assetName, platform) =>
assetResolutionCache.resolve(dirPath, assetName, platform),
resolveRequest: options.resolveRequest,
sourceExts
});
return (id, sourcePath) => {
const from =
sourcePath != null
? new Module(sourcePath, moduleCache, getTransformedFile(sourcePath))
: NULL_MODULE;
const allowHaste = !helpers.isNodeModulesDir(from.path);
return moduleResolver.resolveDependency(from, id, allowHaste, platform)
.path;
};
};