react-native-monorepo-helper
Version:
A helper library that makes React Native development in monorepo projects easier.
485 lines • 38.4 kB
JavaScript
import chalk from 'chalk';
import cp from 'child_process';
import fs from 'fs';
import glob from 'glob';
import path from 'path';
import resolve from 'resolve';
export var Metro;
(function (Metro) {
let ResolutionType;
(function (ResolutionType) {
ResolutionType["ASSET"] = "asset";
ResolutionType["SOURCE_FILE"] = "sourceFile";
})(ResolutionType = Metro.ResolutionType || (Metro.ResolutionType = {}));
})(Metro || (Metro = {}));
// ---
function tryParseJsonFile(filename) {
if (fs.existsSync(filename)) {
const jsonFile = fs.readFileSync(filename);
const json = JSON.parse(jsonFile.toString());
if (typeof json === 'object')
return json;
}
return undefined;
}
function readPackageGlobs(globs, options) {
const cwd = options.cwd;
const ignoredFolders = options.ignoredFolders || [`**/node_modules`];
let results = [];
const globbedIgnoredFolders = ignoredFolders
.map(ignoredFolder => glob.sync(ignoredFolder, { cwd }))
.reduce((accum, elem) => { accum.push(...elem); return accum; }, []);
for (const globStr of globs) {
if (typeof globStr !== 'string')
continue;
const roots = glob
.sync(`${globStr}/package.json`, { cwd, nodir: true })
.map(root => path.dirname(root))
.filter(root => !globbedIgnoredFolders.some(folder => root.startsWith(folder)));
results = results.concat(roots);
}
return results;
}
function unique(array) {
return array.filter((value, index, self) => self.indexOf(value) === index);
}
class MetroConfigHelper {
constructor(options) {
this.mapByFolderFollowingSymlink = (pathname) => {
let stat = fs.existsSync(pathname) ? fs.statSync(pathname) : null;
if (stat && stat.isSymbolicLink()) {
pathname = fs.realpathSync(pathname);
stat = fs.existsSync(pathname) ? fs.statSync(pathname) : null;
}
if (stat && stat.isDirectory())
return pathname;
return '';
};
this.filterByNonEmptyString = (pathname) => {
return typeof pathname === 'string' && !!pathname;
};
options = options || {};
this.logger_ = options.logger || console;
this.defaultConfig_ = options.defaultConfig || {};
this.monorepoFinders_ = [];
this.projectRoot_ = options.projectRoot;
this.watchFolders_ = [];
this.watchFolders_ = [];
this.typeScript_ = false;
this.monorepoFinder(...(options.monorepoFinders || []));
}
projectRoot(newProjectRoot) {
if (newProjectRoot) {
this.projectRoot_ = newProjectRoot;
return this;
}
if (!this.projectRoot_)
throw new Error("Project's root folder not set.");
return this.projectRoot_;
}
monorepoFinder(...finder) {
this.monorepoFinders_ = this.monorepoFinders_.concat(finder.filter(f => typeof f === 'function'));
return this;
}
findMonorepo() {
for (const monorepoFinder of this.monorepoFinders_) {
const monorepo = monorepoFinder(this.projectRoot(), this);
if (monorepo)
return monorepo;
}
return undefined;
}
logger(newLogger) {
if (newLogger) {
this.logger_ = newLogger;
return this;
}
if (!this.logger_)
throw new Error("Logger not set.");
return this.logger_;
}
defaultConfig(newDefaultConfig) {
if (newDefaultConfig) {
this.defaultConfig_ = newDefaultConfig;
return this;
}
if (!this.defaultConfig_)
throw new Error("Default config not set.");
return this.defaultConfig_;
}
monorepo(newMonorepoInfo) {
if (newMonorepoInfo) {
this.monorepo_ = newMonorepoInfo;
return this;
}
else if (!this.monorepo_) {
this.monorepo_ = this.findMonorepo();
}
if (!this.monorepo_)
throw new Error("Monorepo not set.");
return this.monorepo_;
}
typeScript(enabled) {
if (enabled === true) {
this.typeScript_ = defaultTypeScriptConfig;
return this;
}
else if (typeof enabled === "string") {
if (!enabled)
throw new Error("Transformer module name cannot be empty.");
this.typeScript_ = {
...defaultTypeScriptConfig,
transformerModuleName: enabled,
};
return this;
}
else if (typeof enabled === "object" && enabled !== null) {
this.typeScript_ = {
...defaultTypeScriptConfig,
...enabled,
};
}
return this.typeScript_;
}
watchFolder(...folder) {
this.watchFolders_ = this.watchFolders_.concat(folder);
return this;
}
packageRoots() {
return this.monorepo().packages.map(packageInfo => packageInfo.root);
}
watchFolders() {
return unique([
this.monorepo().root,
...this.packageRoots(),
...this.watchFolders_,
]);
}
customResolver(newResolver) {
if (newResolver) {
this.customResolver_ = newResolver;
return this;
}
else if (!this.customResolver_) {
this.customResolver_ = this.createCustomResolver();
}
if (!this.customResolver_)
throw new Error("Custom resolver not set.");
return this.customResolver_;
}
createCustomResolver() {
return (metro, moduleName, platform) => {
const context = {
metro,
moduleName,
platform,
};
const sourceExts = context.metro.sourceExts;
const assetExts = context.metro.assetExts || [];
const resolution = this.resolveInProject(context, Metro.ResolutionType.SOURCE_FILE, sourceExts)
|| this.resolveInProject(context, Metro.ResolutionType.ASSET, assetExts)
|| null;
return resolution;
};
}
config(newConfig) {
if (newConfig) {
this.config_ = newConfig;
return this;
}
else if (!this.config_) {
this.config_ = this.generate();
}
if (!this.config_)
throw new Error("Custom resolver not set.");
return this.config_;
}
generate() {
const config = {
...this.defaultConfig(),
watchFolders: [
...(this.defaultConfig().watchFolders || []),
...this.watchFolders()
.map(this.mapByFolderFollowingSymlink)
.filter(this.filterByNonEmptyString),
],
resolver: {
...(this.defaultConfig().resolver || {}),
resolveRequest: this.customResolver(),
},
};
const typeScript = this.typeScript();
if (this.isTypeScriptConfig(typeScript)) {
config.getTransformModulePath =
config.getTransformModulePath
|| (() => require.resolve(typeScript.transformerModuleName));
config.sourceExts = [
...(config.sourceExts || []),
...typeScript.fileExtensions,
];
}
return config;
}
resolveInProject(context, type, extensions) {
const originModulePath = context.metro.originModulePath;
const moduleName = context.moduleName;
const packageFilter = (pkg) => {
for (const mainField of context.metro.mainFields || []) {
if (typeof pkg[mainField] === 'string') {
pkg.main = pkg[mainField];
break;
}
}
return pkg;
};
extensions = this.generateComplementaryExtensions(context, extensions);
let resolvedName;
let originModuleDir;
// Expectations:
// - originModulePath exists
// - originModulePath is an absolute (or completely
// resolved, to some degree) path in the filesystem.
if (this.isDirectory(originModulePath)) {
originModuleDir = originModulePath;
}
else {
originModuleDir = path.dirname(originModulePath);
}
// For some reason, `resolve` can't resolve relative-path modules...
// TODO Use resolve.sync() instead (if possible; if someone understands why/how)
if (moduleName.startsWith('./') || moduleName.startsWith('../')) {
let basename = path.resolve(originModuleDir, moduleName);
if (this.fileModuleExists(basename)) {
resolvedName = basename;
}
else if (this.isDirectory(basename)) {
basename = path.resolve(basename, 'index');
}
if (!resolvedName) {
for (const extension of extensions) {
const pathname = `${basename}.${extension}`;
if (this.fileModuleExists(pathname)) {
resolvedName = pathname;
break;
}
}
}
if (!resolvedName) {
this.logger().trace(`Could not resolve local-path module '${moduleName}'!`
+ ` includedIn='${originModulePath}'`
+ `, basedir='${originModuleDir}'`
+ `, fileExtensions=${JSON.stringify(extensions)}!`);
}
}
if (!resolvedName) {
originModuleDir = this.projectRoot();
try {
resolvedName = resolve.sync(moduleName, {
extensions,
packageFilter,
basedir: originModuleDir,
});
}
catch (error) { }
if (!resolvedName) {
this.logger().trace(`Could not resolve module '${moduleName}'!`
+ ` includedIn='${originModulePath}'`
+ `, basedir='${originModuleDir}'`
+ `, fileExtensions=${JSON.stringify(extensions)}!`);
}
}
if (resolvedName) {
return { type, filePath: resolvedName };
}
return undefined;
}
fileModuleExists(pathname) {
if (fs.existsSync(pathname)) {
const stat = fs.lstatSync(pathname);
if (stat.isFile() || stat.isFIFO()) {
return true;
}
}
return false;
}
isDirectory(pathname) {
return fs.existsSync(pathname)
&& fs.lstatSync(pathname).isDirectory();
}
generateComplementaryExtensions(context, baseExtensions) {
let filePaths = [];
for (const baseExt of baseExtensions) {
filePaths = filePaths.concat([
`${context.platform}.${baseExt}`,
`${baseExt}`,
]);
}
return filePaths;
}
isTypeScriptConfig(value) {
return typeof value === 'object' && value !== null;
}
}
export function findLernaMonorepo(projectRoot, helper) {
let packageRoots = [];
let found = false;
let monorepoRoot = projectRoot;
while (true) {
helper.logger().debug(`Searching for lerna monorepo at '${monorepoRoot}'...`);
const lernaJsonFilename = path.resolve(monorepoRoot, "lerna.json");
const lernaJson = tryParseJsonFile(lernaJsonFilename);
if (lernaJson) {
found = true;
if (lernaJson.useWorkspaces === true && lernaJson.npmClient === 'yarn') {
const packageJsonFilename = path.resolve(monorepoRoot, "package.json");
const packageJson = tryParseJsonFile(packageJsonFilename);
if (packageJson) {
const workspaces = packageJson.workspaces;
if (workspaces instanceof Array) {
const paths = readPackageGlobs(workspaces, { cwd: monorepoRoot });
packageRoots = packageRoots.concat(paths);
}
else if (typeof workspaces === 'object' && workspaces.packages instanceof Array) {
const paths = readPackageGlobs(workspaces.packages, { cwd: monorepoRoot });
packageRoots = packageRoots.concat(paths);
}
}
}
else if (lernaJson.packages instanceof Array) {
const paths = readPackageGlobs(lernaJson.packages, { cwd: monorepoRoot });
packageRoots = packageRoots.concat(paths);
}
}
if (found)
break;
monorepoRoot = path.dirname(monorepoRoot);
if (path.parse(monorepoRoot).root === monorepoRoot)
break;
}
if (!found) {
helper.logger().debug(`Could not find lerna monorepo starting at project root '${projectRoot}'.`);
return null;
}
const info = {
packages: packageRoots.map(root => ({
root: path.resolve(monorepoRoot, root),
})),
project: {
root: projectRoot,
},
root: monorepoRoot,
};
helper.logger().debug(`Found lerna monorepo.`, info);
return info;
}
export function findYarnMonorepo(projectRoot, helper) {
let packageRoots = [];
let found = false;
let monorepoRoot = projectRoot;
const YARN = process.env.YARN || 'yarn';
let yarnInPath = true;
try {
cp.execFileSync(YARN, ['--version']);
}
catch (err) {
yarnInPath = false;
helper.logger().debug(`** It seems you don't have yarn in your path.`
+ ` Reverting to glob-based package root resolution...`);
}
while (true) {
helper.logger().debug(`Searching for yarn monorepo at '${monorepoRoot}'...`);
const packageJsonFilename = path.resolve(monorepoRoot, "package.json");
const yarnPackageJson = tryParseJsonFile(packageJsonFilename);
const yarnWorkspaces = yarnPackageJson ? yarnPackageJson.workspaces : {};
if (yarnWorkspaces && 'packages' in yarnWorkspaces) {
if (yarnInPath) {
let workspaceInfoJson;
try {
// Unless something is terribly wrong with yarn or the project layout/configuration,
// yarn will fail in this only when the current search folder is not a workspace root.
// We should continue our search upwards in the filesystem tree if the folder is not
// a workspace, hence the try-catch.
workspaceInfoJson = cp.execFileSync(YARN, ['workspaces', 'info', '--silent'], {
cwd: monorepoRoot,
}).toString();
}
catch (err) { }
if (workspaceInfoJson) {
const workspaceInfo = JSON.parse(workspaceInfoJson);
packageRoots = Object.keys(workspaceInfo)
.map(packageName => `${monorepoRoot}/${workspaceInfo[packageName].location}`);
}
}
else {
const packageJson = tryParseJsonFile(packageJsonFilename);
if (packageJson) {
const workspaces = packageJson.workspaces;
if (workspaces instanceof Array) {
const paths = readPackageGlobs(workspaces, { cwd: monorepoRoot });
packageRoots = packageRoots.concat(paths);
}
else if (typeof workspaces === 'object' && workspaces.packages instanceof Array) {
const paths = readPackageGlobs(workspaces.packages, { cwd: monorepoRoot });
packageRoots = packageRoots.concat(paths);
}
}
}
if (packageRoots && packageRoots.length > 0) {
found = true;
}
}
if (found)
break;
monorepoRoot = path.dirname(monorepoRoot);
if (path.parse(monorepoRoot).root === monorepoRoot)
break;
}
if (!found) {
helper.logger().debug(`Could not find lerna monorepo starting at project root '${projectRoot}'.`);
return null;
}
const info = {
root: monorepoRoot,
packages: packageRoots.map(root => ({
root: path.resolve(monorepoRoot, root),
})),
project: {
root: projectRoot,
},
};
helper.logger().debug(`Found yarn monorepo.`, info);
return info;
}
export const nullLogger = {
trace: () => { },
debug: () => { },
error: () => { },
};
/* tslint:disable no-console */
export const consoleLogger = {
trace: (...args) => console.debug(chalk.yellow("[MonorepoHelper|TRACE] "), ...args),
debug: (...args) => console.debug(chalk.yellowBright("[MonorepoHelper|DEBUG] "), ...args),
error: (...args) => console.error(chalk.bgRed.whiteBright("[MonorepoHelper|ERROR] "), ...args),
};
/* tslint:enable no-console */
export const defaultHelperOptions = {
logger: {
trace: nullLogger.trace,
debug: consoleLogger.debug,
error: consoleLogger.error,
},
monorepoFinders: [findLernaMonorepo, findYarnMonorepo],
};
export const defaultTypeScriptConfig = {
fileExtensions: ["ts", "tsx"],
transformerModuleName: "react-native-typescript-transformer",
};
export function metroConfigHelper(projectRoot, options) {
return new MetroConfigHelper(options || defaultHelperOptions)
.projectRoot(projectRoot);
}
export function metroConfig(projectRoot) {
return metroConfigHelper(projectRoot).generate();
}
export default metroConfig;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvQixPQUFPLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDcEIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFROUIsTUFBTSxLQUFXLEtBQUssQ0FtQ3JCO0FBbkNELFdBQWlCLEtBQUs7SUFFbEIsSUFBWSxjQUdYO0lBSEQsV0FBWSxjQUFjO1FBQ3RCLGlDQUFlLENBQUE7UUFDZiw0Q0FBMEIsQ0FBQTtJQUM5QixDQUFDLEVBSFcsY0FBYyxHQUFkLG9CQUFjLEtBQWQsb0JBQWMsUUFHekI7QUE4QkwsQ0FBQyxFQW5DZ0IsS0FBSyxLQUFMLEtBQUssUUFtQ3JCO0FBaUNELE1BQU07QUFHTixTQUFTLGdCQUFnQixDQUF5QixRQUFnQjtJQUM5RCxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUU7UUFDekIsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQzdDLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUTtZQUFFLE9BQU8sSUFBUyxDQUFDO0tBQ2xEO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDckIsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQ3JCLEtBQVksRUFDWixPQUdDO0lBRUQsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztJQUN4QixNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FB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