diff --git a/dist/README.md b/dist/README.md new file mode 100644 index 0000000..43e662b --- /dev/null +++ b/dist/README.md @@ -0,0 +1,146 @@ +# NestLogged +This package provides some decorations to make NestJS logging simpler. +It only uses Logger provided by @nestjs/common package and some dependencies required for nestjs. + +## How to use + +### Route Logging +```ts +import {Controller, Get} from "@nestjs/common"; +import {LoggedRoute} from "./logged"; + +@Controller('whatever') +export class WhateverController { + constructor() {} + + @Get('/you/like') + @LoggedRoute('/you/like') // Add this! + public async whateverYouLikeImpl() { + return 'Whatever You Like'; + } +} +``` + +``` +[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController//you/like (whateverYouLikeImpl) +[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] RETURNED RESPONSE WhateverController//you/like (whateverYouLikeImpl) +``` + +It will automatically log the call and response. + +If function throws any exception, it will also catch exception, log that, and throw it again. + +```ts +import {BadRequestException, Controller, Get} from "@nestjs/common"; +import {LoggedRoute} from "./logged"; + +@Controller('whatever') +export class WhateverController { + constructor() {} + + @Get('/you/like') + @LoggedRoute('/you/like') + public async whateverYouLikeImpl() { + throw new BadRequestException("I don't like this") // Throwing HTTP exception here + } +} +``` + +``` +[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] HIT HTTP WhateverController//you/like (whateverYouLikeImpl) +[Nest] 000000 - 00/00/0000, 00:00:00 AM LOG [WhateverController] WHILE HTTP WhateverController//you/like (whateverYouLikeImpl) ERROR BadRequestException: I don't like this +``` + +Not only HTTP exception, it will also catch all exceptions and log it. + +### Function Logging +```ts +import {LoggedFunction} from "./logged"; + +@LoggedFunction // This decorator will do the magic for you +export async function doILikeThis(stuff: "apple" | "banana"): "yes" | "no" { + return stuff === "apple" ? "yes" : "no" +} +``` + +LoggedFunction decorator will log function calls and returns for you. + +**Note: This decorator is expected to be used with a class method like Service. (we will upgrade that later, so you can use it without class)** + +Like `LoggedRoute` decorator, it will automatically catch all exceptions, log it, and throw it again. + +### Parameter Logging + +```ts +import {LoggedFunction} from "./logged"; +import {LoggedParam} from "./reflected"; + +@LoggedFunction +export async function doILikeThis( + @LoggedParam("stuff") // It will add logs for parameter + stuff: "apple" | "banana" +): "yes" | "no" { + return stuff === "apple" ? "yes" : "no" +} + +doILikeThis("apple") +``` +``` +HIT HTTP WhateverController//you/like (whateverYouLikeImpl) WITH stuff="apple" +``` + +It will add `WITH {param}={value}, {param2}={value2}` in log. +The name of parameter is decided by the first parameter of LoggedParam decorator. + +This decorator also can be used with `LoggedRoute`. + +### Scoped Logging + +You can do scoped logging with `InjectLogger` decorator. + +Like tracebacks, it will add a scope and call stacks in log, so you can easily follow logs. + +```ts +import {LoggedFunction} from "./logged"; +import {InjectLogger, LoggedParam} from "./reflected"; +import {ScopedLogger} from "./logger"; + +@LoggedFunction +export async function doILikeThis( + @LoggedParam("stuff") stuff: string, + @InjectLogger logger: ScopedLogger // First of all, add this. + // Note: If this is planned to be called outside of controller route function, + // this can be optional. like: (@InjectLogger logger?: ScopedLogger) +): "yes" | "no" { + logger.log(`YAY we got ${stuff}`) + return stuff === "apple" ? "yes" : "no" +} +``` + +Then, in controller: + +```ts +import {BadRequestException, Controller, Get, Param} from "@nestjs/common"; +import {LoggedRoute} from "./logged"; +import {InjectLogger, LoggedParam} from "./reflected"; +import {ScopedLogger} from "./logger"; + +@Controller('you') +export class WhateverController { + constructor() { + } + + @Get('/like/:thing') + @LoggedRoute('/like/{thing}') + public async like( + @LoggedParam('thing') @Param('thing') thing: string, + @InjectLogger logger: ScopedLogger, + // When NestJS calls this function, decorator will automatically fills this logger parameter. + ) { + const likeThing = doILikeThis(thing, logger) === "yes" + if (!likeThing) throw BadRequestException("I don't like this") + } +} +``` + +The `@LoggedFunction` decorator that applied to `doILikeThis` function will intercept given logger, and make it scoped. diff --git a/package.json b/package.json index 0c940af..0fd240d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "typescript": "^5.2.2" }, "scripts": { + "docs": "cp ./README.md ./dist/README.md", "build": "rimraf ./dist/lib && tsc", - "up": "yarn build && yarn publish dist" + "up": "yarn docs && yarn build && yarn publish dist" } }