在全局(单个)服务中使用特定于请求的上下文

时间:2019-09-03 14:11:23

标签: node.js express nestjs typeorm

我希望能够登录(如console.log)来完成每个SQL查询。我正在使用Nest.js和TypeORM(它是Nest.js的包装器)。我不知道如何将特定于请求的数据注入到全局(单个)提供程序中。

我正在使用Nest.js v6.6.3和@nestjs/typeorm v6.1.3。

// current-user.service.ts
@Injectable({ scope: Scope.REQUEST })
export class CurrentUserService {
  get currentUser(): string | null {
    if (!this.request || !this.request.user) {
      return null;
    }

    return this.request.user.email;
  }

  constructor(@Optional() @Inject(REQUEST) private request: Request) {}
}

// logger.service.ts
@Injectable()
export class LoggerService extends Logger {
  constructor(private readonly moduleRef: ModuleRef) {
    super();
  }

  log(message: any, context?: string) {
    super.log(this.formatMessage(message), context);
  }

  private formatMessage(message: any) {
    // ** This is the problematic code **
    const currentUserService = this.moduleRef.get(CurrentUserService, {
      strict: false,
    });
    return `[${currentUserService.currentUser}]: ${message}`;
  }
}

// typeorm-logger.service.ts
@Injectable()
export class TypeormLogger implements Logger {
  // Logger is imported from `typeorm`
  constructor(private logger: LoggerService) {}

  logQuery(query: string) {
    // there are more params, don't matter for the sake of the argument
    this.logger.log(query);
  }
}

// logger.module.ts
@Module({
  providers: [LoggerService, TypeormLogger],
  exports: [LoggerService, TypeormLogger],
})
export class LoggerModule {}

// app.module.ts
@Module({
  imports: [
    TypeOrmModule.ForRootAsync({
      imports: [LoggerModule],
      inject: [TypeormLogger],
      useFactory: (typeormLogger: TypeormLogger) => {
        return {
          type: 'mysql',
          logger: typeormLogger,
          keepConnectionAlive: false,
          ...
        };
      },
    }),
  ],
})
export class AppModule {}

使用moduleRef.get()似乎无法进行跨Module的解析,因此我尝试使用moduleRef.resolve()来代替,但是随后我仍然使用{{ 1}}。此外,CurrentUserService返回一个request === undefined,对于类似日志记录的操作来说,这是不理想的。

以上是一个特定的用例,但可以将其概括化-如果您没有直接从Controller调用的代码,则无法注入经过身份验证的用户或请求ID之类的瞬态数据(这对于日志记录都非常有用) )。这似乎很奇怪,尤其是因为Nest.js严重依赖IoC。

1 个答案:

答案 0 :(得分:0)

我最终研究了Nest.js,到目前为止,它似乎还可以正常工作。请注意,我们在内部应用程序中使用了它,因此并发用户数很少,因此YMMV。

该解决方案基于hereasyncctx软件包。您可以找到完整的解决方案here