UNPKG

@ima/cli

Version:

IMA.js CLI tool to build, develop and work with IMA.js applications.

196 lines (195 loc) 7.56 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatWebpackErrors = formatWebpackErrors; exports.formatWebpackWarnings = formatWebpackWarnings; exports.formatStats = formatStats; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const cliUtils_1 = require("@ima/dev-utils/cliUtils"); const logger_1 = require("@ima/dev-utils/logger"); const chalk_1 = __importDefault(require("chalk")); const pretty_bytes_1 = __importDefault(require("pretty-bytes")); const pretty_ms_1 = __importDefault(require("pretty-ms")); const warningsCache = new Set(); /** * Prints formatted webpack errors (stripped from duplicates) into console. */ async function formatWebpackErrors(stats, args) { if (!stats?.hasErrors()) { return; } // Raw verbose if (args.verbose) { return logger_1.logger.write(stats.toString({ all: false, errors: true })); } const { errors } = stats.toJson({ all: false, errors: true }); if (!Array.isArray(errors)) { return; } const uniqueErrorTracker = []; for (const error of errors) { // Format error try { const parsedErrorData = await (0, cliUtils_1.parseError)(error, 'compile'); const formattedError = await (0, cliUtils_1.formatError)(parsedErrorData, args.rootDir, uniqueErrorTracker); // Print unique error formattedError && logger_1.logger.error(formattedError); } catch { // Fallback to original error messsage logger_1.logger.error(await (0, cliUtils_1.formatError)({ name: error?.name, message: error?.message, fileUri: error?.file, stack: error?.stack, }, args.rootDir, uniqueErrorTracker)); } } } /** * Prints cleaned up webpack warnings. */ function formatWebpackWarnings(stats, args) { if (args.ignoreWarnings) { return; } if (!stats?.hasWarnings()) { return; } const { warnings } = stats.toJson({ all: false, warnings: true }); const newWarnings = []; // Cache unique warnings if (Array.isArray(warnings)) { for (const warning of warnings) { // Ignore source-map-loader warnings if (warning.message.includes('Failed to parse source map')) { continue; } if (!warningsCache.has(warning.message)) { warningsCache.add(warning.message); newWarnings.push(warning); } } } if (newWarnings.length === 0) { return; } // Minimal (default) verbose newWarnings?.forEach(warning => { logger_1.logger.warn(`at ${chalk_1.default.blueBright.bold.underline(warning.moduleName)}`); const lines = warning.message.split('\n'); logger_1.logger.write(chalk_1.default.underline(lines.shift())); logger_1.logger.write(lines.join('\n')); }); } /** * Extracts asset paths from it's name (containing basePath) * and output directory. */ function extractAssetPaths(name, outDir) { const fullPath = path_1.default.join(outDir, name); const lastSlashIndex = fullPath.lastIndexOf('/'); const fileName = fullPath.substring(lastSlashIndex + 1); const basePath = fullPath .substring(0, lastSlashIndex + 1) .replace(outDir, ''); return { fileName, fullPath, basePath, }; } /** * Print formatted info about given asset */ function printAssetInfo(asset, outDir, isLastItem = false) { let result = ''; if (!asset || !asset.name) { return; } const assetPaths = extractAssetPaths(asset.name, outDir); // Print output result += chalk_1.default.gray(isLastItem ? ' └ ' : ' ├ '); result += chalk_1.default.gray(assetPaths.basePath); result += chalk_1.default.bold.cyan(assetPaths.fileName); result += ` ${chalk_1.default.green.bold((0, pretty_bytes_1.default)(asset.size))}`; // Prints brotli and gzip sizes Object.values(asset?.info?.related ?? {}) .map(assetName => extractAssetPaths(assetName?.toString() ?? '', outDir)) .filter(({ fullPath }) => fs_1.default.existsSync(fullPath)) .forEach(({ fileName, fullPath }) => { result += '\n'; result += chalk_1.default.gray(isLastItem ? ' ' : ' ǀ '); result += fileName; result += chalk_1.default.yellow(` ${(0, pretty_bytes_1.default)(fs_1.default.statSync(path_1.default.join(fullPath)).size)}`); }); logger_1.logger.write(result); } /** * Handles stats logging during webpack build and watch tasks. * * @param {MultiStats|undefined} stats Webpack stats object. * @param {ImaCliArgs} args Cli and build args. * @returns {void} */ function formatStats(stats, args) { if (!stats) { return logger_1.logger.error('Unknown error, stats are empty'); } // Print raw webpack log if (args?.verbose) { return logger_1.logger.write(stats.toString({ warnings: !args.ignoreWarnings, colors: true, })); } const jsonStats = stats.toJson({ all: false, assets: true, timings: true, version: true, outputPath: true, chunkGroups: true, }); if (!Array.isArray(jsonStats.children) || jsonStats.children?.length === 0) { return; } let totalAssetCount = 0; let chunkAssetsCount = 0; const outDir = jsonStats.children[0].outputPath ?? ''; logger_1.logger.info(`Compilation was ${chalk_1.default.green('successful')} using webpack version: ${chalk_1.default.magenta(jsonStats.children[0].version)}`); args.command === 'dev' && logger_1.logger.info(`Client assets are served from ${args.writeToDisk ? chalk_1.default.blueBright('disk') : chalk_1.default.yellowBright('memory')}`); logger_1.logger.info(`Output folder ${chalk_1.default.magenta(outDir)}, produced:\n`); // Print info about emitted assets jsonStats.children?.forEach(child => { logger_1.logger.write(`${chalk_1.default.underline.bold(child.name)} ${chalk_1.default.gray(`[${(0, pretty_ms_1.default)(child.time ?? 0)}]`)}`); // Count total number of generated assets totalAssetCount += child?.assets?.reduce((acc, cur) => { acc += cur?.filteredRelated ?? 0 + 1; return acc; }, 0) ?? 0; if (!(child.name && child.namedChunkGroups?.[child.name])) { return; } // Child assets const filteredAssets = child.namedChunkGroups?.[child.name]?.assets?.map(({ name }) => child?.assets?.find(childAsset => childAsset.name === name)) ?? []; // Print chunk assets filteredAssets?.forEach((asset, index) => { // Count also related (plugin generated) files chunkAssetsCount += asset?.filteredRelated ?? 0; printAssetInfo(asset, outDir, index === filteredAssets?.length - 1); }); logger_1.logger.write(''); }); // Total number of additional assets const additionalAssetsCount = totalAssetCount - chunkAssetsCount; // Print more information for build task logger_1.logger.write(`The compilation generated ${chalk_1.default.green.bold(additionalAssetsCount)} additional assets.\n`); }