UNPKG

@mjcctech/meteor-desktop

Version:

Build a Meteor's desktop client with hot code push.

251 lines (222 loc) 8.24 kB
"use strict";var module1=module;module1.export({default:()=>Desktop});var regeneratorRuntime;module1.link('regenerator-runtime/runtime',{default(v){regeneratorRuntime=v}},0);var shell;module1.link('shelljs',{default(v){shell=v}},1);var fs;module1.link('fs',{default(v){fs=v}},2);var path;module1.link('path',{default(v){path=v}},3);var Log;module1.link('./log',{default(v){Log=v}},4);// eslint-disable-next-line no-unused-vars shell.config.fatal = true; /** * Checks if the path is empty. * @param {string} searchPath * @returns {boolean} */ function isEmptySync(searchPath) { let stat; try { stat = fs.statSync(searchPath); } catch (e) { return true; } if (stat.isDirectory()) { const items = fs.readdirSync(searchPath); return !items || !items.length; } return false; } /** * Represents the .desktop directory. * @class * @property {desktopSettings} settings */ class Desktop { /** * @param {MeteorDesktop} $ - context * * @constructor */ constructor($) { this.$ = $; this.log = new Log('desktop'); this.settings = null; this.dependencies = null; } /** * Tries to read and returns settings.json contents from .desktop dir. * * @returns {desktopSettings|null} */ getSettings() { if (!this.settings) { try { this.settings = JSON.parse( fs.readFileSync(this.$.env.paths.desktop.settings, 'UTF-8') ); } catch (e) { this.log.error('error while trying to read \'.desktop/settings.json\': ', e); process.exit(1); } } return this.settings; } /** * Returns a version hash representing current .desktop contents. * @returns {string} */ async getHashVersion() { this.log.info('calculating hash version from .desktop contents'); const version = await this.$.utils.readFilesAndComputeHash(this.$.env.paths.desktop.root); this.log.verbose(`calculated .desktop hash version is ${version.hash}`); return version.hash; } /** * Tries to read a module.json file from a module at provided path. * * @param {string} modulePath - path to the module dir * @returns {Object} */ getModuleConfig(modulePath) { let moduleConfig = {}; try { moduleConfig = JSON.parse( fs.readFileSync(path.join(modulePath, 'module.json'), 'UTF-8') ); } catch (e) { this.log.error( `error while trying to read 'module.json' from '${modulePath}' module: `, e ); process.exit(1); } if (!('name' in moduleConfig)) { this.log.error(`no 'name' field defined in 'module.json' in '${modulePath}' module.`); process.exit(1); } return moduleConfig; } /** * Scans all modules for module.json and gathers this configuration altogether. * * @returns {[]} */ gatherModuleConfigs() { const configs = []; if (!isEmptySync(this.$.env.paths.desktop.modules)) { shell.ls('-d', path.join(this.$.env.paths.desktop.modules, '*')).forEach( (module) => { if (fs.lstatSync(module).isDirectory()) { const moduleConfig = this.getModuleConfig(module); moduleConfig.dirName = path.parse(module).name; configs.push(moduleConfig); } } ); } return configs; } /** * Summarizes all dependencies defined in .desktop. * * @params {Object} settings - settings.json * @params {boolean} checkModules - whether to gather modules dependencies * @params {boolean} refresh - recompute * @returns {{fromSettings: {}, plugins: {}, modules: {}}} */ getDependencies(settings = null, checkModules = true, refresh = false) { if (!refresh && this.dependencies) { return this.dependencies; } const dependencies = { fromSettings: {}, plugins: {}, modules: {} }; /** @type {desktopSettings} * */ const settingsJson = settings || this.getSettings(); // Settings can have a 'dependencies' field. if ('dependencies' in settingsJson) { dependencies.fromSettings = settingsJson.dependencies; } // Plugins are also a npm packages. if ('plugins' in settingsJson) { dependencies.plugins = Object.keys(settingsJson.plugins).reduce((plugins, plugin) => { /* eslint-disable no-param-reassign */ if (typeof settingsJson.plugins[plugin] === 'object') { plugins[plugin] = settingsJson.plugins[plugin].version; } else { plugins[plugin] = settingsJson.plugins[plugin]; } return plugins; }, {}); } // Each module can have its own dependencies defined. const moduleDependencies = {}; if (checkModules) { const configs = this.gatherModuleConfigs(); configs.forEach( (moduleConfig) => { if (!('dependencies' in moduleConfig)) { moduleConfig.dependencies = {}; } if (moduleConfig.name in moduleDependencies) { this.log.error(`duplicate name '${moduleConfig.name}' in 'module.json' in ` + `'${moduleConfig.dirName}' - another module already registered the same name.`); process.exit(1); } moduleDependencies[moduleConfig.name] = moduleConfig.dependencies; } ); } dependencies.modules = moduleDependencies; this.dependencies = dependencies; return dependencies; } /** * Copies the .desktop scaffold into the meteor app dir. * Adds entry to .meteor/.gitignore. */ scaffold() { this.log.info('creating .desktop scaffold in your project'); if (this.$.utils.exists(this.$.env.paths.desktop.root)) { this.log.warn('.desktop already exists - delete it if you want a new one to be ' + 'created'); return; } shell.cp('-r', this.$.env.paths.scaffold, this.$.env.paths.desktop.root); shell.mkdir(this.$.env.paths.desktop.import); this.log.info('.desktop directory prepared'); } /** * Verifies if all mandatory files are present in the .desktop. * * @returns {boolean} */ check() { this.log.verbose('checking .desktop existence'); return !!(this.$.utils.exists(this.$.env.paths.desktop.root) && this.$.utils.exists(this.$.env.paths.desktop.settings) && this.$.utils.exists(this.$.env.paths.desktop.desktop)); } } /** * @typedef {Object} desktopSettings * @property {string} name * @property {string} projectName * @property {boolean} devTools * @property {boolean} devtron * @property {boolean} desktopHCP * @property {Object} squirrel * @property {string} squirrel.autoUpdateFeedUrl * @property {Object} squirrel.autoUpdateFeedHeaders * @property {Object} squirrel.autoUpdateCheckOnStart * @property {Object} desktopHCPSettings * @property {boolean} desktopHCPSettings.ignoreCompatibilityVersion * @property {boolean} desktopHCPSettings.blockAppUpdateOnDesktopIncompatibility * @property {number} webAppStartupTimeout * @property {Array} linkPackages * @property {Array} exposedModules * @property {Object} window * @property {Object} windowDev * @property {Object} packageJsonFields * @property {Object} builderOptions * @property {Object} builderCliOptions * @property {Object} packagerOptions * @property {Object} plugins * @property {Object} dependencies * @property {boolean} uglify * @property {string} version * */