Repository: iamolegga/nestjs-pino
Pull request #441 (2021-03-24 13:59:22)

export pino-params provider
With this PR we can now do :

```javascript
// logger.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { Logger, Params, PARAMS_PROVIDER_TOKEN, PinoLogger } from 'nestjs-pino';

@Injectable()
export class LoggerService extends Logger {
    private aProperty: string;
    
    constructor(
        pinoLogger: PinoLogger,
        @Inject(PARAMS_PROVIDER_TOKEN) params: Params,
        aProperty: string
    ) {
        super(pinoLogger, params);
        this.aProperty = aProperty
    }

    aMethod(): void {
        ...
    }
}
```
and 

```javascript
// logger.module.ts
import { Module } from "@nestjs/common";
import { LoggerModule  } from "nestjs-pino";
import { LoggerService } from "./logger.service";

@Module({
  exports: [LoggerService],
  providers: [LoggerService],
  imports: [
   LoggerModule.forRoot()
  ],
})
export class LoggerModule {}
```

AckerApple: I am in appreciation of this PR. I have a more tedious solution injected into a company code base and would like to see this PR merged
jdt6: Yea how soon until this gets merged!???
iamolegga: Hi, looks like @jdt6 really need this feature 😀 And there colud be more users who need this too, so let's add extra section in docs with example and some basic test to be sure that this will not be broken in future. After that I can merge it and release. Thanks

Patch:
diff --git a/README.md b/README.md
index cc82f84..5d1f70a 100644
--- a/README.md
+++ b/README.md
@@ -436,6 +436,52 @@ import { Logger } from "nestjs-pino";
 const app = await NestFactory.create(MyModule, { logger: false });
 app.useLogger(app.get(Logger));
 ```
+## Extend the Logger class
+
+You can extend the Logger class to add your own business logic.
+
+```ts
+// logger.service.ts
+import { Logger, PinoLogger, Params, PARAMS_PROVIDER_TOKEN } from "nestjs-pino";
+
+@Injectable()
+class LoggerService extends Logger() {
+  // regular injecting
+  constructor(
+    logger: PinoLogger,
+    @Inject(PARAMS_PROVIDER_TOKEN) params: Params
+  ) {
+    ...
+  }
+
+  // extended method
+  myMethod(): any {}
+}
+
+import { PinoLogger, Params, PARAMS_PROVIDER_TOKEN } from "nestjs-pino";
+
+@Injectable()
+class LoggerService extends PinoLogger() {
+  // regular injecting
+  constructor(
+    @Inject(PARAMS_PROVIDER_TOKEN) params: Params
+  ) {
+    ...
+  }
+
+  // extended method
+  myMethod(): any {}
+}
+
+
+// logger.module.ts
+@Module({
+  providers: [LoggerService],
+  exports: [LoggerService],
+  imports: [LoggerModule.forRoot()],
+})
+class LoggerModule {}
+```
 
 ## Migrating
 
diff --git a/src/Logger.ts b/src/Logger.ts
index 9452f90..d2731ca 100644
--- a/src/Logger.ts
+++ b/src/Logger.ts
@@ -8,7 +8,7 @@ export class Logger implements LoggerService {
   private readonly contextName: string;
 
   constructor(
-    private readonly logger: PinoLogger,
+    protected readonly logger: PinoLogger,
     @Inject(PARAMS_PROVIDER_TOKEN) { renameContext }: Params
   ) {
     this.contextName = renameContext || "context";
diff --git a/src/LoggerCoreModule.ts b/src/LoggerCoreModule.ts
index c48b81c..23c8c58 100644
--- a/src/LoggerCoreModule.ts
+++ b/src/LoggerCoreModule.ts
@@ -33,7 +33,7 @@ export class LoggerCoreModule implements NestModule {
     return {
       module: LoggerCoreModule,
       providers: [Logger, ...decorated, PinoLogger, paramsProvider],
-      exports: [Logger, ...decorated, PinoLogger]
+      exports: [Logger, ...decorated, PinoLogger, paramsProvider]
     };
   }
 
@@ -58,7 +58,7 @@ export class LoggerCoreModule implements NestModule {
       module: LoggerCoreModule,
       imports: params.imports,
       providers,
-      exports: [Logger, ...decorated, PinoLogger]
+      exports: [Logger, ...decorated, PinoLogger, paramsProvider]
     };
   }
 
diff --git a/src/index.ts b/src/index.ts
index 4d91edc..324e1ef 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -3,3 +3,4 @@ export { Params, LoggerModuleAsyncParams } from "./params";
 export { Logger } from "./Logger";
 export { PinoLogger } from "./PinoLogger";
 export { InjectPinoLogger, getLoggerToken } from "./InjectPinoLogger";
+export { PARAMS_PROVIDER_TOKEN } from './constants'


Test patch:
diff --git a/__tests__/module.spec.ts b/__tests__/module.spec.ts
index a19cc09..a68bf14 100644
--- a/__tests__/module.spec.ts
+++ b/__tests__/module.spec.ts
@@ -1,8 +1,8 @@
 import { NestFactory } from "@nestjs/core";
-import { Module, Controller, Get, Injectable } from "@nestjs/common";
+import { Module, Controller, Get, Injectable, Inject } from "@nestjs/common";
 import MemoryStream = require("memorystream");
 import * as request from "supertest";
-import { Logger, LoggerModule } from "../src";
+import { Logger, PinoLogger, LoggerModule, Params, PARAMS_PROVIDER_TOKEN } from "../src";
 import { platforms } from "./utils/platforms";
 import { fastifyExtraWait } from "./utils/fastifyExtraWait";
 import { parseLogs } from "./utils/logs";
@@ -125,6 +125,125 @@ describe("module initialization", () => {
           const logObject = parsedLogs.find(v => v.msg === random);
           expect(logObject).toBeTruthy();
         });
+
+        it("should work properly with an extended logger service", async() => {
+          const stream = new MemoryStream();
+          const random = Math.random().toString();
+          let logs = "";
+          stream.on("data", (chunk: string) => {
+            logs += chunk.toString();
+          });
+
+          @Injectable()
+          class LoggerService extends Logger {
+            private readonly message: String; 
+            constructor(
+              logger: PinoLogger,
+              @Inject(PARAMS_PROVIDER_TOKEN) params: Params,
+            ) {
+              super(logger, params);
+              this.message = random;
+            }
+            
+            log() {
+              this.logger.info(this.message)
+            }
+          }
+
+          @Controller("/")
+          class TestController {
+            constructor(private readonly logger: LoggerService) {}
+            @Get("/")
+            get() {
+              this.logger.log();
+              return {};
+            }
+          }
+
+          @Module({
+            providers: [LoggerService],
+            exports: [LoggerService],
+            imports: [LoggerModule.forRoot({pinoHttp: stream})],
+            controllers: [TestController]
+          })
+          class TestModule {}
+
+          const app = await NestFactory.create(
+            TestModule,
+            new PlatformAdapter(),
+            { logger: false }
+          );
+          const server = app.getHttpServer();
+
+          await app.init();
+          await fastifyExtraWait(PlatformAdapter, app);
+
+          await request(server).get("/");
+          await app.close();
+
+          const parsedLogs = parseLogs(logs);
+          const logObject = parsedLogs.find(v => v.msg === random);
+          expect(logObject).toBeTruthy();
+        })
+
+        it("should work properly with an extended PinoLogger service", async() => {
+          const stream = new MemoryStream();
+          const random = Math.random().toString();
+          let logs = "";
+          stream.on("data", (chunk: string) => {
+            logs += chunk.toString();
+          });
+
+          @Injectable()
+          class LoggerService extends PinoLogger {
+            private readonly message: String; 
+            constructor(
+              @Inject(PARAMS_PROVIDER_TOKEN) params: Params,
+            ) {
+              super(params);
+              this.message = random;
+            }
+            
+            log() {
+              this.info(this.message)
+            }
+          }
+
+          @Controller("/")
+          class TestController {
+            constructor(private readonly logger: LoggerService) {}
+            @Get("/")
+            get() {
+              this.logger.log();
+              return {};
+            }
+          }
+
+          @Module({
+            providers: [LoggerService],
+            exports: [LoggerService],
+            imports: [LoggerModule.forRoot({pinoHttp: stream})],
+            controllers: [TestController]
+          })
+          class TestModule {}
+
+          const app = await NestFactory.create(
+            TestModule,
+            new PlatformAdapter(),
+            { logger: false }
+          );
+          const server = app.getHttpServer();
+
+          await app.init();
+          await fastifyExtraWait(PlatformAdapter, app);
+
+          await request(server).get("/");
+          await app.close();
+
+          const parsedLogs = parseLogs(logs);
+          const logObject = parsedLogs.find(v => v.msg === random);
+          expect(logObject).toBeTruthy();
+        })
       });
 
       describe("forRootAsync", () => {
@@ -371,6 +490,129 @@ describe("module initialization", () => {
           const logObject = parsedLogs.find(v => v.msg === random);
           expect(logObject).toBeTruthy();
         });
+
+        it("should work properly with an extended logger service", async() => {
+          const stream = new MemoryStream();
+          const random = Math.random().toString();
+          let logs = "";
+          stream.on("data", (chunk: string) => {
+            logs += chunk.toString();
+          });
+
+          @Injectable()
+          class LoggerService extends Logger {
+            private readonly message: String; 
+            constructor(
+              logger: PinoLogger,
+              @Inject(PARAMS_PROVIDER_TOKEN) params: Params,
+            ) {
+              super(logger, params);
+              this.message = random;
+            }
+            
+            log() {
+              this.logger.info(this.message)
+            }
+          }
+
+          @Controller("/")
+          class TestController {
+            constructor(private readonly logger: LoggerService) {}
+            @Get("/")
+            get() {
+              this.logger.log();
+              return {};
+            }
+          }
+
+          @Module({
+            providers: [LoggerService],
+            exports: [LoggerService],
+            imports: [LoggerModule.forRootAsync({
+              useFactory: async() => ({pinoHttp: stream})
+            })],
+            controllers: [TestController]
+          })
+          class TestModule {}
+
+          const app = await NestFactory.create(
+            TestModule,
+            new PlatformAdapter(),
+            { logger: false }
+          );
+          const server = app.getHttpServer();
+
+          await app.init();
+          await fastifyExtraWait(PlatformAdapter, app);
+
+          await request(server).get("/");
+          await app.close();
+
+          const parsedLogs = parseLogs(logs);
+          const logObject = parsedLogs.find(v => v.msg === random);
+          expect(logObject).toBeTruthy();
+        })
+
+        it("should work properly with an extended PinoLogger service", async() => {
+          const stream = new MemoryStream();
+          const random = Math.random().toString();
+          let logs = "";
+          stream.on("data", (chunk: string) => {
+            logs += chunk.toString();
+          });
+
+          @Injectable()
+          class LoggerService extends PinoLogger {
+            private readonly message: String; 
+            constructor(
+              @Inject(PARAMS_PROVIDER_TOKEN) params: Params,
+            ) {
+              super(params);
+              this.message = random;
+            }
+            
+            log() {
+              this.info(this.message)
+            }
+          }
+
+          @Controller("/")
+          class TestController {
+            constructor(private readonly logger: LoggerService) {}
+            @Get("/")
+            get() {
+              this.logger.log();
+              return {};
+            }
+          }
+
+          @Module({
+            providers: [LoggerService],
+            exports: [LoggerService],
+            imports: [LoggerModule.forRootAsync({
+              useFactory: async() => ({pinoHttp: stream})
+            })],
+            controllers: [TestController]
+          })
+          class TestModule {}
+
+          const app = await NestFactory.create(
+            TestModule,
+            new PlatformAdapter(),
+            { logger: false }
+          );
+          const server = app.getHttpServer();
+
+          await app.init();
+          await fastifyExtraWait(PlatformAdapter, app);
+
+          await request(server).get("/");
+          await app.close();
+
+          const parsedLogs = parseLogs(logs);
+          const logObject = parsedLogs.find(v => v.msg === random);
+          expect(logObject).toBeTruthy();
+        })
       });
     });
   }