UNPKG

react-native-monorepo-helper

Version:

A helper library that makes React Native development in monorepo projects easier.

481 lines 39 kB
"use strict"; 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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