UNPKG

lmd

Version:

LMD: Lazy Module Declaration

591 lines (476 loc) 17.6 kB
require('colors'); var path = require('path'), fs = require('fs'), init = require(__dirname + '/init.js'), create = require(__dirname + '/create.js'), list = require(__dirname + '/list.js'), common = require(__dirname + '/../../lib/lmd_common.js'), resolveName = common.getModuleFileByShortName, assembleLmdConfig = common.assembleLmdConfig, flagToOptionNameMap = common.LMD_PLUGINS; var options = { 'sort': { 'describe': 'Sorts modules by that row', 'alias': 'order-by', 'default': 'undefined' }, 'deep': { 'describe': 'Prints deep module analytics', 'boolean': true, 'default': true } }; var optimist = require('optimist'); var YES = '✔'.green, NO = '✘'.yellow, NO_YES = [NO, YES]; function printHelp(cli, errorMessage) { var help = [ 'Usage:'.bold.white.underline, '', ' lmd info ' + '<build_name>'.blue + '[' + '+<mixin>...+<mixin>'.cyan + ']' + ' [' + '<flags>'.green + ']' + ' [' + '<options>'.yellow + ']', '', 'Example:'.bold.white.underline, '', ' lmd info ' + 'development'.blue, ' lmd info ' + 'development'.blue + ' --sort=coverage'.yellow, ' lmd info ' + 'development'.blue + '+corp'.cyan, ' lmd info ' + 'development'.blue + '+en+corp'.cyan, ' lmd info ' + 'development'.blue + '+sourcemap'.cyan, ' lmd info ' + 'development'.blue + '+sourcemap'.cyan + ' --no-pack --async --js --css'.green, ' lmd info ' + 'development'.blue + ' --modules.name=path.js'.green, '' ]; var options = optimist.help().split('\n'); options.unshift(options[0].bold.white.underline); options[1] = ''; help = help.concat(options); cli.help(help, errorMessage); } function printValue(value) { switch (typeof value) { case "boolean": case "undefined": return NO_YES[+!!value]; case "string": return value.green; case "object": return JSON.stringify(value, null, ' ').split('\n') .map(function (line, index) { return '\n' + 'info'.green + ': ' + line; }).join(''); case "function": return 'Function'.blue; } return value; } function printModules(cli, config, deepModulesInfo, conflicts, sortColumnName) { var modulesCount = 0; var bundles = common.groupModulesByBundles(config); common.iterateModulesInfo(bundles, function () { modulesCount++; }); if (!modulesCount) { return; } cli.ok(('Modules (' + modulesCount + ')').white.bold.underline); cli.ok(''); var headers = ['name', 'depends', 'type', 'lazy', 'greedy', 'coverage', 'sandbox', 'bundle']; var columnLengths = headers.map(function (item) { return item.length; }); var moduleRows = []; common.iterateModulesInfo(bundles, function (module, moduleName, bundleName) { var moduleExtra = deepModulesInfo[bundleName][moduleName]; if (moduleName.length > columnLengths[0]) { columnLengths[0] = moduleName.length; } if (module.depends && module.depends.length > columnLengths[1]) { columnLengths[1] = module.depends.length; } if (moduleExtra.type && moduleExtra.type.length > columnLengths[2]) { columnLengths[2] = moduleExtra.type.length; } return moduleRows.push([ moduleName, module.depends ? module.depends : false, moduleExtra.type, !!module.is_lazy, !!module.is_greedy, !!module.is_coverage, !!module.is_sandbox, bundleName === common.ROOT_BUNDLE_ID ? false : bundleName ]); }); var sortColumnIndex = headers.indexOf(sortColumnName); if (sortColumnIndex != -1) { moduleRows = moduleRows.sort(function (a, b) { if (a[sortColumnIndex] > b[sortColumnIndex]) { return 1; } if (a[sortColumnIndex] < b[sortColumnIndex]) { return -1; } return 0; }); } moduleRows.unshift(headers); moduleRows.forEach(function (row, rowIndex) { var rowString = '', isError = false; row.forEach(function (item, index) { var length = item.length || 1, maxColumnLength = columnLengths[index] + 2; //item = typeof item === "boolean" ? NO_YES[+item] : item; if (!rowIndex) { item = item.white.bold.underline; } if (!index && rowIndex) { if (item in conflicts) { item = item.yellow; } else { item = item.cyan; } } // type=not-found if (index === 2 && item === "not-exists") { item = item.red; isError = true; } else if (index) { item = printValue(item); } rowString += item + (maxColumnLength > length ? new Array(maxColumnLength - length).join(' ') : ' '); }); if (isError) { cli.error(rowString); } else { cli.ok(rowString); } }); cli.ok(''); } function printStyles(cli, config) { var styles = config.styles || []; if (!styles.length) { return; } cli.ok(('Styles (' + styles.length + ')').white.bold.underline); cli.ok(''); styles.forEach(function (style) { if (!style.is_exists) { cli.error(style.path.red + ' (not exists)'); } else { cli.ok(style.path.green); } }); cli.ok(''); } function printFlags(cli, config, availableFlags) { var longestName = availableFlags.reduce(function (max, current) { if (typeof config[current] === "undefined") { return max; } return current.length > max ? current.length : max; }, 0); if (!longestName) { return; } longestName += 3; cli.ok('Flags'.white.bold.underline); cli.ok(''); availableFlags.forEach(function (flag) { var value = config[flag]; if (typeof value === "undefined") { return; } cli.ok( flag.cyan + (longestName > flag.length ? new Array(longestName - flag.length).join(' ') : ' ') + printValue(value) + (config.plugins_depends[flag] ? ' (depend of ' + config.plugins_depends[flag].join(', ').cyan + ')' : '') ); }); cli.ok(''); } function printModulePathsAndDepends(cli, config, deepModulesInfo, conflicts, isDeepAnalytics) { var modulesCount = 0, longestName = 0, modulesNames = []; var bundles = common.groupModulesByBundles(config); common.iterateModulesInfo(bundles, function (module, name) { modulesCount++; if (longestName < name.length) { longestName = name.length; } modulesNames.push(name); }); var globalsNames = common.getGlobals(config); if (!modulesCount) { return; } cli.ok('Module Paths, Depends and Features'.white.bold.underline); cli.ok(''); common.iterateModulesInfo(bundles, function (module, moduleName, bundleName) { var moduleShortPadding = new Array(longestName - moduleName.length + 2).join(' '), modulePath = [].concat(module.path); var moduleLongPadding = new Array(moduleName.length + 5).join(' ') + moduleShortPadding; if (module.is_exists) { modulePath.forEach(function (modulePath, index) { var moduleInfo; if (moduleName in conflicts) { modulePath = modulePath.yellow; } else { modulePath = modulePath.green; } if (!index) { moduleInfo = moduleName.cyan + moduleShortPadding + ' <- ' + modulePath; } else { moduleInfo = moduleLongPadding + modulePath; } if (moduleName in conflicts) { cli.ok(moduleInfo + ' (name conflict)'); } else { cli.ok(moduleInfo); } }); } else { modulePath.forEach(function (modulePath, index) { var moduleInfo, // Module may consists of many parts, check each of them isModulePartExists = fs.existsSync(modulePath), color = isModulePartExists ? 'green' : 'red'; if (!index) { moduleInfo = moduleName.cyan + moduleShortPadding + ' <- ' + modulePath[color]; } else { moduleInfo = moduleLongPadding + modulePath[color]; } cli.error(moduleInfo + (isModulePartExists ? '' : ' (not exists)')); }); } if (!isDeepAnalytics) { return; } var depends = deepModulesInfo[bundleName][moduleName].depends; if (depends.length) { depends.forEach(function (name) { var moduleType = common.discoverModuleType(name, modulesNames, globalsNames); switch (moduleType) { case 'in-package': cli.ok(' +-' + name.toString().cyan); break; case 'global': cli.ok(' +-' + name.toString().cyan + ' (' + moduleType + ')'); break; default: cli.ok(' +-' + name.toString().yellow + ' (' + moduleType + ')'); } }); } var features = Object.keys(deepModulesInfo[bundleName][moduleName].features); if (features.length) { cli.ok(' ' + 'Uses'.green + ': ' + features.join(', ')); cli.ok(''); } }); cli.ok(''); } function printUserPlugins(cli, config) { var plugins = config.plugins || {}, pluginsNames = Object.keys(plugins); if (!pluginsNames.length) { return; } cli.ok('User plugins'.white.bold.underline); cli.ok(''); var longestName = pluginsNames.reduce(function (max, name) { return max < name.length ? name.length : max; }, 0); pluginsNames.forEach(function (name) { var message = name.cyan + new Array(longestName - name.length + 2).join(' ') + ' <- '; if (plugins[name].isOk) { cli.ok(message + plugins[name].path.green); } else { cli.warn(message + plugins[name].path.red); } }); cli.ok(''); } function getCompletionOptions(actionOptions) { var plugins = Object.keys(common.LMD_PLUGINS), flags = common.SOURCE_TWEAK_FLAGS, fields = common.MASTER_FIELDS; return Object.keys(actionOptions) // add options or flags .reduce(function (all, current) { all.push(current); if (all.alias) { all.push(all.alias); } return all; }, []) // +plugins .concat(plugins) // +no-plugins .concat(plugins.map(function (name) { return 'no-' + name; })) // +fields .concat(fields) // +no-flags (+flags are in master fields) .concat(flags.map(function (flag) { return 'no-' + flag; })) // add prefixes .map(function (name) { return '--' + name; }); } function getBuilds(cwd) { return list.builds(cwd).map(function (file) { return file.replace(common.RE_LMD_FILE, ''); }); } module.exports = function (cli, argv, cwd) { for (var optionName in options) { optimist.options(optionName, options[optionName]); } argv = optimist.parse(argv); var buildName, status, mixinBuilds = argv._[1], sortOrder = argv.sort, isDeepAnalytics = argv.deep, lmdDir = path.join(cwd, '.lmd'); if (mixinBuilds) { mixinBuilds = mixinBuilds.split('+'); buildName = mixinBuilds.shift(); } // Clear CLI options delete argv.sort; delete argv.deep; delete argv['order-by']; delete argv._; delete argv.$0; if (!init.check(cli, cwd)) { return; } if (!buildName) { printHelp(cli); return; } status = create.checkFile(cwd, buildName); if (status !== true) { printHelp(cli, status === false ? 'build `' + buildName + '` is not exists' : status); return; } // Check mixins if (mixinBuilds.length) { var isCanContinue = mixinBuilds.every(function (buildName) { status = create.checkFile(cwd, buildName); if (status !== true) { printHelp(cli, status === false ? 'mixin build `' + buildName + '` is not exists' : status); return false; } return true; }); if (!isCanContinue) { return; } } mixinBuilds = mixinBuilds.map(function (mixinName) { return resolveName(lmdDir, mixinName); }); if (mixinBuilds.length) { argv.mixins = mixinBuilds; } var buildFile = resolveName(lmdDir, buildName), lmdFile = path.join(lmdDir, buildFile); var rawConfig = common.readConfig(lmdFile), flags = Object.keys(flagToOptionNameMap), extraFlags = common.SOURCE_TWEAK_FLAGS, config = assembleLmdConfig(lmdFile, flags, argv), root = path.resolve(path.join(cwd, '.lmd'), config.root), output = config.output ? path.resolve(root, config.output) : 'STDOUT'.yellow, styles_output = config.styles_output ? path.resolve(root, config.styles_output) : '/dev/null'.yellow, sourcemap = config.sourcemap ? path.resolve(root, config.sourcemap) : false, www = config.www_root ? path.resolve(path.join(cwd, '.lmd'), config.www_root) : false, versionString = config.version ? ' - version ' + config.version.toString().cyan : ''; cli.ok(''); cli.ok('LMD Package `' + buildName.green + '` (' + path.join('.lmd', buildFile).green + ')' + versionString); cli.ok(''); if (rawConfig.extends) { cli.ok('Extends LMD Package `' + (rawConfig.extends + '').green + '`'); cli.ok(''); } if (config.mixins) { cli.ok('Mixins LMD Package ' + config.mixins.map(function (mixin) { return mixin.green; }).join(', ')); cli.ok(''); } if (config.name || config.description) { config.name && cli.ok(config.name.toString().white.bold); if (config.description) { // Multiline description var descriptionLines = config.description.toString().split('\n'); descriptionLines.forEach(function (line) { cli.ok(line); }); } cli.ok(''); } var deepModulesInfo = common.collectModulesInfo(config), conflicts = common.getSuspiciousNames(config, deepModulesInfo).conflicts; printModules(cli, config, deepModulesInfo, conflicts, sortOrder); printModulePathsAndDepends(cli, config, deepModulesInfo, conflicts, isDeepAnalytics); printStyles(cli, config); printUserPlugins(cli, config); printFlags(cli, config, flags.concat(extraFlags)); cli.ok('Paths'.white.bold.underline); cli.ok(''); cli.ok('root'.cyan + ' ' + printValue(root)); cli.ok('output'.cyan + ' ' + printValue(output)); cli.ok('styles_output'.cyan + ' ' + printValue(styles_output)); cli.ok('www_root'.cyan + ' ' + printValue(www)); if (sourcemap) { cli.ok(''); cli.ok('Source Map'.white.bold.underline); cli.ok(''); cli.ok('sourcemap'.cyan + ' ' + printValue(sourcemap)); cli.ok('sourcemap_www'.cyan + ' ' + printValue(config.sourcemap_www || '/')); cli.ok('sourcemap_inline'.cyan + ' ' + printValue(config.sourcemap_inline)); cli.ok('sourcemap_url'.cyan + ' ' + printValue(config.sourcemap_url || '/' + sourcemap.replace(www, ''))); } var errors = config.errors; // pipe warnings common.iterateModulesInfo(deepModulesInfo, function (info) { errors.push.apply(errors, info.warns) }); errors = errors.concat(common.collectFlagsWarnings(config, deepModulesInfo)); if (errors && errors.length) { cli.warn(''); cli.warn('Warnings'.red.bold.underline); cli.warn(''); errors.forEach(function (error) { cli.warn(error); }); } common.collectFlagsNotifications(config).forEach(function (notification) { cli.ok(notification); }); cli.ok(''); }; module.exports.getCompletionOptions = getCompletionOptions; module.exports.getBuilds = getBuilds; module.exports.completion = function (cli, argv, cwd, completionOptions) { // module name completion if (completionOptions.index === 1) { var builds = getBuilds(cwd); return cli.log(builds.join('\n')); } // <flags> & <options> if (completionOptions.index > 1) { var flagsOptions = getCompletionOptions(options); return cli.log(flagsOptions.join('\n')); } };