UNPKG

rnpm-plugin-dom

Version:

rnpm plugin that generates a DOM template project

187 lines (163 loc) 5.72 kB
"use strict"; const fs = require("fs"); const execSync = require("child_process").execSync; const path = require("path"); const semver = require("semver"); const Registry = require("npm-registry"); const validUrl = require("valid-url"); const REACT_NATIVE_PACKAGE_JSON_PATH = function() { return path.resolve( process.cwd(), "node_modules", "react-native", "package.json" ); }; const REACT_NATIVE_DOM_GENERATE_PATH = function() { return path.resolve( process.cwd(), "node_modules", "react-native-dom", "local-cli", "generate-dom.js" ); }; let npmConfReg = execSync("npm config get registry") .toString() .trim(); let NPM_REGISTRY_URL = validUrl.is_uri(npmConfReg) ? npmConfReg : "http://registry.npmjs.org"; const npm = new Registry({ registry: NPM_REGISTRY_URL }); function getLatestVersion() { return new Promise(function(resolve, reject) { npm.packages.release("react-native-dom", "latest", (err, releases) => { if (err) { reject(err); } else if (!releases || releases.length === 0) { reject(new Error("Could not find react-native-dom@latest.")); } else { resolve(releases[0].version); } }); }); } function getMatchingVersion(version) { console.log(`Checking for react-native-dom version matching ${version}...`); return new Promise(function(resolve, reject) { npm.packages.range("react-native-dom", version, (err, release) => { if (err || !release) { return getLatestVersion() .then((latestVersion) => { reject( new Error( `Could not find react-native-dom@${version}. ` + `Latest version of react-native-dom is ${latestVersion}, try switching to ` + `react-native-dom@${semver.major( latestVersion )}.${semver.minor(latestVersion)}.*.` ) ); }) .catch((error) => reject(new Error(`Could not find react-native-dom@${version}.`)) ); } else { resolve(release.version); } }); }); } const getAllReactNativeDomReleases = function(includeCanary) { return new Promise((resolve, reject) => { npm.packages.releases("react-native-dom", (err, releases) => { if (err) return reject(err); resolve( Object.keys(releases) .filter((release) => { if (["latest", "canary"].includes(release)) return false; if (!includeCanary && release.includes("alpha")) return false; return true; }, {}) .map((r) => releases[r]) ); }); }); }; const getInstallPackage = function(version, includeCanary) { if (version) { let packageToInstall = "react-native-dom"; const validVersion = semver.valid(version); const validRange = semver.validRange(version); if (validVersion || validRange) { return getMatchingVersion(version); } else { return Promise.resolve(version); } } else { const reactNativeVersion = getReactNativeVersion(); return getAllReactNativeDomReleases(includeCanary).then((releases) => { releases.sort((a, b) => { if (a.date < b.date) return 1; if (a.date > b.date) return -1; return 0; }); for (const release of releases) { if ( semver.satisfies( reactNativeVersion, release.peerDependencies["react-native"] ) ) return release.version; } throw new Error( `No version of 'react-native-dom' found that satisfies a peer dependency on 'react-native@${reactNativeVersion}'` ); }); } }; const getReactNativeVersion = function() { console.log("Reading react-native version from node_modules..."); if (fs.existsSync(REACT_NATIVE_PACKAGE_JSON_PATH())) { const version = JSON.parse( fs.readFileSync(REACT_NATIVE_PACKAGE_JSON_PATH(), "utf-8") ).version; return version; } }; const getReactNativeAppName = function() { console.log("Reading application name from package.json..."); return JSON.parse(fs.readFileSync("package.json", "utf8")).name; }; /** * Check that 'react-native init' itself used yarn to install React Native. * When using an old global react-native-cli@1.0.0 (or older), we don't want * to install React Native with npm, and React + Jest with yarn. * Let's be safe and not mix yarn and npm in a single project. * @param projectDir e.g. /Users/martin/AwesomeApp */ const isGlobalCliUsingYarn = function(projectDir) { return fs.existsSync(path.join(projectDir, "yarn.lock")); }; module.exports = function dom(config, args, options) { const packageToInstall = "react-native-dom"; const name = args[0] ? args[0] : getReactNativeAppName(); const includeCanary = options.includeCanary ? options.includeCanary : false; const version = options.domVersion; const exact = options.exact; getInstallPackage(version, includeCanary) .then((versionToInstall) => { const rnDomPackage = `${packageToInstall}@${versionToInstall}`; console.log(`Installing ${rnDomPackage}...`); const pkgmgr = isGlobalCliUsingYarn(process.cwd()) ? "yarn add" + (exact ? " --exact" : "") : "npm install" + (exact ? " --save-exact" : " --save"); const execOptions = options.verbose ? { stdio: "inherit" } : {}; execSync(`${pkgmgr} ${rnDomPackage}`, execOptions); console.log(`${rnDomPackage} succesfully installed`); const generateDom = require(REACT_NATIVE_DOM_GENERATE_PATH()); generateDom(process.cwd(), name); }) .catch((error) => console.error(error.message)); };