Skip to content

Commit

Permalink
Better annotate handling. isError. Closes #2279. Closes #2280
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Jan 19, 2020
1 parent 26206ed commit 2417a42
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 28 deletions.
26 changes: 17 additions & 9 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,15 +275,6 @@ Creates a new customized instance of the **joi** module where:

Note that the original **joi** module is not modified by this.

### `isExpression(expression)`

Checks whether or not the provided argument is an expression.

```js
const expression = Joi.x('{a}');
Joi.isExpression(expression); // returns true
```

### `in(ref, [options])`

Creates a [reference](#refkey-options) that when resolved, is used as an array of values to match against the rule, where:
Expand All @@ -299,6 +290,23 @@ const schema = Joi.object({
});
```

### `isError(err)`

Checks whether or not the provided argument is a validation error.

```js
Joi.isError(new Error()); // returns false
```

### `isExpression(expression)`

Checks whether or not the provided argument is an expression.

```js
const expression = Joi.x('{a}');
Joi.isExpression(expression); // returns true
```

### `isRef(ref)`

Checks whether or not the provided argument is a reference. Useful if you want to post-process error messages.
Expand Down
18 changes: 9 additions & 9 deletions lib/annotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ const internals = {
};


exports.error = function (source, stripColorCodes) {
exports.error = function (stripColorCodes) {

if (!source._original ||
typeof source._original !== 'object') {
if (!this._original ||
typeof this._original !== 'object') {

return source.details[0].message;
return this.details[0].message;
}

const redFgEscape = stripColorCodes ? '' : '\u001b[31m';
const redBgEscape = stripColorCodes ? '' : '\u001b[41m';
const endColor = stripColorCodes ? '' : '\u001b[0m';

const obj = Clone(source._original);
const obj = Clone(this._original);

for (let i = source.details.length - 1; i >= 0; --i) { // Reverse order to process deepest child first
for (let i = this.details.length - 1; i >= 0; --i) { // Reverse order to process deepest child first
const pos = i + 1;
const error = source.details[i];
const error = this.details[i];
const path = error.path;
let node = obj;
for (let j = 0; ; ++j) {
Expand Down Expand Up @@ -75,9 +75,9 @@ exports.error = function (source, stripColorCodes) {

message = `${message}\n${redFgEscape}`;

for (let i = 0; i < source.details.length; ++i) {
for (let i = 0; i < this.details.length; ++i) {
const pos = i + 1;
message = `${message}\n[${pos}] ${source.details[i].message}`;
message = `${message}\n[${pos}] ${this.details[i].message}`;
}

message = message + endColor;
Expand Down
17 changes: 9 additions & 8 deletions lib/errors.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
'use strict';

const Assert = require('@hapi/hoek/lib/assert');

const Annotate = require('./annotate');
const Common = require('./common');
const Template = require('./template');
Expand Down Expand Up @@ -243,19 +241,22 @@ exports.details = function (errors, options = {}) {

exports.ValidationError = class extends Error {

isJoi = true;
name = 'ValidationError';

constructor(message, details, original) {

super(message);
this._original = original;
this.details = details;
}

annotate(stripColorCodes) {
static isError(err) {

Assert(Annotate.error, 'Error annotation is not supported');
return Annotate.error(this, stripColorCodes);
return err instanceof exports.ValidationError;
}
};


exports.ValidationError.prototype.isJoi = true;

exports.ValidationError.prototype.name = 'ValidationError';

exports.ValidationError.prototype.annotate = Annotate.error;
4 changes: 2 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ internals.methods = {
return joi;
},

isError: Errors.ValidationError.isError,
isExpression: Template.isTemplate,
isRef: Ref.isRef,
isSchema: Common.isSchema,
Expand Down Expand Up @@ -232,8 +233,7 @@ internals.assert = function (value, schema, annotate, args /* [message], [option
throw message;
}

annotate = annotate && typeof error.annotate === 'function';
const display = annotate ? error.annotate() : error.message;
const display = annotate && typeof error.annotate === 'function' ? error.annotate() : error.message;

if (error instanceof Errors.ValidationError === false) {
error = Clone(error);
Expand Down
1 change: 1 addition & 0 deletions test/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('errors', () => {
const err = Joi.valid('foo').validate('bar').error;
expect(err).to.be.an.error();
expect(err.isJoi).to.be.true();
expect(Joi.isError(err)).to.be.true();
});


Expand Down

0 comments on commit 2417a42

Please sign in to comment.