@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
200 lines (198 loc) • 9.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorUpdater = void 0;
const tslib_1 = require("tslib");
const child_process_1 = require("child_process");
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
const common_1 = require("../common");
const updater_lookup_1 = require("./error-updaters/updater-lookup");
const logger_1 = require("../angular15/utils/logger");
class ErrorUpdater {
/**
* Executes 'ng lint' and attempts to fix returned errors.
* @param {boolean} audit Flag indicating if upgrade is running it audit mode
* @param {string[]} updateSource Array used to emit logs to file
* @returns {Promise<number>} Count of unresolved errors.
*/
async resolveLintErrors(audit, updateSource) {
const errors = await this.parseLintErrors(audit);
const unresolvedCount = await this.fixErrors(audit, errors, updateSource);
return new Promise((resolve) => resolve(unresolvedCount));
}
/**
* Executes 'ng build' and attempts to fix returned errors.
* @param {boolean} audit Flag indicating if upgrade is running it audit mode
* @param {string[]} updateSource Array used to emit logs to file
* @returns {Promise<number>} Count of unresolved errors.
*/
async resolveBuildErrors(audit, updateSource) {
// If running in audit mode, we don't want to build
if (audit) {
return new Promise(resolve => resolve(0));
}
const errors = await this.parseBuildErrors();
const unresolvedCount = await this.fixErrors(false, errors, updateSource);
logger_1.Logger.log('INFO - unresolvedCount' + unresolvedCount);
return new Promise((resolve) => resolve(unresolvedCount));
}
parseLintErrors(audit) {
// If audit is true, run without --fix flag
const cmd = audit ? 'ng lint --project module-app --format json' : 'ng lint --project module-app --fix --format json';
console.log('Linting, please wait...');
return new Promise((resolve) => {
(0, child_process_1.exec)(cmd, (_, stdout) => {
const output = JSON.parse(stdout);
const results = [];
for (const error of output) {
if (error.ruleSeverity === 'error') {
results.push({
filePath: error.name,
type: error.ruleName,
message: error.failure,
position: { line: error.startPosition.line, character: error.startPosition.character },
resolved: common_1.ResolveState.Unresolved
});
}
}
resolve(results);
});
});
}
parseBuildErrors() {
console.log('Building, please wait...');
return new Promise((resolve) => (0, child_process_1.exec)('ng build', (_error, _stdout, stderr) => {
resolve(this.parseBuildErrorsCore(stderr));
}));
}
async fixErrors(audit, errors, updateSource, angularVersion) {
if (!errors || !errors.length) {
return new Promise(resolve => resolve(0));
}
let unresolvedCount = errors.length;
for (const error of errors) {
let message = `File path: ${error.filePath}`;
console.log(message);
updateSource.push(message + '\n');
let fileData = common_1.Common.readFileData(error.filePath);
if (!fileData) {
message = `Couldn't retrieve file data for path ${error.filePath}. Please verify this path is valid.`;
console.log(message);
updateSource.push(message + '\n');
continue;
}
fileData = await this.fixError(audit, fileData, error, updateSource, angularVersion);
if (error.resolved === common_1.ResolveState.Resolved) {
unresolvedCount--;
}
if (fileData) {
fs_extra_1.default.writeFileSync(error.filePath, fileData);
}
console.log('');
updateSource.push('\n');
}
return new Promise(resolve => resolve(unresolvedCount));
}
async fixError(audit, fileData, error, updateSource, augularVerion) {
let message = `\tType: ${error.type}`;
console.log(message);
updateSource.push(message + '\n');
message = `\tLine: ${error?.position?.line}`;
console.log(message);
updateSource.push(message + '\n');
message = `\tChar: ${error?.position?.character}`;
console.log(message);
updateSource.push(message + '\n');
message = `\tMessage: ${error.message}`;
console.log(message);
updateSource.push(message + '\n');
if (audit) {
return fileData;
}
const updaterLookup = updater_lookup_1.UpdaterLookup.initialize(augularVerion);
const updater = updaterLookup[error.type];
logger_1.Logger.log(`error.type = ${error.type}`);
logger_1.Logger.log(updater ? `Found updater for ${error.type}` : `No updater found for ${error.type}`);
const result = updater != null ? await updater.update(fileData, error) : fileData;
message = `\tResolved: ${error.resolved}\n`;
console.log(message);
updateSource.push(message + '\n');
return new Promise(resolve => resolve(result));
}
parseBuildErrorsCore(log) {
const captureAll = /[\s\S]+?(?=(Error|Warning):)/g; // Capture array of build error/warning output by file
const captureFilePath = /(?<=Error: )(.+)(?=:\d+:\d+)/g; // Capture file path of individual error
const captureErrorPosition = /(?<=Error: .+)(\d+:\d+)(?= - error)/g; // Capture file position of individual error
const captureErrorCode = /(?<=Error:.+- error )(TS\d+)/g; // Capture error code of individual error
const captureErrorMessage = /(?<=TS\d+: ).+/g; // Capture error message of individual error
log = log + '\n\n\nWarning:';
const buildOutputByCode = log.match(captureAll);
const results = [];
if (!buildOutputByCode) {
return results;
}
for (const file of buildOutputByCode) {
const filePath = file.match(captureFilePath);
// If no file path found, this match doesn't contain errors
if (!filePath || filePath.length === 0) {
continue;
}
const errorPositionString = file.match(captureErrorPosition);
// If there isn't a position found this isn't a parsable error, skip to next file
if (!errorPositionString || errorPositionString.length === 0) {
continue;
}
const splitValues = errorPositionString[0].split(':');
const errorPosition = { line: parseInt(splitValues[0], null), character: parseInt(splitValues[1], null) };
const errorCode = file.match(captureErrorCode);
// Couldn't get error code, skip to next file
if (!errorCode || errorCode.length === 0) {
continue;
}
const errorMessage = file.match(captureErrorMessage);
results.push({
filePath: filePath[0],
type: errorCode[0],
message: errorMessage[0],
position: errorPosition,
resolved: common_1.ResolveState.Unresolved
});
}
return results;
}
parseBuildWarningsCore(log) {
// Capture array of build error/warning output by file
const captureAll = /[\s\S]+?(?=(Error|Warning):)/g;
// Capture file path of individual error
const captureFilePath = /([^\s\r\n].*\.css)\s*(?=:)/g;
log = log + '\n\n\nWarning:';
const buildOutputByCode = log.match(captureAll);
const results = [];
if (!buildOutputByCode) {
return results;
}
for (const file of buildOutputByCode) {
const filePath = file.match(captureFilePath);
// If no file path found, this match doesn't contain errors
if (!filePath || filePath.length === 0) {
continue;
}
let errorCode;
if (file.includes('css-syntax-error')) {
errorCode = ['css-syntax-error'];
}
// Couldn't get error code, skip to next file
if (!errorCode || errorCode.length === 0) {
continue;
}
results.push({
filePath: filePath[0],
type: errorCode[0],
message: file,
resolved: common_1.ResolveState.Unresolved
});
}
return results;
}
}
exports.ErrorUpdater = ErrorUpdater;
//# sourceMappingURL=error-updater.js.map