class-logger
Version:
Boilerplate-free decorator-based class logging
118 lines (117 loc) • 4.49 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const config_service_1 = require("./config.service");
const constants_1 = require("./constants");
class ClassWrapperService {
constructor() {
this.proxyTrapConstruct = (target, args, newTarget) => {
const config = this.classGetConfigMerged(target.prototype);
if (config.include.construct) {
const messageStart = config.formatter.start({
args,
className: target.name,
include: config.include,
propertyName: 'construct',
});
config.log(messageStart);
}
const instance = Reflect.construct(target, args, newTarget);
const instanceWrapped = this.wrapClassInstance(instance);
return instanceWrapped;
};
this.makeProxyTrapGet = (className) => (target, property, receiver) => {
const prop = Reflect.get(target, property, receiver);
if (typeof prop !== 'function') {
return prop;
}
const configProp = Reflect.getMetadata(constants_1.CLASS_LOGGER_METADATA_KEY, target, property);
if (!configProp) {
return prop;
}
const configClass = this.classGetConfigMerged(target);
const configFinal = config_service_1.ConfigService.configsMerge(configClass, configProp);
const propWrapped = this.wrapFunction(configFinal, prop, className, property, target);
return propWrapped;
};
}
wrap(targetWrap) {
const get = this.makeProxyTrapGet(targetWrap.name);
const proxied = new Proxy(targetWrap, {
construct: this.proxyTrapConstruct,
get,
});
Reflect.getMetadataKeys(targetWrap).forEach((metadataKey) => {
Reflect.defineMetadata(metadataKey, Reflect.getMetadata(metadataKey, targetWrap), proxied);
});
return proxied;
}
wrapClassInstance(instance) {
const get = this.makeProxyTrapGet(instance.constructor.name);
return new Proxy(instance, {
get,
});
}
wrapFunction(config, fn, className, propertyName, classInstance) {
const classWrapper = this;
const res = function (...args) {
const messageStart = config.formatter.start({
args,
classInstance,
className,
include: config.include,
propertyName,
});
config.log(messageStart);
const logEnd = (result, error) => {
const messageEnd = config.formatter.end({
args,
classInstance,
className,
error: !!error,
include: config.include,
propertyName,
result,
});
let logFn = config.log;
if (error) {
logFn = config.logError;
}
logFn(messageEnd);
};
try {
let fnRes = fn.apply(this, args);
if (classWrapper.isPromise(fnRes)) {
fnRes = fnRes
.then((result) => {
logEnd(result);
return result;
})
.catch((error) => {
logEnd(error, true);
throw error;
});
return fnRes;
}
logEnd(fnRes);
return fnRes;
}
catch (error) {
logEnd(error, true);
throw error;
}
};
Object.keys(fn).forEach((prop) => {
res[prop] = fn[prop];
});
return res;
}
isPromise(val) {
return !!val && typeof val === 'object' && typeof val.then === 'function' && typeof val.catch === 'function';
}
classGetConfigMerged(target) {
const configClassMeta = Reflect.getMetadata(constants_1.CLASS_LOGGER_METADATA_KEY, target);
const configRes = config_service_1.ConfigService.configsMerge(config_service_1.ConfigService.config, configClassMeta);
return configRes;
}
}
exports.ClassWrapperService = ClassWrapperService;
;