@applicaster/zapplicaster-cli
Version:
CLI Tool for the zapp app and Quick Brick project
254 lines (201 loc) • 6.89 kB
JavaScript
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 {
logger.log("Cannot patch packages, can't find the patch_rn.js file");
}
}
/**
* {@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.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,
};