react-native-monorepo-helper
Version:
A helper library that makes React Native development in monorepo projects easier.
481 lines • 39 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = __importDefault(require("chalk"));
const child_process_1 = __importDefault(require("child_process"));
const fs_1 = __importDefault(require("fs"));
const glob_1 = __importDefault(require("glob"));
const path_1 = __importDefault(require("path"));
const resolve_1 = __importDefault(require("resolve"));
var Metro;
(function (Metro) {
let ResolutionType;
(function (ResolutionType) {
ResolutionType["ASSET"] = "asset";
ResolutionType["SOURCE_FILE"] = "sourceFile";
})(ResolutionType = Metro.ResolutionType || (Metro.ResolutionType = {}));
})(Metro = exports.Metro || (exports.Metro = {}));
// ---
function tryParseJsonFile(filename) {
if (fs_1.default.existsSync(filename)) {
const jsonFile = fs_1.default.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_1.default.sync(ignoredFolder, { cwd }))
.reduce((accum, elem) => { accum.push(...elem); return accum; }, []);
for (const globStr of globs) {
if (typeof globStr !== 'string')
continue;
const roots = glob_1.default
.sync(`${globStr}/package.json`, { cwd, nodir: true })
.map(root => path_1.default.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_1.default.existsSync(pathname) ? fs_1.default.statSync(pathname) : null;
if (stat && stat.isSymbolicLink()) {
pathname = fs_1.default.realpathSync(pathname);
stat = fs_1.default.existsSync(pathname) ? fs_1.default.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_ = exports.defaultTypeScriptConfig;
return this;
}
else if (typeof enabled === "string") {
if (!enabled)
throw new Error("Transformer module name cannot be empty.");
this.typeScript_ = Object.assign({}, exports.defaultTypeScriptConfig, { transformerModuleName: enabled });
return this;
}
else if (typeof enabled === "object" && enabled !== null) {
this.typeScript_ = Object.assign({}, exports.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 = Object.assign({}, this.defaultConfig(), { watchFolders: [
...(this.defaultConfig().watchFolders || []),
...this.watchFolders()
.map(this.mapByFolderFollowingSymlink)
.filter(this.filterByNonEmptyString),
], resolver: Object.assign({}, (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_1.default.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_1.default.resolve(originModuleDir, moduleName);
if (this.fileModuleExists(basename)) {
resolvedName = basename;
}
else if (this.isDirectory(basename)) {
basename = path_1.default.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_1.default.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_1.default.existsSync(pathname)) {
const stat = fs_1.default.lstatSync(pathname);
if (stat.isFile() || stat.isFIFO()) {
return true;
}
}
return false;
}
isDirectory(pathname) {
return fs_1.default.existsSync(pathname)
&& fs_1.default.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;
}
}
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_1.default.resolve(monorepoRoot, "lerna.json");
const lernaJson = tryParseJsonFile(lernaJsonFilename);
if (lernaJson) {
found = true;
if (lernaJson.useWorkspaces === true && lernaJson.npmClient === 'yarn') {
const packageJsonFilename = path_1.default.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_1.default.dirname(monorepoRoot);
if (path_1.default.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_1.default.resolve(monorepoRoot, root),
})),
project: {
root: projectRoot,
},
root: monorepoRoot,
};
helper.logger().debug(`Found lerna monorepo.`, info);
return info;
}
exports.findLernaMonorepo = findLernaMonorepo;
function findYarnMonorepo(projectRoot, helper) {
let packageRoots = [];
let found = false;
let monorepoRoot = projectRoot;
const YARN = process.env.YARN || 'yarn';
let yarnInPath = true;
try {
child_process_1.default.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_1.default.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 = child_process_1.default.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_1.default.dirname(monorepoRoot);
if (path_1.default.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_1.default.resolve(monorepoRoot, root),
})),
project: {
root: projectRoot,
},
};
helper.logger().debug(`Found yarn monorepo.`, info);
return info;
}
exports.findYarnMonorepo = findYarnMonorepo;
exports.nullLogger = {
trace: () => { },
debug: () => { },
error: () => { },
};
/* tslint:disable no-console */
exports.consoleLogger = {
trace: (...args) => console.debug(chalk_1.default.yellow("[MonorepoHelper|TRACE] "), ...args),
debug: (...args) => console.debug(chalk_1.default.yellowBright("[MonorepoHelper|DEBUG] "), ...args),
error: (...args) => console.error(chalk_1.default.bgRed.whiteBright("[MonorepoHelper|ERROR] "), ...args),
};
/* tslint:enable no-console */
exports.defaultHelperOptions = {
logger: {
trace: exports.nullLogger.trace,
debug: exports.consoleLogger.debug,
error: exports.consoleLogger.error,
},
monorepoFinders: [findLernaMonorepo, findYarnMonorepo],
};
exports.defaultTypeScriptConfig = {
fileExtensions: ["ts", "tsx"],
transformerModuleName: "react-native-typescript-transformer",
};
function metroConfigHelper(projectRoot, options) {
return new MetroConfigHelper(options || exports.defaultHelperOptions)
.projectRoot(projectRoot);
}
exports.metroConfigHelper = metroConfigHelper;
function metroConfig(projectRoot) {
return metroConfigHelper(projectRoot).generate();
}
exports.metroConfig = metroConfig;
exports.default = metroConfig;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSxrREFBMEI7QUFDMUIsa0VBQStCO0FBQy9CLDRDQUFvQjtBQUNwQixnREFBd0I7QUFDeEIsZ0RBQXdCO0FBQ3hCLHNEQUE4QjtBQVE5QixJQUFpQixLQUFLLENBbUNyQjtBQW5DRCxXQUFpQixLQUFLO0lBRWxCLElBQVksY0FHWDtJQUhELFdBQVksY0FBYztRQUN0QixpQ0FBZSxDQUFBO1FBQ2YsNENBQTBCLENBQUE7SUFDOUIsQ0FBQyxFQUhXLGNBQWMsR0FBZCxvQkFBYyxLQUFkLG9CQUFjLFFBR3pCO0FBOEJMLENBQUMsRUFuQ2dCLEtBQUssR0FBTCxhQUFLLEtBQUwsYUFBSyxRQW1DckI7QUFpQ0QsTUFBTTtBQUdOLFNBQVMsZ0JBQWdCLENBQXlCLFFBQWdCO0lBQzlELElBQUksWUFBRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRTtRQUN6QixNQUFNLFFBQVEsR0FBRyxZQUFFLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDN0MsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRO1lBQUUsT0FBTyxJQUFTLENBQUM7S0FDbEQ7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNyQixDQUFDO0FBRUQsU0FBUyxnQkFBZ0IsQ0FDckIsS0FBWSxFQUNaLE9BR0M7SUFFRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO0lBQ3hCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxjQUFjLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3JFLElBQUksT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUUzQixNQUFNLHFCQUFxQixHQUFHLGNBQWM7U0FDdkMsR0FB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