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

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 229 additions and 181 deletions
...@@ -8,25 +8,21 @@ ...@@ -8,25 +8,21 @@
* @class Errors * @class Errors
*/ */
var util = require('util');
var error = module.exports = {};
/** /**
* The Base Error all Sequelize Errors inherit from. * The Base Error all Sequelize Errors inherit from.
* *
* @constructor * @constructor
* @alias Error * @alias Error
*/ */
error.BaseError = function() { class BaseError extends Error {
var tmp = Error.apply(this, arguments); constructor(message) {
tmp.name = this.name = 'SequelizeBaseError'; super(message);
this.name = 'SequelizeBaseError';
this.message = tmp.message; this.message = message;
if (Error.captureStackTrace)
Error.captureStackTrace(this, this.constructor); 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, * Validation Error. Thrown when the sequelize validation has failed. The error contains an `errors` property,
...@@ -38,155 +34,164 @@ util.inherits(error.BaseError, Error); ...@@ -38,155 +34,164 @@ util.inherits(error.BaseError, Error);
* @extends BaseError * @extends BaseError
* @constructor * @constructor
*/ */
error.ValidationError = function(message, errors) { class ValidationError extends BaseError {
error.BaseError.apply(this, arguments); constructor(message, errors) {
this.name = 'SequelizeValidationError'; super(message);
this.message = 'Validation Error'; this.name = 'SequelizeValidationError';
/** this.message = 'Validation Error';
* An array of ValidationErrorItems /**
* @member errors * An array of ValidationErrorItems
*/ * @member errors
this.errors = errors || []; */
this.errors = errors || [];
// Use provided error message if available... // Use provided error message if available...
if (message) { if (message) {
this.message = message; this.message = message;
// ... otherwise create a concatenated message out of existing errors. // ... otherwise create a concatenated message out of existing errors.
} else if (this.errors.length > 0 && this.errors[0].message) { } else if (this.errors.length > 0 && this.errors[0].message) {
this.message = this.errors.map(function(err) { this.message = this.errors.map(err => err.type + ': ' + err.message).join(',\n');
return err.type + ': ' + err.message; }
}).join(',\n');
} }
};
util.inherits(error.ValidationError, error.BaseError);
/** /**
* Gets all validation error items for the path / field specified. * Gets all validation error items for the path / field specified.
* *
* @param {string} path The path to be checked for error items * @param {string} path The path to be checked for error items
* @returns {Array} Validation error items for the specified path * @returns {Array} Validation error items for the specified path
*/ */
error.ValidationError.prototype.get = function(path) { get(path) {
return this.errors.reduce(function(reduced, error) { return this.errors.reduce((reduced, error) => {
if (error.path === path) { if (error.path === path) {
reduced.push(error); reduced.push(error);
} }
return reduced; return reduced;
}, []); }, []);
}; }
}
exports.ValidationError = ValidationError;
/** /**
* A base class for all database related errors. * A base class for all database related errors.
* @extends BaseError * @extends BaseError
* @constructor * @constructor
*/ */
error.DatabaseError = function (parent) { class DatabaseError extends BaseError {
error.BaseError.apply(this, [parent.message]); constructor(parent) {
this.name = 'SequelizeDatabaseError'; super(parent.message);
this.name = 'SequelizeDatabaseError';
/** /**
* The database specific error which triggered this one * The database specific error which triggered this one
* @member parent * @member parent
*/ */
this.parent = parent; this.parent = parent;
this.original = parent; this.original = parent;
/** /**
* The SQL that triggered the error * The SQL that triggered the error
* @member sql * @member sql
*/ */
this.sql = parent.sql; this.sql = parent.sql;
/** /**
* The message from the DB. * The message from the DB.
* @member message * @member message
* @name message * @name message
*/ */
/** /**
* The fields of the unique constraint * The fields of the unique constraint
* @member fields * @member fields
* @name fields * @name fields
*/ */
/** /**
* The value(s) which triggered the error * The value(s) which triggered the error
* @member value * @member value
* @name value * @name value
*/ */
/** /**
* The name of the index that triggered the error * The name of the index that triggered the error
* @member index * @member index
* @name index * @name index
*/ */
}; }
util.inherits(error.DatabaseError, error.BaseError); }
exports.DatabaseError = DatabaseError;
/** /**
* Thrown when a database query times out because of a deadlock * Thrown when a database query times out because of a deadlock
* @extends DatabaseError * @extends DatabaseError
* @constructor * @constructor
*/ */
error.TimeoutError = function (parent) { class TimeoutError extends BaseError {
error.DatabaseError.call(this, parent); constructor(parent) {
this.name = 'SequelizeTimeoutError'; super(parent);
}; this.name = 'SequelizeTimeoutError';
util.inherits(error.TimeoutError, error.BaseError); }
}
exports.TimeoutError = TimeoutError;
/** /**
* Thrown when a unique constraint is violated in the database * Thrown when a unique constraint is violated in the database
* @extends DatabaseError * @extends DatabaseError
* @constructor * @constructor
*/ */
error.UniqueConstraintError = function (options) { class UniqueConstraintError extends ValidationError {
options = options || {}; constructor(options) {
options.parent = options.parent || { sql: '' }; options = options || {};
options.message = options.message || options.parent.message || 'Validation Error'; options.parent = options.parent || { sql: '' };
options.errors = options.errors || {}; 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.name = 'SequelizeUniqueConstraintError'; this.message = options.message;
this.message = options.message; this.errors = options.errors;
this.errors = options.errors; this.fields = options.fields;
this.fields = options.fields; }
}; }
util.inherits(error.UniqueConstraintError, error.ValidationError); exports.UniqueConstraintError = UniqueConstraintError;
/** /**
* Thrown when a foreign key constraint is violated in the database * Thrown when a foreign key constraint is violated in the database
* @extends DatabaseError * @extends DatabaseError
* @constructor * @constructor
*/ */
error.ForeignKeyConstraintError = function (options) { class ForeignKeyConstraintError extends DatabaseError {
options = options || {}; constructor(options) {
options.parent = options.parent || { sql: '' }; options = options || {};
options.parent = options.parent || { sql: '' };
error.DatabaseError.call(this, options.parent); super(options.parent);
this.name = 'SequelizeForeignKeyConstraintError'; this.name = 'SequelizeForeignKeyConstraintError';
this.message = options.message || options.parent.message || 'Database Error'; this.message = options.message || options.parent.message || 'Database Error';
this.fields = options.fields; this.fields = options.fields;
this.table = options.table; this.table = options.table;
this.value = options.value; this.value = options.value;
this.index = options.index; this.index = options.index;
}; }
util.inherits(error.ForeignKeyConstraintError, error.DatabaseError); }
exports.ForeignKeyConstraintError = ForeignKeyConstraintError;
/** /**
* Thrown when an exclusion constraint is violated in the database * Thrown when an exclusion constraint is violated in the database
* @extends DatabaseError * @extends DatabaseError
* @constructor * @constructor
*/ */
error.ExclusionConstraintError = function (options) { class ExclusionConstraintError extends DatabaseError {
options = options || {}; constructor(options) {
options.parent = options.parent || { sql: '' }; options = options || {};
options.parent = options.parent || { sql: '' };
error.DatabaseError.call(this, options.parent); super(options.parent);
this.name = 'SequelizeExclusionConstraintError'; this.name = 'SequelizeExclusionConstraintError';
this.message = options.message || options.parent.message; this.message = options.message || options.parent.message;
this.constraint = options.constraint; this.constraint = options.constraint;
this.fields = options.fields; this.fields = options.fields;
this.table = options.table; this.table = options.table;
}; }
util.inherits(error.ExclusionConstraintError, error.DatabaseError); }
exports.ExclusionConstraintError = ExclusionConstraintError;
/** /**
* Validation Error Item * Validation Error Item
...@@ -198,116 +203,137 @@ util.inherits(error.ExclusionConstraintError, error.DatabaseError); ...@@ -198,116 +203,137 @@ util.inherits(error.ExclusionConstraintError, error.DatabaseError);
* @param {string} value The value that generated the error * @param {string} value The value that generated the error
* @constructor * @constructor
*/ */
error.ValidationErrorItem = function(message, type, path, value) { class ValidationErrorItem {
this.message = message || ''; constructor(message, type, path, value) {
this.type = type || null; this.message = message || '';
this.path = path || null; this.type = type || null;
this.value = value || null; this.path = path || null;
}; this.value = value || null;
}
}
exports.ValidationErrorItem = ValidationErrorItem;
/** /**
* A base class for all connection related errors. * A base class for all connection related errors.
* @extends BaseError * @extends BaseError
* @constructor * @constructor
*/ */
error.ConnectionError = function (parent) { class ConnectionError extends BaseError {
error.BaseError.apply(this, [parent ? parent.message : '']); constructor(parent) {
this.name = 'SequelizeConnectionError'; super(parent ? parent.message : '');
/** this.name = 'SequelizeConnectionError';
* The connection specific error which triggered this one /**
* @member parent * The connection specific error which triggered this one
*/ * @member parent
this.parent = parent; */
this.original = 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 * Thrown when a connection to a database is refused
* @extends ConnectionError * @extends ConnectionError
* @constructor * @constructor
*/ */
error.ConnectionRefusedError = function (parent) { class ConnectionRefusedError extends ConnectionError {
error.ConnectionError.call(this, parent); constructor(parent) {
this.name = 'SequelizeConnectionRefusedError'; 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 * Thrown when a connection to a database is refused due to insufficient privileges
* @extends ConnectionError * @extends ConnectionError
* @constructor * @constructor
*/ */
error.AccessDeniedError = function (parent) { class AccessDeniedError extends ConnectionError {
error.ConnectionError.call(this, parent); constructor(parent) {
this.name = 'SequelizeAccessDeniedError'; 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 * Thrown when a connection to a database has a hostname that was not found
* @extends ConnectionError * @extends ConnectionError
* @constructor * @constructor
*/ */
error.HostNotFoundError = function (parent) { class HostNotFoundError extends ConnectionError {
error.ConnectionError.call(this, parent); constructor(parent) {
this.name = 'SequelizeHostNotFoundError'; 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 * Thrown when a connection to a database has a hostname that was not reachable
* @extends ConnectionError * @extends ConnectionError
* @constructor * @constructor
*/ */
error.HostNotReachableError = function (parent) { class HostNotReachableError extends ConnectionError {
error.ConnectionError.call(this, parent); constructor(parent) {
this.name = 'SequelizeHostNotReachableError'; 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 * Thrown when a connection to a database has invalid values for any of the connection parameters
* @extends ConnectionError * @extends ConnectionError
* @constructor * @constructor
*/ */
error.InvalidConnectionError = function (parent) { class InvalidConnectionError extends ConnectionError {
error.ConnectionError.call(this, parent); constructor(parent) {
this.name = 'SequelizeInvalidConnectionError'; super(parent);
}; this.name = 'SequelizeInvalidConnectionError';
util.inherits(error.InvalidConnectionError, error.ConnectionError); }
}
exports.InvalidConnectionError = InvalidConnectionError;
/** /**
* Thrown when a connection to a database times out * Thrown when a connection to a database times out
* @extends ConnectionError * @extends ConnectionError
* @constructor * @constructor
*/ */
error.ConnectionTimedOutError = function (parent) { class ConnectionTimedOutError extends ConnectionError {
error.ConnectionError.call(this, parent); constructor(parent) {
this.name = 'SequelizeConnectionTimedOutError'; 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) * Thrown when a some problem occurred with Instance methods (see message for details)
* @extends BaseError * @extends BaseError
* @constructor * @constructor
*/ */
error.InstanceError = function (message) { class InstanceError extends BaseError {
error.BaseError.apply(this, arguments); constructor(message) {
this.name = 'SequelizeInstanceError'; super(message);
this.message = 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) * Thrown when a record was not found, Usually used with rejectOnEmpty mode (see message for details)
* @extends BaseError * @extends BaseError
* @constructor * @constructor
*/ */
error.EmptyResultError = function (message) { class EmptyResultError extends BaseError {
error.BaseError.apply(this, arguments); constructor(message) {
this.name = 'SequelizeEmptyResultError'; super(message);
this.message = 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!