UNPKG

@applicaster/zapplicaster-cli

Version:

CLI Tool for the zapp app and Quick Brick project

308 lines (251 loc) • 8.07 kB
const R = require("ramda"); const fs = require("fs"); const semver = require("semver"); const { resolve, join } = require("path"); const { existsSync } = require("fs"); const packageJSON = require("../../../package.json"); const { quickBrickDirectory, getFileDestinationPath, } = require("../../settings/paths"); const { getCLIProperties } = require("../../settings"); const { copyFiles } = require("../../file"); const logger = require("../../logger"); const { exec } = require("shelljs"); const { parseFonts } = require("./parseFonts"); const { gatherDependencies, getPluginDependencies, getExtraPluginDependencies, getSDKAssets, } = require("../../plugins"); const { injectDependencies, injectScripts, renderTemplateFile, } = require("../../render"); const { buildMobileApp } = require("./buildMobile"); async function patchPackages() { if (existsSync(join(process.cwd(), "quick_brick", "patch_rn.js"))) { exec(`node ${process.cwd()}/quick_brick/patch_rn.js`); } else if ( existsSync(join(process.cwd(), "development-app", "patch_rn.js")) ) { exec(`node ${process.cwd()}/development-app/patch_rn.js`); } else if ( existsSync( join( process.cwd(), "packages", "zapp-react-dom-development-app", "patch_rn.js" ) ) ) { const pathToFile = join( process.cwd(), "packages", "zapp-react-dom-development-app", "patch_rn.js" ); exec(`node ${pathToFile}`); } else { logger.log("Cannot patch packages, can't find the patch_rn.js file"); } } /** * fallback to en for missing dayjslocalization * converts the locale code to a dayjs compatible locale code * lowercase input code is expected, e.g. "en-GB" => "en-gb" * @param {string} code - locale code, e.g. "en", "fr", "es-LA" * from @applicaster/zapp-react-native-utils/appUtils/localizationsHelper * */ const toDayJSLocaleMap = (code) => { const map = { hy: "hy-am", fj: null, la: null, no: null, pa: "pa-in", qu: null, sm: null, to: null, xh: null, tt: null, "es-LA": "es", "en-UK": "en-gb", }; if (map[code] === null) { return "en"; } else if (map[code]) { return map[code]; } else { return code.toLowerCase(); } }; /** * {@typedef configuration * @type {Object} * @property {String} appVersionId: ID of the app version in Zapp * @property {Object} buildParams: zapp build params for the app * @property {String} platform: Platform of the app * @property {Boolean} openSdk: whether or not the app should use an open SDK * @property {Boolean} verbose: verbose output flag */ /** * Bootstraps the app * @param {configuration} configuration */ async function appBootstrapper(configuration) { const { destinationPath, platform, yarn, zappReactNative, template, buildMobile, } = configuration; if (zappReactNative) { logger.log("Bootstrapping app for the Zapp React Native Repo"); logger.log("Rendered files will be in ./development-app"); } const quickBrickProjectPath = quickBrickDirectory(destinationPath); logger.log("copying templates files..."); const { templatePath, filesToCopy } = template.files; copyFiles(templatePath, filesToCopy, quickBrickProjectPath, configuration); logger.log("injecting dependencies..."); const { dependencies, scripts } = template; const pluginConfigurations = require( getFileDestinationPath({ destinationPath, platform, folder: "config", fileName: "plugin_configurations.json", }) ); const getExcludedNodeModules = R.compose( R.map((plug) => new RegExp(plug)), R.reduce( (acc, plugin) => R.concat(acc, R.pathOr([], ["api", "excludedNodeModules"])(plugin)), [] ) ); const { name, version } = getCLIProperties(); dependencies.push({ name, version, type: "devDependencies", }); const plugins = gatherDependencies(pluginConfigurations); const pluginDependencies = getPluginDependencies(plugins).concat( getExtraPluginDependencies(plugins) ); await injectDependencies(pluginDependencies, resolve(quickBrickProjectPath)); await injectDependencies(dependencies, resolve(quickBrickProjectPath)); await injectScripts(scripts, resolve(quickBrickProjectPath)); logger.log("rendering templates..."); // Parsing fonts to render with templates const parsedFonts = parseFonts(configuration.buildParams.fonts, platform); configuration.parsedFonts = parsedFonts || []; // We need to import the default SDK assets into the root of the app // Webpack is using this const sdkAssets = await getSDKAssets( platform, resolve(quickBrickProjectPath) ); configuration.sdkAssets = sdkAssets; configuration.buildParams.dayJsLocales = configuration.buildParams.languages .map(toDayJSLocaleMap) .filter((v) => v !== "en"); configuration.excludedNodeModules = getExcludedNodeModules(plugins); const { filesToRender } = template.files; await Promise.all( R.map( renderTemplateFile(configuration, quickBrickProjectPath, plugins), filesToRender ) ); logger.log("installing dependencies..."); const npmInstallResult = zappReactNative ? exec("yarn") : exec(`cd ${quickBrickProjectPath} && ${yarn ? "yarn" : "npm i"}`); if (npmInstallResult.code > 0) { throw new Error("Couldn't not install npm dependencies !"); } const quickBrickVersion = packageJSON.version; checkAllPluginsSatisfiesQuickBrickVersion({ quickBrickVersion, plugins }); await patchPackages(); if (buildMobile) { await buildMobileApp(configuration); } return true; } function checkAllPluginsSatisfiesQuickBrickVersion({ quickBrickVersion, plugins, }) { if (!plugins) { return; } logger.log( `Checking if all plugins satisfies Quick Brick version: ${quickBrickVersion} ` ); if (quickBrickVersion.includes("alpha")) { logger.warn( `QuickBrick SDK with version: ${quickBrickVersion} is canary, can not compare plugins, all plugins allowed.To proper versions check use RC or Stable versions and not canary` // eslint-disable-line ); return; } for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; const packagePath = `${process.cwd()}/node_modules/${ plugin.packageName }/package.json`; if (!fs.existsSync(packagePath)) { return; } const pluginPackage = require(packagePath); checkPluginSatisfiesQuickBrickVersion({ pluginPackage, quickBrickVersion, }); } logger.log( `All satisfies Quick Brick version: ${quickBrickVersion}, check complete` ); } function checkPluginSatisfiesQuickBrickVersion({ pluginPackage, quickBrickVersion, }) { const minQuickBrickVersionNeededForPlugin = pluginPackage?.applicaster?.quickbrick?.min_version; if (!minQuickBrickVersionNeededForPlugin) { return; } if ( quickBrickVersion.includes("alpha") || minQuickBrickVersionNeededForPlugin.includes("alpha") ) { logger.warn( `Plugin: ${pluginPackage.name}, with version: ${pluginPackage.version}, requires QuickBrick version: ${minQuickBrickVersionNeededForPlugin}, it is canary can not compare versions. Plugin allowed. To proper versions check use RC or Stable versions and not canary` // eslint-disable-line ); return; } if ( !isVersionSatisfies(quickBrickVersion, minQuickBrickVersionNeededForPlugin) ) { throw new Error( `Unsupported Plugin Version - Plugin: ${pluginPackage.name}, with version: ${pluginPackage.version} expect Quick Brick version: ${minQuickBrickVersionNeededForPlugin}, but Quick Brick app version has: ${quickBrickVersion}. Please use supported plugin versions` // eslint-disable-line ); } } function isVersionSatisfies(quickBrickVersion, minQuickBrickVersion) { return semver.gte(quickBrickVersion, minQuickBrickVersion); } module.exports = { appBootstrapper, isVersionSatisfies, checkPluginSatisfiesQuickBrickVersion, };