devebot
Version:
Nodejs Microservice Framework
322 lines (317 loc) • 11.8 kB
JavaScript
;
const lodash = require("lodash");
const path = require("path");
const Chalk = require("../utils/chalk");
const chores = require("../utils/chores");
const constx = require("../utils/constx");
const LoggingWrapper = require("./logging-wrapper");
const blockRef = chores.getBlockRef(__filename);
const FRAMEWORK_PACKAGE_NAME = constx.FRAMEWORK.PACKAGE_NAME;
const FRAMEWORK_BRIDGE_LABEL = "bridge";
const FRAMEWORK_PLUGIN_LABEL = "plugin";
function IssueInspector(params = {}) {
const loggingWrapper = new LoggingWrapper(blockRef);
const L = loggingWrapper.getLogger();
const T = loggingWrapper.getTracer();
L && L.has("silly") && L.log("silly", T && T.toMessage({
tags: [blockRef, "constructor-begin"],
text: " + constructor start ..."
}));
const opStates = [];
this.init = function () {
return this.reset();
};
this.collect = function (info) {
if (info instanceof Array) {
Array.prototype.push.apply(opStates, info);
} else {
if (info && typeof info === "object") {
opStates.push(info);
}
}
return this;
};
this.examine = function (options = {}) {
const summary = lodash.reduce(opStates, function (store, item) {
if (item.hasError) {
store.numberOfErrors += 1;
store.failedServices.push(item);
}
return store;
}, {
numberOfErrors: 0,
failedServices: []
});
L && L.has("silly") && L.log("silly", T && T.add({
invoker: options.invoker,
totalOfErrors: summary.numberOfErrors,
errors: summary.failedServices
}).toMessage({
tags: [blockRef, "examine", options.footmark],
text: " - Total of errors: ${totalOfErrors}"
}));
return summary;
};
this.barrier = function (options = {}) {
const summary = this.examine(options);
if (summary.numberOfErrors > 0) {
const silent = _isSilentForced("issue-inspector", options);
if (!silent) {
_consoleError(chalk.errorHeader("[x] There are %s error(s) occurred during load:"), summary.numberOfErrors);
lodash.forEach(summary.failedServices, function (fsv) {
if (fsv.stage === "bootstrap") {
switch (fsv.type) {
case "appbox":
case "application":
case FRAMEWORK_PACKAGE_NAME:
{
_consoleError(chalk.errorMessage("--> [%s:%s] lauching bootstrap has failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case FRAMEWORK_PLUGIN_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] loading plugin is failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case FRAMEWORK_BRIDGE_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] loading bridge is failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
}
}
if (fsv.stage === "package-version") {
_consoleError(chalk.errorMessage("--> [%s:%s] cannot read the version, package.json not found or does not contain 'version'."), fsv.type, fsv.name);
return;
}
if (fsv.stage === "manifest") {
switch (fsv.type) {
case "appbox":
case "application":
case FRAMEWORK_PACKAGE_NAME:
{
_consoleError(chalk.errorMessage("--> [%s:%s] loading manifest has failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case FRAMEWORK_PLUGIN_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] loading plugin's manifest has failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case FRAMEWORK_BRIDGE_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] loading bridge's manifest has failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
}
}
if (fsv.stage === "naming") {
switch (fsv.type) {
case FRAMEWORK_PLUGIN_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] resolving plugin-code is failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case FRAMEWORK_BRIDGE_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] resolving bridge-code is failed, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
}
}
if (fsv.stage === "config/upgrade") {
switch (fsv.type) {
default:
{
_consoleError(chalk.errorMessage("--> [%s:%s] migrating configure has been failed:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
}
}
if (fsv.stage === "config/schema") {
switch (fsv.type) {
case "application":
case FRAMEWORK_PACKAGE_NAME:
case FRAMEWORK_PLUGIN_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] plugin's configure is invalid, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case FRAMEWORK_BRIDGE_LABEL:
{
_consoleError(chalk.errorMessage("--> [%s:%s] bridge's configure is invalid, reasons:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
}
}
if (fsv.stage === "instantiating") {
switch (fsv.type) {
case "ROUTINE":
case "SERVICE":
case "TRIGGER":
{
_consoleError(chalk.errorMessage("--> [%s:%s] new() is failed:"), fsv.type, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
case "DIALECT":
{
_consoleError(chalk.errorMessage("--> [%s:%s/%s] new() is failed:"), fsv.type, fsv.code, fsv.name);
_consoleError(chalk.errorStack(" " + fsv.stack));
return;
}
default:
{
_consoleError(chalk.errorMessage("--> %s"), JSON.stringify(fsv));
return;
}
}
}
if (fsv.stage === "check-methods") {
switch (fsv.type) {
case "TRIGGER":
{
_consoleError(chalk.errorMessage("--> [%s:%s] required method(s): %s not found"), fsv.type, fsv.name, JSON.stringify(fsv.methods));
return;
}
default:
{
_consoleError(chalk.errorMessage("--> %s"), JSON.stringify(fsv));
return;
}
}
}
switch (fsv.type) {
case "CONFIG":
{
_consoleError(chalk.errorMessage("--> [%s] in (%s):"), fsv.type, fsv.file);
_consoleError(chalk.errorStack(" " + fsv.stack));
break;
}
case "ROUTINE":
case "SERVICE":
case "TRIGGER":
{
_consoleError(chalk.errorMessage("--> [%s:%s] - %s in (%s):"), fsv.type, fsv.name, fsv.file, _buildPath(fsv.path, fsv.subDir));
_consoleError(chalk.errorStack(" " + fsv.stack));
break;
}
case "DIALECT":
{
_consoleError(chalk.errorMessage("--> [%s:%s/%s] in (%s):"), fsv.type, fsv.code, fsv.name, fsv.path);
_consoleError(chalk.errorStack(" " + fsv.stack));
break;
}
case "application":
{
_consoleError(chalk.errorMessage("--> [%s:%s] - %s in (%s):"), fsv.type, fsv.name, fsv.file, _buildPath(fsv.path, fsv.subDir));
_consoleError(chalk.errorStack(" " + fsv.stack));
break;
}
default:
{
_consoleError(chalk.errorMessage("--> %s"), JSON.stringify(fsv));
break;
}
}
});
}
L && L.has("silly") && L.log("silly", T && T.add({
invoker: options.invoker,
silent: silent,
exitOnError: options.exitOnError !== false
}).toMessage({
tags: [blockRef, "barrier", options.footmark],
text: " - Program will be exited? (${exitOnError})"
}));
if (options.exitOnError !== false) {
if (!silent) {
_consoleWarn(chalk.warnHeader("[!] The program will exit now."));
_consoleWarn(chalk.warnMessage("... Please fix the issues and then retry again."));
}
this.exit(1);
}
}
};
this.exit = function (exitCode) {
exitCode = lodash.isNumber(exitCode) ? exitCode : 0;
L && L.has("silly") && L.log("silly", T && T.add({
exitCode
}).toMessage({
tags: [blockRef, "exit"],
text: "process.exit(${exitCode}) is invoked"
}));
switch (_fatalErrorReaction()) {
case "exit":
return _processExit(exitCode);
case "exception":
throw new Error("Fatal error, throw exception with code: " + exitCode);
}
if (!_skipProcessExit()) {
_processExit(exitCode);
}
};
this.reset = function () {
opStates.splice(0, opStates.length);
return this;
};
L && L.has("silly") && L.log("silly", T && T.toMessage({
tags: [blockRef, "constructor-end"],
text: " - constructor has finished"
}));
}
IssueInspector.argumentSchema = {
"$id": "issueInspector",
"type": "object",
"properties": {}
};
module.exports = IssueInspector;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ color chalks
const chalk = new Chalk({
themes: {
errorHeader: ["red", "bold"],
errorMessage: ["red"],
errorStack: ["grey"],
warnHeader: ["yellow", "bold"],
warnMessage: ["yellow"]
}
});
function _buildPath(basepath, subpath) {
if (basepath) {
return subpath ? path.join(basepath, subpath) : basepath;
}
return subpath || "-";
}
function _isSilentForced(options) {
return chores.isSilentForced("issue-inspector", options);
}
function _fatalErrorReaction() {
// will return "exit" or "exception"
return chores.fatalErrorReaction();
}
function _skipProcessExit() {
return chores.skipProcessExit();
}
function _processExit() {
return process.exit.apply(process, arguments);
}
const _consoleError = console.error.bind(console);
const _consoleWarn = console.warn.bind(console);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ default instance
let singleton;
Object.defineProperty(IssueInspector, "instance", {
get: function () {
return singleton = singleton || new IssueInspector();
}
});