{"version":3,"file":"index.mjs","names":[],"sources":["../../src/nestjs/index.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseMxllogOptions } from '../shared/middleware'\nimport { extractSafeNodeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n  'middleware context. Make sure MxllogModule.forRoot() is imported in your AppModule.',\n)\n\nexport type MxllogNestJSOptions = BaseMxllogOptions\n\nexport { useLogger }\n\nexport interface MxllogModuleAsyncOptions {\n  /** Modules to import (for dependency injection into the factory) */\n  imports?: any[]\n  /** Factory function that returns mxllog options. Can be async. */\n  useFactory: (...args: any[]) => MxllogNestJSOptions | Promise<MxllogNestJSOptions>\n  /** Injection tokens to resolve and pass to the factory */\n  inject?: any[]\n}\n\ndeclare module 'http' {\n  interface IncomingMessage {\n    log?: RequestLogger\n  }\n}\n\ndeclare module 'express-serve-static-core' {\n  interface Request {\n    log?: RequestLogger\n  }\n}\n\nfunction createMxllogMiddleware(getOptions: () => MxllogNestJSOptions) {\n  return (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n    const options = getOptions()\n    const headers = extractSafeNodeHeaders(req.headers)\n    const url = new URL(req.url || '/', 'http://localhost')\n\n    const { logger, finish, skipped } = createMiddlewareLogger({\n      method: req.method || 'GET',\n      path: url.pathname,\n      requestId: headers['x-request-id'] || crypto.randomUUID(),\n      headers,\n      ...options,\n    })\n\n    if (skipped) {\n      next()\n      return\n    }\n\n    req.log = logger\n\n    res.on('finish', () => {\n      finish({ status: res.statusCode }).catch(() => {})\n    })\n\n    storage.run(logger, () => next())\n  }\n}\n\n/**\n * NestJS module for mxllog wide event logging.\n *\n * Registers a global middleware that creates a request-scoped logger\n * for every incoming request. Use `useLogger()` to access it anywhere\n * in the call stack, or `req.log` directly in controllers.\n *\n * @example\n * ```ts\n * import { Module } from '@nestjs/common'\n * import { MxllogModule } from '@safaricom-mxl/log/nestjs'\n * import { createAxiomDrain } from '@safaricom-mxl/log/axiom'\n *\n * @Module({\n *   imports: [\n *     MxllogModule.forRoot({\n *       drain: createAxiomDrain(),\n *       exclude: ['/health'],\n *     }),\n *   ],\n * })\n * export class AppModule {}\n * ```\n */\nexport class MxllogModule implements NestModule {\n\n  private static options: MxllogNestJSOptions = {}\n\n  /**\n   * Register mxllog with static configuration.\n   *\n   * @example\n   * ```ts\n   * MxllogModule.forRoot({\n   *   drain: createAxiomDrain(),\n   *   enrich: (ctx) => { ctx.event.region = process.env.FLY_REGION },\n   * })\n   * ```\n   */\n  static forRoot(options: MxllogNestJSOptions = {}): DynamicModule {\n    MxllogModule.options = options\n    return {\n      module: MxllogModule,\n      global: true,\n    }\n  }\n\n  /**\n   * Register mxllog with async configuration (e.g. from `ConfigService`).\n   *\n   * @example\n   * ```ts\n   * MxllogModule.forRootAsync({\n   *   imports: [ConfigModule],\n   *   inject: [ConfigService],\n   *   useFactory: (config: ConfigService) => ({\n   *     drain: createAxiomDrain({ token: config.get('AXIOM_TOKEN') }),\n   *   }),\n   * })\n   * ```\n   */\n  static forRootAsync(asyncOptions: MxllogModuleAsyncOptions): DynamicModule {\n    return {\n      module: MxllogModule,\n      imports: asyncOptions.imports || [],\n      providers: [\n        {\n          provide: 'EVLOG_OPTIONS',\n          useFactory: async (...args: any[]) => {\n            MxllogModule.options = await asyncOptions.useFactory(...args)\n            return MxllogModule.options\n          },\n          inject: asyncOptions.inject || [],\n        },\n      ],\n      global: true,\n    }\n  }\n\n  configure(consumer: MiddlewareConsumer): void {\n    consumer\n      .apply(createMxllogMiddleware(() => MxllogModule.options))\n      .forRoutes('*')\n  }\n\n}\n"],"mappings":";;;AAOA,MAAM,EAAE,SAAS,cAAc,oBAC7B,sFACD;AA2BD,SAAS,uBAAuB,YAAuC;AACrE,SAAQ,KAAsB,KAAqB,SAAqB;EACtE,MAAM,UAAU,YAAY;EAC5B,MAAM,UAAU,uBAAuB,IAAI,QAAQ;EACnD,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,mBAAmB;EAEvD,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI;GACV,WAAW,QAAQ,mBAAmB,OAAO,YAAY;GACzD;GACA,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS;AACX,SAAM;AACN;;AAGF,MAAI,MAAM;AAEV,MAAI,GAAG,gBAAgB;AACrB,UAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,CAAC,YAAY,GAAG;IAClD;AAEF,UAAQ,IAAI,cAAc,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BrC,IAAa,eAAb,MAAa,aAAmC;CAE9C,OAAe,UAA+B,EAAE;;;;;;;;;;;;CAahD,OAAO,QAAQ,UAA+B,EAAE,EAAiB;AAC/D,eAAa,UAAU;AACvB,SAAO;GACL,QAAQ;GACR,QAAQ;GACT;;;;;;;;;;;;;;;;CAiBH,OAAO,aAAa,cAAuD;AACzE,SAAO;GACL,QAAQ;GACR,SAAS,aAAa,WAAW,EAAE;GACnC,WAAW,CACT;IACE,SAAS;IACT,YAAY,OAAO,GAAG,SAAgB;AACpC,kBAAa,UAAU,MAAM,aAAa,WAAW,GAAG,KAAK;AAC7D,YAAO,aAAa;;IAEtB,QAAQ,aAAa,UAAU,EAAE;IAClC,CACF;GACD,QAAQ;GACT;;CAGH,UAAU,UAAoC;AAC5C,WACG,MAAM,6BAA6B,aAAa,QAAQ,CAAC,CACzD,UAAU,IAAI"}