Compare commits
7 Commits
dfd4aeba8f
...
59cd199287
Author | SHA1 | Date | |
---|---|---|---|
59cd199287 | |||
3ac9b1d38d | |||
b28bb9e193 | |||
45aa4b96c7 | |||
1196cf7001 | |||
17ce22a57d | |||
70f69c634b |
11
.prettierrc
Normal file
11
.prettierrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"objectWrap": "preserve",
|
||||
"arrowParens": "always"
|
||||
}
|
Binary file not shown.
6
dist/lib/index.d.ts
vendored
6
dist/lib/index.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
export { LoggedRoute, LoggedFunction, LoggedController, LoggedInjectable, LoggedGuard, LoggedInterceptor, } from "./logged";
|
||||
export { ScopedLogger } from "./logger";
|
||||
export { InjectLogger, LoggedParam, LoggedHeaders, LoggedBody, LoggedQuery, Logged, Returns } from "./reflected";
|
||||
export { LoggedRoute, LoggedFunction, LoggedController, LoggedInjectable, LoggedGuard, LoggedInterceptor, } from './logged';
|
||||
export { ScopedLogger } from './logger';
|
||||
export { InjectLogger, LoggedParam, LoggedHeaders, LoggedBody, LoggedQuery, Logged, Returns, } from './reflected';
|
||||
export { getRequestLogger } from './utils';
|
||||
|
6
dist/lib/internals/nest.d.ts
vendored
Normal file
6
dist/lib/internals/nest.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
|
||||
import { ParamData, PipeTransform, Type } from '@nestjs/common';
|
||||
import { ROUTE_ARGS_METADATA } from '@nestjs/common/constants';
|
||||
export { RouteParamtypes, PipeTransform, Type, ROUTE_ARGS_METADATA };
|
||||
export declare function createRouteParamDecorator(paramtype: RouteParamtypes): (data?: ParamData) => ParameterDecorator;
|
||||
export declare const createPipesRouteParamDecorator: (paramtype: RouteParamtypes) => (data?: any, ...pipes: (Type<PipeTransform> | PipeTransform)[]) => ParameterDecorator;
|
24
dist/lib/internals/nest.js
vendored
Normal file
24
dist/lib/internals/nest.js
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPipesRouteParamDecorator = exports.createRouteParamDecorator = exports.ROUTE_ARGS_METADATA = exports.RouteParamtypes = void 0;
|
||||
const route_paramtypes_enum_1 = require("@nestjs/common/enums/route-paramtypes.enum");
|
||||
Object.defineProperty(exports, "RouteParamtypes", { enumerable: true, get: function () { return route_paramtypes_enum_1.RouteParamtypes; } });
|
||||
const common_1 = require("@nestjs/common");
|
||||
const constants_1 = require("@nestjs/common/constants");
|
||||
Object.defineProperty(exports, "ROUTE_ARGS_METADATA", { enumerable: true, get: function () { return constants_1.ROUTE_ARGS_METADATA; } });
|
||||
const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
||||
function createRouteParamDecorator(paramtype) {
|
||||
return (data) => (target, key, index) => {
|
||||
const args = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.defineMetadata(constants_1.ROUTE_ARGS_METADATA, (0, common_1.assignMetadata)(args, paramtype, index, data), target.constructor, key);
|
||||
};
|
||||
}
|
||||
exports.createRouteParamDecorator = createRouteParamDecorator;
|
||||
const createPipesRouteParamDecorator = (paramtype) => (data, ...pipes) => (target, key, index) => {
|
||||
const args = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
const hasParamData = (0, shared_utils_1.isNil)(data) || (0, shared_utils_1.isString)(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
Reflect.defineMetadata(constants_1.ROUTE_ARGS_METADATA, (0, common_1.assignMetadata)(args, paramtype, index, paramData, ...paramPipes), target.constructor, key);
|
||||
};
|
||||
exports.createPipesRouteParamDecorator = createPipesRouteParamDecorator;
|
@ -5,12 +5,7 @@ export declare function includeObjectSync(ocv: any, opt: {
|
||||
export declare function excludeObjectSync(ocv: any, opt: {
|
||||
paths: string[];
|
||||
}): any;
|
||||
export declare function includeOrExcludeObjectSync(ocv: any, paths: string[], currentPath: string[], include: boolean): any;
|
||||
export declare function objectContainedLoggedSync(ocv: any, options?: {
|
||||
include?: string[];
|
||||
exclude: string[];
|
||||
}): string;
|
||||
export declare function imObjectContainedLogSync(ocv: any, options?: {
|
||||
export declare function objectContainedLogSync(ocv: any, options?: {
|
||||
include?: string[];
|
||||
exclude?: string[];
|
||||
}): string;
|
@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getItemByPathSync = exports.imObjectContainedLogSync = exports.objectContainedLoggedSync = exports.includeOrExcludeObjectSync = exports.excludeObjectSync = exports.includeObjectSync = exports.notIncludedSymbol = void 0;
|
||||
exports.notIncludedSymbol = Symbol("notIncluded");
|
||||
exports.getItemByPathSync = exports.objectContainedLogSync = exports.excludeObjectSync = exports.includeObjectSync = exports.notIncludedSymbol = void 0;
|
||||
exports.notIncludedSymbol = Symbol('notIncluded');
|
||||
function includeObjectSync(ocv, opt) {
|
||||
let current = Array.isArray(ocv) ? [] : typeof ocv === 'object' ? {} : ocv;
|
||||
opt.paths.forEach((dotpath) => {
|
||||
@ -31,7 +31,11 @@ function includeObjectSync(ocv, opt) {
|
||||
}
|
||||
exports.includeObjectSync = includeObjectSync;
|
||||
function excludeObjectSync(ocv, opt) {
|
||||
const copied = typeof ocv === 'object' ? Array.isArray(ocv) ? [...ocv] : { ...ocv } : ocv;
|
||||
const copied = typeof ocv === 'object'
|
||||
? Array.isArray(ocv)
|
||||
? [...ocv]
|
||||
: { ...ocv }
|
||||
: ocv;
|
||||
opt.paths.forEach((dotpath) => {
|
||||
let objRef = copied;
|
||||
const path = dotpath.split('.');
|
||||
@ -50,45 +54,7 @@ function excludeObjectSync(ocv, opt) {
|
||||
return copied;
|
||||
}
|
||||
exports.excludeObjectSync = excludeObjectSync;
|
||||
function includeOrExcludeObjectSync(ocv, paths, currentPath = [], include // or exclude
|
||||
) {
|
||||
if (Array.isArray(ocv)) {
|
||||
return (ocv.map((v, i) => includeOrExcludeObjectSync(v, paths, [...currentPath, i.toString()], include))).filter((e) => e !== exports.notIncludedSymbol);
|
||||
}
|
||||
if (typeof ocv === "object") {
|
||||
return Object.fromEntries(Object.entries(ocv).map(([key, value]) => [
|
||||
key,
|
||||
includeOrExcludeObjectSync(value, paths, [...currentPath, key], include),
|
||||
]).filter((e) => e[1] !== exports.notIncludedSymbol));
|
||||
}
|
||||
const isIncluded = paths.includes(currentPath.join("."));
|
||||
return include
|
||||
? isIncluded // include mode, path is in list
|
||||
? ocv
|
||||
: exports.notIncludedSymbol
|
||||
: isIncluded // exclude mode, path is in list
|
||||
? exports.notIncludedSymbol
|
||||
: ocv;
|
||||
}
|
||||
exports.includeOrExcludeObjectSync = includeOrExcludeObjectSync;
|
||||
function objectContainedLoggedSync(ocv, options) {
|
||||
if (options && typeof ocv === "object") {
|
||||
if (options.include && options.include.length > 0) {
|
||||
return JSON.stringify(includeOrExcludeObjectSync(ocv, options.include, [], true));
|
||||
}
|
||||
if (options.exclude && options.exclude.length > 0) {
|
||||
return JSON.stringify(includeOrExcludeObjectSync(ocv, options.exclude, [], false));
|
||||
}
|
||||
}
|
||||
if (typeof ocv === "object") {
|
||||
return JSON.stringify(ocv);
|
||||
}
|
||||
else {
|
||||
return `${ocv}`;
|
||||
}
|
||||
}
|
||||
exports.objectContainedLoggedSync = objectContainedLoggedSync;
|
||||
function imObjectContainedLogSync(ocv, options) {
|
||||
function objectContainedLogSync(ocv, options) {
|
||||
if (options && typeof ocv === 'object' && ocv !== null) {
|
||||
if (options.include && options.include.length > 0) {
|
||||
return JSON.stringify(includeObjectSync(ocv, { paths: options.include }));
|
||||
@ -97,18 +63,18 @@ function imObjectContainedLogSync(ocv, options) {
|
||||
return JSON.stringify(excludeObjectSync(ocv, { paths: options.exclude }));
|
||||
}
|
||||
}
|
||||
if (typeof ocv === "object" && ocv !== null) {
|
||||
if (typeof ocv === 'object' && ocv !== null) {
|
||||
return JSON.stringify(ocv);
|
||||
}
|
||||
else {
|
||||
return `${ocv}`;
|
||||
}
|
||||
}
|
||||
exports.imObjectContainedLogSync = imObjectContainedLogSync;
|
||||
exports.objectContainedLogSync = objectContainedLogSync;
|
||||
function getItemByPathSync(obj, path) {
|
||||
const paths = Array.isArray(path) ? path : path.split(".");
|
||||
const paths = Array.isArray(path) ? path : path.split('.');
|
||||
return Object.keys(obj).includes(paths[0])
|
||||
? typeof obj[paths[0]] === "object"
|
||||
? typeof obj[paths[0]] === 'object'
|
||||
? getItemByPathSync(obj[paths[0]], paths.slice(1))
|
||||
: obj[paths[0]]
|
||||
: undefined;
|
27
dist/lib/logged.d.ts
vendored
27
dist/lib/logged.d.ts
vendored
@ -1,27 +0,0 @@
|
||||
import { LogLevel, ControllerOptions, ScopeOptions, ExecutionContext } from "@nestjs/common";
|
||||
export declare function LoggedInjectable(options?: ScopeOptions & {
|
||||
verbose?: boolean;
|
||||
}): (target: any) => void;
|
||||
export declare function LoggedController(): (target: any) => void;
|
||||
export declare function LoggedController(prefix: string | string[]): (target: any) => void;
|
||||
export declare function LoggedController(options: ControllerOptions & {
|
||||
verbose?: boolean;
|
||||
}): (target: any) => void;
|
||||
interface OverrideBuildOptions {
|
||||
callLogLevel: LogLevel | 'skip';
|
||||
returnLogLevel: LogLevel | 'skip';
|
||||
errorLogLevel: LogLevel | 'skip';
|
||||
/** @deprecated use `callLogLevel: 'skip'` instead */
|
||||
skipCallLog: boolean;
|
||||
/** @deprecated use `returnLogLevel: 'skip'` instead */
|
||||
skipReturnLog: boolean;
|
||||
/** @deprecated use `errorLogLevel: 'skip'` instead */
|
||||
skipErrorLog: boolean;
|
||||
}
|
||||
export declare const REQUEST_LOG_ID = "__nestlogged_request_log_id__";
|
||||
export declare function LoggedFunction<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(...args: F) => R | Promise<R>>) => void;
|
||||
export declare function LoggedRoute<F extends Array<any>, R>(route?: string, options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(...args: F) => R>) => void;
|
||||
export declare function LoggedGuard<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>) => void;
|
||||
export declare function LoggedInterceptor<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>) => void;
|
||||
export declare function LoggedMiddleware<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>) => void;
|
||||
export {};
|
436
dist/lib/logged.js
vendored
436
dist/lib/logged.js
vendored
@ -1,436 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedMiddleware = exports.LoggedInterceptor = exports.LoggedGuard = exports.LoggedRoute = exports.LoggedFunction = exports.REQUEST_LOG_ID = exports.LoggedController = exports.LoggedInjectable = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const logger_1 = require("./logger");
|
||||
const reflected_1 = require("./reflected");
|
||||
const functions_1 = require("./functions");
|
||||
const RevRequestMethod = [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"PATCH",
|
||||
"ALL",
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"SEARCH",
|
||||
];
|
||||
function loggerInit(_target) {
|
||||
if (!Object.getOwnPropertyNames(_target).includes("logger")) {
|
||||
const newTargetLogger = new common_1.Logger(_target.constructor.name);
|
||||
newTargetLogger.log("Logger Initialized.");
|
||||
Object.defineProperty(_target, "logger", {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
value: newTargetLogger,
|
||||
});
|
||||
}
|
||||
}
|
||||
function LoggedInjectable(options) {
|
||||
return (target) => {
|
||||
loggerInit(target.prototype);
|
||||
const logger = target.prototype.logger;
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
methods.forEach((method) => {
|
||||
if (method !== "constructor" &&
|
||||
typeof target.prototype[method] === "function") {
|
||||
if (options && options.verbose)
|
||||
logger.log(`LoggedFunction applied to ${method}`);
|
||||
LoggedFunction()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
(0, common_1.Injectable)(options)(target);
|
||||
};
|
||||
}
|
||||
exports.LoggedInjectable = LoggedInjectable;
|
||||
function LoggedController(param) {
|
||||
return (target) => {
|
||||
loggerInit(target.prototype);
|
||||
const logger = target.prototype.logger;
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
let verbose = typeof param === "object" && Object.keys(param).includes("verbose")
|
||||
? param.verbose
|
||||
: false;
|
||||
methods.forEach((method) => {
|
||||
if (method !== "constructor" &&
|
||||
typeof target.prototype[method] === "function") {
|
||||
if (verbose) {
|
||||
const path = Reflect.getMetadata("path", target.prototype[method]);
|
||||
const httpMethod = Reflect.getMetadata("method", target.prototype[method]);
|
||||
logger.log(`LoggedRoute applied to ${method} (${RevRequestMethod[httpMethod]} ${path})`);
|
||||
}
|
||||
LoggedRoute()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
(0, common_1.Controller)(param)(target);
|
||||
};
|
||||
}
|
||||
exports.LoggedController = LoggedController;
|
||||
const defaultOverrideBuildOptions = {
|
||||
callLogLevel: 'log',
|
||||
returnLogLevel: 'log',
|
||||
errorLogLevel: 'error',
|
||||
skipCallLog: false,
|
||||
skipReturnLog: false,
|
||||
skipErrorLog: false,
|
||||
};
|
||||
class LoggedMetadata {
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...defaultOverrideBuildOptions,
|
||||
...(options ?? {}),
|
||||
};
|
||||
}
|
||||
updateOption(options) {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options
|
||||
};
|
||||
}
|
||||
}
|
||||
const callLogIdentifyMessageDictionary = {
|
||||
route: 'ENDPOINT',
|
||||
function: 'FUNCTION',
|
||||
guard: 'GUARD',
|
||||
interceptor: 'INTERCEPTOR',
|
||||
middleware: 'MIDDLEWARE',
|
||||
};
|
||||
function createCallLogIdentifyMessage(message, type, key, route) {
|
||||
if (message === 'ERROR')
|
||||
return `ERROR WHILE ${callLogIdentifyMessageDictionary[type]} ${key} (${route}): `;
|
||||
if (type === 'guard' || type === 'interceptor' || type === 'middleware' || type === 'route')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key} (${route})`;
|
||||
if (type === 'function')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key}`;
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]}`;
|
||||
}
|
||||
exports.REQUEST_LOG_ID = '__nestlogged_request_log_id__';
|
||||
function overrideBuild(type, originalFunction, baseLogger, metadatas, key, returnsData, logged, route) {
|
||||
return function (...args) {
|
||||
// Creating ScopedLogger
|
||||
let injectedLogger = baseLogger;
|
||||
if (typeof metadatas.scopedLoggerInjectableParam !== "undefined") {
|
||||
if (type === 'function') {
|
||||
if (args.length <= metadatas.scopedLoggerInjectableParam ||
|
||||
!(args[metadatas.scopedLoggerInjectableParam] instanceof logger_1.ScopedLogger)) {
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key);
|
||||
}
|
||||
else {
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromSuper(baseLogger, args[metadatas.scopedLoggerInjectableParam], key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// special, can access to request object
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
// args[0] == ExecutionContext
|
||||
const ctx = args[0];
|
||||
if (ctx.getType() !== 'http') {
|
||||
injectedLogger.error('Cannot inject logger: Request type is not http');
|
||||
}
|
||||
else {
|
||||
let req = ctx.switchToHttp().getRequest();
|
||||
if (req[exports.REQUEST_LOG_ID] === undefined) {
|
||||
req[exports.REQUEST_LOG_ID] = logger_1.ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key, req[exports.REQUEST_LOG_ID]);
|
||||
}
|
||||
}
|
||||
else if (type === 'middleware') {
|
||||
let req = args[0];
|
||||
if (req[exports.REQUEST_LOG_ID] === undefined) {
|
||||
req[exports.REQUEST_LOG_ID] = logger_1.ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key, req[exports.REQUEST_LOG_ID]);
|
||||
}
|
||||
else if (type === 'route') {
|
||||
// args[metadatas.scopedLoggerInjectableParam] is now Request object, thanks to code in @LoggedRoute!!!!
|
||||
let req = args[metadatas.scopedLoggerInjectableParam];
|
||||
if (req[exports.REQUEST_LOG_ID] === undefined) {
|
||||
req[exports.REQUEST_LOG_ID] = logger_1.ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key, req[exports.REQUEST_LOG_ID]);
|
||||
}
|
||||
}
|
||||
injectedLogger = args[metadatas.scopedLoggerInjectableParam];
|
||||
}
|
||||
// If this is ExecutionContext based function (e.g. Guard, Interceptor) get Request from Context
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
const context = args[0];
|
||||
if (context.getType() === 'http') {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
route = /* supporting FastifyRequest */ req.raw ? req.raw.url : req.url;
|
||||
}
|
||||
}
|
||||
// Start Log
|
||||
if (logged.options.callLogLevel !== 'skip') {
|
||||
const callLogIdentifyMessage = type === 'middleware' || type === 'guard' || type === 'interceptor' || type === 'route'
|
||||
? createCallLogIdentifyMessage('HIT', type, key, route)
|
||||
: createCallLogIdentifyMessage('HIT', type, key);
|
||||
injectedLogger[logged.options.callLogLevel](`${callLogIdentifyMessage} ${metadatas.loggedParams && metadatas.loggedParams.length > 0
|
||||
? "WITH " +
|
||||
metadatas.loggedParams.map(({ name, index, include, exclude }) => name +
|
||||
"=" +
|
||||
(0, functions_1.imObjectContainedLogSync)(args[index], {
|
||||
include,
|
||||
exclude,
|
||||
})).join(", ")
|
||||
: ""}`);
|
||||
}
|
||||
try {
|
||||
const r = originalFunction.call(this, ...args); // Try to call original function
|
||||
// Return Log
|
||||
if (logged.options.returnLogLevel !== 'skip') {
|
||||
if (originalFunction.constructor.name === 'AsyncFunction' ||
|
||||
(r && typeof r === 'object' && typeof r['then'] === 'function')) {
|
||||
return r['then']((r) => {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === "object" && r !== null
|
||||
? "WITH " +
|
||||
returnsData.map(({ name, path }) => {
|
||||
const value = (0, functions_1.getItemByPathSync)(r, path);
|
||||
return value !== undefined ? `${name}=${value}` : "";
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(", ")
|
||||
: ""
|
||||
: typeof returnsData === 'string'
|
||||
? "WITH " + returnsData + "=" + typeof r === "object" ? JSON.stringify(r) : r
|
||||
: returnsData
|
||||
? typeof r === "object"
|
||||
? "WITH " + JSON.stringify(r)
|
||||
: "WITH " + r
|
||||
: "";
|
||||
injectedLogger[logged.options.returnLogLevel](`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`);
|
||||
return r;
|
||||
});
|
||||
}
|
||||
else {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === "object" && r !== null
|
||||
? "WITH " +
|
||||
returnsData.map(({ name, path }) => {
|
||||
const value = (0, functions_1.getItemByPathSync)(r, path);
|
||||
return value !== undefined ? `${name}=${value}` : "";
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(", ")
|
||||
: ""
|
||||
: typeof returnsData === 'string'
|
||||
? "WITH " + returnsData + "=" + typeof r === "object" ? JSON.stringify(r) : r
|
||||
: returnsData
|
||||
? typeof r === "object"
|
||||
? "WITH " + JSON.stringify(r)
|
||||
: "WITH " + r
|
||||
: "";
|
||||
injectedLogger[logged.options.returnLogLevel](`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Error Log
|
||||
if (logged.options.errorLogLevel !== 'skip') {
|
||||
injectedLogger[logged.options.errorLogLevel](`${createCallLogIdentifyMessage('ERROR', type, key, route)} ${e}`);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
||||
function LoggedFunction(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
loggerInit(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(`LoggedFunction decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(reflected_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const loggedParams = Reflect.getOwnMetadata(reflected_1.loggedParam, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = overrideBuild('function', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
}, key, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(reflected_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedFunction = LoggedFunction;
|
||||
function LoggedRoute(route, options) {
|
||||
return (_target, key, descriptor) => {
|
||||
loggerInit(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(`LoggedRoute decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(reflected_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const httpPath = Reflect.getMetadata("path", fn);
|
||||
const httpMethod = Reflect.getMetadata("method", fn);
|
||||
const fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${RevRequestMethod[httpMethod]}]`;
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
// if @InjectLogger exists, fake nestjs as it is @Req()
|
||||
if (scopedLoggerInjectableParam !== undefined) {
|
||||
(0, reflected_1.createRouteParamDecorator)(0)()(_target, key, scopedLoggerInjectableParam);
|
||||
}
|
||||
const loggedParams = Reflect.getOwnMetadata(reflected_1.loggedParam, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = overrideBuild('route', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
}, key, returnsData, newMetadata, fullRoute);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(reflected_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedRoute = LoggedRoute;
|
||||
function LoggedGuard(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
loggerInit(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(`LoggedGuard decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(reflected_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = overrideBuild('guard', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
}, _target.constructor.name, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(reflected_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedGuard = LoggedGuard;
|
||||
function LoggedInterceptor(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
loggerInit(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(`LoggedInterceptor decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(reflected_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = overrideBuild('interceptor', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
}, _target.constructor.name, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(reflected_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedInterceptor = LoggedInterceptor;
|
||||
function LoggedMiddleware(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
loggerInit(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(`LoggedMiddleware decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(reflected_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = overrideBuild('middleware', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
}, _target.constructor.name, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(reflected_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedMiddleware = LoggedMiddleware;
|
9
dist/lib/logged/class.d.ts
vendored
Normal file
9
dist/lib/logged/class.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import { ControllerOptions, ScopeOptions } from '@nestjs/common';
|
||||
export declare function LoggedInjectable(options?: ScopeOptions & {
|
||||
verbose?: boolean;
|
||||
}): (target: any) => void;
|
||||
export declare function LoggedController(): (target: any) => void;
|
||||
export declare function LoggedController(prefix: string | string[]): (target: any) => void;
|
||||
export declare function LoggedController(options: ControllerOptions & {
|
||||
verbose?: boolean;
|
||||
}): (target: any) => void;
|
50
dist/lib/logged/class.js
vendored
Normal file
50
dist/lib/logged/class.js
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedController = exports.LoggedInjectable = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const utils_1 = require("./utils");
|
||||
const methods_1 = require("./methods");
|
||||
function LoggedInjectable(options) {
|
||||
return (target) => {
|
||||
(0, utils_1.loggerInit)(target.prototype);
|
||||
const logger = target.prototype.logger;
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
methods.forEach((method) => {
|
||||
if (method !== 'constructor' &&
|
||||
typeof target.prototype[method] === 'function') {
|
||||
if (options && options.verbose)
|
||||
logger.log(`LoggedFunction applied to ${method}`);
|
||||
(0, methods_1.LoggedFunction)()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
(0, common_1.Injectable)(options)(target);
|
||||
};
|
||||
}
|
||||
exports.LoggedInjectable = LoggedInjectable;
|
||||
function LoggedController(param) {
|
||||
return (target) => {
|
||||
(0, utils_1.loggerInit)(target.prototype);
|
||||
const logger = target.prototype.logger;
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
let verbose = typeof param === 'object' && Object.keys(param).includes('verbose')
|
||||
? param.verbose
|
||||
: false;
|
||||
methods.forEach((method) => {
|
||||
if (method !== 'constructor' &&
|
||||
typeof target.prototype[method] === 'function') {
|
||||
if (verbose) {
|
||||
const path = Reflect.getMetadata('path', target.prototype[method]);
|
||||
const httpMethod = Reflect.getMetadata('method', target.prototype[method]);
|
||||
logger.log(`LoggedRoute applied to ${method} (${utils_1.RevRequestMethod[httpMethod]} ${path})`);
|
||||
}
|
||||
(0, methods_1.LoggedRoute)()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
(0, common_1.Controller)(param)(target);
|
||||
};
|
||||
}
|
||||
exports.LoggedController = LoggedController;
|
2
dist/lib/logged/index.d.ts
vendored
Normal file
2
dist/lib/logged/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './methods';
|
||||
export { LoggedController, LoggedInjectable } from './class';
|
21
dist/lib/logged/index.js
vendored
Normal file
21
dist/lib/logged/index.js
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedInjectable = exports.LoggedController = void 0;
|
||||
__exportStar(require("./methods"), exports);
|
||||
var class_1 = require("./class");
|
||||
Object.defineProperty(exports, "LoggedController", { enumerable: true, get: function () { return class_1.LoggedController; } });
|
||||
Object.defineProperty(exports, "LoggedInjectable", { enumerable: true, get: function () { return class_1.LoggedInjectable; } });
|
7
dist/lib/logged/metadata.d.ts
vendored
Normal file
7
dist/lib/logged/metadata.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { OverrideBuildOptions } from './utils';
|
||||
export declare const nestLoggedMetadata: unique symbol;
|
||||
export declare class LoggedMetadata {
|
||||
options: OverrideBuildOptions;
|
||||
constructor(options?: Partial<OverrideBuildOptions>);
|
||||
updateOption(options: Partial<OverrideBuildOptions>): void;
|
||||
}
|
20
dist/lib/logged/metadata.js
vendored
Normal file
20
dist/lib/logged/metadata.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedMetadata = exports.nestLoggedMetadata = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
exports.nestLoggedMetadata = Symbol('nlogdec-metadata');
|
||||
class LoggedMetadata {
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...utils_1.defaultOverrideBuildOptions,
|
||||
...(options ?? {}),
|
||||
};
|
||||
}
|
||||
updateOption(options) {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options,
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.LoggedMetadata = LoggedMetadata;
|
2
dist/lib/logged/methods/function.d.ts
vendored
Normal file
2
dist/lib/logged/methods/function.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
export declare function LoggedFunction<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(...args: F) => R | Promise<R>>) => void;
|
44
dist/lib/logged/methods/function.js
vendored
Normal file
44
dist/lib/logged/methods/function.js
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedFunction = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
const metadata_1 = require("../metadata");
|
||||
const reflected_1 = require("../../reflected");
|
||||
const override_1 = require("../override");
|
||||
function LoggedFunction(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
(0, utils_1.loggerInit)(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(`LoggedFunction decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(metadata_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new metadata_1.LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const loggedParams = Reflect.getOwnMetadata(reflected_1.loggedParam, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = (0, override_1.overrideBuild)('function', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
}, key, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(metadata_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedFunction = LoggedFunction;
|
3
dist/lib/logged/methods/guard.d.ts
vendored
Normal file
3
dist/lib/logged/methods/guard.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { ExecutionContext } from '@nestjs/common';
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
export declare function LoggedGuard<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>) => void;
|
43
dist/lib/logged/methods/guard.js
vendored
Normal file
43
dist/lib/logged/methods/guard.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedGuard = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
const metadata_1 = require("../metadata");
|
||||
const reflected_1 = require("../../reflected");
|
||||
const override_1 = require("../override");
|
||||
function LoggedGuard(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
(0, utils_1.loggerInit)(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(`LoggedGuard decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(metadata_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new metadata_1.LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = (0, override_1.overrideBuild)('guard', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
}, _target.constructor.name, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(metadata_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedGuard = LoggedGuard;
|
5
dist/lib/logged/methods/index.d.ts
vendored
Normal file
5
dist/lib/logged/methods/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export { LoggedFunction } from './function';
|
||||
export { LoggedRoute } from './route';
|
||||
export { LoggedGuard } from './guard';
|
||||
export { LoggedInterceptor } from './interceptor';
|
||||
export { LoggedMiddleware } from './middleware';
|
13
dist/lib/logged/methods/index.js
vendored
Normal file
13
dist/lib/logged/methods/index.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedMiddleware = exports.LoggedInterceptor = exports.LoggedGuard = exports.LoggedRoute = exports.LoggedFunction = void 0;
|
||||
var function_1 = require("./function");
|
||||
Object.defineProperty(exports, "LoggedFunction", { enumerable: true, get: function () { return function_1.LoggedFunction; } });
|
||||
var route_1 = require("./route");
|
||||
Object.defineProperty(exports, "LoggedRoute", { enumerable: true, get: function () { return route_1.LoggedRoute; } });
|
||||
var guard_1 = require("./guard");
|
||||
Object.defineProperty(exports, "LoggedGuard", { enumerable: true, get: function () { return guard_1.LoggedGuard; } });
|
||||
var interceptor_1 = require("./interceptor");
|
||||
Object.defineProperty(exports, "LoggedInterceptor", { enumerable: true, get: function () { return interceptor_1.LoggedInterceptor; } });
|
||||
var middleware_1 = require("./middleware");
|
||||
Object.defineProperty(exports, "LoggedMiddleware", { enumerable: true, get: function () { return middleware_1.LoggedMiddleware; } });
|
3
dist/lib/logged/methods/interceptor.d.ts
vendored
Normal file
3
dist/lib/logged/methods/interceptor.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
import { ExecutionContext } from '@nestjs/common';
|
||||
export declare function LoggedInterceptor<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>) => void;
|
43
dist/lib/logged/methods/interceptor.js
vendored
Normal file
43
dist/lib/logged/methods/interceptor.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedInterceptor = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
const metadata_1 = require("../metadata");
|
||||
const reflected_1 = require("../../reflected");
|
||||
const override_1 = require("../override");
|
||||
function LoggedInterceptor(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
(0, utils_1.loggerInit)(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(`LoggedInterceptor decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(metadata_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new metadata_1.LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = (0, override_1.overrideBuild)('interceptor', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
}, _target.constructor.name, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(metadata_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedInterceptor = LoggedInterceptor;
|
3
dist/lib/logged/methods/middleware.d.ts
vendored
Normal file
3
dist/lib/logged/methods/middleware.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
import { ExecutionContext } from '@nestjs/common';
|
||||
export declare function LoggedMiddleware<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>) => void;
|
43
dist/lib/logged/methods/middleware.js
vendored
Normal file
43
dist/lib/logged/methods/middleware.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedMiddleware = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
const metadata_1 = require("../metadata");
|
||||
const reflected_1 = require("../../reflected");
|
||||
const override_1 = require("../override");
|
||||
function LoggedMiddleware(options) {
|
||||
return (_target, key, descriptor) => {
|
||||
(0, utils_1.loggerInit)(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(`LoggedMiddleware decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(metadata_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new metadata_1.LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = (0, override_1.overrideBuild)('middleware', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
}, _target.constructor.name, returnsData, newMetadata);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(metadata_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedMiddleware = LoggedMiddleware;
|
2
dist/lib/logged/methods/route.d.ts
vendored
Normal file
2
dist/lib/logged/methods/route.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
export declare function LoggedRoute<F extends Array<any>, R>(route?: string, options?: Partial<OverrideBuildOptions>): (_target: any, key: string, descriptor: TypedPropertyDescriptor<(...args: F) => R>) => void;
|
52
dist/lib/logged/methods/route.js
vendored
Normal file
52
dist/lib/logged/methods/route.js
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LoggedRoute = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
const metadata_1 = require("../metadata");
|
||||
const reflected_1 = require("../../reflected");
|
||||
const override_1 = require("../override");
|
||||
const nest_1 = require("../../internals/nest");
|
||||
function LoggedRoute(route, options) {
|
||||
return (_target, key, descriptor) => {
|
||||
(0, utils_1.loggerInit)(_target);
|
||||
const logger = _target.logger;
|
||||
const fn = descriptor.value;
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(`LoggedRoute decorator applied to non-function property: ${key}`);
|
||||
return;
|
||||
}
|
||||
const logMetadata = Reflect.getOwnMetadata(metadata_1.nestLoggedMetadata, _target, key);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new metadata_1.LoggedMetadata(options);
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
const httpPath = Reflect.getMetadata('path', fn);
|
||||
const httpMethod = Reflect.getMetadata('method', fn);
|
||||
const fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${utils_1.RevRequestMethod[httpMethod]}]`;
|
||||
const scopedLoggerInjectableParam = Reflect.getOwnMetadata(reflected_1.scopedLogger, _target, key);
|
||||
// if @InjectLogger exists, fake nestjs as it is @Req()
|
||||
if (scopedLoggerInjectableParam !== undefined) {
|
||||
(0, nest_1.createRouteParamDecorator)(0)()(_target, key, scopedLoggerInjectableParam);
|
||||
}
|
||||
const loggedParams = Reflect.getOwnMetadata(reflected_1.loggedParam, _target, key);
|
||||
const returnsData = Reflect.getOwnMetadata(reflected_1.returns, fn);
|
||||
const overrideFunction = (0, override_1.overrideBuild)('route', fn, logger, {
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
}, key, returnsData, newMetadata, fullRoute);
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
Reflect.defineMetadata(metadata_1.nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.LoggedRoute = LoggedRoute;
|
10
dist/lib/logged/override.d.ts
vendored
Normal file
10
dist/lib/logged/override.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { LoggedParamReflectData, ReturnsReflectData } from '../reflected';
|
||||
import { LoggedMetadata } from './metadata';
|
||||
interface FunctionMetadata {
|
||||
scopedLoggerInjectableParam?: number;
|
||||
loggedParams?: LoggedParamReflectData[];
|
||||
}
|
||||
export declare function overrideBuild<F extends Array<any>, R>(type: 'route', originalFunction: (...args: F) => R, baseLogger: Logger, metadatas: FunctionMetadata, key: string, returnsData: ReturnsReflectData[] | string | true, logged: LoggedMetadata, route: string): (...args: F) => R;
|
||||
export declare function overrideBuild<F extends Array<any>, R>(type: 'function' | 'guard' | 'interceptor' | 'middleware', originalFunction: (...args: F) => R, baseLogger: Logger, metadatas: FunctionMetadata, key: string, returnsData: ReturnsReflectData[] | string | true, logged: LoggedMetadata): (...args: F) => R;
|
||||
export {};
|
152
dist/lib/logged/override.js
vendored
Normal file
152
dist/lib/logged/override.js
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.overrideBuild = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
const utils_2 = require("../internals/utils");
|
||||
const logger_1 = require("../logger");
|
||||
function overrideBuild(type, originalFunction, baseLogger, metadatas, key, returnsData, logged, route) {
|
||||
return function (...args) {
|
||||
// Creating ScopedLogger
|
||||
let injectedLogger = baseLogger;
|
||||
if (typeof metadatas.scopedLoggerInjectableParam !== 'undefined') {
|
||||
if (type === 'function') {
|
||||
if (args.length <= metadatas.scopedLoggerInjectableParam ||
|
||||
!(args[metadatas.scopedLoggerInjectableParam] instanceof logger_1.ScopedLogger)) {
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key);
|
||||
}
|
||||
else {
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromSuper(baseLogger, args[metadatas.scopedLoggerInjectableParam], key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// special, can access to request object
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
// args[0] == ExecutionContext
|
||||
const ctx = args[0];
|
||||
if (ctx.getType() !== 'http') {
|
||||
injectedLogger.error('Cannot inject logger: Request type is not http');
|
||||
}
|
||||
else {
|
||||
let req = ctx.switchToHttp().getRequest();
|
||||
if (req[utils_1.REQUEST_LOG_ID] === undefined) {
|
||||
req[utils_1.REQUEST_LOG_ID] = logger_1.ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key, req[utils_1.REQUEST_LOG_ID]);
|
||||
}
|
||||
}
|
||||
else if (type === 'middleware') {
|
||||
let req = args[0];
|
||||
if (req[utils_1.REQUEST_LOG_ID] === undefined) {
|
||||
req[utils_1.REQUEST_LOG_ID] = logger_1.ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key, req[utils_1.REQUEST_LOG_ID]);
|
||||
}
|
||||
else if (type === 'route') {
|
||||
// args[metadatas.scopedLoggerInjectableParam] is now Request object, thanks to code in @LoggedRoute!!!!
|
||||
let req = args[metadatas.scopedLoggerInjectableParam];
|
||||
if (req[utils_1.REQUEST_LOG_ID] === undefined) {
|
||||
req[utils_1.REQUEST_LOG_ID] = logger_1.ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = logger_1.ScopedLogger.fromRoot(baseLogger, key, req[utils_1.REQUEST_LOG_ID]);
|
||||
}
|
||||
}
|
||||
injectedLogger = args[metadatas.scopedLoggerInjectableParam];
|
||||
}
|
||||
// If this is ExecutionContext based function (e.g. Guard, Interceptor) get Request from Context
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
const context = args[0];
|
||||
if (context.getType() === 'http') {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
route = /* supporting FastifyRequest */ req.raw ? req.raw.url : req.url;
|
||||
}
|
||||
}
|
||||
// Start Log
|
||||
if (logged.options.callLogLevel !== 'skip') {
|
||||
const callLogIdentifyMessage = type === 'middleware' ||
|
||||
type === 'guard' ||
|
||||
type === 'interceptor' ||
|
||||
type === 'route'
|
||||
? (0, utils_1.createCallLogIdentifyMessage)('HIT', type, key, route)
|
||||
: (0, utils_1.createCallLogIdentifyMessage)('HIT', type, key);
|
||||
injectedLogger[logged.options.callLogLevel](`${callLogIdentifyMessage} ${metadatas.loggedParams && metadatas.loggedParams.length > 0
|
||||
? 'WITH ' +
|
||||
metadatas.loggedParams
|
||||
.map(({ name, index, include, exclude }) => name +
|
||||
'=' +
|
||||
(0, utils_2.objectContainedLogSync)(args[index], {
|
||||
include,
|
||||
exclude,
|
||||
}))
|
||||
.join(', ')
|
||||
: ''}`);
|
||||
}
|
||||
try {
|
||||
const r = originalFunction.call(this, ...args); // Try to call original function
|
||||
// Return Log
|
||||
if (logged.options.returnLogLevel !== 'skip') {
|
||||
if (originalFunction.constructor.name === 'AsyncFunction' ||
|
||||
(r && typeof r === 'object' && typeof r['then'] === 'function')) {
|
||||
return r['then']((r) => {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === 'object' && r !== null
|
||||
? 'WITH ' +
|
||||
returnsData
|
||||
.map(({ name, path }) => {
|
||||
const value = (0, utils_2.getItemByPathSync)(r, path);
|
||||
return value !== undefined ? `${name}=${value}` : '';
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(', ')
|
||||
: ''
|
||||
: typeof returnsData === 'string'
|
||||
? 'WITH ' + returnsData + '=' + typeof r === 'object'
|
||||
? JSON.stringify(r)
|
||||
: r
|
||||
: returnsData
|
||||
? typeof r === 'object'
|
||||
? 'WITH ' + JSON.stringify(r)
|
||||
: 'WITH ' + r
|
||||
: '';
|
||||
injectedLogger[logged.options.returnLogLevel](`${(0, utils_1.createCallLogIdentifyMessage)('RETURNED', type, key, route)} ${resultLogged}`);
|
||||
return r;
|
||||
});
|
||||
}
|
||||
else {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === 'object' && r !== null
|
||||
? 'WITH ' +
|
||||
returnsData
|
||||
.map(({ name, path }) => {
|
||||
const value = (0, utils_2.getItemByPathSync)(r, path);
|
||||
return value !== undefined ? `${name}=${value}` : '';
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(', ')
|
||||
: ''
|
||||
: typeof returnsData === 'string'
|
||||
? 'WITH ' + returnsData + '=' + typeof r === 'object'
|
||||
? JSON.stringify(r)
|
||||
: r
|
||||
: returnsData
|
||||
? typeof r === 'object'
|
||||
? 'WITH ' + JSON.stringify(r)
|
||||
: 'WITH ' + r
|
||||
: '';
|
||||
injectedLogger[logged.options.returnLogLevel](`${(0, utils_1.createCallLogIdentifyMessage)('RETURNED', type, key, route)} ${resultLogged}`);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Error Log
|
||||
if (logged.options.errorLogLevel !== 'skip') {
|
||||
injectedLogger[logged.options.errorLogLevel](`${(0, utils_1.createCallLogIdentifyMessage)('ERROR', type, key, route)} ${e}`);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.overrideBuild = overrideBuild;
|
18
dist/lib/logged/utils.d.ts
vendored
Normal file
18
dist/lib/logged/utils.d.ts
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
import { LogLevel } from '@nestjs/common';
|
||||
export declare const RevRequestMethod: string[];
|
||||
export declare function loggerInit(_target: any): void;
|
||||
export type BuildType = 'route' | 'function' | 'guard' | 'interceptor' | 'middleware';
|
||||
export declare function createCallLogIdentifyMessage(message: 'HIT' | 'RETURNED' | 'ERROR', type: BuildType, key?: string, route?: string): string;
|
||||
export declare const REQUEST_LOG_ID = "__nestlogged_request_log_id__";
|
||||
export interface OverrideBuildOptions {
|
||||
callLogLevel: LogLevel | 'skip';
|
||||
returnLogLevel: LogLevel | 'skip';
|
||||
errorLogLevel: LogLevel | 'skip';
|
||||
/** @deprecated use `callLogLevel: 'skip'` instead */
|
||||
skipCallLog: boolean;
|
||||
/** @deprecated use `returnLogLevel: 'skip'` instead */
|
||||
skipReturnLog: boolean;
|
||||
/** @deprecated use `errorLogLevel: 'skip'` instead */
|
||||
skipErrorLog: boolean;
|
||||
}
|
||||
export declare const defaultOverrideBuildOptions: OverrideBuildOptions;
|
57
dist/lib/logged/utils.js
vendored
Normal file
57
dist/lib/logged/utils.js
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.defaultOverrideBuildOptions = exports.REQUEST_LOG_ID = exports.createCallLogIdentifyMessage = exports.loggerInit = exports.RevRequestMethod = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
exports.RevRequestMethod = [
|
||||
'GET',
|
||||
'POST',
|
||||
'PUT',
|
||||
'DELETE',
|
||||
'PATCH',
|
||||
'ALL',
|
||||
'OPTIONS',
|
||||
'HEAD',
|
||||
'SEARCH',
|
||||
];
|
||||
function loggerInit(_target) {
|
||||
if (!Object.getOwnPropertyNames(_target).includes('logger')) {
|
||||
const newTargetLogger = new common_1.Logger(_target.constructor.name);
|
||||
newTargetLogger.log('Logger Initialized.');
|
||||
Object.defineProperty(_target, 'logger', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
value: newTargetLogger,
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.loggerInit = loggerInit;
|
||||
const callLogIdentifyMessageDictionary = {
|
||||
route: 'ENDPOINT',
|
||||
function: 'FUNCTION',
|
||||
guard: 'GUARD',
|
||||
interceptor: 'INTERCEPTOR',
|
||||
middleware: 'MIDDLEWARE',
|
||||
};
|
||||
function createCallLogIdentifyMessage(message, type, key, route) {
|
||||
if (message === 'ERROR')
|
||||
return `ERROR WHILE ${callLogIdentifyMessageDictionary[type]} ${key} (${route}): `;
|
||||
if (type === 'guard' ||
|
||||
type === 'interceptor' ||
|
||||
type === 'middleware' ||
|
||||
type === 'route')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key} (${route})`;
|
||||
if (type === 'function')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key}`;
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]}`;
|
||||
}
|
||||
exports.createCallLogIdentifyMessage = createCallLogIdentifyMessage;
|
||||
exports.REQUEST_LOG_ID = '__nestlogged_request_log_id__';
|
||||
exports.defaultOverrideBuildOptions = {
|
||||
callLogLevel: 'log',
|
||||
returnLogLevel: 'log',
|
||||
errorLogLevel: 'error',
|
||||
skipCallLog: false,
|
||||
skipReturnLog: false,
|
||||
skipErrorLog: false,
|
||||
};
|
2
dist/lib/logger.d.ts
vendored
2
dist/lib/logger.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { Logger } from '@nestjs/common';
|
||||
export declare class ScopedLogger extends Logger {
|
||||
private logger;
|
||||
private scope;
|
||||
|
16
dist/lib/logger.js
vendored
16
dist/lib/logger.js
vendored
@ -10,26 +10,24 @@ class ScopedLogger extends common_1.Logger {
|
||||
this.logger = logger;
|
||||
this.scope = scope;
|
||||
this.scopeId = scopeId;
|
||||
this.debug = this.scopedLog("debug");
|
||||
this.log = this.scopedLog("log");
|
||||
this.warn = this.scopedLog("warn");
|
||||
this.verbose = this.scopedLog("verbose");
|
||||
this.error = this.scopedLog("error");
|
||||
this.fatal = this.scopedLog("fatal");
|
||||
this.debug = this.scopedLog('debug');
|
||||
this.log = this.scopedLog('log');
|
||||
this.warn = this.scopedLog('warn');
|
||||
this.verbose = this.scopedLog('verbose');
|
||||
this.error = this.scopedLog('error');
|
||||
this.fatal = this.scopedLog('fatal');
|
||||
}
|
||||
scopedLog(method) {
|
||||
return (message) => {
|
||||
this.logger[method](`${this.scopeId ? `(ID ${this.scopeId}) | ` : ""}${this.scope.join(" -> ")}: ${message}`);
|
||||
this.logger[method](`${this.scopeId ? `(ID ${this.scopeId}) | ` : ''}${this.scope.join(' -> ')}: ${message}`);
|
||||
};
|
||||
}
|
||||
static fromSuper(baseLogger, logger, scope) {
|
||||
return new ScopedLogger(baseLogger, [...logger.scope, scope], logger.scopeId);
|
||||
}
|
||||
;
|
||||
static fromRoot(logger, scope, scopeId) {
|
||||
return new ScopedLogger(logger, [scope], scopeId);
|
||||
}
|
||||
;
|
||||
static createScopeId() {
|
||||
return createId();
|
||||
}
|
||||
|
5
dist/lib/reflected.d.ts
vendored
5
dist/lib/reflected.d.ts
vendored
@ -1,6 +1,4 @@
|
||||
import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
|
||||
import { ParamData, PipeTransform, Type } from "@nestjs/common";
|
||||
export declare function createRouteParamDecorator(paramtype: RouteParamtypes): (data?: ParamData) => ParameterDecorator;
|
||||
import { Type, PipeTransform } from './internals/nest';
|
||||
export type Path = string | string[];
|
||||
export type Paths = Path[];
|
||||
export interface IncludeExcludePath {
|
||||
@ -26,7 +24,6 @@ export interface ReturnsReflectData {
|
||||
export declare const scopedLogger: unique symbol;
|
||||
export declare const loggedParam: unique symbol;
|
||||
export declare const returns: unique symbol;
|
||||
export declare const nestLoggedMetadata: unique symbol;
|
||||
export declare function InjectLogger(target: any, propertyKey: string | symbol, parameterIndex: number): void;
|
||||
type ParameterDecoratorType = (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
||||
type LoggedParamReturns = (name: string, options?: IncludeExcludePath) => ParameterDecoratorType;
|
||||
|
40
dist/lib/reflected.js
vendored
40
dist/lib/reflected.js
vendored
@ -1,28 +1,10 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Returns = exports.LoggedHeaders = exports.LoggedBody = exports.LoggedQuery = exports.LoggedParam = exports.Logged = exports.InjectLogger = exports.nestLoggedMetadata = exports.returns = exports.loggedParam = exports.scopedLogger = exports.createRouteParamDecorator = void 0;
|
||||
const route_paramtypes_enum_1 = require("@nestjs/common/enums/route-paramtypes.enum");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
||||
const ROUTE_ARGS_METADATA = '__routeArguments__';
|
||||
function createRouteParamDecorator(paramtype) {
|
||||
return (data) => (target, key, index) => {
|
||||
const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.defineMetadata(ROUTE_ARGS_METADATA, (0, common_1.assignMetadata)(args, paramtype, index, data), target.constructor, key);
|
||||
};
|
||||
}
|
||||
exports.createRouteParamDecorator = createRouteParamDecorator;
|
||||
const createPipesRouteParamDecorator = (paramtype) => (data, ...pipes) => (target, key, index) => {
|
||||
const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
const hasParamData = (0, shared_utils_1.isNil)(data) || (0, shared_utils_1.isString)(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
Reflect.defineMetadata(ROUTE_ARGS_METADATA, (0, common_1.assignMetadata)(args, paramtype, index, paramData, ...paramPipes), target.constructor, key);
|
||||
};
|
||||
exports.scopedLogger = Symbol("nlogdec-scopedLogger");
|
||||
exports.loggedParam = Symbol("nlogdec-loggedParam");
|
||||
exports.returns = Symbol("nlogdec-returns");
|
||||
exports.nestLoggedMetadata = Symbol("nlogdec-metadata");
|
||||
exports.Returns = exports.LoggedHeaders = exports.LoggedBody = exports.LoggedQuery = exports.LoggedParam = exports.Logged = exports.InjectLogger = exports.returns = exports.loggedParam = exports.scopedLogger = void 0;
|
||||
const nest_1 = require("./internals/nest");
|
||||
exports.scopedLogger = Symbol('nlogdec-scopedLogger');
|
||||
exports.loggedParam = Symbol('nlogdec-loggedParam');
|
||||
exports.returns = Symbol('nlogdec-returns');
|
||||
function InjectLogger(target, propertyKey, parameterIndex) {
|
||||
Reflect.defineMetadata(exports.scopedLogger, parameterIndex, target, propertyKey);
|
||||
}
|
||||
@ -36,10 +18,10 @@ function createLoggedFunctionParam(name, options) {
|
||||
// If path is provided in string[] type, convert it to string path because it is used in string type
|
||||
include: options &&
|
||||
options.includePath &&
|
||||
options.includePath.map((v) => (Array.isArray(v) ? v.join(".") : v)),
|
||||
options.includePath.map((v) => (Array.isArray(v) ? v.join('.') : v)),
|
||||
exclude: options &&
|
||||
options.excludePath &&
|
||||
options.excludePath.map((v) => (Array.isArray(v) ? v.join(".") : v)),
|
||||
options.excludePath.map((v) => (Array.isArray(v) ? v.join('.') : v)),
|
||||
});
|
||||
Reflect.defineMetadata(exports.loggedParam, existingLoggedParams, target, propertyKey);
|
||||
};
|
||||
@ -49,7 +31,7 @@ exports.Logged = Logged;
|
||||
function LoggedParam(property, ...pipes) {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.PARAM)(property, ...pipes)(target, propertyKey, parameterIndex);
|
||||
(0, nest_1.createPipesRouteParamDecorator)(nest_1.RouteParamtypes.PARAM)(property, ...pipes)(target, propertyKey, parameterIndex);
|
||||
createLoggedFunctionParam(name, options)(target, propertyKey, parameterIndex);
|
||||
};
|
||||
};
|
||||
@ -58,7 +40,7 @@ exports.LoggedParam = LoggedParam;
|
||||
function LoggedQuery(property, ...pipes) {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.QUERY)(property, ...pipes)(target, propertyKey, parameterIndex);
|
||||
(0, nest_1.createPipesRouteParamDecorator)(nest_1.RouteParamtypes.QUERY)(property, ...pipes)(target, propertyKey, parameterIndex);
|
||||
createLoggedFunctionParam(name, options)(target, propertyKey, parameterIndex);
|
||||
};
|
||||
};
|
||||
@ -67,7 +49,7 @@ exports.LoggedQuery = LoggedQuery;
|
||||
function LoggedBody(property, ...pipes) {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.BODY)(property, ...pipes)(target, propertyKey, parameterIndex);
|
||||
(0, nest_1.createPipesRouteParamDecorator)(nest_1.RouteParamtypes.BODY)(property, ...pipes)(target, propertyKey, parameterIndex);
|
||||
createLoggedFunctionParam(name, options)(target, propertyKey, parameterIndex);
|
||||
};
|
||||
};
|
||||
@ -76,7 +58,7 @@ exports.LoggedBody = LoggedBody;
|
||||
function LoggedHeaders(property) {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.HEADERS)(property)(target, propertyKey, parameterIndex);
|
||||
(0, nest_1.createRouteParamDecorator)(nest_1.RouteParamtypes.HEADERS)(property)(target, propertyKey, parameterIndex);
|
||||
createLoggedFunctionParam(name, options)(target, propertyKey, parameterIndex);
|
||||
};
|
||||
};
|
||||
|
2
dist/lib/utils.d.ts
vendored
2
dist/lib/utils.d.ts
vendored
@ -1,2 +1,2 @@
|
||||
import { ScopedLogger } from "./logger";
|
||||
import { ScopedLogger } from './logger';
|
||||
export declare function getRequestLogger(functionName: string, req: any): ScopedLogger;
|
||||
|
4
dist/lib/utils.js
vendored
4
dist/lib/utils.js
vendored
@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getRequestLogger = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const logger_1 = require("./logger");
|
||||
const logged_1 = require("./logged");
|
||||
const utils_1 = require("./logged/utils");
|
||||
const logger = new common_1.Logger();
|
||||
function getRequestLogger(functionName, req) {
|
||||
return new logger_1.ScopedLogger(logger, [functionName], req[logged_1.REQUEST_LOG_ID]);
|
||||
return new logger_1.ScopedLogger(logger, [functionName], req[utils_1.REQUEST_LOG_ID]);
|
||||
}
|
||||
exports.getRequestLogger = getRequestLogger;
|
||||
|
2
dist/package.json
vendored
2
dist/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nestlogged",
|
||||
"version": "3.2.0",
|
||||
"version": "3.2.1",
|
||||
"description": "A NestJS Logger Decorator Library",
|
||||
"main": "lib/index.js",
|
||||
"repository": "https://git.psw.kr/p-sw/nestlogged",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nestlogged",
|
||||
"version": "3.2.0",
|
||||
"version": "3.2.1",
|
||||
"description": "A NestJS Logger Decorator Library",
|
||||
"main": "./dist/lib/index.js",
|
||||
"repository": "https://git.psw.kr/p-sw/nestlogged",
|
||||
@ -15,6 +15,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.9.1",
|
||||
"prettier": "^3.5.3",
|
||||
"rimraf": "^5.0.5",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
@ -24,7 +25,8 @@
|
||||
"build": "rimraf ./dist/lib && tsc --project tsconfig.build.json",
|
||||
"up": "yarn docs && yarn build && yarn npm publish dist",
|
||||
"up:beta": "yarn docs && yarn build && yarn npm publish dist --tag beta",
|
||||
"test": "ts-node ./src/test/index.ts"
|
||||
"test": "ts-node ./src/test/index.ts",
|
||||
"format": "prettier --write \"./src/**/*.ts\""
|
||||
},
|
||||
"packageManager": "yarn@4.7.0+sha512.5a0afa1d4c1d844b3447ee3319633797bcd6385d9a44be07993ae52ff4facabccafb4af5dcd1c2f9a94ac113e5e9ff56f6130431905884414229e284e37bb7c9"
|
||||
}
|
||||
|
166
src/functions.ts
166
src/functions.ts
@ -1,166 +0,0 @@
|
||||
export const notIncludedSymbol = Symbol("notIncluded");
|
||||
|
||||
export function includeObjectSync(
|
||||
ocv: any,
|
||||
opt: {
|
||||
paths: string[],
|
||||
}
|
||||
) {
|
||||
let current = Array.isArray(ocv) ? [] : typeof ocv === 'object' ? {} : ocv
|
||||
opt.paths.forEach((dotpath) => {
|
||||
let query = ocv;
|
||||
let objRef = current;
|
||||
const path = dotpath.split('.');
|
||||
for (const [index, key] of Object.entries(path)) {
|
||||
query = query[key]
|
||||
if (query !== undefined && objRef[key] === undefined) {
|
||||
if (typeof query === 'object') {
|
||||
if (Array.isArray(query)) {
|
||||
objRef[key] = []
|
||||
} else {
|
||||
objRef[key] = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof query !== 'object' || index === (path.length - 1).toString()) {
|
||||
objRef[key] = query;
|
||||
break
|
||||
}
|
||||
objRef = objRef[key]
|
||||
}
|
||||
})
|
||||
return current;
|
||||
}
|
||||
|
||||
export function excludeObjectSync(
|
||||
ocv: any,
|
||||
opt: {
|
||||
paths: string[]
|
||||
}
|
||||
) {
|
||||
const copied = typeof ocv === 'object' ? Array.isArray(ocv) ? [...ocv] : { ...ocv } : ocv;
|
||||
opt.paths.forEach((dotpath) => {
|
||||
let objRef = copied;
|
||||
const path = dotpath.split('.')
|
||||
const lastIndex = (path.length - 1).toString()
|
||||
for (const [index, key] of Object.entries(path)) {
|
||||
if (index === lastIndex) {
|
||||
delete objRef[key];
|
||||
break;
|
||||
}
|
||||
objRef = objRef[key];
|
||||
if (typeof objRef !== 'object') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return copied
|
||||
}
|
||||
|
||||
export function includeOrExcludeObjectSync(
|
||||
ocv: any,
|
||||
paths: string[],
|
||||
currentPath: string[] = [],
|
||||
include: boolean // or exclude
|
||||
) {
|
||||
if (Array.isArray(ocv)) {
|
||||
return (
|
||||
ocv.map(
|
||||
(v, i) =>
|
||||
includeOrExcludeObjectSync(
|
||||
v,
|
||||
paths,
|
||||
[...currentPath, i.toString()],
|
||||
include
|
||||
)
|
||||
)
|
||||
).filter((e) => e !== notIncludedSymbol);
|
||||
}
|
||||
|
||||
if (typeof ocv === "object") {
|
||||
return Object.fromEntries(
|
||||
Object.entries(ocv).map(([key, value]) => [
|
||||
key,
|
||||
includeOrExcludeObjectSync(
|
||||
value,
|
||||
paths,
|
||||
[...currentPath, key],
|
||||
include
|
||||
),
|
||||
]).filter((e) => e[1] !== notIncludedSymbol)
|
||||
);
|
||||
}
|
||||
|
||||
const isIncluded = paths.includes(currentPath.join("."));
|
||||
|
||||
return include
|
||||
? isIncluded // include mode, path is in list
|
||||
? ocv
|
||||
: notIncludedSymbol
|
||||
: isIncluded // exclude mode, path is in list
|
||||
? notIncludedSymbol
|
||||
: ocv;
|
||||
}
|
||||
|
||||
|
||||
export function objectContainedLoggedSync(
|
||||
ocv: any,
|
||||
options?: { include?: string[]; exclude: string[] }
|
||||
): string {
|
||||
if (options && typeof ocv === "object") {
|
||||
if (options.include && options.include.length > 0) {
|
||||
return JSON.stringify(
|
||||
includeOrExcludeObjectSync(ocv, options.include, [], true)
|
||||
);
|
||||
}
|
||||
if (options.exclude && options.exclude.length > 0) {
|
||||
return JSON.stringify(
|
||||
includeOrExcludeObjectSync(ocv, options.exclude, [], false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof ocv === "object") {
|
||||
return JSON.stringify(ocv);
|
||||
} else {
|
||||
return `${ocv}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function imObjectContainedLogSync(
|
||||
ocv: any,
|
||||
options?: {
|
||||
include?: string[];
|
||||
exclude?: string[];
|
||||
}
|
||||
): string {
|
||||
if (options && typeof ocv === 'object' && ocv !== null) {
|
||||
if (options.include && options.include.length > 0) {
|
||||
return JSON.stringify(
|
||||
includeObjectSync(ocv, { paths: options.include })
|
||||
);
|
||||
}
|
||||
if (options.exclude && options.exclude.length > 0) {
|
||||
return JSON.stringify(
|
||||
excludeObjectSync(ocv, { paths: options.exclude })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof ocv === "object" && ocv !== null) {
|
||||
return JSON.stringify(ocv);
|
||||
} else {
|
||||
return `${ocv}`
|
||||
}
|
||||
}
|
||||
|
||||
export function getItemByPathSync(obj: object, path: string | string[]) {
|
||||
const paths = Array.isArray(path) ? path : path.split(".");
|
||||
|
||||
return Object.keys(obj).includes(paths[0])
|
||||
? typeof obj[paths[0]] === "object"
|
||||
? getItemByPathSync(obj[paths[0]], paths.slice(1))
|
||||
: obj[paths[0]]
|
||||
: undefined;
|
||||
}
|
12
src/index.ts
12
src/index.ts
@ -5,8 +5,8 @@ export {
|
||||
LoggedInjectable,
|
||||
LoggedGuard,
|
||||
LoggedInterceptor,
|
||||
} from "./logged";
|
||||
export { ScopedLogger } from "./logger";
|
||||
} from './logged';
|
||||
export { ScopedLogger } from './logger';
|
||||
export {
|
||||
InjectLogger,
|
||||
LoggedParam,
|
||||
@ -14,8 +14,6 @@ export {
|
||||
LoggedBody,
|
||||
LoggedQuery,
|
||||
Logged,
|
||||
Returns
|
||||
} from "./reflected";
|
||||
export {
|
||||
getRequestLogger
|
||||
} from './utils'
|
||||
Returns,
|
||||
} from './reflected';
|
||||
export { getRequestLogger } from './utils';
|
||||
|
52
src/internals/nest.ts
Normal file
52
src/internals/nest.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
|
||||
import {
|
||||
assignMetadata,
|
||||
ParamData,
|
||||
PipeTransform,
|
||||
RouteParamMetadata,
|
||||
Type,
|
||||
} from '@nestjs/common';
|
||||
import { ROUTE_ARGS_METADATA } from '@nestjs/common/constants';
|
||||
import { isNil, isString } from '@nestjs/common/utils/shared.utils';
|
||||
|
||||
export { RouteParamtypes, PipeTransform, Type, ROUTE_ARGS_METADATA };
|
||||
|
||||
export function createRouteParamDecorator(paramtype: RouteParamtypes) {
|
||||
return (data?: ParamData): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata<RouteParamtypes, Record<number, RouteParamMetadata>>(
|
||||
args,
|
||||
paramtype,
|
||||
index,
|
||||
data,
|
||||
),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const createPipesRouteParamDecorator =
|
||||
(paramtype: RouteParamtypes) =>
|
||||
(
|
||||
data?: any,
|
||||
...pipes: (Type<PipeTransform> | PipeTransform)[]
|
||||
): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
const hasParamData = isNil(data) || isString(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, paramData, ...paramPipes),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
97
src/internals/utils.ts
Normal file
97
src/internals/utils.ts
Normal file
@ -0,0 +1,97 @@
|
||||
export const notIncludedSymbol = Symbol('notIncluded');
|
||||
|
||||
export function includeObjectSync(
|
||||
ocv: any,
|
||||
opt: {
|
||||
paths: string[];
|
||||
},
|
||||
) {
|
||||
let current = Array.isArray(ocv) ? [] : typeof ocv === 'object' ? {} : ocv;
|
||||
opt.paths.forEach((dotpath) => {
|
||||
let query = ocv;
|
||||
let objRef = current;
|
||||
const path = dotpath.split('.');
|
||||
for (const [index, key] of Object.entries(path)) {
|
||||
query = query[key];
|
||||
if (query !== undefined && objRef[key] === undefined) {
|
||||
if (typeof query === 'object') {
|
||||
if (Array.isArray(query)) {
|
||||
objRef[key] = [];
|
||||
} else {
|
||||
objRef[key] = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof query !== 'object' || index === (path.length - 1).toString()) {
|
||||
objRef[key] = query;
|
||||
break;
|
||||
}
|
||||
objRef = objRef[key];
|
||||
}
|
||||
});
|
||||
return current;
|
||||
}
|
||||
|
||||
export function excludeObjectSync(
|
||||
ocv: any,
|
||||
opt: {
|
||||
paths: string[];
|
||||
},
|
||||
) {
|
||||
const copied =
|
||||
typeof ocv === 'object'
|
||||
? Array.isArray(ocv)
|
||||
? [...ocv]
|
||||
: { ...ocv }
|
||||
: ocv;
|
||||
opt.paths.forEach((dotpath) => {
|
||||
let objRef = copied;
|
||||
const path = dotpath.split('.');
|
||||
const lastIndex = (path.length - 1).toString();
|
||||
for (const [index, key] of Object.entries(path)) {
|
||||
if (index === lastIndex) {
|
||||
delete objRef[key];
|
||||
break;
|
||||
}
|
||||
objRef = objRef[key];
|
||||
if (typeof objRef !== 'object') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
||||
export function objectContainedLogSync(
|
||||
ocv: any,
|
||||
options?: {
|
||||
include?: string[];
|
||||
exclude?: string[];
|
||||
},
|
||||
): string {
|
||||
if (options && typeof ocv === 'object' && ocv !== null) {
|
||||
if (options.include && options.include.length > 0) {
|
||||
return JSON.stringify(includeObjectSync(ocv, { paths: options.include }));
|
||||
}
|
||||
if (options.exclude && options.exclude.length > 0) {
|
||||
return JSON.stringify(excludeObjectSync(ocv, { paths: options.exclude }));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof ocv === 'object' && ocv !== null) {
|
||||
return JSON.stringify(ocv);
|
||||
} else {
|
||||
return `${ocv}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function getItemByPathSync(obj: object, path: string | string[]) {
|
||||
const paths = Array.isArray(path) ? path : path.split('.');
|
||||
|
||||
return Object.keys(obj).includes(paths[0])
|
||||
? typeof obj[paths[0]] === 'object'
|
||||
? getItemByPathSync(obj[paths[0]], paths.slice(1))
|
||||
: obj[paths[0]]
|
||||
: undefined;
|
||||
}
|
767
src/logged.ts
767
src/logged.ts
@ -1,767 +0,0 @@
|
||||
import {
|
||||
Logger,
|
||||
LogLevel,
|
||||
Injectable,
|
||||
Controller,
|
||||
ControllerOptions,
|
||||
ScopeOptions,
|
||||
ExecutionContext,
|
||||
} from "@nestjs/common";
|
||||
import { ScopedLogger } from "./logger";
|
||||
import {
|
||||
LoggedParamReflectData,
|
||||
ReturnsReflectData,
|
||||
returns,
|
||||
nestLoggedMetadata,
|
||||
loggedParam,
|
||||
scopedLogger,
|
||||
createRouteParamDecorator
|
||||
} from "./reflected";
|
||||
import { imObjectContainedLogSync, getItemByPathSync } from "./functions";
|
||||
import { RequestMethod } from "@nestjs/common";
|
||||
|
||||
const RevRequestMethod = [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"PATCH",
|
||||
"ALL",
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"SEARCH",
|
||||
];
|
||||
|
||||
function loggerInit(_target: any) {
|
||||
if (!Object.getOwnPropertyNames(_target).includes("logger")) {
|
||||
const newTargetLogger = new Logger(_target.constructor.name);
|
||||
newTargetLogger.log("Logger Initialized.");
|
||||
Object.defineProperty(_target, "logger", {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
value: newTargetLogger,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function LoggedInjectable(
|
||||
options?: ScopeOptions & { verbose?: boolean }
|
||||
) {
|
||||
return (target: any) => {
|
||||
loggerInit(target.prototype);
|
||||
|
||||
const logger = target.prototype.logger;
|
||||
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
|
||||
methods.forEach((method) => {
|
||||
if (
|
||||
method !== "constructor" &&
|
||||
typeof target.prototype[method] === "function"
|
||||
) {
|
||||
if (options && options.verbose)
|
||||
logger.log(`LoggedFunction applied to ${method}`);
|
||||
LoggedFunction()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Injectable(options)(target);
|
||||
};
|
||||
}
|
||||
|
||||
export function LoggedController(): (target: any) => void;
|
||||
export function LoggedController(
|
||||
prefix: string | string[]
|
||||
): (target: any) => void;
|
||||
export function LoggedController(
|
||||
options: ControllerOptions & { verbose?: boolean }
|
||||
): (target: any) => void;
|
||||
|
||||
export function LoggedController(param?: any): (target: any) => void {
|
||||
return (target: any) => {
|
||||
loggerInit(target.prototype);
|
||||
|
||||
const logger = target.prototype.logger;
|
||||
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
|
||||
let verbose =
|
||||
typeof param === "object" && Object.keys(param).includes("verbose")
|
||||
? param.verbose
|
||||
: false;
|
||||
|
||||
methods.forEach((method) => {
|
||||
if (
|
||||
method !== "constructor" &&
|
||||
typeof target.prototype[method] === "function"
|
||||
) {
|
||||
if (verbose) {
|
||||
const path = Reflect.getMetadata("path", target.prototype[method]);
|
||||
const httpMethod = Reflect.getMetadata(
|
||||
"method",
|
||||
target.prototype[method]
|
||||
);
|
||||
logger.log(
|
||||
`LoggedRoute applied to ${method} (${RevRequestMethod[httpMethod]} ${path})`
|
||||
);
|
||||
}
|
||||
LoggedRoute()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Controller(param)(target);
|
||||
};
|
||||
}
|
||||
|
||||
interface FunctionMetadata {
|
||||
scopedLoggerInjectableParam?: number;
|
||||
loggedParams?: LoggedParamReflectData[];
|
||||
}
|
||||
|
||||
interface OverrideBuildOptions {
|
||||
callLogLevel: LogLevel | 'skip';
|
||||
returnLogLevel: LogLevel | 'skip';
|
||||
errorLogLevel: LogLevel | 'skip';
|
||||
/** @deprecated use `callLogLevel: 'skip'` instead */
|
||||
skipCallLog: boolean;
|
||||
/** @deprecated use `returnLogLevel: 'skip'` instead */
|
||||
skipReturnLog: boolean;
|
||||
/** @deprecated use `errorLogLevel: 'skip'` instead */
|
||||
skipErrorLog: boolean;
|
||||
}
|
||||
|
||||
const defaultOverrideBuildOptions: OverrideBuildOptions = {
|
||||
callLogLevel: 'log',
|
||||
returnLogLevel: 'log',
|
||||
errorLogLevel: 'error',
|
||||
skipCallLog: false,
|
||||
skipReturnLog: false,
|
||||
skipErrorLog: false,
|
||||
}
|
||||
|
||||
class LoggedMetadata {
|
||||
options: OverrideBuildOptions
|
||||
|
||||
constructor(options?: Partial<OverrideBuildOptions>) {
|
||||
this.options = {
|
||||
...defaultOverrideBuildOptions,
|
||||
...(options ?? {}),
|
||||
}
|
||||
}
|
||||
|
||||
updateOption(options: Partial<OverrideBuildOptions>) {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type BuildType = 'route' | 'function' | 'guard' | 'interceptor' | 'middleware';
|
||||
|
||||
const callLogIdentifyMessageDictionary: Record<BuildType, string> = {
|
||||
route: 'ENDPOINT',
|
||||
function: 'FUNCTION',
|
||||
guard: 'GUARD',
|
||||
interceptor: 'INTERCEPTOR',
|
||||
middleware: 'MIDDLEWARE',
|
||||
}
|
||||
|
||||
function createCallLogIdentifyMessage(message: 'HIT' | 'RETURNED' | 'ERROR', type: BuildType, key?: string, route?: string) {
|
||||
if (message === 'ERROR')
|
||||
return `ERROR WHILE ${callLogIdentifyMessageDictionary[type]} ${key} (${route}): `;
|
||||
|
||||
if (type === 'guard' || type === 'interceptor' || type === 'middleware' || type === 'route')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key} (${route})`
|
||||
if (type === 'function')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key}`;
|
||||
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]}`;
|
||||
}
|
||||
|
||||
export const REQUEST_LOG_ID = '__nestlogged_request_log_id__';
|
||||
|
||||
function overrideBuild<F extends Array<any>, R>(
|
||||
type: 'route',
|
||||
originalFunction: (...args: F) => R,
|
||||
baseLogger: Logger,
|
||||
metadatas: FunctionMetadata,
|
||||
key: string,
|
||||
returnsData: ReturnsReflectData[] | string | true,
|
||||
logged: LoggedMetadata,
|
||||
route: string,
|
||||
): (...args: F) => R;
|
||||
function overrideBuild<F extends Array<any>, R>(
|
||||
type: 'function' | 'guard' | 'interceptor' | 'middleware',
|
||||
originalFunction: (...args: F) => R,
|
||||
baseLogger: Logger,
|
||||
metadatas: FunctionMetadata,
|
||||
key: string,
|
||||
returnsData: ReturnsReflectData[] | string | true,
|
||||
logged: LoggedMetadata,
|
||||
): (...args: F) => R;
|
||||
function overrideBuild<F extends Array<any>, R>(
|
||||
type: BuildType,
|
||||
originalFunction: (...args: F) => R,
|
||||
baseLogger: Logger,
|
||||
metadatas: FunctionMetadata,
|
||||
key: string,
|
||||
returnsData: ReturnsReflectData[] | string | true,
|
||||
logged: LoggedMetadata,
|
||||
route?: string,
|
||||
): (...args: F) => R {
|
||||
return function (...args: F): R {
|
||||
// Creating ScopedLogger
|
||||
let injectedLogger: Logger = baseLogger;
|
||||
if (typeof metadatas.scopedLoggerInjectableParam !== "undefined") {
|
||||
if (type === 'function') {
|
||||
if (
|
||||
args.length <= metadatas.scopedLoggerInjectableParam ||
|
||||
!(args[metadatas.scopedLoggerInjectableParam] instanceof ScopedLogger)
|
||||
) {
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(baseLogger, key);
|
||||
} else {
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromSuper(baseLogger, args[metadatas.scopedLoggerInjectableParam], key);
|
||||
}
|
||||
} else {
|
||||
// special, can access to request object
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
// args[0] == ExecutionContext
|
||||
const ctx = (args[0] as ExecutionContext);
|
||||
if (ctx.getType() !== 'http') {
|
||||
injectedLogger.error('Cannot inject logger: Request type is not http');
|
||||
} else {
|
||||
let req = ctx.switchToHttp().getRequest();
|
||||
if (req[REQUEST_LOG_ID] === undefined) {
|
||||
req[REQUEST_LOG_ID] = ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(baseLogger, key, req[REQUEST_LOG_ID]);
|
||||
}
|
||||
} else if (type === 'middleware') {
|
||||
let req = args[0];
|
||||
if (req[REQUEST_LOG_ID] === undefined) {
|
||||
req[REQUEST_LOG_ID] = ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(baseLogger, key, req[REQUEST_LOG_ID]);
|
||||
} else if (type === 'route') {
|
||||
// args[metadatas.scopedLoggerInjectableParam] is now Request object, thanks to code in @LoggedRoute!!!!
|
||||
let req = args[metadatas.scopedLoggerInjectableParam];
|
||||
if (req[REQUEST_LOG_ID] === undefined) {
|
||||
req[REQUEST_LOG_ID] = ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(baseLogger, key, req[REQUEST_LOG_ID]);
|
||||
}
|
||||
}
|
||||
|
||||
injectedLogger = args[metadatas.scopedLoggerInjectableParam];
|
||||
}
|
||||
|
||||
// If this is ExecutionContext based function (e.g. Guard, Interceptor) get Request from Context
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
const context = args[0] as ExecutionContext;
|
||||
if (context.getType() === 'http') {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
route = /* supporting FastifyRequest */ req.raw ? req.raw.url : req.url;
|
||||
}
|
||||
}
|
||||
|
||||
// Start Log
|
||||
if (logged.options.callLogLevel !== 'skip') {
|
||||
const callLogIdentifyMessage =
|
||||
type === 'middleware' || type === 'guard' || type === 'interceptor' || type === 'route'
|
||||
? createCallLogIdentifyMessage('HIT', type, key, route)
|
||||
: createCallLogIdentifyMessage('HIT', type, key);
|
||||
injectedLogger[logged.options.callLogLevel](
|
||||
`${callLogIdentifyMessage} ${metadatas.loggedParams && metadatas.loggedParams.length > 0
|
||||
? "WITH " +
|
||||
metadatas.loggedParams.map(
|
||||
({ name, index, include, exclude }) =>
|
||||
name +
|
||||
"=" +
|
||||
imObjectContainedLogSync(args[index], {
|
||||
include,
|
||||
exclude,
|
||||
})
|
||||
).join(", ")
|
||||
: ""
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const r: R = originalFunction.call(this, ...args); // Try to call original function
|
||||
|
||||
// Return Log
|
||||
if (logged.options.returnLogLevel !== 'skip') {
|
||||
if (
|
||||
originalFunction.constructor.name === 'AsyncFunction' ||
|
||||
(r && typeof r === 'object' && typeof r['then'] === 'function')
|
||||
) {
|
||||
return r['then']((r: any) => {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === "object" && r !== null
|
||||
? "WITH " +
|
||||
returnsData.map(({ name, path }) => {
|
||||
const value = getItemByPathSync(r, path);
|
||||
|
||||
return value !== undefined ? `${name}=${value}` : "";
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(", ")
|
||||
: ""
|
||||
: typeof returnsData === 'string'
|
||||
? "WITH " + returnsData + "=" + typeof r === "object" ? JSON.stringify(r) : r
|
||||
: returnsData
|
||||
? typeof r === "object"
|
||||
? "WITH " + JSON.stringify(r)
|
||||
: "WITH " + r
|
||||
: "";
|
||||
|
||||
injectedLogger[logged.options.returnLogLevel](`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`);
|
||||
return r;
|
||||
})
|
||||
} else {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === "object" && r !== null
|
||||
? "WITH " +
|
||||
returnsData.map(({ name, path }) => {
|
||||
const value = getItemByPathSync(r, path);
|
||||
|
||||
return value !== undefined ? `${name}=${value}` : "";
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(", ")
|
||||
: ""
|
||||
: typeof returnsData === 'string'
|
||||
? "WITH " + returnsData + "=" + typeof r === "object" ? JSON.stringify(r) : r
|
||||
: returnsData
|
||||
? typeof r === "object"
|
||||
? "WITH " + JSON.stringify(r)
|
||||
: "WITH " + r
|
||||
: "";
|
||||
|
||||
injectedLogger[logged.options.returnLogLevel](`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`);
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
} catch (e) {
|
||||
// Error Log
|
||||
if (logged.options.errorLogLevel !== 'skip') {
|
||||
injectedLogger[logged.options.errorLogLevel](`${createCallLogIdentifyMessage('ERROR', type, key, route)} ${e}`);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function LoggedFunction<F extends Array<any>, R>(
|
||||
options?: Partial<OverrideBuildOptions>
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(...args: F) => R | Promise<R>>
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(
|
||||
`LoggedFunction decorator applied to non-function property: ${key}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options)
|
||||
return
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
|
||||
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
|
||||
loggedParam,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'function',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
},
|
||||
key,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(
|
||||
nestLoggedMetadata,
|
||||
newMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function LoggedRoute<F extends Array<any>, R>(route?: string, options?: Partial<OverrideBuildOptions>) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(...args: F) => R>
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== "function") {
|
||||
logger.warn(
|
||||
`LoggedRoute decorator applied to non-function property: ${key}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options)
|
||||
return
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const httpPath: string = Reflect.getMetadata("path", fn);
|
||||
const httpMethod: RequestMethod = Reflect.getMetadata("method", fn);
|
||||
|
||||
const fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${RevRequestMethod[httpMethod]
|
||||
}]`;
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
// if @InjectLogger exists, fake nestjs as it is @Req()
|
||||
if (scopedLoggerInjectableParam !== undefined) {
|
||||
createRouteParamDecorator(0)()(_target, key, scopedLoggerInjectableParam);
|
||||
}
|
||||
|
||||
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
|
||||
loggedParam,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'route',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
},
|
||||
key,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
fullRoute,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(
|
||||
nestLoggedMetadata,
|
||||
newMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function LoggedGuard<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn!== "function") {
|
||||
logger.warn(
|
||||
`LoggedGuard decorator applied to non-function property: ${key}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options)
|
||||
return
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'guard',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
},
|
||||
_target.constructor.name,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(
|
||||
nestLoggedMetadata,
|
||||
newMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function LoggedInterceptor<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn!== "function") {
|
||||
logger.warn(
|
||||
`LoggedInterceptor decorator applied to non-function property: ${key}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options)
|
||||
return
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'interceptor',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
},
|
||||
_target.constructor.name,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(
|
||||
nestLoggedMetadata,
|
||||
newMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function LoggedMiddleware<F extends Array<any>, R>(options?: Partial<OverrideBuildOptions>) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R>
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn!== "function") {
|
||||
logger.warn(
|
||||
`LoggedMiddleware decorator applied to non-function property: ${key}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options)
|
||||
return
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'middleware',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
},
|
||||
_target.constructor.name,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(
|
||||
nestLoggedMetadata,
|
||||
newMetadata,
|
||||
_target,
|
||||
key
|
||||
)
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
}
|
||||
}
|
81
src/logged/class.ts
Normal file
81
src/logged/class.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import {
|
||||
Injectable,
|
||||
Controller,
|
||||
ControllerOptions,
|
||||
ScopeOptions,
|
||||
} from '@nestjs/common';
|
||||
import { loggerInit, RevRequestMethod } from './utils';
|
||||
import { LoggedRoute, LoggedFunction } from './methods';
|
||||
|
||||
export function LoggedInjectable(
|
||||
options?: ScopeOptions & { verbose?: boolean },
|
||||
) {
|
||||
return (target: any) => {
|
||||
loggerInit(target.prototype);
|
||||
|
||||
const logger = target.prototype.logger;
|
||||
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
|
||||
methods.forEach((method) => {
|
||||
if (
|
||||
method !== 'constructor' &&
|
||||
typeof target.prototype[method] === 'function'
|
||||
) {
|
||||
if (options && options.verbose)
|
||||
logger.log(`LoggedFunction applied to ${method}`);
|
||||
LoggedFunction()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Injectable(options)(target);
|
||||
};
|
||||
}
|
||||
|
||||
export function LoggedController(): (target: any) => void;
|
||||
export function LoggedController(
|
||||
prefix: string | string[],
|
||||
): (target: any) => void;
|
||||
export function LoggedController(
|
||||
options: ControllerOptions & { verbose?: boolean },
|
||||
): (target: any) => void;
|
||||
|
||||
export function LoggedController(param?: any): (target: any) => void {
|
||||
return (target: any) => {
|
||||
loggerInit(target.prototype);
|
||||
|
||||
const logger = target.prototype.logger;
|
||||
|
||||
const methods = Object.getOwnPropertyNames(target.prototype);
|
||||
|
||||
let verbose =
|
||||
typeof param === 'object' && Object.keys(param).includes('verbose')
|
||||
? param.verbose
|
||||
: false;
|
||||
|
||||
methods.forEach((method) => {
|
||||
if (
|
||||
method !== 'constructor' &&
|
||||
typeof target.prototype[method] === 'function'
|
||||
) {
|
||||
if (verbose) {
|
||||
const path = Reflect.getMetadata('path', target.prototype[method]);
|
||||
const httpMethod = Reflect.getMetadata(
|
||||
'method',
|
||||
target.prototype[method],
|
||||
);
|
||||
logger.log(
|
||||
`LoggedRoute applied to ${method} (${RevRequestMethod[httpMethod]} ${path})`,
|
||||
);
|
||||
}
|
||||
LoggedRoute()(target.prototype, method, {
|
||||
value: target.prototype[method],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Controller(param)(target);
|
||||
};
|
||||
}
|
2
src/logged/index.ts
Normal file
2
src/logged/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './methods';
|
||||
export { LoggedController, LoggedInjectable } from './class';
|
21
src/logged/metadata.ts
Normal file
21
src/logged/metadata.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { OverrideBuildOptions, defaultOverrideBuildOptions } from './utils';
|
||||
|
||||
export const nestLoggedMetadata = Symbol('nlogdec-metadata');
|
||||
|
||||
export class LoggedMetadata {
|
||||
options: OverrideBuildOptions;
|
||||
|
||||
constructor(options?: Partial<OverrideBuildOptions>) {
|
||||
this.options = {
|
||||
...defaultOverrideBuildOptions,
|
||||
...(options ?? {}),
|
||||
};
|
||||
}
|
||||
|
||||
updateOption(options: Partial<OverrideBuildOptions>) {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options,
|
||||
};
|
||||
}
|
||||
}
|
90
src/logged/methods/function.ts
Normal file
90
src/logged/methods/function.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { OverrideBuildOptions, loggerInit } from '../utils';
|
||||
import { LoggedMetadata, nestLoggedMetadata } from '../metadata';
|
||||
import {
|
||||
loggedParam,
|
||||
scopedLogger,
|
||||
returns,
|
||||
ReturnsReflectData,
|
||||
LoggedParamReflectData,
|
||||
} from '../../reflected';
|
||||
import { overrideBuild } from '../override';
|
||||
|
||||
export function LoggedFunction<F extends Array<any>, R>(
|
||||
options?: Partial<OverrideBuildOptions>,
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(...args: F) => R | Promise<R>>,
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(
|
||||
`LoggedFunction decorator applied to non-function property: ${key}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
|
||||
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
|
||||
loggedParam,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn,
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'function',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
},
|
||||
key,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
80
src/logged/methods/guard.ts
Normal file
80
src/logged/methods/guard.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { ExecutionContext, Logger } from '@nestjs/common';
|
||||
import { OverrideBuildOptions, loggerInit } from '../utils';
|
||||
import { LoggedMetadata, nestLoggedMetadata } from '../metadata';
|
||||
import { scopedLogger, returns, ReturnsReflectData } from '../../reflected';
|
||||
import { overrideBuild } from '../override';
|
||||
|
||||
export function LoggedGuard<F extends Array<any>, R>(
|
||||
options?: Partial<OverrideBuildOptions>,
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<
|
||||
(context: ExecutionContext, ...args: F) => R
|
||||
>,
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(
|
||||
`LoggedGuard decorator applied to non-function property: ${key}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn,
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'guard',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
},
|
||||
_target.constructor.name,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
5
src/logged/methods/index.ts
Normal file
5
src/logged/methods/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export { LoggedFunction } from './function';
|
||||
export { LoggedRoute } from './route';
|
||||
export { LoggedGuard } from './guard';
|
||||
export { LoggedInterceptor } from './interceptor';
|
||||
export { LoggedMiddleware } from './middleware';
|
81
src/logged/methods/interceptor.ts
Normal file
81
src/logged/methods/interceptor.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
import { ExecutionContext, Logger } from '@nestjs/common';
|
||||
import { loggerInit } from '../utils';
|
||||
import { LoggedMetadata, nestLoggedMetadata } from '../metadata';
|
||||
import { scopedLogger, returns, ReturnsReflectData } from '../../reflected';
|
||||
import { overrideBuild } from '../override';
|
||||
|
||||
export function LoggedInterceptor<F extends Array<any>, R>(
|
||||
options?: Partial<OverrideBuildOptions>,
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<
|
||||
(context: ExecutionContext, ...args: F) => R
|
||||
>,
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(
|
||||
`LoggedInterceptor decorator applied to non-function property: ${key}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn,
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'interceptor',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
},
|
||||
_target.constructor.name,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
81
src/logged/methods/middleware.ts
Normal file
81
src/logged/methods/middleware.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import { OverrideBuildOptions } from '../utils';
|
||||
import { ExecutionContext, Logger } from '@nestjs/common';
|
||||
import { loggerInit } from '../utils';
|
||||
import { LoggedMetadata, nestLoggedMetadata } from '../metadata';
|
||||
import { scopedLogger, returns, ReturnsReflectData } from '../../reflected';
|
||||
import { overrideBuild } from '../override';
|
||||
|
||||
export function LoggedMiddleware<F extends Array<any>, R>(
|
||||
options?: Partial<OverrideBuildOptions>,
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<
|
||||
(context: ExecutionContext, ...args: F) => R
|
||||
>,
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger: Logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(
|
||||
`LoggedMiddleware decorator applied to non-function property: ${key}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn,
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'middleware',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams: [],
|
||||
},
|
||||
_target.constructor.name,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
104
src/logged/methods/route.ts
Normal file
104
src/logged/methods/route.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { RequestMethod } from '@nestjs/common';
|
||||
import { OverrideBuildOptions, loggerInit, RevRequestMethod } from '../utils';
|
||||
import { LoggedMetadata, nestLoggedMetadata } from '../metadata';
|
||||
import {
|
||||
loggedParam,
|
||||
scopedLogger,
|
||||
returns,
|
||||
ReturnsReflectData,
|
||||
LoggedParamReflectData,
|
||||
} from '../../reflected';
|
||||
import { overrideBuild } from '../override';
|
||||
import { createRouteParamDecorator } from '../../internals/nest';
|
||||
|
||||
export function LoggedRoute<F extends Array<any>, R>(
|
||||
route?: string,
|
||||
options?: Partial<OverrideBuildOptions>,
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
key: string,
|
||||
descriptor: TypedPropertyDescriptor<(...args: F) => R>,
|
||||
) => {
|
||||
loggerInit(_target);
|
||||
|
||||
const logger = _target.logger;
|
||||
|
||||
const fn = descriptor.value;
|
||||
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
logger.warn(
|
||||
`LoggedRoute decorator applied to non-function property: ${key}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata(
|
||||
nestLoggedMetadata,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
if (logMetadata) {
|
||||
// already applied, override instead
|
||||
logMetadata.updateOption(options);
|
||||
return;
|
||||
}
|
||||
const newMetadata = new LoggedMetadata(options);
|
||||
|
||||
const all = Reflect.getMetadataKeys(fn).map((k) => [
|
||||
k,
|
||||
Reflect.getMetadata(k, fn),
|
||||
]);
|
||||
|
||||
const httpPath: string = Reflect.getMetadata('path', fn);
|
||||
const httpMethod: RequestMethod = Reflect.getMetadata('method', fn);
|
||||
|
||||
const fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${
|
||||
RevRequestMethod[httpMethod]
|
||||
}]`;
|
||||
|
||||
const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata(
|
||||
scopedLogger,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
// if @InjectLogger exists, fake nestjs as it is @Req()
|
||||
if (scopedLoggerInjectableParam !== undefined) {
|
||||
createRouteParamDecorator(0)()(_target, key, scopedLoggerInjectableParam);
|
||||
}
|
||||
|
||||
const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata(
|
||||
loggedParam,
|
||||
_target,
|
||||
key,
|
||||
);
|
||||
|
||||
const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata(
|
||||
returns,
|
||||
fn,
|
||||
);
|
||||
|
||||
const overrideFunction = overrideBuild(
|
||||
'route',
|
||||
fn,
|
||||
logger,
|
||||
{
|
||||
scopedLoggerInjectableParam,
|
||||
loggedParams,
|
||||
},
|
||||
key,
|
||||
returnsData,
|
||||
newMetadata,
|
||||
fullRoute,
|
||||
);
|
||||
|
||||
_target[key] = overrideFunction;
|
||||
descriptor.value = overrideFunction;
|
||||
|
||||
Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key);
|
||||
all.forEach(([k, v]) => {
|
||||
Reflect.defineMetadata(k, v, _target[key]);
|
||||
Reflect.defineMetadata(k, v, descriptor.value);
|
||||
});
|
||||
};
|
||||
}
|
229
src/logged/override.ts
Normal file
229
src/logged/override.ts
Normal file
@ -0,0 +1,229 @@
|
||||
import { Logger, ExecutionContext } from '@nestjs/common';
|
||||
import { LoggedParamReflectData, ReturnsReflectData } from '../reflected';
|
||||
import { LoggedMetadata } from './metadata';
|
||||
import {
|
||||
BuildType,
|
||||
REQUEST_LOG_ID,
|
||||
createCallLogIdentifyMessage,
|
||||
} from './utils';
|
||||
import { objectContainedLogSync, getItemByPathSync } from '../internals/utils';
|
||||
import { ScopedLogger } from '../logger';
|
||||
|
||||
interface FunctionMetadata {
|
||||
scopedLoggerInjectableParam?: number;
|
||||
loggedParams?: LoggedParamReflectData[];
|
||||
}
|
||||
|
||||
export function overrideBuild<F extends Array<any>, R>(
|
||||
type: 'route',
|
||||
originalFunction: (...args: F) => R,
|
||||
baseLogger: Logger,
|
||||
metadatas: FunctionMetadata,
|
||||
key: string,
|
||||
returnsData: ReturnsReflectData[] | string | true,
|
||||
logged: LoggedMetadata,
|
||||
route: string,
|
||||
): (...args: F) => R;
|
||||
export function overrideBuild<F extends Array<any>, R>(
|
||||
type: 'function' | 'guard' | 'interceptor' | 'middleware',
|
||||
originalFunction: (...args: F) => R,
|
||||
baseLogger: Logger,
|
||||
metadatas: FunctionMetadata,
|
||||
key: string,
|
||||
returnsData: ReturnsReflectData[] | string | true,
|
||||
logged: LoggedMetadata,
|
||||
): (...args: F) => R;
|
||||
export function overrideBuild<F extends Array<any>, R>(
|
||||
type: BuildType,
|
||||
originalFunction: (...args: F) => R,
|
||||
baseLogger: Logger,
|
||||
metadatas: FunctionMetadata,
|
||||
key: string,
|
||||
returnsData: ReturnsReflectData[] | string | true,
|
||||
logged: LoggedMetadata,
|
||||
route?: string,
|
||||
): (...args: F) => R {
|
||||
return function (...args: F): R {
|
||||
// Creating ScopedLogger
|
||||
let injectedLogger: Logger = baseLogger;
|
||||
if (typeof metadatas.scopedLoggerInjectableParam !== 'undefined') {
|
||||
if (type === 'function') {
|
||||
if (
|
||||
args.length <= metadatas.scopedLoggerInjectableParam ||
|
||||
!(args[metadatas.scopedLoggerInjectableParam] instanceof ScopedLogger)
|
||||
) {
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(
|
||||
baseLogger,
|
||||
key,
|
||||
);
|
||||
} else {
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromSuper(
|
||||
baseLogger,
|
||||
args[metadatas.scopedLoggerInjectableParam],
|
||||
key,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// special, can access to request object
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
// args[0] == ExecutionContext
|
||||
const ctx = args[0] as ExecutionContext;
|
||||
if (ctx.getType() !== 'http') {
|
||||
injectedLogger.error(
|
||||
'Cannot inject logger: Request type is not http',
|
||||
);
|
||||
} else {
|
||||
let req = ctx.switchToHttp().getRequest();
|
||||
if (req[REQUEST_LOG_ID] === undefined) {
|
||||
req[REQUEST_LOG_ID] = ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(
|
||||
baseLogger,
|
||||
key,
|
||||
req[REQUEST_LOG_ID],
|
||||
);
|
||||
}
|
||||
} else if (type === 'middleware') {
|
||||
let req = args[0];
|
||||
if (req[REQUEST_LOG_ID] === undefined) {
|
||||
req[REQUEST_LOG_ID] = ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(
|
||||
baseLogger,
|
||||
key,
|
||||
req[REQUEST_LOG_ID],
|
||||
);
|
||||
} else if (type === 'route') {
|
||||
// args[metadatas.scopedLoggerInjectableParam] is now Request object, thanks to code in @LoggedRoute!!!!
|
||||
let req = args[metadatas.scopedLoggerInjectableParam];
|
||||
if (req[REQUEST_LOG_ID] === undefined) {
|
||||
req[REQUEST_LOG_ID] = ScopedLogger.createScopeId();
|
||||
}
|
||||
args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot(
|
||||
baseLogger,
|
||||
key,
|
||||
req[REQUEST_LOG_ID],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
injectedLogger = args[metadatas.scopedLoggerInjectableParam];
|
||||
}
|
||||
|
||||
// If this is ExecutionContext based function (e.g. Guard, Interceptor) get Request from Context
|
||||
if (type === 'guard' || type === 'interceptor') {
|
||||
const context = args[0] as ExecutionContext;
|
||||
if (context.getType() === 'http') {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
route = /* supporting FastifyRequest */ req.raw ? req.raw.url : req.url;
|
||||
}
|
||||
}
|
||||
|
||||
// Start Log
|
||||
if (logged.options.callLogLevel !== 'skip') {
|
||||
const callLogIdentifyMessage =
|
||||
type === 'middleware' ||
|
||||
type === 'guard' ||
|
||||
type === 'interceptor' ||
|
||||
type === 'route'
|
||||
? createCallLogIdentifyMessage('HIT', type, key, route)
|
||||
: createCallLogIdentifyMessage('HIT', type, key);
|
||||
injectedLogger[logged.options.callLogLevel](
|
||||
`${callLogIdentifyMessage} ${
|
||||
metadatas.loggedParams && metadatas.loggedParams.length > 0
|
||||
? 'WITH ' +
|
||||
metadatas.loggedParams
|
||||
.map(
|
||||
({ name, index, include, exclude }) =>
|
||||
name +
|
||||
'=' +
|
||||
objectContainedLogSync(args[index], {
|
||||
include,
|
||||
exclude,
|
||||
}),
|
||||
)
|
||||
.join(', ')
|
||||
: ''
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const r: R = originalFunction.call(this, ...args); // Try to call original function
|
||||
|
||||
// Return Log
|
||||
if (logged.options.returnLogLevel !== 'skip') {
|
||||
if (
|
||||
originalFunction.constructor.name === 'AsyncFunction' ||
|
||||
(r && typeof r === 'object' && typeof r['then'] === 'function')
|
||||
) {
|
||||
return r['then']((r: any) => {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === 'object' && r !== null
|
||||
? 'WITH ' +
|
||||
returnsData
|
||||
.map(({ name, path }) => {
|
||||
const value = getItemByPathSync(r, path);
|
||||
|
||||
return value !== undefined ? `${name}=${value}` : '';
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(', ')
|
||||
: ''
|
||||
: typeof returnsData === 'string'
|
||||
? 'WITH ' + returnsData + '=' + typeof r === 'object'
|
||||
? JSON.stringify(r)
|
||||
: r
|
||||
: returnsData
|
||||
? typeof r === 'object'
|
||||
? 'WITH ' + JSON.stringify(r)
|
||||
: 'WITH ' + r
|
||||
: '';
|
||||
|
||||
injectedLogger[logged.options.returnLogLevel](
|
||||
`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`,
|
||||
);
|
||||
return r;
|
||||
});
|
||||
} else {
|
||||
const resultLogged = Array.isArray(returnsData)
|
||||
? typeof r === 'object' && r !== null
|
||||
? 'WITH ' +
|
||||
returnsData
|
||||
.map(({ name, path }) => {
|
||||
const value = getItemByPathSync(r, path);
|
||||
|
||||
return value !== undefined ? `${name}=${value}` : '';
|
||||
})
|
||||
.filter((v) => v.length > 0)
|
||||
.join(', ')
|
||||
: ''
|
||||
: typeof returnsData === 'string'
|
||||
? 'WITH ' + returnsData + '=' + typeof r === 'object'
|
||||
? JSON.stringify(r)
|
||||
: r
|
||||
: returnsData
|
||||
? typeof r === 'object'
|
||||
? 'WITH ' + JSON.stringify(r)
|
||||
: 'WITH ' + r
|
||||
: '';
|
||||
|
||||
injectedLogger[logged.options.returnLogLevel](
|
||||
`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`,
|
||||
);
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
} catch (e) {
|
||||
// Error Log
|
||||
if (logged.options.errorLogLevel !== 'skip') {
|
||||
injectedLogger[logged.options.errorLogLevel](
|
||||
`${createCallLogIdentifyMessage('ERROR', type, key, route)} ${e}`,
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
86
src/logged/utils.ts
Normal file
86
src/logged/utils.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { Logger, LogLevel } from '@nestjs/common';
|
||||
|
||||
export const RevRequestMethod = [
|
||||
'GET',
|
||||
'POST',
|
||||
'PUT',
|
||||
'DELETE',
|
||||
'PATCH',
|
||||
'ALL',
|
||||
'OPTIONS',
|
||||
'HEAD',
|
||||
'SEARCH',
|
||||
];
|
||||
|
||||
export function loggerInit(_target: any) {
|
||||
if (!Object.getOwnPropertyNames(_target).includes('logger')) {
|
||||
const newTargetLogger = new Logger(_target.constructor.name);
|
||||
newTargetLogger.log('Logger Initialized.');
|
||||
Object.defineProperty(_target, 'logger', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
value: newTargetLogger,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type BuildType =
|
||||
| 'route'
|
||||
| 'function'
|
||||
| 'guard'
|
||||
| 'interceptor'
|
||||
| 'middleware';
|
||||
|
||||
const callLogIdentifyMessageDictionary: Record<BuildType, string> = {
|
||||
route: 'ENDPOINT',
|
||||
function: 'FUNCTION',
|
||||
guard: 'GUARD',
|
||||
interceptor: 'INTERCEPTOR',
|
||||
middleware: 'MIDDLEWARE',
|
||||
};
|
||||
|
||||
export function createCallLogIdentifyMessage(
|
||||
message: 'HIT' | 'RETURNED' | 'ERROR',
|
||||
type: BuildType,
|
||||
key?: string,
|
||||
route?: string,
|
||||
) {
|
||||
if (message === 'ERROR')
|
||||
return `ERROR WHILE ${callLogIdentifyMessageDictionary[type]} ${key} (${route}): `;
|
||||
|
||||
if (
|
||||
type === 'guard' ||
|
||||
type === 'interceptor' ||
|
||||
type === 'middleware' ||
|
||||
type === 'route'
|
||||
)
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key} (${route})`;
|
||||
if (type === 'function')
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]} ${key}`;
|
||||
|
||||
return `${message} ${callLogIdentifyMessageDictionary[type]}`;
|
||||
}
|
||||
|
||||
export const REQUEST_LOG_ID = '__nestlogged_request_log_id__';
|
||||
|
||||
export interface OverrideBuildOptions {
|
||||
callLogLevel: LogLevel | 'skip';
|
||||
returnLogLevel: LogLevel | 'skip';
|
||||
errorLogLevel: LogLevel | 'skip';
|
||||
/** @deprecated use `callLogLevel: 'skip'` instead */
|
||||
skipCallLog: boolean;
|
||||
/** @deprecated use `returnLogLevel: 'skip'` instead */
|
||||
skipReturnLog: boolean;
|
||||
/** @deprecated use `errorLogLevel: 'skip'` instead */
|
||||
skipErrorLog: boolean;
|
||||
}
|
||||
|
||||
export const defaultOverrideBuildOptions: OverrideBuildOptions = {
|
||||
callLogLevel: 'log',
|
||||
returnLogLevel: 'log',
|
||||
errorLogLevel: 'error',
|
||||
skipCallLog: false,
|
||||
skipReturnLog: false,
|
||||
skipErrorLog: false,
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { Logger, LogLevel } from "@nestjs/common";
|
||||
import { Logger, LogLevel } from '@nestjs/common';
|
||||
import * as hyperid from 'hyperid';
|
||||
|
||||
const createId = hyperid({ fixedLength: true })
|
||||
const createId = hyperid({ fixedLength: true });
|
||||
|
||||
export class ScopedLogger extends Logger {
|
||||
constructor(
|
||||
@ -15,30 +15,39 @@ export class ScopedLogger extends Logger {
|
||||
private scopedLog(method: LogLevel) {
|
||||
return (message: string) => {
|
||||
this.logger[method](
|
||||
`${this.scopeId ? `(ID ${this.scopeId}) | ` : ""
|
||||
}${this.scope.join(" -> ")}: ${message}`
|
||||
`${
|
||||
this.scopeId ? `(ID ${this.scopeId}) | ` : ''
|
||||
}${this.scope.join(' -> ')}: ${message}`,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
debug = this.scopedLog("debug");
|
||||
log = this.scopedLog("log");
|
||||
warn = this.scopedLog("warn");
|
||||
verbose = this.scopedLog("verbose");
|
||||
error = this.scopedLog("error");
|
||||
fatal = this.scopedLog("fatal");
|
||||
debug = this.scopedLog('debug');
|
||||
log = this.scopedLog('log');
|
||||
warn = this.scopedLog('warn');
|
||||
verbose = this.scopedLog('verbose');
|
||||
error = this.scopedLog('error');
|
||||
fatal = this.scopedLog('fatal');
|
||||
|
||||
static fromSuper(baseLogger: Logger, logger: ScopedLogger, scope: string): ScopedLogger {
|
||||
static fromSuper(
|
||||
baseLogger: Logger,
|
||||
logger: ScopedLogger,
|
||||
scope: string,
|
||||
): ScopedLogger {
|
||||
return new ScopedLogger(
|
||||
baseLogger, [...logger.scope, scope], logger.scopeId
|
||||
)
|
||||
};
|
||||
static fromRoot(logger: Logger, scope: string, scopeId?: string): ScopedLogger {
|
||||
return new ScopedLogger(
|
||||
logger, [scope], scopeId
|
||||
)
|
||||
};
|
||||
baseLogger,
|
||||
[...logger.scope, scope],
|
||||
logger.scopeId,
|
||||
);
|
||||
}
|
||||
static fromRoot(
|
||||
logger: Logger,
|
||||
scope: string,
|
||||
scopeId?: string,
|
||||
): ScopedLogger {
|
||||
return new ScopedLogger(logger, [scope], scopeId);
|
||||
}
|
||||
static createScopeId(): string {
|
||||
return createId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
173
src/reflected.ts
173
src/reflected.ts
@ -1,48 +1,10 @@
|
||||
import {RouteParamtypes} from '@nestjs/common/enums/route-paramtypes.enum';
|
||||
import {assignMetadata, ParamData, PipeTransform, RouteParamMetadata, Type} from "@nestjs/common";
|
||||
import {isNil, isString} from "@nestjs/common/utils/shared.utils";
|
||||
|
||||
const ROUTE_ARGS_METADATA = '__routeArguments__';
|
||||
|
||||
export function createRouteParamDecorator(paramtype: RouteParamtypes) {
|
||||
return (data?: ParamData): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata<RouteParamtypes, Record<number, RouteParamMetadata>>(
|
||||
args,
|
||||
paramtype,
|
||||
index,
|
||||
data,
|
||||
),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const createPipesRouteParamDecorator =
|
||||
(paramtype: RouteParamtypes) =>
|
||||
(
|
||||
data?: any,
|
||||
...pipes: (Type<PipeTransform> | PipeTransform)[]
|
||||
): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
const hasParamData = isNil(data) || isString(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, paramData, ...paramPipes),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
||||
import {
|
||||
RouteParamtypes,
|
||||
Type,
|
||||
PipeTransform,
|
||||
createPipesRouteParamDecorator,
|
||||
createRouteParamDecorator,
|
||||
} from './internals/nest';
|
||||
|
||||
export type Path = string | string[];
|
||||
export type Paths = Path[];
|
||||
@ -71,30 +33,32 @@ export interface ReturnsReflectData {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export const scopedLogger = Symbol("nlogdec-scopedLogger");
|
||||
export const loggedParam = Symbol("nlogdec-loggedParam");
|
||||
export const returns = Symbol("nlogdec-returns");
|
||||
|
||||
export const nestLoggedMetadata = Symbol("nlogdec-metadata");
|
||||
export const scopedLogger = Symbol('nlogdec-scopedLogger');
|
||||
export const loggedParam = Symbol('nlogdec-loggedParam');
|
||||
export const returns = Symbol('nlogdec-returns');
|
||||
|
||||
export function InjectLogger(
|
||||
target: any,
|
||||
propertyKey: string | symbol,
|
||||
parameterIndex: number
|
||||
parameterIndex: number,
|
||||
) {
|
||||
Reflect.defineMetadata(scopedLogger, parameterIndex, target, propertyKey);
|
||||
}
|
||||
|
||||
type ParameterDecoratorType = (target: any, propertyKey: string | symbol, parameterIndex: number) => void
|
||||
type ParameterDecoratorType = (
|
||||
target: any,
|
||||
propertyKey: string | symbol,
|
||||
parameterIndex: number,
|
||||
) => void;
|
||||
|
||||
function createLoggedFunctionParam(
|
||||
name: string,
|
||||
options?: IncludeExcludePath
|
||||
options?: IncludeExcludePath,
|
||||
): ParameterDecoratorType {
|
||||
return (
|
||||
target: any,
|
||||
propertyKey: string | symbol,
|
||||
parameterIndex: number
|
||||
parameterIndex: number,
|
||||
) => {
|
||||
const existingLoggedParams: LoggedParamReflectData[] =
|
||||
Reflect.getOwnMetadata(loggedParam, target, propertyKey) || [];
|
||||
@ -106,33 +70,34 @@ function createLoggedFunctionParam(
|
||||
include:
|
||||
options &&
|
||||
options.includePath &&
|
||||
options.includePath.map((v) => (Array.isArray(v) ? v.join(".") : v)),
|
||||
options.includePath.map((v) => (Array.isArray(v) ? v.join('.') : v)),
|
||||
exclude:
|
||||
options &&
|
||||
options.excludePath &&
|
||||
options.excludePath.map((v) => (Array.isArray(v) ? v.join(".") : v)),
|
||||
options.excludePath.map((v) => (Array.isArray(v) ? v.join('.') : v)),
|
||||
});
|
||||
|
||||
Reflect.defineMetadata(
|
||||
loggedParam,
|
||||
existingLoggedParams,
|
||||
target,
|
||||
propertyKey
|
||||
propertyKey,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
type LoggedParamReturns = (name: string, options?: IncludeExcludePath) => ParameterDecoratorType;
|
||||
type LoggedParamReturns = (
|
||||
name: string,
|
||||
options?: IncludeExcludePath,
|
||||
) => ParameterDecoratorType;
|
||||
|
||||
export const Logged: LoggedParamReturns = (name, options) =>
|
||||
createLoggedFunctionParam(name, options)
|
||||
createLoggedFunctionParam(name, options);
|
||||
|
||||
type Pipe = Type<PipeTransform> | PipeTransform
|
||||
type Pipe = Type<PipeTransform> | PipeTransform;
|
||||
|
||||
export function LoggedParam(): LoggedParamReturns;
|
||||
export function LoggedParam(
|
||||
...pipes: Pipe[]
|
||||
): LoggedParamReturns;
|
||||
export function LoggedParam(...pipes: Pipe[]): LoggedParamReturns;
|
||||
export function LoggedParam(
|
||||
property: string,
|
||||
...pipes: Pipe[]
|
||||
@ -143,10 +108,7 @@ export function LoggedParam(
|
||||
): LoggedParamReturns {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createPipesRouteParamDecorator(RouteParamtypes.PARAM)(
|
||||
property,
|
||||
...pipes,
|
||||
)(
|
||||
createPipesRouteParamDecorator(RouteParamtypes.PARAM)(property, ...pipes)(
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
@ -155,15 +117,13 @@ export function LoggedParam(
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function LoggedQuery(): LoggedParamReturns;
|
||||
export function LoggedQuery(
|
||||
...pipes: Pipe[]
|
||||
): LoggedParamReturns;
|
||||
export function LoggedQuery(...pipes: Pipe[]): LoggedParamReturns;
|
||||
export function LoggedQuery(
|
||||
property: string,
|
||||
...pipes: Pipe[]
|
||||
@ -174,23 +134,23 @@ export function LoggedQuery(
|
||||
): LoggedParamReturns {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createPipesRouteParamDecorator(RouteParamtypes.QUERY)(
|
||||
property, ...pipes
|
||||
)(
|
||||
target, propertyKey, parameterIndex,
|
||||
createPipesRouteParamDecorator(RouteParamtypes.QUERY)(property, ...pipes)(
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
);
|
||||
|
||||
createLoggedFunctionParam(name, options)(
|
||||
target, propertyKey, parameterIndex,
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function LoggedBody(): LoggedParamReturns;
|
||||
export function LoggedBody(
|
||||
...pipes: Pipe[]
|
||||
): LoggedParamReturns;
|
||||
export function LoggedBody(...pipes: Pipe[]): LoggedParamReturns;
|
||||
export function LoggedBody(
|
||||
property: string,
|
||||
...pipes: Pipe[]
|
||||
@ -201,41 +161,50 @@ export function LoggedBody(
|
||||
): LoggedParamReturns {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createPipesRouteParamDecorator(RouteParamtypes.BODY)(
|
||||
property,
|
||||
...pipes,
|
||||
)(
|
||||
target, propertyKey, parameterIndex
|
||||
createPipesRouteParamDecorator(RouteParamtypes.BODY)(property, ...pipes)(
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
);
|
||||
|
||||
createLoggedFunctionParam(name, options)(
|
||||
target, propertyKey, parameterIndex,
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function LoggedHeaders(property?: string): LoggedParamReturns {
|
||||
return (name, options) => {
|
||||
return (target, propertyKey, parameterIndex) => {
|
||||
createRouteParamDecorator(RouteParamtypes.HEADERS)(property)(
|
||||
target, propertyKey, parameterIndex,
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
);
|
||||
|
||||
createLoggedFunctionParam(name, options)(
|
||||
target, propertyKey, parameterIndex,
|
||||
)
|
||||
}
|
||||
}
|
||||
target,
|
||||
propertyKey,
|
||||
parameterIndex,
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function Returns<F extends Array<any>, R>(namePaths?: {
|
||||
[name: string]: string;
|
||||
} | string) {
|
||||
export function Returns<F extends Array<any>, R>(
|
||||
namePaths?:
|
||||
| {
|
||||
[name: string]: string;
|
||||
}
|
||||
| string,
|
||||
) {
|
||||
return (
|
||||
_target: any,
|
||||
_key: string | symbol,
|
||||
descriptor: TypedPropertyDescriptor<(...args: F) => Promise<R> | R>
|
||||
descriptor: TypedPropertyDescriptor<(...args: F) => Promise<R> | R>,
|
||||
) => {
|
||||
Reflect.defineMetadata(
|
||||
returns,
|
||||
@ -244,10 +213,10 @@ export function Returns<F extends Array<any>, R>(namePaths?: {
|
||||
? namePaths
|
||||
: Object.entries(namePaths).reduce<ReturnsReflectData[]>(
|
||||
(prev, curr) => [...prev, { name: curr[0], path: curr[1] }],
|
||||
[]
|
||||
[],
|
||||
)
|
||||
: true,
|
||||
descriptor.value
|
||||
descriptor.value,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
import { LoggedFunction, LoggedInjectable } from "../logged";
|
||||
import { ScopedLogger } from "../logger";
|
||||
import {
|
||||
InjectLogger,
|
||||
Logged,
|
||||
Returns,
|
||||
} from "../reflected";
|
||||
import { LoggedFunction, LoggedInjectable } from '../logged';
|
||||
import { ScopedLogger } from '../logger';
|
||||
import { InjectLogger, Logged, Returns } from '../reflected';
|
||||
|
||||
type TestObject = {
|
||||
a: string;
|
||||
@ -17,151 +13,149 @@ type TestObject = {
|
||||
class TestService {
|
||||
public async service(paramA: string, @InjectLogger logger: ScopedLogger) {
|
||||
logger.log(`received paramA ${paramA}`);
|
||||
return paramA
|
||||
return paramA;
|
||||
}
|
||||
}
|
||||
|
||||
@LoggedInjectable()
|
||||
class LoggedClass {
|
||||
constructor(
|
||||
private service: TestService
|
||||
) { }
|
||||
constructor(private service: TestService) {}
|
||||
|
||||
async testParameterLoggingWithoutInjection(@Logged("key") key: number) {
|
||||
async testParameterLoggingWithoutInjection(@Logged('key') key: number) {
|
||||
console.log(key);
|
||||
}
|
||||
|
||||
async testMultiParameterLoggingWithoutInjection(
|
||||
@Logged("key") key: number,
|
||||
@Logged("key2") key2: string
|
||||
@Logged('key') key: number,
|
||||
@Logged('key2') key2: string,
|
||||
) {
|
||||
console.log(key, key2);
|
||||
}
|
||||
|
||||
async testParameterLoggingWithInjection(
|
||||
@Logged("key") key: number,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@Logged('key') key: number,
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(key.toString());
|
||||
}
|
||||
|
||||
async testMultiParameterLoggingWithInjection(
|
||||
@Logged("key") key: number,
|
||||
@Logged("key2") key2: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@Logged('key') key: number,
|
||||
@Logged('key2') key2: string,
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(key.toString() + key2);
|
||||
}
|
||||
|
||||
async testObjectParameterLogging(
|
||||
@Logged("key") key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@Logged('key') key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
async testObjectParameterDotIncludeLogging(
|
||||
@Logged("key", { includePath: ["a", "b.c", "d.0", "e"] })
|
||||
@Logged('key', { includePath: ['a', 'b.c', 'd.0', 'e'] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
async testObjectParameterArrayIncludeLogging(
|
||||
@Logged("key", { includePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
|
||||
@Logged('key', { includePath: [['a'], ['b', 'c'], ['d', '0'], ['e']] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
async testObjectParameterDotExcludeLogging(
|
||||
@Logged("key", { excludePath: ["a", "b.c", "d.0", "e"] })
|
||||
@Logged('key', { excludePath: ['a', 'b.c', 'd.0', 'e'] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
async testObjectParameterArrayExcludeLogging(
|
||||
@Logged("key", { excludePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
|
||||
@Logged('key', { excludePath: [['a'], ['b', 'c'], ['d', '0'], ['e']] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
@Returns({ result: "http.result", userId: "body.user.id" })
|
||||
@Returns({ result: 'http.result', userId: 'body.user.id' })
|
||||
async testReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return {
|
||||
http: {
|
||||
result: "success",
|
||||
result: 'success',
|
||||
code: 200,
|
||||
},
|
||||
body: {
|
||||
user: {
|
||||
id: userId,
|
||||
name: "tester",
|
||||
name: 'tester',
|
||||
},
|
||||
secret: "supersecret",
|
||||
secret: 'supersecret',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@Returns({ result: "http.result", userId: "body.user.id" })
|
||||
@Returns({ result: 'http.result', userId: 'body.user.id' })
|
||||
async testMissingReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return {
|
||||
body: {
|
||||
user: {
|
||||
id: userId,
|
||||
name: "tester",
|
||||
name: 'tester',
|
||||
},
|
||||
secret: "supersecret",
|
||||
secret: 'supersecret',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@Returns()
|
||||
async testRawObjectReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return {
|
||||
body: {
|
||||
user: {
|
||||
id: userId,
|
||||
name: "tester",
|
||||
name: 'tester',
|
||||
},
|
||||
secret: "supersecret",
|
||||
secret: 'supersecret',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@Returns()
|
||||
async testRawValueReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return true;
|
||||
}
|
||||
|
||||
async testLoggerRootLogging2(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log("2");
|
||||
logger.log('2');
|
||||
}
|
||||
|
||||
async testLoggerRootLogging(@InjectLogger logger?: ScopedLogger) {
|
||||
@ -169,16 +163,16 @@ class LoggedClass {
|
||||
}
|
||||
|
||||
testSyncLoggerRootLogging2(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log('2')
|
||||
return 2
|
||||
logger.log('2');
|
||||
return 2;
|
||||
}
|
||||
|
||||
testSyncLoggerRootLogging(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log(this.testSyncLoggerRootLogging2(logger).toString())
|
||||
logger.log(this.testSyncLoggerRootLogging2(logger).toString());
|
||||
}
|
||||
|
||||
testSyncLogging(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log("synced yay");
|
||||
logger.log('synced yay');
|
||||
}
|
||||
|
||||
async testService(@InjectLogger logger?: ScopedLogger) {
|
||||
@ -187,128 +181,126 @@ class LoggedClass {
|
||||
|
||||
@LoggedFunction({ skipCallLog: true, skipReturnLog: true })
|
||||
testOptionOverriding(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log("testOptionOverriding");
|
||||
logger.log('testOptionOverriding');
|
||||
}
|
||||
}
|
||||
|
||||
class LoggedMethodsClass {
|
||||
constructor(
|
||||
private service: TestService
|
||||
) { }
|
||||
constructor(private service: TestService) {}
|
||||
|
||||
@LoggedFunction()
|
||||
async testParameterLoggingWithoutInjection(@Logged("key") key: number) {
|
||||
async testParameterLoggingWithoutInjection(@Logged('key') key: number) {
|
||||
console.log(key);
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testMultiParameterLoggingWithoutInjection(
|
||||
@Logged("key") key: number,
|
||||
@Logged("key2") key2: string
|
||||
@Logged('key') key: number,
|
||||
@Logged('key2') key2: string,
|
||||
) {
|
||||
console.log(key, key2);
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testParameterLoggingWithInjection(
|
||||
@Logged("key") key: number,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@Logged('key') key: number,
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(key.toString());
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testMultiParameterLoggingWithInjection(
|
||||
@Logged("key") key: number,
|
||||
@Logged("key2") key2: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@Logged('key') key: number,
|
||||
@Logged('key2') key2: string,
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(key.toString() + key2);
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testObjectParameterLogging(
|
||||
@Logged("key") key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@Logged('key') key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testObjectParameterDotIncludeLogging(
|
||||
@Logged("key", { includePath: ["a", "b.c", "d.0", "e"] })
|
||||
@Logged('key', { includePath: ['a', 'b.c', 'd.0', 'e'] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testObjectParameterArrayIncludeLogging(
|
||||
@Logged("key", { includePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
|
||||
@Logged('key', { includePath: [['a'], ['b', 'c'], ['d', '0'], ['e']] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testObjectParameterDotExcludeLogging(
|
||||
@Logged("key", { excludePath: ["a", "b.c", "d.0", "e"] })
|
||||
@Logged('key', { excludePath: ['a', 'b.c', 'd.0', 'e'] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
async testObjectParameterArrayExcludeLogging(
|
||||
@Logged("key", { excludePath: [["a"], ["b", "c"], ["d", "0"], ["e"]] })
|
||||
@Logged('key', { excludePath: [['a'], ['b', 'c'], ['d', '0'], ['e']] })
|
||||
key: TestObject,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(JSON.stringify(key));
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
@Returns({ result: "http.result", userId: "body.user.id" })
|
||||
@Returns({ result: 'http.result', userId: 'body.user.id' })
|
||||
async testReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
|
||||
return {
|
||||
http: {
|
||||
result: "success",
|
||||
result: 'success',
|
||||
code: 200,
|
||||
},
|
||||
body: {
|
||||
user: {
|
||||
id: userId,
|
||||
name: "tester",
|
||||
name: 'tester',
|
||||
},
|
||||
secret: "supersecret",
|
||||
secret: 'supersecret',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
@Returns({ result: "http.result", userId: "body.user.id" })
|
||||
@Returns({ result: 'http.result', userId: 'body.user.id' })
|
||||
async testMissingReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return {
|
||||
body: {
|
||||
user: {
|
||||
id: userId,
|
||||
name: "tester",
|
||||
name: 'tester',
|
||||
},
|
||||
secret: "supersecret",
|
||||
secret: 'supersecret',
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -316,18 +308,18 @@ class LoggedMethodsClass {
|
||||
@LoggedFunction()
|
||||
@Returns()
|
||||
async testRawObjectReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return {
|
||||
body: {
|
||||
user: {
|
||||
id: userId,
|
||||
name: "tester",
|
||||
name: 'tester',
|
||||
},
|
||||
secret: "supersecret",
|
||||
secret: 'supersecret',
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -335,9 +327,9 @@ class LoggedMethodsClass {
|
||||
@LoggedFunction()
|
||||
@Returns()
|
||||
async testRawValueReturnLogging(
|
||||
@Logged("userId")
|
||||
@Logged('userId')
|
||||
userId: string,
|
||||
@InjectLogger logger?: ScopedLogger
|
||||
@InjectLogger logger?: ScopedLogger,
|
||||
) {
|
||||
logger.log(userId);
|
||||
return true;
|
||||
@ -345,7 +337,7 @@ class LoggedMethodsClass {
|
||||
|
||||
@LoggedFunction()
|
||||
async testLoggerRootLogging2(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log("2");
|
||||
logger.log('2');
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
@ -355,18 +347,18 @@ class LoggedMethodsClass {
|
||||
|
||||
@LoggedFunction()
|
||||
testSyncLoggerRootLogging2(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log('2')
|
||||
return 2
|
||||
logger.log('2');
|
||||
return 2;
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
testSyncLoggerRootLogging(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log(this.testSyncLoggerRootLogging2(logger).toString())
|
||||
logger.log(this.testSyncLoggerRootLogging2(logger).toString());
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
testSyncLogging(@InjectLogger logger?: ScopedLogger) {
|
||||
logger.log("synced yay");
|
||||
logger.log('synced yay');
|
||||
}
|
||||
|
||||
@LoggedFunction()
|
||||
@ -375,8 +367,6 @@ class LoggedMethodsClass {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// const service = new TestService();
|
||||
|
||||
/**
|
||||
|
10
src/utils.ts
10
src/utils.ts
@ -1,9 +1,9 @@
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { ScopedLogger } from "./logger";
|
||||
import { REQUEST_LOG_ID } from "./logged";
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { ScopedLogger } from './logger';
|
||||
import { REQUEST_LOG_ID } from './logged/utils';
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
export function getRequestLogger(functionName: string, req: any): ScopedLogger {
|
||||
return new ScopedLogger(logger, [functionName], req[REQUEST_LOG_ID])
|
||||
}
|
||||
return new ScopedLogger(logger, [functionName], req[REQUEST_LOG_ID]);
|
||||
}
|
||||
|
10
yarn.lock
10
yarn.lock
@ -372,6 +372,7 @@ __metadata:
|
||||
"@nestjs/common": "npm:^10.2.8"
|
||||
"@types/node": "npm:^20.9.1"
|
||||
hyperid: "npm:^3.1.1"
|
||||
prettier: "npm:^3.5.3"
|
||||
reflect-metadata: "npm:^0.1.13"
|
||||
rimraf: "npm:^5.0.5"
|
||||
rxjs: "npm:^7.8.1"
|
||||
@ -397,6 +398,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^3.5.3":
|
||||
version: 3.5.3
|
||||
resolution: "prettier@npm:3.5.3"
|
||||
bin:
|
||||
prettier: bin/prettier.cjs
|
||||
checksum: 10c0/3880cb90b9dc0635819ab52ff571518c35bd7f15a6e80a2054c05dbc8a3aa6e74f135519e91197de63705bcb38388ded7e7230e2178432a1468005406238b877
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"reflect-metadata@npm:^0.1.13":
|
||||
version: 0.1.13
|
||||
resolution: "reflect-metadata@npm:0.1.13"
|
||||
|
Loading…
x
Reference in New Issue
Block a user