Skip to content

Commit

Permalink
feat(types): transition lib/errors (#13710)
Browse files Browse the repository at this point in the history
* feat(types): transition lib/errors

* feat(types): importing model type from existing types

* feat(types): don't export AsyncQueueError from lib/errors

* feat(types): storing key not value of enum in class

* feat(types): migrate async-queue to typescript

* fix(tests): adjust tests for typescript migration

* feat(types): using inline export for named exports

* feat(types): rework type definitions

* feat(types): export AsyncQueueError from errors/index

Co-authored-by: Sascha Depold <sdepold@users.noreply.github.com>
  • Loading branch information
Keimeno and sdepold committed Dec 5, 2021
1 parent b0865ec commit 8cdce6a
Show file tree
Hide file tree
Showing 41 changed files with 731 additions and 616 deletions.
46 changes: 0 additions & 46 deletions lib/dialects/mssql/async-queue.js

This file was deleted.

59 changes: 59 additions & 0 deletions lib/dialects/mssql/async-queue.ts
@@ -0,0 +1,59 @@
import { BaseError, ConnectionError } from '../../errors';

/**
* Thrown when a connection to a database is closed while an operation is in progress
*/
export class AsyncQueueError extends BaseError {
constructor(message: string) {
super(message);
this.name = 'SequelizeAsyncQueueError';
}
}

class AsyncQueue {
previous: Promise<unknown>;
closed: boolean;
rejectCurrent: (reason?: any) => void;

constructor() {
this.previous = Promise.resolve();
this.closed = false;
this.rejectCurrent = () => {
/** do nothing */
};
}

close() {
this.closed = true;
this.rejectCurrent(
new ConnectionError(
new AsyncQueueError(
'the connection was closed before this query could finish executing'
)
)
);
}

enqueue(asyncFunction: (...args: any[]) => Promise<unknown>) {
// This outer promise might seems superflous since down below we return asyncFunction().then(resolve, reject).
// However, this ensures that this.previous will never be a rejected promise so the queue will
// always keep going, while still communicating rejection from asyncFunction to the user.
return new Promise((resolve, reject) => {
this.previous = this.previous.then(() => {
this.rejectCurrent = reject;
if (this.closed) {
return reject(
new ConnectionError(
new AsyncQueueError(
'the connection was closed before this query could be executed'
)
)
);
}
return asyncFunction().then(resolve, reject);
});
});
}
}

export default AsyncQueue;
34 changes: 0 additions & 34 deletions lib/errors/aggregate-error.js

This file was deleted.

31 changes: 31 additions & 0 deletions lib/errors/aggregate-error.ts
@@ -0,0 +1,31 @@
import BaseError from './base-error';

/**
* A wrapper for multiple Errors
*
* @param errors Array of errors
*/
class AggregateError extends BaseError {
errors: Array<AggregateError | Error>;

constructor(errors: Array<AggregateError | Error>) {
super();
this.errors = errors;
this.name = 'AggregateError';
}

toString(): string {
const message = `AggregateError of:\n${this.errors
.map((error: Error | AggregateError) =>
error === this
? '[Circular AggregateError]'
: error instanceof AggregateError
? String(error).replace(/\n$/, '').replace(/^/gm, ' ')
: String(error).replace(/^/gm, ' ').substring(2)
)
.join('\n')}\n`;
return message;
}
}

export default AggregateError;
@@ -1,15 +1,13 @@
'use strict';

const BaseError = require('./base-error');
import BaseError from './base-error';

/**
* Thrown when an association is improperly constructed (see message for details)
*/
class AssociationError extends BaseError {
constructor(message) {
constructor(message: string) {
super(message);
this.name = 'SequelizeAssociationError';
}
}

module.exports = AssociationError;
export default AssociationError;
21 changes: 17 additions & 4 deletions lib/errors/base-error.js → lib/errors/base-error.ts
@@ -1,4 +1,17 @@
'use strict';
export interface ErrorOptions {
stack?: string;
}

export interface CommonErrorProperties {
/** The database specific error which triggered this one */
readonly parent: Error;

/** The database specific error which triggered this one */
readonly original: Error;

/** The SQL that triggered the error */
readonly sql: string;
}

/**
* Sequelize provides a host of custom error classes, to allow you to do easier debugging. All of these errors are exposed on the sequelize object and the sequelize constructor.
Expand All @@ -7,11 +20,11 @@
* This means that errors can be accessed using `Sequelize.ValidationError`
* The Base Error all Sequelize Errors inherit from.
*/
class BaseError extends Error {
constructor(message) {
abstract class BaseError extends Error {
constructor(message?: string) {
super(message);
this.name = 'SequelizeBaseError';
}
}

module.exports = BaseError;
export default BaseError;
21 changes: 0 additions & 21 deletions lib/errors/bulk-record-error.js

This file was deleted.

23 changes: 23 additions & 0 deletions lib/errors/bulk-record-error.ts
@@ -0,0 +1,23 @@
import BaseError from './base-error';
import type { Model } from '../../types/lib/model';

/**
* Thrown when bulk operation fails, it represent per record level error.
* Used with AggregateError
*
* @param error Error for a given record/instance
* @param record DAO instance that error belongs to
*/
class BulkRecordError extends BaseError {
errors: Error;
record: Model;

constructor(error: Error, record: Model) {
super(error.message);
this.name = 'SequelizeBulkRecordError';
this.errors = error;
this.record = record;
}
}

export default BulkRecordError;
17 changes: 7 additions & 10 deletions lib/errors/connection-error.js → lib/errors/connection-error.ts
@@ -1,22 +1,19 @@
'use strict';

const BaseError = require('./base-error');
import BaseError from './base-error';

/**
* A base class for all connection related errors.
*/
class ConnectionError extends BaseError {
constructor(parent) {
/** The connection specific error which triggered this one */
parent: Error;
original: Error;

constructor(parent: Error) {
super(parent ? parent.message : '');
this.name = 'SequelizeConnectionError';
/**
* The connection specific error which triggered this one
*
* @type {Error}
*/
this.parent = parent;
this.original = parent;
}
}

module.exports = ConnectionError;
export default ConnectionError;
@@ -1,15 +1,13 @@
'use strict';

const ConnectionError = require('./../connection-error');
import ConnectionError from './../connection-error';

/**
* Thrown when a connection to a database is refused due to insufficient privileges
*/
class AccessDeniedError extends ConnectionError {
constructor(parent) {
constructor(parent: Error) {
super(parent);
this.name = 'SequelizeAccessDeniedError';
}
}

module.exports = AccessDeniedError;
export default AccessDeniedError;
@@ -1,15 +1,13 @@
'use strict';

const ConnectionError = require('./../connection-error');
import ConnectionError from '../connection-error';

/**
* Thrown when connection is not acquired due to timeout
*/
class ConnectionAcquireTimeoutError extends ConnectionError {
constructor(parent) {
constructor(parent: Error) {
super(parent);
this.name = 'SequelizeConnectionAcquireTimeoutError';
}
}

module.exports = ConnectionAcquireTimeoutError;
export default ConnectionAcquireTimeoutError;
@@ -1,15 +1,13 @@
'use strict';

const ConnectionError = require('./../connection-error');
import ConnectionError from '../connection-error';

/**
* Thrown when a connection to a database is refused
*/
class ConnectionRefusedError extends ConnectionError {
constructor(parent) {
constructor(parent: Error) {
super(parent);
this.name = 'SequelizeConnectionRefusedError';
}
}

module.exports = ConnectionRefusedError;
export default ConnectionRefusedError;
@@ -1,15 +1,13 @@
'use strict';

const ConnectionError = require('./../connection-error');
import ConnectionError from '../connection-error';

/**
* Thrown when a connection to a database times out
*/
class ConnectionTimedOutError extends ConnectionError {
constructor(parent) {
constructor(parent: Error) {
super(parent);
this.name = 'SequelizeConnectionTimedOutError';
}
}

module.exports = ConnectionTimedOutError;
export default ConnectionTimedOutError;
@@ -1,15 +1,13 @@
'use strict';

const ConnectionError = require('./../connection-error');
import ConnectionError from '../connection-error';

/**
* Thrown when a connection to a database has a hostname that was not found
*/
class HostNotFoundError extends ConnectionError {
constructor(parent) {
constructor(parent: Error) {
super(parent);
this.name = 'SequelizeHostNotFoundError';
}
}

module.exports = HostNotFoundError;
export default HostNotFoundError;

0 comments on commit 8cdce6a

Please sign in to comment.