{"version":3,"file":"index.mjs","names":[],"sources":["../../src/fastify/index.ts"],"sourcesContent":["import type { FastifyPluginCallback } from 'fastify'\nimport { createMiddlewareLogger, type BaseMxllogOptions } from '../shared/middleware'\nimport { extractSafeNodeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n  'plugin context. Make sure app.register(mxllog) is called before your routes.',\n)\n\nexport type MxllogFastifyOptions = BaseMxllogOptions\n\nexport { useLogger }\n\ndeclare module 'fastify' {\n  interface FastifyRequest {\n    // Overrides Fastify's built-in pino logger on the request with mxllog's RequestLogger.\n    log: any\n  }\n}\n\ninterface RequestState {\n  finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n}\n\nconst mxllogPlugin: FastifyPluginCallback<MxllogFastifyOptions> = (fastify, options, done) => {\n  const emitted = new WeakSet<object>()\n  const requestState = new WeakMap<object, RequestState>()\n\n  fastify.addHook('onRequest', (request, _reply, done) => {\n    const headers = extractSafeNodeHeaders(request.headers)\n    const path = new URL(request.url, 'http://localhost').pathname\n\n    const { logger, finish, skipped } = createMiddlewareLogger({\n      method: request.method,\n      path,\n      requestId: headers['x-request-id'] || crypto.randomUUID(),\n      headers,\n      ...options,\n    })\n\n    if (skipped) {\n      done()\n      return\n    }\n\n    // Shadow Fastify's built-in pino logger with mxllog's request-scoped logger\n    const req = request as any\n    req.log = logger\n    requestState.set(request, { finish })\n\n    storage.run(logger, () => done())\n  })\n\n  fastify.addHook('onResponse', async (request, reply) => {\n    const state = requestState.get(request)\n    if (!state || emitted.has(request)) return\n    emitted.add(request)\n    await state.finish({ status: reply.statusCode })\n  })\n\n  fastify.addHook('onError', async (request, _reply, error) => {\n    const state = requestState.get(request)\n    if (!state || emitted.has(request)) return\n    emitted.add(request)\n    const logger = (request as any).log\n    const err = error instanceof Error ? error : new Error(String(error))\n    if (logger && typeof logger.error === 'function') logger.error(err)\n    await state.finish({ error: err })\n  })\n\n  done()\n}\n\n// Break Fastify plugin encapsulation without a runtime dependency on fastify-plugin.\n// This is the same mechanism fastify-plugin uses internally.\nconst plugin = mxllogPlugin as any\nplugin[Symbol.for('skip-override')] = true\nplugin[Symbol.for('fastify.display-name')] = '@safaricom-mxl/log'\n\n/**\n * Create an mxllog plugin for Fastify.\n *\n * @example\n * ```ts\n * import Fastify from 'fastify'\n * import { initLogger } from '@safaricom-mxl/log'\n * import { mxllog } from '@safaricom-mxl/log/fastify'\n * import { createAxiomDrain } from '@safaricom-mxl/log/axiom'\n *\n * initLogger({ env: { service: 'fastify-api' } })\n *\n * const app = Fastify()\n * await app.register(mxllog, {\n *   drain: createAxiomDrain(),\n *   enrich: (ctx) => {\n *     ctx.event.region = process.env.FLY_REGION\n *   },\n * })\n * ```\n */\nexport const mxllog = mxllogPlugin\n"],"mappings":";;;AAKA,MAAM,EAAE,SAAS,cAAc,oBAC7B,+EACD;AAiBD,MAAM,gBAA6D,SAAS,SAAS,SAAS;CAC5F,MAAM,0BAAU,IAAI,SAAiB;CACrC,MAAM,+BAAe,IAAI,SAA+B;AAExD,SAAQ,QAAQ,cAAc,SAAS,QAAQ,SAAS;EACtD,MAAM,UAAU,uBAAuB,QAAQ,QAAQ;EACvD,MAAM,OAAO,IAAI,IAAI,QAAQ,KAAK,mBAAmB,CAAC;EAEtD,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,QAAQ;GAChB;GACA,WAAW,QAAQ,mBAAmB,OAAO,YAAY;GACzD;GACA,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS;AACX,SAAM;AACN;;EAIF,MAAM,MAAM;AACZ,MAAI,MAAM;AACV,eAAa,IAAI,SAAS,EAAE,QAAQ,CAAC;AAErC,UAAQ,IAAI,cAAc,MAAM,CAAC;GACjC;AAEF,SAAQ,QAAQ,cAAc,OAAO,SAAS,UAAU;EACtD,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,QAAQ,IAAI,QAAQ,CAAE;AACpC,UAAQ,IAAI,QAAQ;AACpB,QAAM,MAAM,OAAO,EAAE,QAAQ,MAAM,YAAY,CAAC;GAChD;AAEF,SAAQ,QAAQ,WAAW,OAAO,SAAS,QAAQ,UAAU;EAC3D,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,QAAQ,IAAI,QAAQ,CAAE;AACpC,UAAQ,IAAI,QAAQ;EACpB,MAAM,SAAU,QAAgB;EAChC,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AACrE,MAAI,UAAU,OAAO,OAAO,UAAU,WAAY,QAAO,MAAM,IAAI;AACnE,QAAM,MAAM,OAAO,EAAE,OAAO,KAAK,CAAC;GAClC;AAEF,OAAM;;AAKR,MAAM,SAAS;AACf,OAAO,OAAO,IAAI,gBAAgB,IAAI;AACtC,OAAO,OAAO,IAAI,uBAAuB,IAAI;;;;;;;;;;;;;;;;;;;;;;AAuB7C,MAAa,SAAS"}