From d39344ee5df55a526f5aa11705d745d5dd0f41af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iva=CC=81n=20Zaera=20Avello=CC=81n?= Date: Wed, 14 Mar 2018 10:17:42 +0100 Subject: [PATCH] Use reporting system from liferay-npm-bundler Fixes #83 --- .../src/__tests__/config.test.js | 6 +- packages/liferay-npm-bundler/src/config.js | 28 +++- packages/liferay-npm-bundler/src/index.js | 139 +++++++++++++----- 3 files changed, 130 insertions(+), 43 deletions(-) diff --git a/packages/liferay-npm-bundler/src/__tests__/config.test.js b/packages/liferay-npm-bundler/src/__tests__/config.test.js index a0e4061a..e81e9d46 100644 --- a/packages/liferay-npm-bundler/src/__tests__/config.test.js +++ b/packages/liferay-npm-bundler/src/__tests__/config.test.js @@ -211,9 +211,11 @@ describe('getBabelConfig()', () => { describe('getPluginVersions()', () => { it.only('analyzes default config correctly', () => { - const versions = cfg.getPluginVersions(); + const versions = cfg.getVersionsInfo(); + const myVersion = require('../../package.json').version; - expect(Object.keys(versions).length).toEqual(8); + expect(Object.keys(versions).length).toEqual(9); + expect(versions['liferay-npm-bundler']).toEqual(myVersion); expect(versions['liferay-npm-bundler-plugin-test-0']).toEqual('1.0.0'); expect(versions['liferay-npm-bundler-plugin-test-1']).toEqual('1.0.1'); expect(versions['liferay-npm-bundler-plugin-test-2']).toEqual('1.0.2'); diff --git a/packages/liferay-npm-bundler/src/config.js b/packages/liferay-npm-bundler/src/config.js index a7aa2d3d..f2b62df1 100644 --- a/packages/liferay-npm-bundler/src/config.js +++ b/packages/liferay-npm-bundler/src/config.js @@ -69,6 +69,14 @@ export function getOutputDir() { return path.normalize(dir); } +/** + * Get the path to the report file or null if no report is configured. + * @return {String} a normalized path or null + */ +export function getReportFilePath() { + return path.join('.', 'liferay-npm-bundler-report.html'); +} + /** * Get the configured file exclusions for a given package. * @param {Object} pkg the package descriptor hash containing id, name, version @@ -132,8 +140,9 @@ export function getPlugins(phase, pkg) { ); return { - run: pluginModule.default, + name: pluginName, config: pluginConfig, + run: pluginModule.default, }; }); } @@ -164,11 +173,26 @@ export function isVerbose() { return config['verbose'] || false; } +/** + * Get versions information + * @return {void} + */ +export function getVersionsInfo() { + const pkgJson = require('../package.json'); + + let info = { + 'liferay-npm-bundler': pkgJson.version, + }; + + info = Object.assign(info, getPluginVersions()); + + return info; +} /** * Get version numbers of all plugins used in the build. * @return {Object} a map of {plugin-name: version} values */ -export function getPluginVersions() { +function getPluginVersions() { let pluginVersions = {}; // Get preset plugin version diff --git a/packages/liferay-npm-bundler/src/index.js b/packages/liferay-npm-bundler/src/index.js index 11ad502c..4219426d 100644 --- a/packages/liferay-npm-bundler/src/index.js +++ b/packages/liferay-npm-bundler/src/index.js @@ -2,6 +2,7 @@ import * as babel from 'babel-core'; import fs from 'fs-extra'; import globby from 'globby'; import {getPackageTargetDir} from 'liferay-npm-build-tools-common/lib/packages'; +import PluginLogger from 'liferay-npm-build-tools-common/lib/plugin-logger'; import path from 'path'; import pretty from 'pretty-time'; import readJsonSync from 'read-json-sync'; @@ -10,6 +11,7 @@ import semver from 'semver'; import * as config from './config'; import {getPackageDependencies} from './dependencies'; import * as log from './log'; +import report from './report'; /** * Default entry point for the liferay-npm-bundler. @@ -19,11 +21,15 @@ import * as log from './log'; export default function(args) { let promises = []; + const versionsInfo = config.getVersionsInfo(); + if (args[0] === '-v' || args[0] === '--version') { - showVersions(); + console.log(JSON.stringify(versionsInfo, null, 2)); return; } + report.versionsInfo(versionsInfo); + const outputDir = path.resolve(config.getOutputDir()); // Create work directories @@ -37,12 +43,18 @@ export default function(args) { pkgs = Object.keys(pkgs).map(id => pkgs[id]); pkgs = pkgs.filter(pkg => pkg.dir != '.'); + report.dependencies(pkgs); + // Process NPM dependencies const start = process.hrtime(); log.info(`Bundling ${pkgs.length} dependencies...`); if (config.isProcessSerially()) { + report.warn( + 'Option process-serially is on: this may degrade build performance.' + ); + promises.push( iterateSerially(pkgs, pkg => bundlePackage(pkg, outputDir)) ); @@ -51,29 +63,21 @@ export default function(args) { } Promise.all(promises) - .then(() => log.info(`Bundling took ${pretty(process.hrtime(start))}`)) + .then(() => { + const hrtime = process.hrtime(start); + + log.info(`Bundling took ${pretty(hrtime)}`); + report.executionTime(hrtime); + + fs.writeFileSync(config.getReportFilePath(), report.toHtml()); + log.info(`Report written to ${config.getReportFilePath()}`); + }) .catch(function(err) { log.error(err); process.exit(1); }); } -/** - * Show versions information - * @return {void} - */ -function showVersions() { - const pkgJson = require('../package.json'); - - let info = { - 'liferay-npm-bundler': pkgJson.version, - }; - - info = Object.assign(info, config.getPluginVersions()); - - console.log(JSON.stringify(info, null, 2)); -} - /** * Copy project root package.json file to output directory. * @param {String} outputDir the output directory path @@ -86,14 +90,21 @@ function copyRootPackageJson(outputDir) { Object.keys(pkgJson[scope]).forEach(depName => { const depVersion = pkgJson[scope][depName]; - if (semver.valid(depVersion) == null) { + if (semver.validRange(depVersion) == null) { const depPkgJsonPath = path.join( depVersion.substring(5), 'package.json' ); + const depPkgJson = readJsonSync(depPkgJsonPath); pkgJson[scope][depName] = depPkgJson.version; + + report.linkedDependency( + depName, + depVersion, + depPkgJson.version + ); } }); }); @@ -121,7 +132,9 @@ function iterateSerially(values, asyncProcess) { let val = values[0]; - asyncProcess(val).then(() => { + let p = asyncProcess(val); + + p.then(() => { iterateSerially(values.slice(1), asyncProcess).then(() => { resolve(); }); @@ -146,7 +159,7 @@ function bundlePackage(pkg, outputDir) { try { if (fs.statSync(outPkgDir).isDirectory()) { log.debug(`Skipping ${pkg.id} (already bundled)`); - return; + return Promise.resolve(); } } catch (err) {} @@ -170,16 +183,26 @@ function bundlePackage(pkg, outputDir) { * @return {Promise} a Promise fulfilled when the copy has been finished */ function copyPackage(pkg, dir) { + const rawGlobs = [`${pkg.dir}/**/*`, `!${pkg.dir}/node_modules/**/*`]; + const exclusions = config.getExclusions(pkg); - const globs = [`${pkg.dir}/**/*`, `!${pkg.dir}/node_modules/**/*`].concat( + const globs = rawGlobs.concat( exclusions.map(exclusion => `!${pkg.dir}/${exclusion}`) ); return globby(globs).then(paths => { - paths = paths - .filter(path => fs.statSync(path).isFile()) - .map(path => path.substring(pkg.dir.length + 1)); + const fileFilter = path => fs.statSync(path).isFile(); + const relativePathMapper = path => path.substring(pkg.dir.length + 1); + + paths = paths.filter(fileFilter).map(relativePathMapper); + + const rawPaths = globby + .sync(rawGlobs) + .filter(fileFilter) + .map(relativePathMapper); + + report.packageCopy(pkg, rawPaths, paths, exclusions); const promises = paths.map(path => fs.copy(`${pkg.dir}/${path}`, `${dir}/${path}`) @@ -209,7 +232,11 @@ function processPackage(phase, pkg) { try { config.getPlugins(phase, pkg).forEach(plugin => { - plugin.run({pkg, config: plugin.config}, state); + let logger = new PluginLogger(); + + plugin.run({pkg, config: plugin.config, log: logger}, state); + + report.packageProcessBundlerPlugin(phase, pkg, plugin, logger); }); } catch (err) { reject(err); @@ -228,14 +255,8 @@ function processPackage(phase, pkg) { * @return {Promise} a Promise fulfilled when the process has been finished */ function runBabel(pkg) { - const babelConfig = config.getBabelConfig(pkg); - - // Intercept presets and plugins to load them from here - babelConfig.plugins = config.loadBabelPlugins( - babelConfig.presets || [], - babelConfig.plugins || [] - ); - babelConfig.presets = []; + // Make a copy of the package's Babel configuration + const babelConfig = Object.assign({}, config.getBabelConfig(pkg)); // Tune babel config babelConfig.babelrc = false; @@ -244,11 +265,25 @@ function runBabel(pkg) { babelConfig.sourceMaps = true; } + // Report a copy of the package's Babel configuration before loading plugins + report.packageProcessBabelConfig(pkg, Object.assign({}, babelConfig)); + + // Intercept presets and plugins to load them from here + babelConfig.plugins = config.loadBabelPlugins( + babelConfig.presets || [], + babelConfig.plugins || [] + ); + babelConfig.presets = []; + // Run babel through it return globby([`${pkg.dir}/**/*.js`]).then(filePaths => { const promises = filePaths.map( filePath => - new Promise((resolve, reject) => { + new Promise(resolve => { + const logger = new PluginLogger(); + + PluginLogger.set(filePath, logger); + babel.transformFile( filePath, Object.assign( @@ -258,9 +293,22 @@ function runBabel(pkg) { babelConfig ), (err, result) => { + // Generate and/or log results if (err) { - log.error(`Error processing file: ${filePath}`); - reject(err); + log.error( + `Babel failed processing`, + `${filePath.substr( + filePath.indexOf(pkg.id) + )}:`, + 'it will be copied verbatim (see report file for more info)' + ); + + logger.error('babel', err); + + report.warn( + 'Babel failed processing some .js files: check details of Babel transformations for more info.', + {unique: true} + ); } else { const fileName = path.basename(filePath); @@ -274,9 +322,22 @@ function runBabel(pkg) { `${filePath}.map`, JSON.stringify(result.map) ); - - resolve(); } + + // Report result of babel run + report.packageProcessBabelRun( + pkg, + filePath.substr( + filePath.indexOf(pkg.id) + pkg.id.length + 1 + ), + logger + ); + + // Get rid of logger + PluginLogger.delete(filePath); + + // Resolve promise + resolve(); } ); })