@magna_shogun/catch-decorator
Version:
Handle exceptions by just annotating a method or class with a decorator. Based on enkot/catch-decorator.
94 lines (88 loc) • 3.84 kB
JavaScript
/**
* MIT License
*
* Copyright (c) 2020 omirobarcelo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global['catch-decorator'] = {})));
}(this, (function (exports) { 'use strict';
function _handleError(ctx, errorType, handler, error) {
// Check if error is instance of given error type
if (typeof handler === 'function' && error instanceof errorType) {
// Run handler with error object and class context
handler.call(null, error, ctx);
}
else {
// Throw error further
// Next decorator in chain can catch it
throw error;
}
}
function _generateDescriptor(descriptor, errorType, handler) {
// Save a reference to the original method
const originalMethod = descriptor.value;
// Rewrite original method with try/catch wrapper
descriptor.value = function (...args) {
try {
const result = originalMethod.apply(this, args);
// Check if method is asynchronous
if (result && result instanceof Promise) {
// Return promise
return result.catch((error) => {
_handleError(this, errorType, handler, error);
});
}
// Return actual result
return result;
}
catch (error) {
_handleError(this, errorType, handler, error);
}
};
return descriptor;
}
// Decorator factory function
const Catch = (errorType, handler) => {
return (target, propertyKey, descriptor) => {
// Method decorator
if (descriptor) {
return _generateDescriptor(descriptor, errorType, handler);
}
// Class decorator
else {
// Iterate over class properties except constructor
for (const propertyName of Reflect.ownKeys(target.prototype).filter(prop => prop !== 'constructor')) {
const desc = Object.getOwnPropertyDescriptor(target.prototype, propertyName);
const isMethod = desc.value instanceof Function;
if (!isMethod)
continue;
Object.defineProperty(target.prototype, propertyName, _generateDescriptor(desc, errorType, handler));
}
}
};
};
const CatchAll = (handler) => Catch(Error, handler);
exports.Catch = Catch;
exports.CatchAll = CatchAll;
Object.defineProperty(exports, '__esModule', { value: true });
})));