From 3ac9b1d38d97bff231660cabef698e27ecba0789 Mon Sep 17 00:00:00 2001 From: Shinwoo PARK Date: Fri, 21 Mar 2025 09:38:36 +0900 Subject: [PATCH] style: add prettier --- .prettierrc | 11 ++ .yarn/install-state.gz | Bin 41781 -> 42641 bytes package.json | 4 +- src/index.ts | 12 +- src/internals/nest.ts | 64 ++++++----- src/internals/utils.ts | 59 +++++----- src/logged/class.ts | 114 +++++++++--------- src/logged/index.ts | 4 +- src/logged/metadata.ts | 12 +- src/logged/methods/function.ts | 49 ++++---- src/logged/methods/guard.ts | 45 ++++---- src/logged/methods/index.ts | 10 +- src/logged/methods/interceptor.ts | 45 ++++---- src/logged/methods/middleware.ts | 45 ++++---- src/logged/methods/route.ts | 61 +++++----- src/logged/override.ts | 167 +++++++++++++++++---------- src/logged/utils.ts | 53 ++++++--- src/logger.ts | 49 ++++---- src/reflected.ts | 127 ++++++++++++--------- src/test/index.ts | 184 ++++++++++++++---------------- src/utils.ts | 10 +- yarn.lock | 10 ++ 22 files changed, 617 insertions(+), 518 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b446905 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "as-needed", + "trailingComma": "all", + "bracketSpacing": true, + "objectWrap": "preserve", + "arrowParens": "always" +} \ No newline at end of file diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index 63b4182f4478f6a5e59f5719b0df69c32a3838f4..1fcbde9ec08a8a75923325ab234f92456fdeecb4 100644 GIT binary patch literal 42641 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 VEzje5qSEk%{|g(}9cKto0sth9;ZOho literal 41781 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 diff --git a/package.json b/package.json index 0265c83..add8c81 100644 --- a/package.json +++ b/package.json @@ -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" } diff --git a/src/index.ts b/src/index.ts index a4f5c5a..cec08a5 100644 --- a/src/index.ts +++ b/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' \ No newline at end of file + Returns, +} from './reflected'; +export { getRequestLogger } from './utils'; diff --git a/src/internals/nest.ts b/src/internals/nest.ts index 80f8591..059d19c 100644 --- a/src/internals/nest.ts +++ b/src/internals/nest.ts @@ -1,44 +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"; +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) || {}; + const args = + Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {}; Reflect.defineMetadata( ROUTE_ARGS_METADATA, assignMetadata>( - args, - paramtype, - index, - data, + args, + paramtype, + index, + data, ), target.constructor, key, ); }; -}; - +} + export const createPipesRouteParamDecorator = (paramtype: RouteParamtypes) => - ( - data?: any, - ...pipes: (Type | 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, - ); - }; \ No newline at end of file + ( + data?: any, + ...pipes: (Type | 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, + ); + }; diff --git a/src/internals/utils.ts b/src/internals/utils.ts index f76fc1f..a78179c 100644 --- a/src/internals/utils.ts +++ b/src/internals/utils.ts @@ -1,48 +1,53 @@ -export const notIncludedSymbol = Symbol("notIncluded"); +export const notIncludedSymbol = Symbol('notIncluded'); export function includeObjectSync( ocv: any, opt: { - paths: string[], - } + paths: string[]; + }, ) { - let current = Array.isArray(ocv) ? [] : typeof ocv === 'object' ? {} : ocv + 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] + query = query[key]; if (query !== undefined && objRef[key] === undefined) { if (typeof query === 'object') { if (Array.isArray(query)) { - objRef[key] = [] + objRef[key] = []; } else { - objRef[key] = {} + objRef[key] = {}; } } } if (typeof query !== 'object' || index === (path.length - 1).toString()) { objRef[key] = query; - break + break; } - objRef = objRef[key] + objRef = objRef[key]; } - }) + }); return current; } export function excludeObjectSync( ocv: any, opt: { - paths: string[] - } + paths: string[]; + }, ) { - 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('.') - const lastIndex = (path.length - 1).toString() + const path = dotpath.split('.'); + const lastIndex = (path.length - 1).toString(); for (const [index, key] of Object.entries(path)) { if (index === lastIndex) { delete objRef[key]; @@ -53,9 +58,9 @@ export function excludeObjectSync( break; } } - }) + }); - return copied + return copied; } export function objectContainedLogSync( @@ -63,34 +68,30 @@ export function objectContainedLogSync( 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 }) - ); + return JSON.stringify(includeObjectSync(ocv, { paths: options.include })); } if (options.exclude && options.exclude.length > 0) { - return JSON.stringify( - excludeObjectSync(ocv, { paths: options.exclude }) - ) + 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}` + return `${ocv}`; } } export function getItemByPathSync(obj: object, path: string | string[]) { - 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; -} \ No newline at end of file +} diff --git a/src/logged/class.ts b/src/logged/class.ts index b8b47dc..1b1561e 100644 --- a/src/logged/class.ts +++ b/src/logged/class.ts @@ -3,30 +3,24 @@ import { Controller, ControllerOptions, ScopeOptions, -} from "@nestjs/common"; -import { - loggerInit, - RevRequestMethod -} from './utils'; -import { - LoggedRoute, - LoggedFunction -} from "./methods"; +} from '@nestjs/common'; +import { loggerInit, RevRequestMethod } from './utils'; +import { LoggedRoute, LoggedFunction } from './methods'; export function LoggedInjectable( - options?: ScopeOptions & { verbose?: boolean } + 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" + method !== 'constructor' && + typeof target.prototype[method] === 'function' ) { if (options && options.verbose) logger.log(`LoggedFunction applied to ${method}`); @@ -39,49 +33,49 @@ export function LoggedInjectable( 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], - }); + +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})`, + ); } - }); - - Controller(param)(target); - }; - } \ No newline at end of file + LoggedRoute()(target.prototype, method, { + value: target.prototype[method], + }); + } + }); + + Controller(param)(target); + }; +} diff --git a/src/logged/index.ts b/src/logged/index.ts index d6e5803..67b66e2 100644 --- a/src/logged/index.ts +++ b/src/logged/index.ts @@ -1,2 +1,2 @@ -export * from "./methods"; -export { LoggedController, LoggedInjectable } from "./class" \ No newline at end of file +export * from './methods'; +export { LoggedController, LoggedInjectable } from './class'; diff --git a/src/logged/metadata.ts b/src/logged/metadata.ts index a48d753..6715a23 100644 --- a/src/logged/metadata.ts +++ b/src/logged/metadata.ts @@ -1,21 +1,21 @@ import { OverrideBuildOptions, defaultOverrideBuildOptions } from './utils'; -export const nestLoggedMetadata = Symbol("nlogdec-metadata"); +export const nestLoggedMetadata = Symbol('nlogdec-metadata'); export class LoggedMetadata { - options: OverrideBuildOptions + options: OverrideBuildOptions; constructor(options?: Partial) { this.options = { ...defaultOverrideBuildOptions, ...(options ?? {}), - } + }; } updateOption(options: Partial) { this.options = { ...this.options, - ...options - } + ...options, + }; } -} \ No newline at end of file +} diff --git a/src/logged/methods/function.ts b/src/logged/methods/function.ts index 75110e1..3805302 100644 --- a/src/logged/methods/function.ts +++ b/src/logged/methods/function.ts @@ -1,16 +1,22 @@ -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"; +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, R>( - options?: Partial + options?: Partial, ) { return ( _target: any, key: string, - descriptor: TypedPropertyDescriptor<(...args: F) => R | Promise> + descriptor: TypedPropertyDescriptor<(...args: F) => R | Promise>, ) => { loggerInit(_target); @@ -18,9 +24,9 @@ export function LoggedFunction, R>( const fn = descriptor.value; - if (!fn || typeof fn !== "function") { + if (!fn || typeof fn !== 'function') { logger.warn( - `LoggedFunction decorator applied to non-function property: ${key}` + `LoggedFunction decorator applied to non-function property: ${key}`, ); return; } @@ -28,12 +34,12 @@ export function LoggedFunction, R>( const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata( nestLoggedMetadata, _target, - key - ) + key, + ); if (logMetadata) { // already applied, override instead - logMetadata.updateOption(options) - return + logMetadata.updateOption(options); + return; } const newMetadata = new LoggedMetadata(options); @@ -45,18 +51,18 @@ export function LoggedFunction, R>( const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata( scopedLogger, _target, - key + key, ); const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata( loggedParam, _target, - key + key, ); const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata( returns, - fn + fn, ); const overrideFunction = overrideBuild( @@ -75,15 +81,10 @@ export function LoggedFunction, R>( _target[key] = overrideFunction; descriptor.value = overrideFunction; - Reflect.defineMetadata( - nestLoggedMetadata, - newMetadata, - _target, - key - ) + Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key); all.forEach(([k, v]) => { Reflect.defineMetadata(k, v, _target[key]); Reflect.defineMetadata(k, v, descriptor.value); }); - } -} \ No newline at end of file + }; +} diff --git a/src/logged/methods/guard.ts b/src/logged/methods/guard.ts index 8f8d0e6..0cb592b 100644 --- a/src/logged/methods/guard.ts +++ b/src/logged/methods/guard.ts @@ -1,14 +1,18 @@ -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"; +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, R>(options?: Partial) { +export function LoggedGuard, R>( + options?: Partial, +) { return ( _target: any, key: string, - descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R> + descriptor: TypedPropertyDescriptor< + (context: ExecutionContext, ...args: F) => R + >, ) => { loggerInit(_target); @@ -16,9 +20,9 @@ export function LoggedGuard, R>(options?: Partial, R>(options?: Partial, R>(options?: Partial, R>(options?: Partial { Reflect.defineMetadata(k, v, _target[key]); Reflect.defineMetadata(k, v, descriptor.value); }); - } -} \ No newline at end of file + }; +} diff --git a/src/logged/methods/index.ts b/src/logged/methods/index.ts index 48548ea..9aeedf1 100644 --- a/src/logged/methods/index.ts +++ b/src/logged/methods/index.ts @@ -1,5 +1,5 @@ -export { LoggedFunction } from "./function"; -export { LoggedRoute } from "./route"; -export { LoggedGuard } from "./guard"; -export { LoggedInterceptor } from "./interceptor"; -export { LoggedMiddleware } from "./middleware"; \ No newline at end of file +export { LoggedFunction } from './function'; +export { LoggedRoute } from './route'; +export { LoggedGuard } from './guard'; +export { LoggedInterceptor } from './interceptor'; +export { LoggedMiddleware } from './middleware'; diff --git a/src/logged/methods/interceptor.ts b/src/logged/methods/interceptor.ts index b3e29af..2a1bf72 100644 --- a/src/logged/methods/interceptor.ts +++ b/src/logged/methods/interceptor.ts @@ -1,15 +1,19 @@ -import { OverrideBuildOptions } from "../utils"; -import { ExecutionContext, Logger } from "@nestjs/common"; -import { loggerInit } from "../utils"; +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"; +import { scopedLogger, returns, ReturnsReflectData } from '../../reflected'; +import { overrideBuild } from '../override'; -export function LoggedInterceptor, R>(options?: Partial) { +export function LoggedInterceptor, R>( + options?: Partial, +) { return ( _target: any, key: string, - descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R> + descriptor: TypedPropertyDescriptor< + (context: ExecutionContext, ...args: F) => R + >, ) => { loggerInit(_target); @@ -17,9 +21,9 @@ export function LoggedInterceptor, R>(options?: Partial, R>(options?: Partial, R>(options?: Partial, R>(options?: Partial { Reflect.defineMetadata(k, v, _target[key]); Reflect.defineMetadata(k, v, descriptor.value); }); - } -} \ No newline at end of file + }; +} diff --git a/src/logged/methods/middleware.ts b/src/logged/methods/middleware.ts index 613cbd5..0c33318 100644 --- a/src/logged/methods/middleware.ts +++ b/src/logged/methods/middleware.ts @@ -1,15 +1,19 @@ -import { OverrideBuildOptions } from "../utils"; -import { ExecutionContext, Logger } from "@nestjs/common"; -import { loggerInit } from "../utils"; +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"; +import { scopedLogger, returns, ReturnsReflectData } from '../../reflected'; +import { overrideBuild } from '../override'; -export function LoggedMiddleware, R>(options?: Partial) { +export function LoggedMiddleware, R>( + options?: Partial, +) { return ( _target: any, key: string, - descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R> + descriptor: TypedPropertyDescriptor< + (context: ExecutionContext, ...args: F) => R + >, ) => { loggerInit(_target); @@ -17,9 +21,9 @@ export function LoggedMiddleware, R>(options?: Partial, R>(options?: Partial, R>(options?: Partial, R>(options?: Partial { Reflect.defineMetadata(k, v, _target[key]); Reflect.defineMetadata(k, v, descriptor.value); }); - } -} \ No newline at end of file + }; +} diff --git a/src/logged/methods/route.ts b/src/logged/methods/route.ts index 164fea9..952b20f 100644 --- a/src/logged/methods/route.ts +++ b/src/logged/methods/route.ts @@ -1,15 +1,24 @@ -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"; +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, R>(route?: string, options?: Partial) { +export function LoggedRoute, R>( + route?: string, + options?: Partial, +) { return ( _target: any, key: string, - descriptor: TypedPropertyDescriptor<(...args: F) => R> + descriptor: TypedPropertyDescriptor<(...args: F) => R>, ) => { loggerInit(_target); @@ -17,9 +26,9 @@ export function LoggedRoute, R>(route?: string, options?: P const fn = descriptor.value; - if (!fn || typeof fn !== "function") { + if (!fn || typeof fn !== 'function') { logger.warn( - `LoggedRoute decorator applied to non-function property: ${key}` + `LoggedRoute decorator applied to non-function property: ${key}`, ); return; } @@ -27,12 +36,12 @@ export function LoggedRoute, R>(route?: string, options?: P const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata( nestLoggedMetadata, _target, - key - ) + key, + ); if (logMetadata) { // already applied, override instead - logMetadata.updateOption(options) - return + logMetadata.updateOption(options); + return; } const newMetadata = new LoggedMetadata(options); @@ -41,16 +50,17 @@ export function LoggedRoute, R>(route?: string, options?: P Reflect.getMetadata(k, fn), ]); - const httpPath: string = Reflect.getMetadata("path", fn); - const httpMethod: RequestMethod = Reflect.getMetadata("method", 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 fullRoute = `${_target.constructor.name}::${route ?? httpPath}[${ + RevRequestMethod[httpMethod] + }]`; const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata( scopedLogger, _target, - key + key, ); // if @InjectLogger exists, fake nestjs as it is @Req() if (scopedLoggerInjectableParam !== undefined) { @@ -60,12 +70,12 @@ export function LoggedRoute, R>(route?: string, options?: P const loggedParams: LoggedParamReflectData[] = Reflect.getOwnMetadata( loggedParam, _target, - key + key, ); const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata( returns, - fn + fn, ); const overrideFunction = overrideBuild( @@ -85,15 +95,10 @@ export function LoggedRoute, R>(route?: string, options?: P _target[key] = overrideFunction; descriptor.value = overrideFunction; - Reflect.defineMetadata( - nestLoggedMetadata, - newMetadata, - _target, - key - ) + Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key); all.forEach(([k, v]) => { Reflect.defineMetadata(k, v, _target[key]); Reflect.defineMetadata(k, v, descriptor.value); }); }; -} \ No newline at end of file +} diff --git a/src/logged/override.ts b/src/logged/override.ts index 922bfcf..5c02b01 100644 --- a/src/logged/override.ts +++ b/src/logged/override.ts @@ -1,9 +1,13 @@ -import { Logger, ExecutionContext } from "@nestjs/common"; -import { LoggedParamReflectData, ReturnsReflectData } from "../reflected"; +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"; +import { + BuildType, + REQUEST_LOG_ID, + createCallLogIdentifyMessage, +} from './utils'; +import { objectContainedLogSync, getItemByPathSync } from '../internals/utils'; +import { ScopedLogger } from '../logger'; interface FunctionMetadata { scopedLoggerInjectableParam?: number; @@ -42,43 +46,64 @@ export function overrideBuild, R>( return function (...args: F): R { // Creating ScopedLogger let injectedLogger: Logger = baseLogger; - if (typeof metadatas.scopedLoggerInjectableParam !== "undefined") { + 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); + args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot( + baseLogger, + key, + ); } else { - args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromSuper(baseLogger, args[metadatas.scopedLoggerInjectableParam], key); + 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); + const ctx = args[0] as ExecutionContext; if (ctx.getType() !== 'http') { - injectedLogger.error('Cannot inject logger: Request type is not 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]); + 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]); + 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]); + args[metadatas.scopedLoggerInjectableParam] = ScopedLogger.fromRoot( + baseLogger, + key, + req[REQUEST_LOG_ID], + ); } } @@ -96,24 +121,30 @@ export function overrideBuild, R>( // Start Log if (logged.options.callLogLevel !== 'skip') { - const callLogIdentifyMessage = - type === 'middleware' || type === 'guard' || type === 'interceptor' || type === 'route' + 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(", ") - : "" - }` + `${callLogIdentifyMessage} ${ + metadatas.loggedParams && metadatas.loggedParams.length > 0 + ? 'WITH ' + + metadatas.loggedParams + .map( + ({ name, index, include, exclude }) => + name + + '=' + + objectContainedLogSync(args[index], { + include, + exclude, + }), + ) + .join(', ') + : '' + }`, ); } @@ -128,48 +159,58 @@ export function overrideBuild, R>( ) { 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); + ? 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(", ") - : "" + return value !== undefined ? `${name}=${value}` : ''; + }) + .filter((v) => v.length > 0) + .join(', ') + : '' : typeof returnsData === 'string' - ? "WITH " + returnsData + "=" + typeof r === "object" ? JSON.stringify(r) : r + ? 'WITH ' + returnsData + '=' + typeof r === 'object' + ? JSON.stringify(r) + : r : returnsData - ? typeof r === "object" - ? "WITH " + JSON.stringify(r) - : "WITH " + r - : ""; + ? typeof r === 'object' + ? 'WITH ' + JSON.stringify(r) + : 'WITH ' + r + : ''; - injectedLogger[logged.options.returnLogLevel](`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`); + 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); + ? 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(", ") - : "" + return value !== undefined ? `${name}=${value}` : ''; + }) + .filter((v) => v.length > 0) + .join(', ') + : '' : typeof returnsData === 'string' - ? "WITH " + returnsData + "=" + typeof r === "object" ? JSON.stringify(r) : r + ? 'WITH ' + returnsData + '=' + typeof r === 'object' + ? JSON.stringify(r) + : r : returnsData - ? typeof r === "object" - ? "WITH " + JSON.stringify(r) - : "WITH " + r - : ""; + ? typeof r === 'object' + ? 'WITH ' + JSON.stringify(r) + : 'WITH ' + r + : ''; - injectedLogger[logged.options.returnLogLevel](`${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`); + injectedLogger[logged.options.returnLogLevel]( + `${createCallLogIdentifyMessage('RETURNED', type, key, route)} ${resultLogged}`, + ); return r; } } else { @@ -178,9 +219,11 @@ export function overrideBuild, R>( } catch (e) { // Error Log if (logged.options.errorLogLevel !== 'skip') { - injectedLogger[logged.options.errorLogLevel](`${createCallLogIdentifyMessage('ERROR', type, key, route)} ${e}`); + injectedLogger[logged.options.errorLogLevel]( + `${createCallLogIdentifyMessage('ERROR', type, key, route)} ${e}`, + ); } throw e; } - } -} \ No newline at end of file + }; +} diff --git a/src/logged/utils.ts b/src/logged/utils.ts index 2545ea2..01098f2 100644 --- a/src/logged/utils.ts +++ b/src/logged/utils.ts @@ -1,22 +1,22 @@ -import { Logger, LogLevel } from "@nestjs/common"; +import { Logger, LogLevel } from '@nestjs/common'; export const RevRequestMethod = [ - "GET", - "POST", - "PUT", - "DELETE", - "PATCH", - "ALL", - "OPTIONS", - "HEAD", - "SEARCH", + 'GET', + 'POST', + 'PUT', + 'DELETE', + 'PATCH', + 'ALL', + 'OPTIONS', + 'HEAD', + 'SEARCH', ]; export function loggerInit(_target: any) { - if (!Object.getOwnPropertyNames(_target).includes("logger")) { + if (!Object.getOwnPropertyNames(_target).includes('logger')) { const newTargetLogger = new Logger(_target.constructor.name); - newTargetLogger.log("Logger Initialized."); - Object.defineProperty(_target, "logger", { + newTargetLogger.log('Logger Initialized.'); + Object.defineProperty(_target, 'logger', { writable: false, enumerable: false, configurable: false, @@ -25,7 +25,12 @@ export function loggerInit(_target: any) { } } -export type BuildType = 'route' | 'function' | 'guard' | 'interceptor' | 'middleware'; +export type BuildType = + | 'route' + | 'function' + | 'guard' + | 'interceptor' + | 'middleware'; const callLogIdentifyMessageDictionary: Record = { route: 'ENDPOINT', @@ -33,14 +38,24 @@ const callLogIdentifyMessageDictionary: Record = { guard: 'GUARD', interceptor: 'INTERCEPTOR', middleware: 'MIDDLEWARE', -} +}; -export function createCallLogIdentifyMessage(message: 'HIT' | 'RETURNED' | 'ERROR', type: BuildType, key?: string, route?: string) { +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 === 'guard' || + type === 'interceptor' || + type === 'middleware' || + type === 'route' + ) + return `${message} ${callLogIdentifyMessageDictionary[type]} ${key} (${route})`; if (type === 'function') return `${message} ${callLogIdentifyMessageDictionary[type]} ${key}`; @@ -68,4 +83,4 @@ export const defaultOverrideBuildOptions: OverrideBuildOptions = { skipCallLog: false, skipReturnLog: false, skipErrorLog: false, -} \ No newline at end of file +}; diff --git a/src/logger.ts b/src/logger.ts index 9854f0c..5d20d48 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -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(); } -} \ No newline at end of file +} diff --git a/src/reflected.ts b/src/reflected.ts index 7ab6047..1e001d2 100644 --- a/src/reflected.ts +++ b/src/reflected.ts @@ -1,4 +1,10 @@ -import { RouteParamtypes, Type, PipeTransform, createPipesRouteParamDecorator, createRouteParamDecorator } from "./internals/nest"; +import { + RouteParamtypes, + Type, + PipeTransform, + createPipesRouteParamDecorator, + createRouteParamDecorator, +} from './internals/nest'; export type Path = string | string[]; export type Paths = Path[]; @@ -27,28 +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 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) || []; @@ -60,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 +type Pipe = Type | PipeTransform; export function LoggedParam(): LoggedParamReturns; -export function LoggedParam( - ...pipes: Pipe[] -): LoggedParamReturns; +export function LoggedParam(...pipes: Pipe[]): LoggedParamReturns; export function LoggedParam( property: string, ...pipes: Pipe[] @@ -97,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, @@ -109,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[] @@ -128,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[] @@ -155,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, R>(namePaths?: { - [name: string]: string; -} | string) { +export function Returns, R>( + namePaths?: + | { + [name: string]: string; + } + | string, +) { return ( _target: any, _key: string | symbol, - descriptor: TypedPropertyDescriptor<(...args: F) => Promise | R> + descriptor: TypedPropertyDescriptor<(...args: F) => Promise | R>, ) => { Reflect.defineMetadata( returns, @@ -198,10 +213,10 @@ export function Returns, R>(namePaths?: { ? namePaths : Object.entries(namePaths).reduce( (prev, curr) => [...prev, { name: curr[0], path: curr[1] }], - [] + [], ) : true, - descriptor.value + descriptor.value, ); }; } diff --git a/src/test/index.ts b/src/test/index.ts index c40c65d..0faa556 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -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(); /** diff --git a/src/utils.ts b/src/utils.ts index 7908b99..cb05120 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,9 +1,9 @@ -import { Logger } from "@nestjs/common"; -import { ScopedLogger } from "./logger"; -import { REQUEST_LOG_ID } from "./logged/utils"; +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]) -} \ No newline at end of file + return new ScopedLogger(logger, [functionName], req[REQUEST_LOG_ID]); +} diff --git a/yarn.lock b/yarn.lock index 129a855..143fe3a 100644 --- a/yarn.lock +++ b/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"