不要怂,就是干,撸起袖子干!

Commit c032ec90 by Felix Becker Committed by Jan Aagaard Meier

ES6 refactor: errors (#6040)

* ES6 refactor of errors.js

Use classes and export

* Add stack trace test
1 parent dc5a38f2
Showing with 138 additions and 90 deletions
......@@ -8,25 +8,21 @@
* @class Errors
*/
var util = require('util');
var error = module.exports = {};
/**
* The Base Error all Sequelize Errors inherit from.
*
* @constructor
* @alias Error
*/
error.BaseError = function() {
var tmp = Error.apply(this, arguments);
tmp.name = this.name = 'SequelizeBaseError';
this.message = tmp.message;
if (Error.captureStackTrace)
class BaseError extends Error {
constructor(message) {
super(message);
this.name = 'SequelizeBaseError';
this.message = message;
Error.captureStackTrace(this, this.constructor);
};
util.inherits(error.BaseError, Error);
}
}
exports.BaseError = BaseError;
/**
* Validation Error. Thrown when the sequelize validation has failed. The error contains an `errors` property,
......@@ -38,11 +34,12 @@ util.inherits(error.BaseError, Error);
* @extends BaseError
* @constructor
*/
error.ValidationError = function(message, errors) {
error.BaseError.apply(this, arguments);
class ValidationError extends BaseError {
constructor(message, errors) {
super(message);
this.name = 'SequelizeValidationError';
this.message = 'Validation Error';
/**
/**
* An array of ValidationErrorItems
* @member errors
*/
......@@ -54,111 +51,116 @@ error.ValidationError = function(message, errors) {
// ... otherwise create a concatenated message out of existing errors.
} else if (this.errors.length > 0 && this.errors[0].message) {
this.message = this.errors.map(function(err) {
return err.type + ': ' + err.message;
}).join(',\n');
this.message = this.errors.map(err => err.type + ': ' + err.message).join(',\n');
}
}
};
util.inherits(error.ValidationError, error.BaseError);
/**
/**
* Gets all validation error items for the path / field specified.
*
* @param {string} path The path to be checked for error items
* @returns {Array} Validation error items for the specified path
*/
error.ValidationError.prototype.get = function(path) {
return this.errors.reduce(function(reduced, error) {
get(path) {
return this.errors.reduce((reduced, error) => {
if (error.path === path) {
reduced.push(error);
}
return reduced;
}, []);
};
}
}
exports.ValidationError = ValidationError;
/**
* A base class for all database related errors.
* @extends BaseError
* @constructor
*/
error.DatabaseError = function (parent) {
error.BaseError.apply(this, [parent.message]);
class DatabaseError extends BaseError {
constructor(parent) {
super(parent.message);
this.name = 'SequelizeDatabaseError';
/**
/**
* The database specific error which triggered this one
* @member parent
*/
this.parent = parent;
this.original = parent;
/**
/**
* The SQL that triggered the error
* @member sql
*/
this.sql = parent.sql;
/**
/**
* The message from the DB.
* @member message
* @name message
*/
/**
/**
* The fields of the unique constraint
* @member fields
* @name fields
*/
/**
/**
* The value(s) which triggered the error
* @member value
* @name value
*/
/**
/**
* The name of the index that triggered the error
* @member index
* @name index
*/
};
util.inherits(error.DatabaseError, error.BaseError);
}
}
exports.DatabaseError = DatabaseError;
/**
* Thrown when a database query times out because of a deadlock
* @extends DatabaseError
* @constructor
*/
error.TimeoutError = function (parent) {
error.DatabaseError.call(this, parent);
class TimeoutError extends BaseError {
constructor(parent) {
super(parent);
this.name = 'SequelizeTimeoutError';
};
util.inherits(error.TimeoutError, error.BaseError);
}
}
exports.TimeoutError = TimeoutError;
/**
* Thrown when a unique constraint is violated in the database
* @extends DatabaseError
* @constructor
*/
error.UniqueConstraintError = function (options) {
class UniqueConstraintError extends ValidationError {
constructor(options) {
options = options || {};
options.parent = options.parent || { sql: '' };
options.message = options.message || options.parent.message || 'Validation Error';
options.errors = options.errors || {};
super(options.message, options.errors);
error.ValidationError.call(this, options.message, options.errors);
this.name = 'SequelizeUniqueConstraintError';
this.message = options.message;
this.errors = options.errors;
this.fields = options.fields;
};
util.inherits(error.UniqueConstraintError, error.ValidationError);
}
}
exports.UniqueConstraintError = UniqueConstraintError;
/**
* Thrown when a foreign key constraint is violated in the database
* @extends DatabaseError
* @constructor
*/
error.ForeignKeyConstraintError = function (options) {
class ForeignKeyConstraintError extends DatabaseError {
constructor(options) {
options = options || {};
options.parent = options.parent || { sql: '' };
error.DatabaseError.call(this, options.parent);
super(options.parent);
this.name = 'SequelizeForeignKeyConstraintError';
this.message = options.message || options.parent.message || 'Database Error';
......@@ -166,27 +168,30 @@ error.ForeignKeyConstraintError = function (options) {
this.table = options.table;
this.value = options.value;
this.index = options.index;
};
util.inherits(error.ForeignKeyConstraintError, error.DatabaseError);
}
}
exports.ForeignKeyConstraintError = ForeignKeyConstraintError;
/**
* Thrown when an exclusion constraint is violated in the database
* @extends DatabaseError
* @constructor
*/
error.ExclusionConstraintError = function (options) {
class ExclusionConstraintError extends DatabaseError {
constructor(options) {
options = options || {};
options.parent = options.parent || { sql: '' };
error.DatabaseError.call(this, options.parent);
super(options.parent);
this.name = 'SequelizeExclusionConstraintError';
this.message = options.message || options.parent.message;
this.constraint = options.constraint;
this.fields = options.fields;
this.table = options.table;
};
util.inherits(error.ExclusionConstraintError, error.DatabaseError);
}
}
exports.ExclusionConstraintError = ExclusionConstraintError;
/**
* Validation Error Item
......@@ -198,116 +203,137 @@ util.inherits(error.ExclusionConstraintError, error.DatabaseError);
* @param {string} value The value that generated the error
* @constructor
*/
error.ValidationErrorItem = function(message, type, path, value) {
class ValidationErrorItem {
constructor(message, type, path, value) {
this.message = message || '';
this.type = type || null;
this.path = path || null;
this.value = value || null;
};
}
}
exports.ValidationErrorItem = ValidationErrorItem;
/**
* A base class for all connection related errors.
* @extends BaseError
* @constructor
*/
error.ConnectionError = function (parent) {
error.BaseError.apply(this, [parent ? parent.message : '']);
class ConnectionError extends BaseError {
constructor(parent) {
super(parent ? parent.message : '');
this.name = 'SequelizeConnectionError';
/**
/**
* The connection specific error which triggered this one
* @member parent
*/
this.parent = parent;
this.original = parent;
};
util.inherits(error.ConnectionError, error.BaseError);
}
}
exports.ConnectionError = ConnectionError;
/**
* Thrown when a connection to a database is refused
* @extends ConnectionError
* @constructor
*/
error.ConnectionRefusedError = function (parent) {
error.ConnectionError.call(this, parent);
class ConnectionRefusedError extends ConnectionError {
constructor(parent) {
super(parent);
this.name = 'SequelizeConnectionRefusedError';
};
util.inherits(error.ConnectionRefusedError, error.ConnectionError);
}
}
exports.ConnectionRefusedError = ConnectionRefusedError;
/**
* Thrown when a connection to a database is refused due to insufficient privileges
* @extends ConnectionError
* @constructor
*/
error.AccessDeniedError = function (parent) {
error.ConnectionError.call(this, parent);
class AccessDeniedError extends ConnectionError {
constructor(parent) {
super(parent);
this.name = 'SequelizeAccessDeniedError';
};
util.inherits(error.AccessDeniedError, error.ConnectionError);
}
}
exports.AccessDeniedError = AccessDeniedError;
/**
* Thrown when a connection to a database has a hostname that was not found
* @extends ConnectionError
* @constructor
*/
error.HostNotFoundError = function (parent) {
error.ConnectionError.call(this, parent);
class HostNotFoundError extends ConnectionError {
constructor(parent) {
super(parent);
this.name = 'SequelizeHostNotFoundError';
};
util.inherits(error.HostNotFoundError, error.ConnectionError);
}
}
exports.HostNotFoundError = HostNotFoundError;
/**
* Thrown when a connection to a database has a hostname that was not reachable
* @extends ConnectionError
* @constructor
*/
error.HostNotReachableError = function (parent) {
error.ConnectionError.call(this, parent);
class HostNotReachableError extends ConnectionError {
constructor(parent) {
super(parent);
this.name = 'SequelizeHostNotReachableError';
};
util.inherits(error.HostNotReachableError, error.ConnectionError);
}
}
exports.HostNotReachableError = HostNotReachableError;
/**
* Thrown when a connection to a database has invalid values for any of the connection parameters
* @extends ConnectionError
* @constructor
*/
error.InvalidConnectionError = function (parent) {
error.ConnectionError.call(this, parent);
class InvalidConnectionError extends ConnectionError {
constructor(parent) {
super(parent);
this.name = 'SequelizeInvalidConnectionError';
};
util.inherits(error.InvalidConnectionError, error.ConnectionError);
}
}
exports.InvalidConnectionError = InvalidConnectionError;
/**
* Thrown when a connection to a database times out
* @extends ConnectionError
* @constructor
*/
error.ConnectionTimedOutError = function (parent) {
error.ConnectionError.call(this, parent);
class ConnectionTimedOutError extends ConnectionError {
constructor(parent) {
super(parent);
this.name = 'SequelizeConnectionTimedOutError';
};
util.inherits(error.ConnectionTimedOutError, error.ConnectionError);
}
}
exports.ConnectionTimedOutError = ConnectionTimedOutError;
/**
* Thrown when a some problem occurred with Instance methods (see message for details)
* @extends BaseError
* @constructor
*/
error.InstanceError = function (message) {
error.BaseError.apply(this, arguments);
class InstanceError extends BaseError {
constructor(message) {
super(message);
this.name = 'SequelizeInstanceError';
this.message = message;
};
util.inherits(error.InstanceError, error.BaseError);
}
}
exports.InstanceError = InstanceError;
/**
* Thrown when a record was not found, Usually used with rejectOnEmpty mode (see message for details)
* @extends BaseError
* @constructor
*/
error.EmptyResultError = function (message) {
error.BaseError.apply(this, arguments);
class EmptyResultError extends BaseError {
constructor(message) {
super(message);
this.name = 'SequelizeEmptyResultError';
this.message = message;
};
util.inherits(error.EmptyResultError, error.BaseError);
}
}
exports.EmptyResultError = EmptyResultError;
'use strict';
/* jshint expr: true */
const errors = require('../../lib/errors');
const expect = require('chai').expect;
describe('errors', () => {
it('should maintain stack trace', () => {
function throwError() {
throw new errors.ValidationError('this is a message');
}
let err;
try {
throwError();
} catch (error) {
err = error;
}
expect(err).to.exist;
const stackParts = err.stack.split('\n');
expect(stackParts[0]).to.equal('SequelizeValidationError: this is a message');
expect(stackParts[1]).to.match(/^ at throwError \(.*errors.test.js:\d+:\d+\)$/);
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!