mirror of https://gitee.com/bigwinds/arangodb
Better foxx errors (#6264)
* Fix codeFrame formatting Pushing the codeFrame first results in ugly line breaks or extra spaces. * Include cause in MODULE_FAILURE message The error is always a wrapper for an underlying cause so it should be easier to determine what caused it. * Add a codeFrame for failed _install We normally only want this in dev mode but service CRUD should always provide detailed info. * Expose codeFrame in Foxx CRUD The codeFrame can only come from a failed _install, so let's make it visible to Foxx CLI and friends. * Add codeFrame to runScript Scripts can also only be executed with access to the Foxx API so we can provide the same info as during CRUD. * Trim codeFrame fileName to basePath If we have a basePath, we don't need to expose the full path to the user for the codeFrame to be meaningful. * Fix getReadableName Previously 'catch-fire' would become 'Catch Ire'. * Add to changelog
This commit is contained in:
parent
953027ba63
commit
cfa0e0db55
|
@ -1,6 +1,14 @@
|
||||||
devel
|
devel
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* improved error messages when managing Foxx services
|
||||||
|
|
||||||
|
Install/replace/upgrade will now provide additional information when an error
|
||||||
|
is encountered during setup. Errors encountered during a `require` call will
|
||||||
|
also include information about the underlying cause in the error message.
|
||||||
|
|
||||||
|
* fixed some Foxx script names being displayed incorrectly in web UI and Foxx CLI
|
||||||
|
|
||||||
* major revision of the maintenance feature
|
* major revision of the maintenance feature
|
||||||
|
|
||||||
* added `uuidv4` and `genRandomBytes` methods to crypto module
|
* added `uuidv4` and `genRandomBytes` methods to crypto module
|
||||||
|
|
|
@ -89,7 +89,11 @@ router.use((req, res, next) => {
|
||||||
if (e.isArangoError) {
|
if (e.isArangoError) {
|
||||||
const status = actions.arangoErrorToHttpCode(e.errorNum);
|
const status = actions.arangoErrorToHttpCode(e.errorNum);
|
||||||
console.errorStack(e);
|
console.errorStack(e);
|
||||||
res.throw(status, e.errorMessage, {
|
res.throw(status, (
|
||||||
|
e.codeFrame
|
||||||
|
? `${e.codeFrame}\n${e}`
|
||||||
|
: String(e)
|
||||||
|
), {
|
||||||
errorNum: e.errorNum,
|
errorNum: e.errorNum,
|
||||||
cause: e
|
cause: e
|
||||||
});
|
});
|
||||||
|
|
|
@ -542,7 +542,7 @@
|
||||||
Module._extensions[extension](this, filename);
|
Module._extensions[extension](this, filename);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.errorNum !== internal.errors.ERROR_MODULE_FAILURE.code) {
|
if (e.errorNum !== internal.errors.ERROR_MODULE_FAILURE.code) {
|
||||||
let msg = `${internal.errors.ERROR_MODULE_FAILURE.message}`;
|
let msg = `${internal.errors.ERROR_MODULE_FAILURE.message}\nReason: ${e}`;
|
||||||
|
|
||||||
if (e.fileName !== undefined) {
|
if (e.fileName !== undefined) {
|
||||||
msg += `\nFile: ${e.fileName}`;
|
msg += `\nFile: ${e.fileName}`;
|
||||||
|
|
|
@ -438,12 +438,6 @@ global.DEFINE_MODULE('console', (function () {
|
||||||
|
|
||||||
exports.levelStack = function (lvl, e, msg) {
|
exports.levelStack = function (lvl, e, msg) {
|
||||||
let logStrings = [];
|
let logStrings = [];
|
||||||
if (msg) {
|
|
||||||
logStrings.push(msg);
|
|
||||||
}
|
|
||||||
if (e.codeFrame) {
|
|
||||||
logStrings.push(e.codeFrame);
|
|
||||||
}
|
|
||||||
let err = e;
|
let err = e;
|
||||||
while (err) {
|
while (err) {
|
||||||
if (!msg && err === e) {
|
if (!msg && err === e) {
|
||||||
|
@ -458,6 +452,13 @@ global.DEFINE_MODULE('console', (function () {
|
||||||
}
|
}
|
||||||
err = err.cause;
|
err = err.cause;
|
||||||
}
|
}
|
||||||
|
if (e.codeFrame) {
|
||||||
|
logStrings[0] = `\n${logStrings[0]}`;
|
||||||
|
logStrings.unshift(e.codeFrame);
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
logStrings.unshift(msg);
|
||||||
|
}
|
||||||
exports.logLvlLines(lvl, logStrings);
|
exports.logLvlLines(lvl, logStrings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,12 @@ var pathRegex = /^((\.{0,2}(\/|\\))|(~\/)|[a-zA-Z]:\\)/;
|
||||||
const DEFAULT_REPLICATION_FACTOR_SYSTEM = internal.DEFAULT_REPLICATION_FACTOR_SYSTEM;
|
const DEFAULT_REPLICATION_FACTOR_SYSTEM = internal.DEFAULT_REPLICATION_FACTOR_SYSTEM;
|
||||||
|
|
||||||
function getReadableName (name) {
|
function getReadableName (name) {
|
||||||
return name.charAt(0).toUpperCase() + name.substr(1)
|
const readable = name
|
||||||
.replace(/([-_]|\s)+/g, ' ')
|
.replace(/([-_]|\s)+/g, ' ')
|
||||||
.replace(/([a-z])([A-Z])/g, (m) => `${m[0]} ${m[1]}`)
|
.replace(/([a-z])([A-Z])/g, (m) => `${m[0]} ${m[1]}`)
|
||||||
.replace(/([A-Z])([A-Z][a-z])/g, (m) => `${m[0]} ${m[1]}`)
|
.replace(/([A-Z])([A-Z][a-z])/g, (m) => `${m[0]} ${m[1]}`)
|
||||||
.replace(/\s([a-z])/g, (m) => ` ${m[0].toUpperCase()}`);
|
.replace(/\s([a-z])/g, (m) => ` ${m[1].toUpperCase()}`);
|
||||||
|
return readable.charAt(0).toUpperCase() + readable.substr(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStorage () {
|
function getStorage () {
|
||||||
|
|
|
@ -108,7 +108,9 @@ exports.codeFrame = function (e, basePath, withColor = internal.COLOR_OUTPUT) {
|
||||||
highlightCode: withColor,
|
highlightCode: withColor,
|
||||||
forceColor: withColor
|
forceColor: withColor
|
||||||
});
|
});
|
||||||
const location = `@ ${ctx.fileName}:${ctx.lineNumber}:${ctx.columnNumber}\n`;
|
const location = `@ ${
|
||||||
|
basePath ? ctx.fileName.slice(basePath.length + 1) : ctx.fileName
|
||||||
|
}:${ctx.lineNumber}:${ctx.columnNumber}\n`;
|
||||||
return (withColor ? chalk.grey(location) : location) + frame;
|
return (withColor ? chalk.grey(location) : location) + frame;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
"use strict";
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const { getReadableName } = require("@arangodb/foxx/manager-utils");
|
||||||
|
|
||||||
|
test("getReadableName", () => {
|
||||||
|
expect(getReadableName("catch-fire")).to.equal("Catch Fire");
|
||||||
|
expect(getReadableName("catchFire")).to.equal("Catch Fire");
|
||||||
|
expect(getReadableName("CatchFire")).to.equal("Catch Fire");
|
||||||
|
expect(getReadableName("cAtChFiRe")).to.equal("C At Ch Fi Re");
|
||||||
|
});
|
|
@ -44,6 +44,7 @@ const ArangoClusterControl = require('@arangodb/cluster');
|
||||||
const request = require('@arangodb/request');
|
const request = require('@arangodb/request');
|
||||||
const actions = require('@arangodb/actions');
|
const actions = require('@arangodb/actions');
|
||||||
const isZipBuffer = require('@arangodb/util').isZipBuffer;
|
const isZipBuffer = require('@arangodb/util').isZipBuffer;
|
||||||
|
const codeFrame = require('@arangodb/util').codeFrame;
|
||||||
|
|
||||||
const SYSTEM_SERVICE_MOUNTS = [
|
const SYSTEM_SERVICE_MOUNTS = [
|
||||||
'/_admin/aardvark', // Admin interface.
|
'/_admin/aardvark', // Admin interface.
|
||||||
|
@ -676,6 +677,7 @@ function _install (mount, tempPaths, options = {}) {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!options.force) {
|
if (!options.force) {
|
||||||
|
e.codeFrame = codeFrame(e, servicePath);
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
console.warnStack(e);
|
console.warnStack(e);
|
||||||
|
@ -940,8 +942,13 @@ function runScript (scriptName, mount, options) {
|
||||||
service = reloadInstalledService(mount, runSetup);
|
service = reloadInstalledService(mount, runSetup);
|
||||||
}
|
}
|
||||||
ensureServiceLoaded(mount);
|
ensureServiceLoaded(mount);
|
||||||
|
try {
|
||||||
const result = service.executeScript(scriptName, options);
|
const result = service.executeScript(scriptName, options);
|
||||||
return result === undefined ? null : result;
|
return result === undefined ? null : result;
|
||||||
|
} catch (e) {
|
||||||
|
e.codeFrame = codeFrame(e, service.basePath);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function runTests (mount, options = {}) {
|
function runTests (mount, options = {}) {
|
||||||
|
|
Loading…
Reference in New Issue