@netlify/build
Version:
Netlify build module
89 lines (88 loc) • 3.68 kB
JavaScript
// We group errors by `error.message`. However some `error.message` contain
// unique IDs, etc. which defeats that grouping. So we normalize those to make
// them consistent
export const normalizeGroupingMessage = function (message, type) {
const messageA = removeDependenciesLogs(message, type);
const messageB = NORMALIZE_REGEXPS.reduce(normalizeMessage, messageA);
// If this is a functions bundling error, we'll use additional normalization
// rules to group errors more aggressively.
if (type === 'functionsBundling') {
return FUNCTIONS_BUNDLING_REGEXPS.reduce(normalizeMessage, messageB);
}
return messageB;
};
// Discard debug/info installation information
const removeDependenciesLogs = function (message, type) {
if (type !== 'dependencies') {
return message;
}
return message.split('\n').filter(isErrorLine).join('\n');
};
const isErrorLine = function (line) {
return ERROR_LINES.some((errorLine) => line.startsWith(errorLine));
};
const ERROR_LINES = [
// Prefix for npm
'npm ERR!',
// Prefix for Yarn
'error',
];
const normalizeMessage = function (message, [regExp, replacement]) {
return message.replace(regExp, replacement);
};
const NORMALIZE_REGEXPS = [
// Base64 URL
[/(data:[^;]+;base64),[\w+/-=]+/g, 'dataURI'],
// Node builtins mapping - normalize it to single one so it's not dependent on Node.js version it did run on
[/(\\"[^"]+\\":\\"node:[^"]+\\",)+/g, '\\"builtins\\":\\"node:builtins\\",'],
// File paths
[/(["'`, ]|^)([^"'`, \n]*[/\\][^"'`, \n]*)(?=["'`, ]|$)/gm, '$1/file/path'],
// Semantic versions
[/\d+\.\d+\.\d+(-\d+)?/g, '1.0.0'],
[/version "[^"]+"/g, 'version "1.0.0"'],
// Cypress plugin prints the user's platform
[/^Platform: .*/gm, ''],
// URLs
[/https?:[\w.+~!$&'()*,;=:@/?#]+/g, 'https://domain.com'],
// Numbers, e.g. number of issues/problems
[/\d+/g, '0'],
// Hexadecimal strings
[/[\da-fA-F-]{6,}/g, 'hex'],
// On unknown inputs, we print the inputs
[/(does not accept any inputs but you specified: ).*/, '$1'],
[/(Unknown inputs for plugin).*/, '$1'],
[/(Plugin inputs should be one of: ).*/, '$1'],
// On required inputs, we print the inputs
[/^Plugin inputs[^]*/gm, ''],
[/(Required inputs for plugin).*/gm, '$1'],
// Netlify Functions validation check
[/(should target a directory, not a regular file):.*/, '$1'],
// zip-it-and-ship-it error when there is an `import()` but dependencies
// were not installed
[/(Cannot find module) '([^']+)'/g, "$1 'moduleName'"],
[/(A Netlify Function is using) "[^"]+"/g, '$1 "moduleName"'],
// Deploy upload errors include the filename
[/(Upload cancelled).*/g, '$1'],
[/(aborting upload of file).*/g, '$1'],
// netlify-plugin-inline-critical-css errors prints a list of file paths
[/Searched in: .*/g, ''],
// netlify-plugin-subfont prints font name in errors
[/(is not supported yet): .*/, '$1'],
// netlify-plugin-subfont prints generic information in every error that
// is highly build-specific
[/^(vers?ions|Plugin configuration|Subfont called with): {[^}]+}/gm, ''],
[/^Resolved entry points: \[[^\]]+]/gm, ''],
// netlify-plugin-minify-html parse error
[/(Parse Error):[^]*/, '$1'],
// Multiple empty lines
[/^\s*$/gm, ''],
];
const FUNCTIONS_BUNDLING_REGEXPS = [
// String literals and identifiers
[/"([^"]+)"/g, '""'],
[/'([^']+)'/g, "''"],
[/`([^`]+)`/g, '``'],
// Rust crates
[/(?:Downloaded \S+ v[\d.]+\s*)+/gm, 'Downloaded crates'],
[/(?:Compiling \S+ v[\d.]+\s*)+/gm, 'Compiled crates'],
];