@burdenoff/be-sdk 2026.513.4 → 2026.513.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EventQueueFactory-TWDDFMQY.js +8 -0
- package/dist/{EventQueueFactory-FNE7H66N.js.map → EventQueueFactory-TWDDFMQY.js.map} +1 -1
- package/dist/{chunk-WPGSKLAG.js → chunk-3JBKPVWY.js} +24 -5
- package/dist/chunk-3JBKPVWY.js.map +1 -0
- package/dist/{chunk-KSO6QQVD.js → chunk-EMSON3UD.js} +952 -10
- package/dist/chunk-EMSON3UD.js.map +1 -0
- package/dist/{chunk-LRL6GKXI.js → chunk-L72RC2EI.js} +3 -3
- package/dist/{chunk-LRL6GKXI.js.map → chunk-L72RC2EI.js.map} +1 -1
- package/dist/{chunk-NUZZRJNN.js → chunk-MI72VKNQ.js} +171 -5
- package/dist/chunk-MI72VKNQ.js.map +1 -0
- package/dist/{chunk-SXIL2AJF.js → chunk-OMKFTTAN.js} +5 -5
- package/dist/{chunk-SXIL2AJF.js.map → chunk-OMKFTTAN.js.map} +1 -1
- package/dist/{chunk-S52PJKSW.js → chunk-Q6HJARHV.js} +3 -3
- package/dist/{chunk-S52PJKSW.js.map → chunk-Q6HJARHV.js.map} +1 -1
- package/dist/{chunk-COSUYUCB.js → chunk-QKJR4L7B.js} +149 -3
- package/dist/chunk-QKJR4L7B.js.map +1 -0
- package/dist/{chunk-VOFKF27Q.js → chunk-UVYDP6P6.js} +3 -2
- package/dist/chunk-UVYDP6P6.js.map +1 -0
- package/dist/{chunk-DR5AQJT6.js → chunk-Y4TPKRZB.js} +3 -3
- package/dist/{chunk-DR5AQJT6.js.map → chunk-Y4TPKRZB.js.map} +1 -1
- package/dist/config-QVYSAUMT.js +4 -0
- package/dist/{config-7U7J3QXQ.js.map → config-QVYSAUMT.js.map} +1 -1
- package/dist/esm-M2M7HGV4.js +1356 -0
- package/dist/esm-M2M7HGV4.js.map +1 -0
- package/dist/event-queue/index.d.ts +1 -1
- package/dist/event-queue/index.js +5 -5
- package/dist/graph/index.js +6 -6
- package/dist/graphql/index.d.ts +1 -1
- package/dist/graphql/index.js +2 -2
- package/dist/{index-HkD7NBED.d.ts → index-CDFQRL-h.d.ts} +24 -2
- package/dist/{index-BF2uh_h9.d.ts → index-eUvoVdr7.d.ts} +158 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +12 -12
- package/dist/init/index.js +4 -4
- package/dist/prisma/index.js +5 -5
- package/dist/server/index.js +20 -0
- package/dist/server/index.js.map +1 -1
- package/dist/telemetry/index.js.map +1 -1
- package/package.json +14 -3
- package/dist/EventQueueFactory-FNE7H66N.js +0 -8
- package/dist/chunk-COSUYUCB.js.map +0 -1
- package/dist/chunk-KSO6QQVD.js.map +0 -1
- package/dist/chunk-NUZZRJNN.js.map +0 -1
- package/dist/chunk-VOFKF27Q.js.map +0 -1
- package/dist/chunk-WPGSKLAG.js.map +0 -1
- package/dist/config-7U7J3QXQ.js +0 -4
- package/dist/esm-K6H7EIWK.js +0 -1450
- package/dist/esm-K6H7EIWK.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/telemetry/health.ts","../../src/telemetry/metrics-endpoint.ts","../../src/telemetry/prisma-logging.ts","../../src/telemetry/index.ts"],"names":["createHealthRoutes","_deps","Proxy","get","_target","prop","undefined","loadDefaultRegistry","mod","collectDefaultMetrics","register","createMetricsRoutesImpl","app","opts","path","ctx","registry","ctxWithSet","set","status","headers","contentType","metrics","createMetricsRoutes","createPrismaLoggingExtension","logger","name","query","$allOperations","model","operation","args","start","Date","now","result","debug","duration_ms","redactSensitiveFields","err","error","Error","message","String","resolveEnv","explicit","fromEnv","process","env","resolveVersion","resolveEndpoint","proto","resolveSampling","Number","isFinite","Math","min","max","parsed","resolveOtelSdkEnabled","sdkDisabled","otelEnabled","bootstrapTelemetry","cfg","serviceVersion","otlpEndpoint","sampleRatio","createPinoLogger","serviceName","version","setActiveTelemetryLogger","instrumentation","setupInstrumentation","tracing","samplingRate","otelSdk","createOtelSdk","boundary","module","info","metricsEnabled","metricsDropReason","warn","reason","shutdown","defaultLogger","setLevel","getLevel"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `/health`, `/health/live`, `/health/ready` Elysia routes with a 1s\n * result cache so readiness checks can't stampede Postgres.\n *\n * Dependencies (prisma, nats, valkey) are optional — omit any client and\n * the readiness check simply skips it.\n */\n\ninterface PrismaLike {\n $queryRaw: (strings: TemplateStringsArray) => Promise<unknown>;\n}\ninterface NatsLike {\n isConnected?: () => boolean | Promise<boolean>;\n healthCheck?: () => Promise<{ ok: boolean }>;\n}\ninterface ValkeyLike {\n ping: () => Promise<unknown>;\n}\n\nexport interface HealthDeps {\n prisma?: PrismaLike;\n nats?: NatsLike;\n valkey?: ValkeyLike;\n /** Service version reported on /health. */\n version?: string;\n /** Service name reported on /health. */\n serviceName?: string;\n}\n\ninterface CachedStatus {\n ready: boolean;\n checked: Record<string, { ok: boolean; error?: string }>;\n at: number;\n}\n\nconst CACHE_TTL_MS = 1000;\n\nasync function probeReady(deps: HealthDeps): Promise<CachedStatus> {\n const checked: Record<string, { ok: boolean; error?: string }> = {};\n\n if (deps.prisma) {\n try {\n await deps.prisma.$queryRaw`SELECT 1`;\n checked['postgres'] = { ok: true };\n } catch (err) {\n checked['postgres'] = {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n if (deps.nats) {\n try {\n const connected =\n typeof deps.nats.isConnected === 'function'\n ? await Promise.resolve(deps.nats.isConnected())\n : ((await deps.nats.healthCheck?.())?.ok ?? true);\n checked['nats'] = { ok: Boolean(connected) };\n } catch (err) {\n checked['nats'] = {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n if (deps.valkey) {\n try {\n await deps.valkey.ping();\n checked['valkey'] = { ok: true };\n } catch (err) {\n checked['valkey'] = {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const ready = Object.values(checked).every((c) => c.ok);\n return { ready, checked, at: Date.now() };\n}\n\nexport function createHealthRoutes(_deps: HealthDeps = {}): unknown {\n // Return an Elysia app lazily so be-sdk doesn't hard-require elysia.\n return new Proxy(\n {},\n {\n get(_target, prop): unknown {\n // Tell TypeScript consumers the returned object is an Elysia plugin;\n // the actual mount happens via `createHealthRoutesImpl`. Services\n // that prefer direct use can call `createHealthRoutesImpl(elysia, deps)`.\n if (prop === 'use' || prop === 'then') return undefined;\n return undefined;\n },\n }\n );\n}\n\n/**\n * Mount health routes on an existing Elysia app. Callers hold a reference\n * to Elysia themselves; be-sdk stays decoupled.\n */\nexport function createHealthRoutesImpl<\n App extends {\n get: (path: string, handler: (ctx: unknown) => unknown) => App;\n },\n>(app: App, deps: HealthDeps = {}): App {\n let cache: CachedStatus | null = null;\n\n const getStatus = async (): Promise<CachedStatus> => {\n if (cache && Date.now() - cache.at < CACHE_TTL_MS) return cache;\n cache = await probeReady(deps);\n return cache;\n };\n\n app.get('/health/live', () => ({\n status: 'ok',\n serviceName: deps.serviceName,\n version: deps.version,\n }));\n\n app.get('/health/ready', async (ctx: unknown): Promise<unknown> => {\n const status = await getStatus();\n const ctxWithSet = ctx as { set?: { status?: number } };\n if (!status.ready && ctxWithSet.set) ctxWithSet.set.status = 503;\n return {\n status: status.ready ? 'ok' : 'degraded',\n serviceName: deps.serviceName,\n version: deps.version,\n checks: status.checked,\n };\n });\n\n app.get('/health', async (ctx: unknown): Promise<unknown> => {\n const status = await getStatus();\n const ctxWithSet = ctx as { set?: { status?: number } };\n if (!status.ready && ctxWithSet.set) ctxWithSet.set.status = 503;\n return {\n status: status.ready ? 'ok' : 'degraded',\n serviceName: deps.serviceName,\n version: deps.version,\n checks: status.checked,\n uptime_s: Math.round(process.uptime()),\n };\n });\n\n return app;\n}\n","/**\n * Prometheus `/metrics` route mounter. Uses the shared `prom-client`\n * default registry so all instrumentation (GraphQL Envelop, Prisma,\n * runtime) shows up on a single endpoint.\n */\n\ninterface PromRegistryLike {\n metrics: () => Promise<string> | string;\n contentType?: string;\n}\n\nexport interface MetricsMountOptions {\n registry?: PromRegistryLike;\n path?: string;\n}\n\nasync function loadDefaultRegistry(): Promise<PromRegistryLike | null> {\n try {\n const mod = (await import('prom-client')) as unknown as {\n register: PromRegistryLike;\n collectDefaultMetrics: (opts?: Record<string, unknown>) => void;\n };\n // Kick runtime metrics into the default registry if not already.\n try {\n mod.collectDefaultMetrics({ register: mod.register });\n } catch {\n // Already registered — ignore duplicate-metric errors.\n }\n return mod.register;\n } catch {\n return null;\n }\n}\n\nexport function createMetricsRoutesImpl<\n App extends {\n get: (path: string, handler: (ctx: unknown) => unknown) => App;\n },\n>(app: App, opts: MetricsMountOptions = {}): App {\n const path = opts.path ?? '/metrics';\n\n app.get(path, async (ctx: unknown): Promise<unknown> => {\n const registry = opts.registry ?? (await loadDefaultRegistry());\n const ctxWithSet = ctx as { set?: { status?: number; headers?: Record<string, string> } };\n if (!registry) {\n if (ctxWithSet.set) ctxWithSet.set.status = 503;\n return '# prom-client not installed\\n';\n }\n if (ctxWithSet.set) {\n ctxWithSet.set.status = 200;\n ctxWithSet.set.headers = {\n 'content-type': registry.contentType ?? 'text/plain; version=0.0.4; charset=utf-8',\n };\n }\n return registry.metrics();\n });\n\n return app;\n}\n\n/**\n * Legacy export name used by the service template. Composes the Elysia\n * plugin-style function that `new Elysia().use(...)` accepts.\n */\nexport function createMetricsRoutes(opts: MetricsMountOptions = {}): unknown {\n return (app: Parameters<typeof createMetricsRoutesImpl>[0]): unknown => createMetricsRoutesImpl(app, opts);\n}\n","/**\n * Prisma client extension that pipes query events through the SDK logger\n * with trace/span correlation fields auto-injected. The\n * `@prisma/instrumentation` peer provides the spans\n * themselves; this extension only adds structured log events on top.\n */\nimport type { Logger } from '../logger/index.js';\nimport { redactSensitiveFields } from '../logger/index.js';\n\ntype PrismaQueryArgs = {\n model?: string;\n operation: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n};\n\n/**\n * Returns a Prisma Client extension object compatible with the\n * `$extends()` API (Prisma v5+).\n *\n * ```ts\n * export const prisma = new PrismaClient().$extends(\n * createPrismaLoggingExtension(logger)\n * );\n * ```\n */\nexport function createPrismaLoggingExtension(logger: Logger): {\n name: string;\n query: {\n $allOperations: (args: PrismaQueryArgs) => Promise<unknown>;\n };\n} {\n return {\n name: 'burdenoff-pino-logging',\n query: {\n async $allOperations({ model, operation, args, query }: PrismaQueryArgs): Promise<unknown> {\n const start = Date.now();\n try {\n const result = await query(args);\n logger.debug('prisma.query', {\n model,\n operation,\n duration_ms: Date.now() - start,\n args: redactSensitiveFields(args),\n });\n return result;\n } catch (err) {\n logger.error('prisma.error', {\n model,\n operation,\n duration_ms: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n },\n },\n };\n}\n","/**\n * Unified telemetry bootstrap for Burdenoff services.\n *\n * Composes the existing `instrumentation/` + `observability/` + `logger/`\n * modules and adds:\n * - `bootstrapTelemetry({ serviceName, boundary, module, env })` — single\n * call that initializes OTel, wires Pino logger with trace fields,\n * exposes GraphQL Yoga plugins, registers process exit hooks.\n * - `createHealthRoutes({ prisma, nats, valkey, version })` — `/health`,\n * `/health/live`, `/health/ready` Elysia routes.\n * - `createMetricsRoutes(registry?)` — `/metrics` Prometheus exposition.\n * - `createPrismaLoggingExtension(logger)` — Prisma extension that pipes\n * query events through Pino with trace/span correlation ids.\n *\n * The module does not pull in `@opentelemetry/sdk-node` or `pino` as direct\n * deps — services install those as optional peers, and imports are lazy so\n * services that don't install them still load.\n */\n\nimport type { Logger as BaseLogger } from '../logger/index.js';\nimport { logger as defaultLogger } from '../logger/index.js';\nimport {\n initializeInstrumentation,\n setupInstrumentation,\n type SetupInstrumentationOptions,\n type InstrumentationSetupResult,\n} from '../instrumentation/index.js';\nimport { setActiveTelemetryLogger } from './logger-state.js';\nimport type { OtelSdkHandle } from './sdk.js';\n\nexport { createHealthRoutes } from './health.js';\nexport { createMetricsRoutes } from './metrics-endpoint.js';\nexport { createPrismaLoggingExtension } from './prisma-logging.js';\nexport { DEFAULT_REDACT_PATHS } from './pino-redaction.js';\nexport { createPinoLogger } from './pino-logger.js';\n\nexport type Boundary = 'wspace' | 'global' | 'gateway';\nexport type Env = 'alpha' | 'prod' | 'dev';\n\nexport interface TelemetryConfig {\n /** Full service name, e.g. \"wspace-auth-svc\". */\n serviceName: string;\n /** Semver of the service deployment; defaults to `process.env.npm_package_version`. */\n serviceVersion?: string;\n /** Monorepo boundary: `wspace`, `global`, or `gateway`. */\n boundary: Boundary;\n /** Module slug, e.g. `auth` (omit for gateways). */\n module?: string;\n /** Deployment environment; defaults to alpha for non-production NODE_ENV. */\n env?: Env;\n /**\n * OTLP endpoint for spans/metrics/logs. Defaults to\n * `$OTEL_EXPORTER_OTLP_ENDPOINT` or\n * `http://alloy.sre.svc.cluster.local:4318`.\n */\n otlpEndpoint?: string;\n /** Head-based sampling ratio. Default: alpha=1.0, prod=0.1. */\n sampleRatio?: number;\n /** Extra options forwarded to `setupInstrumentation`. */\n instrumentation?: SetupInstrumentationOptions;\n}\n\nexport interface TelemetryHandle {\n /** The configured service name (for use in health routes, etc.). */\n serviceName: string;\n /** The resolved service version. */\n serviceVersion: string;\n /** Environment. */\n env: Env;\n /** The Pino-backed logger. */\n logger: BaseLogger;\n /** Initialized instrumentation (tracer + metrics + plugins). */\n instrumentation: InstrumentationSetupResult;\n /** Cleanup hook; services call on SIGTERM. */\n shutdown: () => Promise<void>;\n}\n\nfunction resolveEnv(explicit?: Env): Env {\n if (explicit) return explicit;\n const fromEnv = process.env['DEPLOY_ENV'] ?? process.env['NODE_ENV'] ?? '';\n if (fromEnv === 'production' || fromEnv === 'prod') return 'prod';\n if (fromEnv === 'development' || fromEnv === 'dev') return 'dev';\n return 'alpha';\n}\n\nfunction resolveVersion(explicit?: string): string {\n if (explicit) return explicit;\n return process.env['npm_package_version'] ?? process.env['SERVICE_VERSION'] ?? '0.0.0';\n}\n\nfunction resolveEndpoint(explicit?: string): string {\n if (explicit) return explicit;\n const proto = 'http';\n return process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] ?? `${proto}://alloy.sre.svc.cluster.local:4318`;\n}\n\nfunction resolveSampling(explicit: number | undefined, env: Env): number {\n if (typeof explicit === 'number' && Number.isFinite(explicit)) return Math.min(1, Math.max(0, explicit));\n const fromEnv = process.env['OTEL_TRACES_SAMPLER_ARG'];\n if (fromEnv) {\n const parsed = Number(fromEnv);\n if (Number.isFinite(parsed)) return Math.min(1, Math.max(0, parsed));\n }\n if (env === 'prod') return 0.1;\n return 1.0;\n}\n\nfunction resolveOtelSdkEnabled(): boolean {\n const sdkDisabled = process.env['OTEL_SDK_DISABLED'];\n if (sdkDisabled === 'true' || sdkDisabled === '1') return false;\n const otelEnabled = process.env['OTEL_ENABLED'];\n if (otelEnabled === 'false' || otelEnabled === '0') return false;\n return true;\n}\n\n/**\n * Bootstrap the full telemetry stack for a service.\n *\n * Services call this ONCE at startup **before** importing Prisma / GraphQL\n * Yoga / NATS so OTel can auto-instrument their dependencies.\n *\n * ```ts\n * // src/telemetry.ts\n * import { bootstrapTelemetry } from '@burdenoff/be-sdk/telemetry';\n * export const telemetry = await bootstrapTelemetry({\n * serviceName: 'wspace-auth-svc',\n * boundary: 'wspace',\n * module: 'auth',\n * });\n *\n * // src/index.ts — must be the FIRST import line.\n * import './telemetry.js';\n * ```\n */\nexport async function bootstrapTelemetry(cfg: TelemetryConfig): Promise<TelemetryHandle> {\n const env = resolveEnv(cfg.env);\n const serviceVersion = resolveVersion(cfg.serviceVersion);\n const otlpEndpoint = resolveEndpoint(cfg.otlpEndpoint);\n const sampleRatio = resolveSampling(cfg.sampleRatio, env);\n\n // Pino logger with trace/span correlation + redaction.\n // createPinoLogger is async (loads pino via dynamic import); awaiting it\n // is required — without await, `logger` is a Promise and calls like\n // logger.warn(...) crash with \"logger.warn is not a function\" during the\n // sdk-node fallback path.\n const { createPinoLogger } = await import('./pino-logger.js');\n const logger = await createPinoLogger({\n serviceName: cfg.serviceName,\n env,\n version: serviceVersion,\n });\n setActiveTelemetryLogger(logger);\n\n // Initialize core instrumentation (tracer, metrics registry, envelop plugins).\n // `setupInstrumentation` internally calls `initializeInstrumentation`.\n const instrumentation = setupInstrumentation(cfg.serviceName, {\n ...cfg.instrumentation,\n tracing: {\n serviceName: cfg.serviceName,\n ...(cfg.instrumentation?.tracing ?? {}),\n samplingRate: sampleRatio,\n },\n metrics: {\n serviceName: cfg.serviceName,\n ...(cfg.instrumentation?.metrics ?? {}),\n },\n });\n\n // Start the NodeSDK exporter pipeline if sdk-node is present (optional).\n let otelSdk: OtelSdkHandle | undefined;\n if (resolveOtelSdkEnabled()) {\n try {\n const { createOtelSdk } = await import('./sdk.js');\n otelSdk = await createOtelSdk({\n serviceName: cfg.serviceName,\n serviceVersion,\n boundary: cfg.boundary,\n module: cfg.module,\n env,\n otlpEndpoint,\n sampleRatio,\n });\n // Explicit success log includes metrics path status so an operator can\n // distinguish traces-only startup from full traces+metrics startup.\n logger.info('[telemetry] OpenTelemetry exporter pipeline started', {\n serviceName: cfg.serviceName,\n otlpEndpoint: otlpEndpoint ? '<configured>' : '<not set>',\n sampleRatio,\n metricsEnabled: otelSdk.metricsEnabled,\n });\n\n if (!otelSdk.metricsEnabled && otelSdk.metricsDropReason) {\n logger.warn('[telemetry] OpenTelemetry metrics reader disabled; continuing with traces only', {\n serviceName: cfg.serviceName,\n reason: otelSdk.metricsDropReason,\n });\n }\n } catch (err) {\n logger.warn('[telemetry] OpenTelemetry exporter pipeline failed to start; continuing with logs only', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n } else {\n logger.info('[telemetry] OTel SDK exporter disabled by env');\n }\n\n const shutdown = async (): Promise<void> => {\n try {\n if (otelSdk?.shutdown) await otelSdk.shutdown();\n } catch (err) {\n (logger as unknown as BaseLogger).warn('[telemetry] shutdown error (ignored)', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n };\n\n // Mirror defaultLogger so services that still use the singleton get trace-enriched output.\n defaultLogger.setLevel(logger.getLevel?.() ?? 'info');\n\n return {\n serviceName: cfg.serviceName,\n serviceVersion,\n env,\n logger: logger as unknown as BaseLogger,\n instrumentation,\n shutdown,\n };\n}\n\n// Re-export what services typically import.\nexport { initializeInstrumentation, setupInstrumentation };\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/telemetry/health.ts","../../src/telemetry/metrics-endpoint.ts","../../src/telemetry/prisma-logging.ts","../../src/telemetry/index.ts"],"names":["createHealthRoutes","_deps","Proxy","get","_target","prop","undefined","loadDefaultRegistry","mod","collectDefaultMetrics","register","createMetricsRoutesImpl","app","opts","path","ctx","registry","ctxWithSet","set","status","headers","contentType","metrics","createMetricsRoutes","createPrismaLoggingExtension","logger","name","query","$allOperations","model","operation","args","start","Date","now","result","debug","duration_ms","redactSensitiveFields","err","error","Error","message","String","resolveEnv","explicit","fromEnv","process","env","resolveVersion","resolveEndpoint","proto","resolveSampling","Number","isFinite","Math","min","max","parsed","resolveOtelSdkEnabled","sdkDisabled","otelEnabled","bootstrapTelemetry","cfg","serviceVersion","otlpEndpoint","sampleRatio","createPinoLogger","serviceName","version","setActiveTelemetryLogger","instrumentation","setupInstrumentation","tracing","samplingRate","otelSdk","createOtelSdk","boundary","module","info","metricsEnabled","metricsDropReason","warn","reason","shutdown","defaultLogger","setLevel","getLevel"],"mappings":";;;;;;;AAmFO,SAASA,kBAAAA,CAAmBC,KAAAA,GAAoB,EAAC,EAAC;AAEvD,EAAA,OAAO,IAAIC,KAAAA,CACT,EAAC,EACD;AACEC,IAAAA,GAAAA,CAAIC,SAASC,IAAAA,EAAI;AAIf,MAAA,IAAIA,IAAAA,KAAS,KAAA,IAASA,IAAAA,KAAS,MAAA,EAAQ,OAAOC,MAAAA;AAC9C,MAAA,OAAOA,MAAAA;AACT,IAAA;GACF,CAAA;AAEJ;AAdgBN,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;;;ACnEhB,eAAsBO,mBAAAA,GAAAA;AACpB,EAAA,IAAI;AACF,IAAA,MAAMC,GAAAA,GAAO,MAAM,OAAO,aAAA,CAAA;AAK1B,IAAA,IAAI;AACFA,MAAAA,GAAAA,CAAIC,qBAAAA,CAAsB;AAAEC,QAAAA,QAAAA,EAAUF,GAAAA,CAAIE;OAAS,CAAA;IACrD,CAAA,CAAA,MAAQ;AAER,IAAA;AACA,IAAA,OAAOF,GAAAA,CAAIE,QAAAA;EACb,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AACT,EAAA;AACF;AAhBsBH,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAkBf,SAASI,uBAAAA,CAIdC,GAAAA,EAAUC,IAAAA,GAA4B,EAAC,EAAC;AACxC,EAAA,MAAMC,IAAAA,GAAOD,KAAKC,IAAAA,IAAQ,UAAA;AAE1BF,EAAAA,GAAAA,CAAIT,GAAAA,CAAIW,IAAAA,EAAM,OAAOC,GAAAA,KAAAA;AACnB,IAAA,MAAMC,QAAAA,GAAWH,IAAAA,CAAKG,QAAAA,IAAa,MAAMT,mBAAAA,EAAAA;AACzC,IAAA,MAAMU,UAAAA,GAAaF,GAAAA;AACnB,IAAA,IAAI,CAACC,QAAAA,EAAU;AACb,MAAA,IAAIC,UAAAA,CAAWC,GAAAA,EAAKD,UAAAA,CAAWC,GAAAA,CAAIC,MAAAA,GAAS,GAAA;AAC5C,MAAA,OAAO,+BAAA;AACT,IAAA;AACA,IAAA,IAAIF,WAAWC,GAAAA,EAAK;AAClBD,MAAAA,UAAAA,CAAWC,IAAIC,MAAAA,GAAS,GAAA;AACxBF,MAAAA,UAAAA,CAAWC,IAAIE,OAAAA,GAAU;AACvB,QAAA,cAAA,EAAgBJ,SAASK,WAAAA,IAAe;AAC1C,OAAA;AACF,IAAA;AACA,IAAA,OAAOL,SAASM,OAAAA,EAAO;EACzB,CAAA,CAAA;AAEA,EAAA,OAAOV,GAAAA;AACT;AAxBgBD,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AA8BT,SAASY,mBAAAA,CAAoBV,IAAAA,GAA4B,EAAC,EAAC;AAChE,EAAA,OAAO,CAACD,GAAAA,KAAgED,uBAAAA,CAAwBC,GAAAA,EAAKC,IAAAA,CAAAA;AACvG;AAFgBU,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;;;ACtCT,SAASC,6BAA6BC,OAAAA,EAAc;AAMzD,EAAA,OAAO;IACLC,IAAAA,EAAM,wBAAA;IACNC,KAAAA,EAAO;AACL,MAAA,MAAMC,eAAe,EAAEC,KAAAA,EAAOC,SAAAA,EAAWC,IAAAA,EAAMJ,OAAK,EAAmB;AACrE,QAAA,MAAMK,KAAAA,GAAQC,KAAKC,GAAAA,EAAG;AACtB,QAAA,IAAI;AACF,UAAA,MAAMC,MAAAA,GAAS,MAAMR,KAAAA,CAAMI,IAAAA,CAAAA;AAC3BN,UAAAA,OAAAA,CAAOW,MAAM,cAAA,EAAgB;AAC3BP,YAAAA,KAAAA;AACAC,YAAAA,SAAAA;YACAO,WAAAA,EAAaJ,IAAAA,CAAKC,KAAG,GAAKF,KAAAA;AAC1BD,YAAAA,IAAAA,EAAMO,sBAAsBP,IAAAA;WAC9B,CAAA;AACA,UAAA,OAAOI,MAAAA;AACT,QAAA,CAAA,CAAA,OAASI,GAAAA,EAAK;AACZd,UAAAA,OAAAA,CAAOe,MAAM,cAAA,EAAgB;AAC3BX,YAAAA,KAAAA;AACAC,YAAAA,SAAAA;YACAO,WAAAA,EAAaJ,IAAAA,CAAKC,KAAG,GAAKF,KAAAA;AAC1BQ,YAAAA,KAAAA,EAAOD,GAAAA,YAAeE,KAAAA,GAAQF,GAAAA,CAAIG,OAAAA,GAAUC,OAAOJ,GAAAA;WACrD,CAAA;AACA,UAAA,MAAMA,GAAAA;AACR,QAAA;AACF,MAAA;AACF;AACF,GAAA;AACF;AAhCgBf,MAAAA,CAAAA,4BAAAA,EAAAA,8BAAAA,CAAAA;;;ACmDhB,SAASoB,WAAWC,QAAAA,EAAc;AAChC,EAAA,IAAIA,UAAU,OAAOA,QAAAA;AACrB,EAAA,MAAMC,OAAAA,GAAUC,QAAQC,GAAAA,CAAI,YAAA,KAAiBD,OAAAA,CAAQC,GAAAA,CAAI,UAAA,CAAA,IAAe,EAAA;AACxE,EAAA,IAAIF,OAAAA,KAAY,YAAA,IAAgBA,OAAAA,KAAY,MAAA,EAAQ,OAAO,MAAA;AAC3D,EAAA,IAAIA,OAAAA,KAAY,aAAA,IAAiBA,OAAAA,KAAY,KAAA,EAAO,OAAO,KAAA;AAC3D,EAAA,OAAO,OAAA;AACT;AANSF,MAAAA,CAAAA,UAAAA,EAAAA,YAAAA,CAAAA;AAQT,SAASK,eAAeJ,QAAAA,EAAiB;AACvC,EAAA,IAAIA,UAAU,OAAOA,QAAAA;AACrB,EAAA,OAAOE,QAAQC,GAAAA,CAAI,qBAAA,KAA0BD,OAAAA,CAAQC,GAAAA,CAAI,iBAAA,CAAA,IAAsB,OAAA;AACjF;AAHSC,MAAAA,CAAAA,cAAAA,EAAAA,gBAAAA,CAAAA;AAKT,SAASC,gBAAgBL,QAAAA,EAAiB;AACxC,EAAA,IAAIA,UAAU,OAAOA,QAAAA;AACrB,EAAA,MAAMM,KAAAA,GAAQ,MAAA;AACd,EAAA,OAAOJ,OAAAA,CAAQC,GAAAA,CAAI,6BAAA,CAAA,IAAkC,GAAGG,KAAAA,CAAAA,mCAAAA,CAAAA;AAC1D;AAJSD,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAMT,SAASE,eAAAA,CAAgBP,UAA8BG,GAAAA,EAAQ;AAC7D,EAAA,IAAI,OAAOH,QAAAA,KAAa,QAAA,IAAYQ,MAAAA,CAAOC,SAAST,QAAAA,CAAAA,EAAW,OAAOU,IAAAA,CAAKC,IAAI,CAAA,EAAGD,IAAAA,CAAKE,GAAAA,CAAI,CAAA,EAAGZ,QAAAA,CAAAA,CAAAA;AAC9F,EAAA,MAAMC,OAAAA,GAAUC,OAAAA,CAAQC,GAAAA,CAAI,yBAAA,CAAA;AAC5B,EAAA,IAAIF,OAAAA,EAAS;AACX,IAAA,MAAMY,MAAAA,GAASL,OAAOP,OAAAA,CAAAA;AACtB,IAAA,IAAIO,MAAAA,CAAOC,QAAAA,CAASI,MAAAA,CAAAA,EAAS,OAAOH,IAAAA,CAAKC,GAAAA,CAAI,CAAA,EAAGD,IAAAA,CAAKE,GAAAA,CAAI,CAAA,EAAGC,MAAAA,CAAAA,CAAAA;AAC9D,EAAA;AACA,EAAA,IAAIV,GAAAA,KAAQ,QAAQ,OAAO,GAAA;AAC3B,EAAA,OAAO,CAAA;AACT;AATSI,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAWT,SAASO,qBAAAA,GAAAA;AACP,EAAA,MAAMC,WAAAA,GAAcb,OAAAA,CAAQC,GAAAA,CAAI,mBAAA,CAAA;AAChC,EAAA,IAAIY,WAAAA,KAAgB,MAAA,IAAUA,WAAAA,KAAgB,GAAA,EAAK,OAAO,KAAA;AAC1D,EAAA,MAAMC,WAAAA,GAAcd,OAAAA,CAAQC,GAAAA,CAAI,cAAA,CAAA;AAChC,EAAA,IAAIa,WAAAA,KAAgB,OAAA,IAAWA,WAAAA,KAAgB,GAAA,EAAK,OAAO,KAAA;AAC3D,EAAA,OAAO,IAAA;AACT;AANSF,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;AA2BT,eAAsBG,mBAAmBC,GAAAA,EAAoB;AAC3D,EAAA,MAAMf,GAAAA,GAAMJ,UAAAA,CAAWmB,GAAAA,CAAIf,GAAG,CAAA;AAC9B,EAAA,MAAMgB,cAAAA,GAAiBf,cAAAA,CAAec,GAAAA,CAAIC,cAAc,CAAA;AACxD,EAAA,MAAMC,YAAAA,GAAef,eAAAA,CAAgBa,GAAAA,CAAIE,YAAY,CAAA;AACrD,EAAA,MAAMC,WAAAA,GAAcd,eAAAA,CAAgBW,GAAAA,CAAIG,WAAAA,EAAalB,GAAAA,CAAAA;AAOrD,EAAA,MAAM,EAAEmB,gBAAAA,EAAAA,iBAAAA,EAAgB,GAAK,MAAM,OAAO,4BAAA,CAAA;AAC1C,EAAA,MAAM1C,OAAAA,GAAS,MAAM0C,iBAAAA,CAAiB;AACpCC,IAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;AACjBpB,IAAAA,GAAAA;IACAqB,OAAAA,EAASL;GACX,CAAA;AACAM,EAAAA,wBAAAA,CAAyB7C,OAAAA,CAAAA;AAIzB,EAAA,MAAM8C,eAAAA,GAAkBC,oBAAAA,CAAqBT,GAAAA,CAAIK,WAAAA,EAAa;AAC5D,IAAA,GAAGL,GAAAA,CAAIQ,eAAAA;IACPE,OAAAA,EAAS;AACPL,MAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;MACjB,GAAIL,GAAAA,CAAIQ,eAAAA,EAAiBE,OAAAA,IAAW,EAAC;MACrCC,YAAAA,EAAcR;AAChB,KAAA;IACA5C,OAAAA,EAAS;AACP8C,MAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;MACjB,GAAIL,GAAAA,CAAIQ,eAAAA,EAAiBjD,OAAAA,IAAW;AACtC;GACF,CAAA;AAGA,EAAA,IAAIqD,OAAAA;AACJ,EAAA,IAAIhB,uBAAAA,EAAyB;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,EAAEiB,aAAAA,EAAa,GAAK,MAAM,OAAO,oBAAA,CAAA;AACvCD,MAAAA,OAAAA,GAAU,MAAMC,aAAAA,CAAc;AAC5BR,QAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;AACjBJ,QAAAA,cAAAA;AACAa,QAAAA,QAAAA,EAAUd,GAAAA,CAAIc,QAAAA;AACdC,QAAAA,MAAAA,EAAQf,GAAAA,CAAIe,MAAAA;AACZ9B,QAAAA,GAAAA;AACAiB,QAAAA,YAAAA;AACAC,QAAAA;OACF,CAAA;AAGAzC,MAAAA,OAAAA,CAAOsD,KAAK,qDAAA,EAAuD;AACjEX,QAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;AACjBH,QAAAA,YAAAA,EAAcA,eAAe,cAAA,GAAiB,WAAA;AAC9CC,QAAAA,WAAAA;AACAc,QAAAA,cAAAA,EAAgBL,OAAAA,CAAQK;OAC1B,CAAA;AAEA,MAAA,IAAI,CAACL,OAAAA,CAAQK,cAAAA,IAAkBL,OAAAA,CAAQM,iBAAAA,EAAmB;AACxDxD,QAAAA,OAAAA,CAAOyD,KAAK,gFAAA,EAAkF;AAC5Fd,UAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;AACjBe,UAAAA,MAAAA,EAAQR,OAAAA,CAAQM;SAClB,CAAA;AACF,MAAA;AACF,IAAA,CAAA,CAAA,OAAS1C,GAAAA,EAAK;AACZd,MAAAA,OAAAA,CAAOyD,KAAK,wFAAA,EAA0F;AACpG1C,QAAAA,KAAAA,EAAOD,GAAAA,YAAeE,KAAAA,GAAQF,GAAAA,CAAIG,OAAAA,GAAUC,OAAOJ,GAAAA;OACrD,CAAA;AACF,IAAA;EACF,CAAA,MAAO;AACLd,IAAAA,OAAAA,CAAOsD,KAAK,+CAAA,CAAA;AACd,EAAA;AAEA,EAAA,MAAMK,2BAAW,MAAA,CAAA,YAAA;AACf,IAAA,IAAI;AACF,MAAA,IAAIT,OAAAA,EAASS,QAAAA,EAAU,MAAMT,OAAAA,CAAQS,QAAAA,EAAQ;AAC/C,IAAA,CAAA,CAAA,OAAS7C,GAAAA,EAAK;AACXd,MAAAA,OAAAA,CAAiCyD,KAAK,sCAAA,EAAwC;AAC7E1C,QAAAA,KAAAA,EAAOD,GAAAA,YAAeE,KAAAA,GAAQF,GAAAA,CAAIG,OAAAA,GAAUC,OAAOJ,GAAAA;OACrD,CAAA;AACF,IAAA;EACF,CAAA,EARiB,UAAA,CAAA;AAWjB8C,EAAAA,MAAAA,CAAcC,QAAAA,CAAS7D,OAAAA,CAAO8D,QAAAA,IAAQ,IAAQ,MAAA,CAAA;AAE9C,EAAA,OAAO;AACLnB,IAAAA,WAAAA,EAAaL,GAAAA,CAAIK,WAAAA;AACjBJ,IAAAA,cAAAA;AACAhB,IAAAA,GAAAA;IACAvB,MAAAA,EAAQA,OAAAA;AACR8C,IAAAA,eAAAA;AACAa,IAAAA;AACF,GAAA;AACF;AA7FsBtB,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA","file":"index.js","sourcesContent":["/**\n * `/health`, `/health/live`, `/health/ready` Elysia routes with a 1s\n * result cache so readiness checks can't stampede Postgres.\n *\n * Dependencies (prisma, nats, valkey) are optional — omit any client and\n * the readiness check simply skips it.\n */\n\ninterface PrismaLike {\n $queryRaw: (strings: TemplateStringsArray) => Promise<unknown>;\n}\ninterface NatsLike {\n isConnected?: () => boolean | Promise<boolean>;\n healthCheck?: () => Promise<{ ok: boolean }>;\n}\ninterface ValkeyLike {\n ping: () => Promise<unknown>;\n}\n\nexport interface HealthDeps {\n prisma?: PrismaLike;\n nats?: NatsLike;\n valkey?: ValkeyLike;\n /** Service version reported on /health. */\n version?: string;\n /** Service name reported on /health. */\n serviceName?: string;\n}\n\ninterface CachedStatus {\n ready: boolean;\n checked: Record<string, { ok: boolean; error?: string }>;\n at: number;\n}\n\nconst CACHE_TTL_MS = 1000;\n\nasync function probeReady(deps: HealthDeps): Promise<CachedStatus> {\n const checked: Record<string, { ok: boolean; error?: string }> = {};\n\n if (deps.prisma) {\n try {\n await deps.prisma.$queryRaw`SELECT 1`;\n checked['postgres'] = { ok: true };\n } catch (err) {\n checked['postgres'] = {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n if (deps.nats) {\n try {\n const connected =\n typeof deps.nats.isConnected === 'function'\n ? await Promise.resolve(deps.nats.isConnected())\n : ((await deps.nats.healthCheck?.())?.ok ?? true);\n checked['nats'] = { ok: Boolean(connected) };\n } catch (err) {\n checked['nats'] = {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n if (deps.valkey) {\n try {\n await deps.valkey.ping();\n checked['valkey'] = { ok: true };\n } catch (err) {\n checked['valkey'] = {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const ready = Object.values(checked).every((c) => c.ok);\n return { ready, checked, at: Date.now() };\n}\n\nexport function createHealthRoutes(_deps: HealthDeps = {}): unknown {\n // Return an Elysia app lazily so be-sdk doesn't hard-require elysia.\n return new Proxy(\n {},\n {\n get(_target, prop): unknown {\n // Tell TypeScript consumers the returned object is an Elysia plugin;\n // the actual mount happens via `createHealthRoutesImpl`. Services\n // that prefer direct use can call `createHealthRoutesImpl(elysia, deps)`.\n if (prop === 'use' || prop === 'then') return undefined;\n return undefined;\n },\n }\n );\n}\n\n/**\n * Mount health routes on an existing Elysia app. Callers hold a reference\n * to Elysia themselves; be-sdk stays decoupled.\n */\nexport function createHealthRoutesImpl<\n App extends {\n get: (path: string, handler: (ctx: unknown) => unknown) => App;\n },\n>(app: App, deps: HealthDeps = {}): App {\n let cache: CachedStatus | null = null;\n\n const getStatus = async (): Promise<CachedStatus> => {\n if (cache && Date.now() - cache.at < CACHE_TTL_MS) return cache;\n cache = await probeReady(deps);\n return cache;\n };\n\n app.get('/health/live', () => ({\n status: 'ok',\n serviceName: deps.serviceName,\n version: deps.version,\n }));\n\n app.get('/health/ready', async (ctx: unknown): Promise<unknown> => {\n const status = await getStatus();\n const ctxWithSet = ctx as { set?: { status?: number } };\n if (!status.ready && ctxWithSet.set) ctxWithSet.set.status = 503;\n return {\n status: status.ready ? 'ok' : 'degraded',\n serviceName: deps.serviceName,\n version: deps.version,\n checks: status.checked,\n };\n });\n\n app.get('/health', async (ctx: unknown): Promise<unknown> => {\n const status = await getStatus();\n const ctxWithSet = ctx as { set?: { status?: number } };\n if (!status.ready && ctxWithSet.set) ctxWithSet.set.status = 503;\n return {\n status: status.ready ? 'ok' : 'degraded',\n serviceName: deps.serviceName,\n version: deps.version,\n checks: status.checked,\n uptime_s: Math.round(process.uptime()),\n };\n });\n\n return app;\n}\n","/**\n * Prometheus `/metrics` route mounter. Uses the shared `prom-client`\n * default registry so all instrumentation (GraphQL Envelop, Prisma,\n * runtime) shows up on a single endpoint.\n */\n\ninterface PromRegistryLike {\n metrics: () => Promise<string> | string;\n contentType?: string;\n}\n\nexport interface MetricsMountOptions {\n registry?: PromRegistryLike;\n path?: string;\n}\n\nexport async function loadDefaultRegistry(): Promise<PromRegistryLike | null> {\n try {\n const mod = (await import('prom-client')) as unknown as {\n register: PromRegistryLike;\n collectDefaultMetrics: (opts?: Record<string, unknown>) => void;\n };\n // Kick runtime metrics into the default registry if not already.\n try {\n mod.collectDefaultMetrics({ register: mod.register });\n } catch {\n // Already registered — ignore duplicate-metric errors.\n }\n return mod.register;\n } catch {\n return null;\n }\n}\n\nexport function createMetricsRoutesImpl<\n App extends {\n get: (path: string, handler: (ctx: unknown) => unknown) => App;\n },\n>(app: App, opts: MetricsMountOptions = {}): App {\n const path = opts.path ?? '/metrics';\n\n app.get(path, async (ctx: unknown): Promise<unknown> => {\n const registry = opts.registry ?? (await loadDefaultRegistry());\n const ctxWithSet = ctx as { set?: { status?: number; headers?: Record<string, string> } };\n if (!registry) {\n if (ctxWithSet.set) ctxWithSet.set.status = 503;\n return '# prom-client not installed\\n';\n }\n if (ctxWithSet.set) {\n ctxWithSet.set.status = 200;\n ctxWithSet.set.headers = {\n 'content-type': registry.contentType ?? 'text/plain; version=0.0.4; charset=utf-8',\n };\n }\n return registry.metrics();\n });\n\n return app;\n}\n\n/**\n * Legacy export name used by the service template. Composes the Elysia\n * plugin-style function that `new Elysia().use(...)` accepts.\n */\nexport function createMetricsRoutes(opts: MetricsMountOptions = {}): unknown {\n return (app: Parameters<typeof createMetricsRoutesImpl>[0]): unknown => createMetricsRoutesImpl(app, opts);\n}\n","/**\n * Prisma client extension that pipes query events through the SDK logger\n * with trace/span correlation fields auto-injected. The\n * `@prisma/instrumentation` peer provides the spans\n * themselves; this extension only adds structured log events on top.\n */\nimport type { Logger } from '../logger/index.js';\nimport { redactSensitiveFields } from '../logger/index.js';\n\ntype PrismaQueryArgs = {\n model?: string;\n operation: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n};\n\n/**\n * Returns a Prisma Client extension object compatible with the\n * `$extends()` API (Prisma v5+).\n *\n * ```ts\n * export const prisma = new PrismaClient().$extends(\n * createPrismaLoggingExtension(logger)\n * );\n * ```\n */\nexport function createPrismaLoggingExtension(logger: Logger): {\n name: string;\n query: {\n $allOperations: (args: PrismaQueryArgs) => Promise<unknown>;\n };\n} {\n return {\n name: 'burdenoff-pino-logging',\n query: {\n async $allOperations({ model, operation, args, query }: PrismaQueryArgs): Promise<unknown> {\n const start = Date.now();\n try {\n const result = await query(args);\n logger.debug('prisma.query', {\n model,\n operation,\n duration_ms: Date.now() - start,\n args: redactSensitiveFields(args),\n });\n return result;\n } catch (err) {\n logger.error('prisma.error', {\n model,\n operation,\n duration_ms: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n },\n },\n };\n}\n","/**\n * Unified telemetry bootstrap for Burdenoff services.\n *\n * Composes the existing `instrumentation/` + `observability/` + `logger/`\n * modules and adds:\n * - `bootstrapTelemetry({ serviceName, boundary, module, env })` — single\n * call that initializes OTel, wires Pino logger with trace fields,\n * exposes GraphQL Yoga plugins, registers process exit hooks.\n * - `createHealthRoutes({ prisma, nats, valkey, version })` — `/health`,\n * `/health/live`, `/health/ready` Elysia routes.\n * - `createMetricsRoutes(registry?)` — `/metrics` Prometheus exposition.\n * - `createPrismaLoggingExtension(logger)` — Prisma extension that pipes\n * query events through Pino with trace/span correlation ids.\n *\n * The module does not pull in `@opentelemetry/sdk-node` or `pino` as direct\n * deps — services install those as optional peers, and imports are lazy so\n * services that don't install them still load.\n */\n\nimport type { Logger as BaseLogger } from '../logger/index.js';\nimport { logger as defaultLogger } from '../logger/index.js';\nimport {\n initializeInstrumentation,\n setupInstrumentation,\n type SetupInstrumentationOptions,\n type InstrumentationSetupResult,\n} from '../instrumentation/index.js';\nimport { setActiveTelemetryLogger } from './logger-state.js';\nimport type { OtelSdkHandle } from './sdk.js';\n\nexport { createHealthRoutes } from './health.js';\nexport { createMetricsRoutes } from './metrics-endpoint.js';\nexport { createPrismaLoggingExtension } from './prisma-logging.js';\nexport { DEFAULT_REDACT_PATHS } from './pino-redaction.js';\nexport { createPinoLogger } from './pino-logger.js';\n\nexport type Boundary = 'wspace' | 'global' | 'gateway';\nexport type Env = 'alpha' | 'prod' | 'dev';\n\nexport interface TelemetryConfig {\n /** Full service name, e.g. \"wspace-auth-svc\". */\n serviceName: string;\n /** Semver of the service deployment; defaults to `process.env.npm_package_version`. */\n serviceVersion?: string;\n /** Monorepo boundary: `wspace`, `global`, or `gateway`. */\n boundary: Boundary;\n /** Module slug, e.g. `auth` (omit for gateways). */\n module?: string;\n /** Deployment environment; defaults to alpha for non-production NODE_ENV. */\n env?: Env;\n /**\n * OTLP endpoint for spans/metrics/logs. Defaults to\n * `$OTEL_EXPORTER_OTLP_ENDPOINT` or\n * `http://alloy.sre.svc.cluster.local:4318`.\n */\n otlpEndpoint?: string;\n /** Head-based sampling ratio. Default: alpha=1.0, prod=0.1. */\n sampleRatio?: number;\n /** Extra options forwarded to `setupInstrumentation`. */\n instrumentation?: SetupInstrumentationOptions;\n}\n\nexport interface TelemetryHandle {\n /** The configured service name (for use in health routes, etc.). */\n serviceName: string;\n /** The resolved service version. */\n serviceVersion: string;\n /** Environment. */\n env: Env;\n /** The Pino-backed logger. */\n logger: BaseLogger;\n /** Initialized instrumentation (tracer + metrics + plugins). */\n instrumentation: InstrumentationSetupResult;\n /** Cleanup hook; services call on SIGTERM. */\n shutdown: () => Promise<void>;\n}\n\nfunction resolveEnv(explicit?: Env): Env {\n if (explicit) return explicit;\n const fromEnv = process.env['DEPLOY_ENV'] ?? process.env['NODE_ENV'] ?? '';\n if (fromEnv === 'production' || fromEnv === 'prod') return 'prod';\n if (fromEnv === 'development' || fromEnv === 'dev') return 'dev';\n return 'alpha';\n}\n\nfunction resolveVersion(explicit?: string): string {\n if (explicit) return explicit;\n return process.env['npm_package_version'] ?? process.env['SERVICE_VERSION'] ?? '0.0.0';\n}\n\nfunction resolveEndpoint(explicit?: string): string {\n if (explicit) return explicit;\n const proto = 'http';\n return process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] ?? `${proto}://alloy.sre.svc.cluster.local:4318`;\n}\n\nfunction resolveSampling(explicit: number | undefined, env: Env): number {\n if (typeof explicit === 'number' && Number.isFinite(explicit)) return Math.min(1, Math.max(0, explicit));\n const fromEnv = process.env['OTEL_TRACES_SAMPLER_ARG'];\n if (fromEnv) {\n const parsed = Number(fromEnv);\n if (Number.isFinite(parsed)) return Math.min(1, Math.max(0, parsed));\n }\n if (env === 'prod') return 0.1;\n return 1.0;\n}\n\nfunction resolveOtelSdkEnabled(): boolean {\n const sdkDisabled = process.env['OTEL_SDK_DISABLED'];\n if (sdkDisabled === 'true' || sdkDisabled === '1') return false;\n const otelEnabled = process.env['OTEL_ENABLED'];\n if (otelEnabled === 'false' || otelEnabled === '0') return false;\n return true;\n}\n\n/**\n * Bootstrap the full telemetry stack for a service.\n *\n * Services call this ONCE at startup **before** importing Prisma / GraphQL\n * Yoga / NATS so OTel can auto-instrument their dependencies.\n *\n * ```ts\n * // src/telemetry.ts\n * import { bootstrapTelemetry } from '@burdenoff/be-sdk/telemetry';\n * export const telemetry = await bootstrapTelemetry({\n * serviceName: 'wspace-auth-svc',\n * boundary: 'wspace',\n * module: 'auth',\n * });\n *\n * // src/index.ts — must be the FIRST import line.\n * import './telemetry.js';\n * ```\n */\nexport async function bootstrapTelemetry(cfg: TelemetryConfig): Promise<TelemetryHandle> {\n const env = resolveEnv(cfg.env);\n const serviceVersion = resolveVersion(cfg.serviceVersion);\n const otlpEndpoint = resolveEndpoint(cfg.otlpEndpoint);\n const sampleRatio = resolveSampling(cfg.sampleRatio, env);\n\n // Pino logger with trace/span correlation + redaction.\n // createPinoLogger is async (loads pino via dynamic import); awaiting it\n // is required — without await, `logger` is a Promise and calls like\n // logger.warn(...) crash with \"logger.warn is not a function\" during the\n // sdk-node fallback path.\n const { createPinoLogger } = await import('./pino-logger.js');\n const logger = await createPinoLogger({\n serviceName: cfg.serviceName,\n env,\n version: serviceVersion,\n });\n setActiveTelemetryLogger(logger);\n\n // Initialize core instrumentation (tracer, metrics registry, envelop plugins).\n // `setupInstrumentation` internally calls `initializeInstrumentation`.\n const instrumentation = setupInstrumentation(cfg.serviceName, {\n ...cfg.instrumentation,\n tracing: {\n serviceName: cfg.serviceName,\n ...(cfg.instrumentation?.tracing ?? {}),\n samplingRate: sampleRatio,\n },\n metrics: {\n serviceName: cfg.serviceName,\n ...(cfg.instrumentation?.metrics ?? {}),\n },\n });\n\n // Start the NodeSDK exporter pipeline if sdk-node is present (optional).\n let otelSdk: OtelSdkHandle | undefined;\n if (resolveOtelSdkEnabled()) {\n try {\n const { createOtelSdk } = await import('./sdk.js');\n otelSdk = await createOtelSdk({\n serviceName: cfg.serviceName,\n serviceVersion,\n boundary: cfg.boundary,\n module: cfg.module,\n env,\n otlpEndpoint,\n sampleRatio,\n });\n // Explicit success log includes metrics path status so an operator can\n // distinguish traces-only startup from full traces+metrics startup.\n logger.info('[telemetry] OpenTelemetry exporter pipeline started', {\n serviceName: cfg.serviceName,\n otlpEndpoint: otlpEndpoint ? '<configured>' : '<not set>',\n sampleRatio,\n metricsEnabled: otelSdk.metricsEnabled,\n });\n\n if (!otelSdk.metricsEnabled && otelSdk.metricsDropReason) {\n logger.warn('[telemetry] OpenTelemetry metrics reader disabled; continuing with traces only', {\n serviceName: cfg.serviceName,\n reason: otelSdk.metricsDropReason,\n });\n }\n } catch (err) {\n logger.warn('[telemetry] OpenTelemetry exporter pipeline failed to start; continuing with logs only', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n } else {\n logger.info('[telemetry] OTel SDK exporter disabled by env');\n }\n\n const shutdown = async (): Promise<void> => {\n try {\n if (otelSdk?.shutdown) await otelSdk.shutdown();\n } catch (err) {\n (logger as unknown as BaseLogger).warn('[telemetry] shutdown error (ignored)', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n };\n\n // Mirror defaultLogger so services that still use the singleton get trace-enriched output.\n defaultLogger.setLevel(logger.getLevel?.() ?? 'info');\n\n return {\n serviceName: cfg.serviceName,\n serviceVersion,\n env,\n logger: logger as unknown as BaseLogger,\n instrumentation,\n shutdown,\n };\n}\n\n// Re-export what services typically import.\nexport { initializeInstrumentation, setupInstrumentation };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/be-sdk",
|
|
3
|
-
"version": "2026.513.
|
|
3
|
+
"version": "2026.513.6",
|
|
4
4
|
"description": "Backend SDK for Burdenoff products providing unified access to notifications, RBAC, activity tracking, usage monitoring, and more",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -113,8 +113,7 @@
|
|
|
113
113
|
"dependencies": {
|
|
114
114
|
"@graphql-yoga/logger": "^2.0.1",
|
|
115
115
|
"@prisma/generator-helper": "^7.2.0",
|
|
116
|
-
"@sinclair/typebox": "^0.34.45"
|
|
117
|
-
"jose": "^6.1.2"
|
|
116
|
+
"@sinclair/typebox": "^0.34.45"
|
|
118
117
|
},
|
|
119
118
|
"peerDependencies": {
|
|
120
119
|
"@clickhouse/client": "^1.14.0",
|
|
@@ -134,13 +133,21 @@
|
|
|
134
133
|
"graphql-request": "^7.3.5",
|
|
135
134
|
"graphql-yoga": "^5.17.0",
|
|
136
135
|
"@valkey/valkey-glide": "^2.2.6",
|
|
136
|
+
"jose": "^6.1.2",
|
|
137
137
|
"jsonwebtoken": "^9.0.2",
|
|
138
138
|
"nats": "^2.29.3",
|
|
139
|
+
"ioredis": "^5.4.1",
|
|
139
140
|
"pg": "^8.16.3",
|
|
140
141
|
"prom-client": "^15.1.3",
|
|
141
142
|
"reflect-metadata": "^0.2.2"
|
|
142
143
|
},
|
|
143
144
|
"peerDependenciesMeta": {
|
|
145
|
+
"ioredis": {
|
|
146
|
+
"optional": true
|
|
147
|
+
},
|
|
148
|
+
"nats": {
|
|
149
|
+
"optional": true
|
|
150
|
+
},
|
|
144
151
|
"@clickhouse/client": {
|
|
145
152
|
"optional": true
|
|
146
153
|
},
|
|
@@ -159,6 +166,9 @@
|
|
|
159
166
|
"@prisma/adapter-pg": {
|
|
160
167
|
"optional": true
|
|
161
168
|
},
|
|
169
|
+
"jose": {
|
|
170
|
+
"optional": true
|
|
171
|
+
},
|
|
162
172
|
"jsonwebtoken": {
|
|
163
173
|
"optional": true
|
|
164
174
|
},
|
|
@@ -213,6 +223,7 @@
|
|
|
213
223
|
"jose": "^6.1.3",
|
|
214
224
|
"jsonwebtoken": "^9.0.3",
|
|
215
225
|
"lefthook": "^2.1.1",
|
|
226
|
+
"ioredis": "^5.4.1",
|
|
216
227
|
"nats": "^2.29.3",
|
|
217
228
|
"pg": "^8.16.3",
|
|
218
229
|
"prettier": "^3.7.4",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { EventQueueFactory } from './chunk-KSO6QQVD.js';
|
|
2
|
-
import './chunk-VOFKF27Q.js';
|
|
3
|
-
import './chunk-COSUYUCB.js';
|
|
4
|
-
import './chunk-NGMEI42S.js';
|
|
5
|
-
import './chunk-CBZNP6RF.js';
|
|
6
|
-
import './chunk-XE4OXN2W.js';
|
|
7
|
-
//# sourceMappingURL=EventQueueFactory-FNE7H66N.js.map
|
|
8
|
-
//# sourceMappingURL=EventQueueFactory-FNE7H66N.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event-queue/implementations/nats/NatsConnection.ts"],"names":["NatsConnectionManager","nc","js","jsm","connected","connectionPromise","config","connect","logger","debug","_doConnect","connectionOptions","createNatsConnectionOptions","jetstream","jetstreamManager","info","url","name","setupEventHandlers","error","Error","message","status","type","catch","disconnect","drain","close","isConnected","isClosed","getJetStream","getJetStreamManager","getNatsConnection","servers","user","pass","password","token","maxReconnectAttempts","reconnectTimeWait","creds","resolveNatsCreds","authenticator","credsAuthenticator","TextEncoder","encode","normalizeNatsCreds","credsFile","undefined","fs","readFile","startsWith","Buffer","from","slice","length","toString","includes","replaceAll"],"mappings":"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","file":"chunk-COSUYUCB.js","sourcesContent":["/**\n * NATS JetStream Connection Manager\n * Handles connection lifecycle and provides access to NATS clients\n */\nimport { logger } from '../../../logger/index.js';\nimport {\n type ConnectionOptions,\n type JetStreamClient,\n type JetStreamManager,\n type NatsConnection,\n connect,\n credsAuthenticator,\n} from 'nats';\n\nimport type { BaseQueueConfig } from '../../types/config.js';\n\n/**\n * Internal connection manager for NATS JetStream\n * Shared between NatsEventPublisher and NatsEventConsumer\n */\nexport class NatsConnectionManager {\n private nc: NatsConnection | null = null;\n private js: JetStreamClient | null = null;\n private jsm: JetStreamManager | null = null;\n private connected: boolean = false;\n private connectionPromise: Promise<void> | null = null;\n\n constructor(private config: BaseQueueConfig) {}\n\n /**\n * Connect to NATS server\n */\n async connect(): Promise<void> {\n // Prevent multiple concurrent connections\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.connected) {\n logger.debug('[NatsConnection] Already connected');\n return;\n }\n\n this.connectionPromise = this._doConnect();\n try {\n await this.connectionPromise;\n } finally {\n this.connectionPromise = null;\n }\n }\n\n /**\n * Internal connection logic\n */\n private async _doConnect(): Promise<void> {\n try {\n const connectionOptions = await createNatsConnectionOptions(this.config);\n\n this.nc = await connect(connectionOptions);\n this.js = this.nc.jetstream();\n this.jsm = await this.nc.jetstreamManager();\n this.connected = true;\n\n logger.info('[NatsConnection] Connected to NATS', {\n url: this.config.url,\n name: this.config.name,\n });\n\n // Handle connection events\n this.setupEventHandlers();\n } catch (error) {\n logger.error('[NatsConnection] Failed to connect to NATS', {\n error: error instanceof Error ? error.message : 'Unknown error',\n url: this.config.url,\n });\n throw error;\n }\n }\n\n /**\n * Setup connection event handlers\n */\n private setupEventHandlers(): void {\n if (!this.nc) return;\n\n (async (): Promise<void> => {\n if (!this.nc) return;\n\n for await (const status of this.nc.status()) {\n if (status.type === 'disconnect') {\n this.connected = false;\n } else if (status.type === 'reconnect') {\n this.connected = true;\n }\n }\n })().catch((error) => {\n logger.error('[NatsConnection] Error handling connection events', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n });\n }\n\n /**\n * Disconnect from NATS\n */\n async disconnect(): Promise<void> {\n if (!this.connected || !this.nc) {\n return;\n }\n\n try {\n await this.nc.drain();\n await this.nc.close();\n this.connected = false;\n this.nc = null;\n this.js = null;\n this.jsm = null;\n\n logger.info('[NatsConnection] Disconnected from NATS');\n } catch (error) {\n logger.error('[NatsConnection] Error disconnecting from NATS', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.nc !== null && !this.nc.isClosed();\n }\n\n /**\n * Get JetStream client\n */\n getJetStream(): JetStreamClient {\n if (!this.js) {\n throw new Error('NATS not connected - call connect() first');\n }\n return this.js;\n }\n\n /**\n * Get JetStream Manager\n */\n getJetStreamManager(): JetStreamManager {\n if (!this.jsm) {\n throw new Error('NATS not connected - call connect() first');\n }\n return this.jsm;\n }\n\n /**\n * Get NATS connection\n */\n getNatsConnection(): NatsConnection {\n if (!this.nc) {\n throw new Error('NATS not connected - call connect() first');\n }\n return this.nc;\n }\n}\n\nexport async function createNatsConnectionOptions(config: BaseQueueConfig): Promise<ConnectionOptions> {\n const connectionOptions: ConnectionOptions = {\n servers: config.url,\n name: config.name,\n user: config.user,\n pass: config.password,\n token: config.token,\n maxReconnectAttempts: config.maxReconnectAttempts ?? -1,\n reconnectTimeWait: config.reconnectTimeWait ?? 2000,\n };\n\n const creds = await resolveNatsCreds(config);\n if (creds) {\n connectionOptions.authenticator = credsAuthenticator(new TextEncoder().encode(creds));\n delete connectionOptions.user;\n delete connectionOptions.pass;\n delete connectionOptions.token;\n }\n\n return connectionOptions;\n}\n\nexport async function resolveNatsCreds(\n config: Pick<BaseQueueConfig, 'creds' | 'credsFile'>\n): Promise<string | undefined> {\n if (config.creds) {\n return normalizeNatsCreds(config.creds);\n }\n\n if (!config.credsFile) {\n return undefined;\n }\n\n const fs = await import('node:fs/promises');\n return normalizeNatsCreds(await fs.readFile(config.credsFile, 'utf8'));\n}\n\nfunction normalizeNatsCreds(creds: string): string {\n if (creds.startsWith('base64:')) {\n return Buffer.from(creds.slice('base64:'.length), 'base64').toString('utf8');\n }\n\n if (creds.includes('\\\\n') && !creds.includes('\\n')) {\n return creds.replaceAll('\\\\n', '\\n');\n }\n\n return creds;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event-queue/implementations/nats/trace-context.ts","../src/event-queue/implementations/nats/NatsEventConsumer.ts","../src/event-queue/implementations/nats/NatsEventPublisher.ts","../src/event-queue/factory/EventQueueFactory.ts"],"names":["otelApiPromise","loadOtelApi","mod","logger","debug","setter","set","carrier","key","value","getter","get","keys","Object","injectW3CTraceContext","hdrs","api","propagation","inject","context","active","entries","err","error","Error","message","String","extractW3CTraceContext","undefined","extract","runWithConsumerSpan","subject","handler","parentCtx","tracer","trace","getTracer","Promise","resolve","reject","startActiveSpan","kind","attributes","span","result","setStatus","code","end","recordException","DEFAULT_STREAM_MAX_BYTES","NatsSubscription","stats","messagesReceived","messagesProcessed","messagesFailed","lastActivity","Date","toISOString","id","stopFn","unsubscribe","isActive","getStats","incrementReceived","incrementProcessed","incrementFailed","NatsEventConsumer","connectionManager","subscriptions","Map","config","baseConfig","type","url","user","password","token","creds","credsFile","maxReconnectAttempts","reconnectTimeWait","connectionTimeout","name","NatsConnectionManager","connect","disconnect","unsubscribeAll","isConnected","healthCheck","status","timestamp","connected","details","activeSubscriptions","size","getStatistics","totalReceived","totalProcessed","totalFailed","subscription","values","messagesPublished","messagesConsumed","activeConsumers","activePublishers","queueSize","ensureStream","jsm","getJetStreamManager","streams","info","stream","streamConfig","subjects","retention","mapRetentionPolicy","storage","mapStorageType","max_consumers","maxConsumers","max_msgs","maxMsgs","max_bytes","maxBytes","max_age","maxAge","duplicate_window","duplicateWindow","add","ensureConsumer","consumers","consumer","durable_name","filter_subject","filterSubject","ack_policy","mapAckPolicy","ackPolicy","deliver_policy","mapDeliverPolicy","deliverPolicy","max_deliver","maxDeliver","ack_wait","ackWait","max_ack_pending","maxAckPending","includes","deriveStreamSubjects","firstSegment","split","replace","subscribe","options","js","getJetStream","streamName","consumerName","streamSubjects","errorMessage","find","requestedStream","subscriptionId","now","crypto","randomUUID","substring","stopRequested","consumeMessages","maxConcurrent","catch","subscribeMultiple","push","pull","messages","fetch","max_messages","batch","expires","timeout","events","msg","event","wrapMessage","unsubscribePromises","Array","from","map","all","clear","getSubscriptions","processDLQ","_handler","warn","listSubjects","consume","headers","nak","eventMessage","JSON","parse","data","toString","sequence","seq","ack","delay","term","isRedelivered","redelivered","getDeliveryAttempt","deliveryCount","policy","toLowerCase","RetentionPolicy","Limits","Interest","Workqueue","StorageType","Memory","File","AckPolicy","None","All","Explicit","DeliverPolicy","New","Last","LastPerSubject","NatsEventPublisher","publishCount","lastPublishTime","list","next","streamCount","length","deriveStreamName","toUpperCase","publish","messageId","generateMessageId","metadata","source","correlationId","generateCorrelationId","userId","workspaceId","priority","defaultPriority","publishOpts","msgID","enableDeduplication","ttl","stringify","publishBatch","results","publishWithAck","nc","getNatsConnection","response","request","EventQueueFactory","createPublisher","QueueType","NATS","createConsumer","createPublisherFromEnv","process","env","parseInt","defaultTTL","createConsumerFromEnv","createPublisherForLayer","layer","serviceName","envPrefix","defaults","DEFAULT_LAYER_RESOURCES","natsUrl","createConsumerForLayer"],"mappings":"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","file":"chunk-KSO6QQVD.js","sourcesContent":["/**\n * W3C trace context injection/extraction for NATS headers.\n *\n * Uses `@opentelemetry/api` when available to read/write `traceparent`,\n * `tracestate`, and `baggage` headers. When the API module isn't installed\n * (optional peer dep), these helpers are no-ops so NATS continues to work.\n */\nimport { logger } from '../../../logger/index.js';\nimport type { MsgHdrs } from 'nats';\n\ntype OtelApi = {\n propagation: {\n inject: (\n ctx: unknown,\n carrier: Record<string, string>,\n setter: { set: (c: Record<string, string>, k: string, v: string) => void }\n ) => void;\n extract: (\n ctx: unknown,\n carrier: Record<string, string>,\n getter: {\n get: (c: Record<string, string>, k: string) => string | undefined;\n keys: (c: Record<string, string>) => string[];\n }\n ) => unknown;\n };\n context: { active: () => unknown; with: <T>(ctx: unknown, fn: () => T) => T };\n trace: { getTracer: (name: string, version?: string) => { startActiveSpan: (...args: unknown[]) => unknown } };\n};\n\nlet otelApiPromise: Promise<OtelApi | null> | null = null;\n\nasync function loadOtelApi(): Promise<OtelApi | null> {\n if (otelApiPromise) {\n return otelApiPromise;\n }\n otelApiPromise = (async () => {\n try {\n // Dynamic import so services without OTel installed still work.\n const mod = (await import('@opentelemetry/api')) as unknown as OtelApi;\n return mod;\n } catch {\n logger.debug('[trace-context] @opentelemetry/api not available; NATS traces disabled');\n return null;\n }\n })();\n return otelApiPromise;\n}\n\nconst setter = {\n set(carrier: Record<string, string>, key: string, value: string): void {\n carrier[key] = value;\n },\n};\n\nconst getter = {\n get(carrier: Record<string, string>, key: string): string | undefined {\n return carrier[key];\n },\n keys(carrier: Record<string, string>): string[] {\n return Object.keys(carrier);\n },\n};\n\n/**\n * Inject the active W3C trace context into the given NATS headers.\n * Adds `traceparent`, `tracestate`, and `baggage` when present in the\n * active context.\n */\nexport async function injectW3CTraceContext(hdrs: MsgHdrs): Promise<void> {\n const api = await loadOtelApi();\n if (!api) return;\n try {\n const carrier: Record<string, string> = {};\n api.propagation.inject(api.context.active(), carrier, setter);\n for (const [key, value] of Object.entries(carrier)) {\n if (value) hdrs.set(key, value);\n }\n } catch (err) {\n logger.debug('[trace-context] injection failed', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n/**\n * Extract a W3C trace context from the given NATS headers and return the\n * resulting OTel context. Callers wrap their handler in `context.with(...)`\n * to stitch parent spans.\n */\nexport async function extractW3CTraceContext(hdrs: MsgHdrs | undefined): Promise<unknown> {\n const api = await loadOtelApi();\n if (!api || !hdrs) return undefined;\n try {\n const carrier: Record<string, string> = {};\n for (const key of ['traceparent', 'tracestate', 'baggage']) {\n const value = hdrs.get(key);\n if (value) carrier[key] = value;\n }\n return api.propagation.extract(api.context.active(), carrier, getter);\n } catch (err) {\n logger.debug('[trace-context] extraction failed', {\n error: err instanceof Error ? err.message : String(err),\n });\n return undefined;\n }\n}\n\n/**\n * Wrap a NATS consumer handler in a CONSUMER-kind span rooted at the\n * extracted W3C context. If OTel isn't available, the handler runs\n * directly. Errors are recorded on the span and re-thrown so ack/nak\n * semantics are preserved by the caller.\n */\nexport async function runWithConsumerSpan<T>(\n subject: string,\n hdrs: MsgHdrs | undefined,\n handler: () => Promise<T>\n): Promise<T> {\n const api = await loadOtelApi();\n if (!api) return handler();\n try {\n const parentCtx = await extractW3CTraceContext(hdrs);\n const tracer = api.trace.getTracer('@burdenoff/be-sdk/nats');\n return await new Promise<T>((resolve, reject) => {\n tracer.startActiveSpan(\n `nats.consume ${subject}`,\n { kind: 5, attributes: { 'messaging.system': 'nats', 'messaging.destination.name': subject } },\n parentCtx,\n async (span: {\n setStatus: (status: { code: number; message?: string }) => void;\n recordException: (err: Error) => void;\n end: () => void;\n }) => {\n try {\n const result = await handler();\n span.setStatus({ code: 1 });\n span.end();\n resolve(result);\n } catch (err) {\n span.recordException(err as Error);\n span.setStatus({ code: 2, message: err instanceof Error ? err.message : String(err) });\n span.end();\n reject(err);\n }\n }\n );\n });\n } catch (err) {\n logger.debug('[trace-context] consumer span failed to start; running without span', {\n error: err instanceof Error ? err.message : String(err),\n });\n return handler();\n }\n}\n","/**\n * NATS Event Consumer Implementation\n * Implements IEventConsumer interface for NATS JetStream\n */\nimport { logger } from '../../../logger/index.js';\nimport { runWithConsumerSpan } from './trace-context.js';\nimport {\n AckPolicy,\n type Consumer,\n DeliverPolicy,\n type JsMsg,\n type StreamConfig as NatsStreamConfig,\n RetentionPolicy,\n StorageType,\n} from 'nats';\n\nimport type { IEventConsumer, ISubscription } from '../../interfaces/IEventConsumer.js';\nimport type {\n AcknowledgeableEvent,\n ConsumerConfig,\n EventHandler,\n EventMessage,\n EventQueueHealthCheckResult,\n QueueStatistics,\n StreamConfig,\n SubscriptionOptions,\n} from '../../types/index.js';\nimport { NatsConnectionManager } from './NatsConnection.js';\n\nconst DEFAULT_STREAM_MAX_BYTES = 10 * 1024 * 1024;\n\n/**\n * NATS Subscription Implementation\n */\nclass NatsSubscription implements ISubscription {\n private active: boolean = true;\n private stats = {\n messagesReceived: 0,\n messagesProcessed: 0,\n messagesFailed: 0,\n lastActivity: new Date().toISOString(),\n };\n\n constructor(\n public readonly id: string,\n public readonly subject: string,\n private stopFn: () => void\n ) {}\n\n async unsubscribe(): Promise<void> {\n if (!this.active) {\n return Promise.resolve();\n }\n this.active = false;\n this.stopFn();\n return Promise.resolve();\n }\n\n isActive(): boolean {\n return this.active;\n }\n\n getStats(): {\n messagesReceived: number;\n messagesProcessed: number;\n messagesFailed: number;\n lastActivity: string;\n } {\n return {\n messagesReceived: this.stats.messagesReceived,\n messagesProcessed: this.stats.messagesProcessed,\n messagesFailed: this.stats.messagesFailed,\n lastActivity: this.stats.lastActivity,\n };\n }\n\n incrementReceived(): void {\n this.stats.messagesReceived++;\n this.stats.lastActivity = new Date().toISOString();\n }\n\n incrementProcessed(): void {\n this.stats.messagesProcessed++;\n this.stats.lastActivity = new Date().toISOString();\n }\n\n incrementFailed(): void {\n this.stats.messagesFailed++;\n this.stats.lastActivity = new Date().toISOString();\n }\n}\n\n/**\n * NATS implementation of IEventConsumer\n */\nexport class NatsEventConsumer implements IEventConsumer {\n private connectionManager: NatsConnectionManager;\n private subscriptions: Map<string, NatsSubscription> = new Map();\n\n constructor(private config: ConsumerConfig) {\n // Create base config for connection manager\n const baseConfig = {\n type: config.type || 'nats',\n url: config.url || 'nats://localhost:4222',\n user: config.user,\n password: config.password,\n token: config.token,\n creds: config.creds,\n credsFile: config.credsFile,\n maxReconnectAttempts: config.maxReconnectAttempts,\n reconnectTimeWait: config.reconnectTimeWait,\n connectionTimeout: config.connectionTimeout,\n name: config.name,\n };\n this.connectionManager = new NatsConnectionManager(baseConfig);\n }\n\n /**\n * Connect to NATS server\n */\n async connect(): Promise<void> {\n await this.connectionManager.connect();\n }\n\n /**\n * Disconnect from NATS server\n */\n async disconnect(): Promise<void> {\n await this.unsubscribeAll();\n await this.connectionManager.disconnect();\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connectionManager.isConnected();\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<EventQueueHealthCheckResult> {\n await Promise.resolve();\n const isConnected = this.isConnected();\n\n return {\n status: isConnected ? 'healthy' : 'unhealthy',\n timestamp: new Date().toISOString(),\n connected: isConnected,\n details: {\n type: 'nats',\n url: this.config.url,\n activeSubscriptions: this.subscriptions.size,\n },\n };\n }\n\n /**\n * Get queue statistics\n */\n async getStatistics(): Promise<QueueStatistics> {\n await Promise.resolve();\n let totalReceived = 0;\n let totalProcessed = 0;\n let totalFailed = 0;\n let lastActivity: string | null = null;\n\n for (const subscription of this.subscriptions.values()) {\n const stats = subscription.getStats();\n totalReceived += stats.messagesReceived;\n totalProcessed += stats.messagesProcessed;\n totalFailed += stats.messagesFailed;\n\n if (stats.lastActivity && (!lastActivity || stats.lastActivity > lastActivity)) {\n lastActivity = stats.lastActivity;\n }\n }\n\n return {\n messagesPublished: 0, // Consumer doesn't track publishing\n messagesConsumed: totalProcessed,\n messagesFailed: totalFailed,\n activeConsumers: this.subscriptions.size,\n activePublishers: 0,\n queueSize: 0,\n lastActivity: lastActivity,\n details: {\n totalReceived,\n type: 'nats',\n },\n };\n }\n\n /**\n * Ensure a stream exists\n */\n async ensureStream(config: StreamConfig): Promise<void> {\n const jsm = this.connectionManager.getJetStreamManager();\n\n try {\n // Check if stream exists\n try {\n await jsm.streams.info(config.name);\n logger.debug('[NatsEventConsumer] Stream already exists', {\n stream: config.name,\n });\n return;\n } catch {\n // Stream doesn't exist, create it\n }\n\n const streamConfig: Partial<NatsStreamConfig> = {\n name: config.name,\n subjects: config.subjects,\n retention: this.mapRetentionPolicy(config.retention),\n storage: this.mapStorageType(config.storage),\n max_consumers: config.maxConsumers,\n max_msgs: config.maxMsgs,\n max_bytes: config.maxBytes ?? DEFAULT_STREAM_MAX_BYTES,\n max_age: config.maxAge,\n duplicate_window: config.duplicateWindow,\n };\n\n await jsm.streams.add(streamConfig);\n\n logger.info('[NatsEventConsumer] Stream created successfully', {\n stream: config.name,\n subjects: config.subjects,\n });\n } catch (error) {\n logger.error('[NatsEventConsumer] Failed to ensure stream', {\n stream: config.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Ensure a consumer exists\n */\n async ensureConsumer(config: ConsumerConfig): Promise<void> {\n const jsm = this.connectionManager.getJetStreamManager();\n\n try {\n await jsm.consumers.add(config.stream, {\n name: config.consumer,\n durable_name: config.consumer,\n filter_subject: config.filterSubject,\n ack_policy: this.mapAckPolicy(config.ackPolicy),\n deliver_policy: this.mapDeliverPolicy(config.deliverPolicy),\n max_deliver: config.maxDeliver || 3,\n ack_wait: config.ackWait || 30_000_000_000, // 30 seconds in nanoseconds\n max_ack_pending: config.maxAckPending || 100,\n });\n\n logger.info('[NatsEventConsumer] Consumer created successfully', {\n stream: config.stream,\n consumer: config.consumer,\n });\n } catch (error) {\n if (error instanceof Error && error.message?.includes('already exists')) {\n logger.debug('[NatsEventConsumer] Consumer already exists', {\n stream: config.stream,\n consumer: config.consumer,\n });\n } else {\n logger.error('[NatsEventConsumer] Failed to ensure consumer', {\n stream: config.stream,\n consumer: config.consumer,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n }\n\n /**\n * Derive stream subject pattern from subscription subject\n * Examples:\n * - \"channel.conversation.message\" → [\"channel.>\"]\n * - \"wspace.tags.created\" → [\"wspace.>\"]\n * - \"global.auth.login\" → [\"global.>\"]\n */\n private deriveStreamSubjects(subject: string): string[] {\n // Extract the first segment and create a wildcard pattern\n const firstSegment = subject.split('.')[0];\n if (firstSegment) {\n return [`${firstSegment}.>`];\n }\n // Fallback to the subject itself with a wildcard\n return [`${subject.replace(/\\.[^.]+$/, '.>')}`];\n }\n\n /**\n * Subscribe to a subject\n */\n async subscribe<T = unknown>(options: {\n subject: string;\n handler: EventHandler<T>;\n options?: SubscriptionOptions;\n }): Promise<ISubscription> {\n const js = this.connectionManager.getJetStream();\n const jsm = this.connectionManager.getJetStreamManager();\n\n try {\n let streamName = options.options?.stream || this.config.stream;\n const consumerName =\n options.options?.consumer || `${this.config.consumer}-${options.subject.replace(/\\./g, '-')}`;\n\n // Auto-create stream if it doesn't exist\n // Derive subjects from the subscription subject pattern\n const streamSubjects = options.options?.streamSubjects || this.deriveStreamSubjects(options.subject);\n try {\n await this.ensureStream({\n name: streamName,\n subjects: streamSubjects,\n retention: options.options?.retention || 'limits',\n storage: options.options?.storage || 'file',\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (!errorMessage.includes('subjects overlap')) {\n throw error;\n }\n\n streamName = await jsm.streams.find(options.subject);\n logger.info('[NatsEventConsumer] Using existing stream for overlapping subject', {\n requestedStream: options.options?.stream || this.config.stream,\n stream: streamName,\n subject: options.subject,\n });\n }\n\n // Ensure consumer exists\n await this.ensureConsumer({\n type: this.config.type,\n url: this.config.url,\n consumer: consumerName,\n stream: streamName,\n filterSubject: options.subject,\n ackPolicy: options.options?.ackPolicy,\n deliverPolicy: options.options?.deliverPolicy,\n maxDeliver: options.options?.maxDeliver || this.config.maxDeliver,\n ackWait: options.options?.ackWait || this.config.ackWait,\n maxAckPending: options.options?.maxAckPending,\n });\n\n // Get consumer\n const consumer = await js.consumers.get(streamName, consumerName);\n\n const subscriptionId = `sub_${Date.now()}_${crypto.randomUUID().substring(0, 7)}`;\n let stopRequested = false;\n\n // Create subscription\n const stopFn = (): void => {\n stopRequested = true;\n };\n\n const subscription = new NatsSubscription(subscriptionId, options.subject, stopFn);\n\n this.subscriptions.set(subscriptionId, subscription);\n\n // Start consuming messages\n this.consumeMessages(\n consumer,\n subscription,\n options.handler,\n options.options?.maxConcurrent || this.config.maxConcurrent || 1,\n () => stopRequested\n ).catch((error) => {\n logger.error('[NatsEventConsumer] Error in message consumption loop', {\n subject: options.subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n });\n\n logger.info('[NatsEventConsumer] Subscription created', {\n subscriptionId,\n subject: options.subject,\n });\n\n return subscription;\n } catch (error) {\n logger.error('[NatsEventConsumer] Failed to subscribe', {\n subject: options.subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Subscribe to multiple subjects\n */\n async subscribeMultiple<T = unknown>(\n subjects: string[],\n handler: EventHandler<T>,\n options?: SubscriptionOptions\n ): Promise<ISubscription[]> {\n const subscriptions: ISubscription[] = [];\n\n for (const subject of subjects) {\n const subscription = await this.subscribe({\n subject,\n handler,\n options,\n });\n subscriptions.push(subscription);\n }\n\n return subscriptions;\n }\n\n /**\n * Pull messages manually\n */\n async pull<T = unknown>(options: {\n subject: string;\n batch?: number;\n timeout?: number;\n }): Promise<AcknowledgeableEvent<T>[]> {\n const js = this.connectionManager.getJetStream();\n\n try {\n const consumer = await js.consumers.get(this.config.stream, this.config.consumer);\n\n const messages = await consumer.fetch({\n max_messages: options.batch || 10,\n expires: options.timeout || 30000,\n });\n\n const events: AcknowledgeableEvent<T>[] = [];\n\n for await (const msg of messages) {\n const event = this.wrapMessage<T>(msg);\n events.push(event);\n }\n\n return events;\n } catch (error) {\n logger.error('[NatsEventConsumer] Failed to pull messages', {\n subject: options.subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Unsubscribe from all active subscriptions\n */\n async unsubscribeAll(): Promise<void> {\n const unsubscribePromises = Array.from(this.subscriptions.values()).map(async (subscription) =>\n subscription.unsubscribe()\n );\n\n await Promise.all(unsubscribePromises);\n\n this.subscriptions.clear();\n\n logger.info('[NatsEventConsumer] All subscriptions unsubscribed');\n }\n\n /**\n * Get all active subscriptions\n */\n getSubscriptions(): ISubscription[] {\n return Array.from(this.subscriptions.values());\n }\n\n /**\n * Process pending messages in dead letter queue\n */\n async processDLQ<T = unknown>(_handler: EventHandler<T>): Promise<void> {\n await Promise.resolve();\n // Would need to implement DLQ stream pattern\n logger.warn('[NatsEventConsumer] DLQ processing not yet implemented');\n }\n\n /**\n * List subjects for the configured stream\n */\n async listSubjects(streamName?: string): Promise<string[]> {\n const jsm = this.connectionManager.getJetStreamManager();\n const info = await jsm.streams.info(streamName || this.config.stream);\n return info.config.subjects || [];\n }\n\n /**\n * Consume messages from consumer\n */\n private async consumeMessages<T>(\n consumer: Consumer,\n subscription: NatsSubscription,\n handler: EventHandler<T>,\n maxConcurrent: number,\n stopRequested: () => boolean\n ): Promise<void> {\n try {\n const messages = await consumer.consume({\n max_messages: maxConcurrent,\n expires: 30000, // 30 seconds\n });\n\n for await (const msg of messages) {\n if (stopRequested()) {\n break;\n }\n\n subscription.incrementReceived();\n\n try {\n const event = this.wrapMessage<T>(msg);\n // Wrap in a CONSUMER-kind span rooted at the producer's trace\n // context (if present in headers). No-op when OTel isn't installed.\n await runWithConsumerSpan(msg.subject, msg.headers, async () => handler(event));\n subscription.incrementProcessed();\n } catch (error) {\n subscription.incrementFailed();\n logger.error('[NatsEventConsumer] Error processing message', {\n subject: msg.subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n // Don't ack - let it retry\n msg.nak();\n }\n }\n } catch (error) {\n logger.error('[NatsEventConsumer] Error consuming messages', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Wrap NATS message in AcknowledgeableEvent\n */\n private wrapMessage<T>(msg: JsMsg): AcknowledgeableEvent<T> {\n const eventMessage: EventMessage<T> = JSON.parse(msg.data.toString());\n\n return {\n ...eventMessage,\n sequence: msg.seq,\n ack: async (): Promise<void> => {\n await Promise.resolve();\n msg.ack();\n },\n nak: async (delay?: number): Promise<void> => {\n await Promise.resolve();\n if (delay) {\n msg.nak(delay);\n } else {\n msg.nak();\n }\n },\n term: async (): Promise<void> => {\n await Promise.resolve();\n msg.term();\n },\n isRedelivered: (): boolean => {\n return msg.redelivered;\n },\n getDeliveryAttempt: (): number => {\n return msg.info.deliveryCount;\n },\n };\n }\n\n /**\n * Map retention policy string to NATS enum\n */\n private mapRetentionPolicy(policy?: string): RetentionPolicy {\n switch (policy?.toLowerCase()) {\n case 'limits':\n return RetentionPolicy.Limits;\n case 'interest':\n return RetentionPolicy.Interest;\n case 'workqueue':\n default:\n return RetentionPolicy.Workqueue;\n }\n }\n\n /**\n * Map storage type string to NATS enum\n */\n private mapStorageType(storage?: string): StorageType {\n switch (storage?.toLowerCase()) {\n case 'memory':\n return StorageType.Memory;\n case 'file':\n default:\n return StorageType.File;\n }\n }\n\n /**\n * Map ack policy string to NATS enum\n */\n private mapAckPolicy(policy?: string): AckPolicy {\n switch (policy?.toLowerCase()) {\n case 'none':\n return AckPolicy.None;\n case 'all':\n return AckPolicy.All;\n case 'explicit':\n default:\n return AckPolicy.Explicit;\n }\n }\n\n /**\n * Map deliver policy string to NATS enum\n */\n private mapDeliverPolicy(policy?: string): DeliverPolicy {\n switch (policy?.toLowerCase()) {\n case 'new':\n return DeliverPolicy.New;\n case 'last':\n return DeliverPolicy.Last;\n case 'lastpersubject':\n return DeliverPolicy.LastPerSubject;\n case 'all':\n default:\n return DeliverPolicy.All;\n }\n }\n}\n","/**\n * NATS Event Publisher Implementation\n * Implements IEventPublisher interface for NATS JetStream\n */\nimport { logger } from '../../../logger/index.js';\nimport { injectW3CTraceContext } from './trace-context.js';\nimport { type StreamConfig as NatsStreamConfig, RetentionPolicy, StorageType, headers } from 'nats';\n\nimport type { IEventPublisher, PublishOptions } from '../../interfaces/IEventPublisher.js';\nimport type { PublisherConfig } from '../../types/config.js';\nimport type {\n EventMessage,\n EventMetadata,\n EventQueueHealthCheckResult,\n QueueStatistics,\n StreamConfig,\n} from '../../types/index.js';\nimport { NatsConnectionManager } from './NatsConnection.js';\n\nconst DEFAULT_STREAM_MAX_BYTES = 10 * 1024 * 1024;\n\n/**\n * NATS implementation of IEventPublisher\n */\nexport class NatsEventPublisher implements IEventPublisher {\n private connectionManager: NatsConnectionManager;\n private publishCount: number = 0;\n private lastPublishTime: Date | null = null;\n\n constructor(private config: PublisherConfig) {\n this.connectionManager = new NatsConnectionManager(config);\n }\n\n /**\n * Connect to NATS server\n */\n async connect(): Promise<void> {\n await this.connectionManager.connect();\n }\n\n /**\n * Disconnect from NATS server\n */\n async disconnect(): Promise<void> {\n await this.connectionManager.disconnect();\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connectionManager.isConnected();\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<EventQueueHealthCheckResult> {\n await Promise.resolve();\n const isConnected = this.isConnected();\n\n return {\n status: isConnected ? 'healthy' : 'unhealthy',\n timestamp: new Date().toISOString(),\n details: {\n connected: isConnected,\n type: 'nats',\n url: this.config.url,\n },\n };\n }\n\n /**\n * Get queue statistics\n */\n async getStatistics(): Promise<QueueStatistics> {\n const jsm = this.connectionManager.getJetStreamManager();\n\n try {\n const streams = await jsm.streams.list().next();\n const streamCount = streams.length;\n\n return {\n messagesPublished: this.publishCount,\n messagesConsumed: 0, // Publisher doesn't track consumption\n messagesFailed: 0,\n activeConsumers: 0,\n activePublishers: 1,\n queueSize: 0, // Would need to sum all stream messages\n lastActivity: this.lastPublishTime?.toISOString() || null,\n details: {\n streamCount,\n type: 'nats',\n },\n };\n } catch (error) {\n logger.error('[NatsEventPublisher] Failed to get statistics', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Ensure a stream exists\n */\n async ensureStream(config: StreamConfig): Promise<void> {\n const jsm = this.connectionManager.getJetStreamManager();\n\n try {\n // Check if stream exists\n try {\n await jsm.streams.info(config.name);\n logger.debug('[NatsEventPublisher] Stream already exists', {\n stream: config.name,\n });\n return;\n } catch {\n // Stream doesn't exist, create it\n }\n\n const streamConfig: Partial<NatsStreamConfig> = {\n name: config.name,\n subjects: config.subjects,\n retention: this.mapRetentionPolicy(config.retention),\n storage: this.mapStorageType(config.storage),\n max_consumers: config.maxConsumers,\n max_msgs: config.maxMsgs,\n max_bytes: config.maxBytes ?? DEFAULT_STREAM_MAX_BYTES,\n max_age: config.maxAge,\n duplicate_window: config.duplicateWindow,\n };\n\n await jsm.streams.add(streamConfig);\n\n logger.info('[NatsEventPublisher] Stream created successfully', {\n stream: config.name,\n subjects: config.subjects,\n });\n } catch (error) {\n logger.error('[NatsEventPublisher] Failed to ensure stream', {\n stream: config.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Derive stream subject pattern from subscription subject\n * Examples:\n * - \"channel.conversation.message\" → [\"channel.>\"]\n * - \"wspace.tags.created\" → [\"wspace.>\"]\n * - \"global.auth.login\" → [\"global.>\"]\n */\n private deriveStreamSubjects(subject: string): string[] {\n // Extract the first segment and create a wildcard pattern\n const firstSegment = subject.split('.')[0];\n if (firstSegment) {\n return [`${firstSegment}.>`];\n }\n // Fallback to the subject itself with a wildcard\n return [`${subject.replace(/\\.[^.]+$/, '.>')}`];\n }\n\n /**\n * Derive stream name from subject\n * Examples:\n * - \"channel.conversation.message\" → \"CHANNEL_EVENTS\"\n * - \"wspace.tags.created\" → \"WSPACE_EVENTS\"\n * - \"global.auth.login\" → \"GLOBAL_EVENTS\"\n */\n private deriveStreamName(subject: string): string {\n const firstSegment = subject.split('.')[0];\n if (firstSegment) {\n return `${firstSegment.toUpperCase()}_EVENTS`;\n }\n return 'EVENTS';\n }\n\n /**\n * Publish an event to a subject\n */\n async publish<T = unknown>(options: {\n subject: string;\n data: T;\n metadata?: Partial<EventMetadata>;\n options?: PublishOptions;\n }): Promise<number | string> {\n const js = this.connectionManager.getJetStream();\n\n try {\n // Auto-create stream if it doesn't exist\n const streamName = options.options?.stream || this.deriveStreamName(options.subject);\n const streamSubjects = options.options?.streamSubjects || this.deriveStreamSubjects(options.subject);\n await this.ensureStream({\n name: streamName,\n subjects: streamSubjects,\n retention: options.options?.retention || 'limits',\n storage: options.options?.storage || 'file',\n });\n\n // Create event message\n const message: EventMessage<T> = {\n id: options.options?.messageId || this.generateMessageId(),\n subject: options.subject,\n data: options.data,\n metadata: {\n source: options.metadata?.source || 'workspaces-backend',\n correlationId: options.metadata?.correlationId || this.generateCorrelationId(),\n userId: options.metadata?.userId,\n workspaceId: options.metadata?.workspaceId,\n priority: options.options?.priority || this.config.defaultPriority || 'normal',\n ...options.metadata,\n },\n timestamp: new Date().toISOString(),\n };\n\n // Create headers\n const hdrs = headers();\n hdrs.set('message-id', message.id);\n hdrs.set('correlation-id', message.metadata.correlationId);\n\n if (message.metadata.source) {\n hdrs.set('source', message.metadata.source);\n }\n if (message.metadata['priority'] && typeof message.metadata['priority'] === 'string') {\n hdrs.set('priority', message.metadata['priority']);\n }\n if (message.metadata.userId) {\n hdrs.set('user-id', message.metadata.userId);\n }\n if (message.metadata.workspaceId) {\n hdrs.set('workspace-id', message.metadata.workspaceId);\n }\n\n // Inject W3C trace context so the consumer can link its span to the\n // producer's trace. Dynamic import keeps @opentelemetry/api optional.\n await injectW3CTraceContext(hdrs);\n\n // Publish options\n const publishOpts: {\n msgID?: string;\n headers: ReturnType<typeof headers>;\n } = {\n msgID: this.config.enableDeduplication ? message.id : undefined,\n headers: hdrs,\n };\n\n // Handle TTL\n if (options.options?.ttl) {\n // NATS doesn't have per-message TTL, would need stream-level configuration\n logger.warn('[NatsEventPublisher] Per-message TTL not supported in NATS', {\n subject: options.subject,\n ttl: options.options.ttl,\n });\n }\n\n // Handle delay\n if (options.options?.delay) {\n // NATS doesn't have native delay, would need to implement with separate delayed stream\n logger.warn('[NatsEventPublisher] Message delay not supported in NATS', {\n subject: options.subject,\n delay: options.options.delay,\n });\n }\n\n // Publish message\n const ack = await js.publish(options.subject, JSON.stringify(message), publishOpts);\n\n this.publishCount++;\n this.lastPublishTime = new Date();\n\n logger.debug('[NatsEventPublisher] Event published', {\n subject: options.subject,\n messageId: message.id,\n sequence: ack.seq,\n });\n\n return ack.seq;\n } catch (error) {\n logger.error('[NatsEventPublisher] Failed to publish event', {\n subject: options.subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Publish multiple events in a batch\n */\n async publishBatch<T = unknown>(\n events: Array<{\n subject: string;\n data: T;\n metadata?: Partial<EventMetadata>;\n options?: PublishOptions;\n }>\n ): Promise<Array<number | string>> {\n const results: Array<number | string> = [];\n\n for (const event of events) {\n const seq = await this.publish(event);\n results.push(seq);\n }\n\n return results;\n }\n\n /**\n * Publish an event and wait for acknowledgment\n * Note: This is not natively supported by NATS JetStream\n * Would require implementing request-reply pattern\n */\n async publishWithAck<T = unknown, R = unknown>(options: {\n subject: string;\n data: T;\n metadata?: Partial<EventMetadata>;\n timeout?: number;\n }): Promise<R> {\n const nc = this.connectionManager.getNatsConnection();\n\n try {\n const message: EventMessage<T> = {\n id: this.generateMessageId(),\n subject: options.subject,\n data: options.data,\n metadata: {\n source: options.metadata?.source || 'workspaces-backend',\n correlationId: options.metadata?.correlationId || this.generateCorrelationId(),\n userId: options.metadata?.userId,\n workspaceId: options.metadata?.workspaceId,\n ...options.metadata,\n },\n timestamp: new Date().toISOString(),\n };\n\n const response = await nc.request(options.subject, JSON.stringify(message), {\n timeout: options.timeout || 30000,\n });\n\n const result = JSON.parse(response.data.toString()) as R;\n\n logger.debug('[NatsEventPublisher] Event published with ack', {\n subject: options.subject,\n messageId: message.id,\n });\n\n return result;\n } catch (error) {\n logger.error('[NatsEventPublisher] Failed to publish event with ack', {\n subject: options.subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n }\n\n /**\n * Map retention policy string to NATS enum\n */\n private mapRetentionPolicy(policy?: string): RetentionPolicy {\n switch (policy?.toLowerCase()) {\n case 'limits':\n return RetentionPolicy.Limits;\n case 'interest':\n return RetentionPolicy.Interest;\n case 'workqueue':\n default:\n return RetentionPolicy.Workqueue;\n }\n }\n\n /**\n * Map storage type string to NATS enum\n */\n private mapStorageType(storage?: string): StorageType {\n switch (storage?.toLowerCase()) {\n case 'memory':\n return StorageType.Memory;\n case 'file':\n default:\n return StorageType.File;\n }\n }\n\n /**\n * Generate unique message ID\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${crypto.randomUUID().substring(0, 13)}`;\n }\n\n /**\n * Generate correlation ID\n */\n private generateCorrelationId(): string {\n return `corr_${Date.now()}_${crypto.randomUUID().substring(0, 13)}`;\n }\n}\n","/**\n * Event Queue Factory\n * Creates appropriate event queue instances based on configuration\n */\nimport { logger } from '../../logger/index.js';\nimport type { ServiceLayer } from '../../types/layer.js';\nimport { DEFAULT_LAYER_RESOURCES } from '../../types/layer.js';\n\nimport { NatsEventConsumer } from '../implementations/nats/NatsEventConsumer.js';\nimport { NatsEventPublisher } from '../implementations/nats/NatsEventPublisher.js';\nimport type { IEventConsumer } from '../interfaces/IEventConsumer.js';\nimport type { IEventPublisher } from '../interfaces/IEventPublisher.js';\nimport { type ConsumerConfig, type PublisherConfig, QueueType } from '../types/config.js';\n\n/**\n * Factory for creating event queue instances\n */\nexport class EventQueueFactory {\n /**\n * Create an event publisher based on configuration\n */\n static createPublisher(config: PublisherConfig): IEventPublisher {\n logger.info('[EventQueueFactory] Creating event publisher', {\n type: config.type,\n url: config.url,\n });\n\n if (config.type === QueueType.NATS) {\n return new NatsEventPublisher(config);\n }\n\n // Future implementations can be added here\n // if (config.type === QueueType.RABBITMQ) {\n // return new RabbitMQEventPublisher(config);\n // }\n // if (config.type === QueueType.KAFKA) {\n // return new KafkaEventPublisher(config);\n // }\n // if (config.type === QueueType.SQS) {\n // return new SQSEventPublisher(config);\n // }\n\n throw new Error(`Unsupported queue type: ${config.type}`);\n }\n\n /**\n * Create an event consumer based on configuration\n */\n static createConsumer(config: ConsumerConfig): IEventConsumer {\n logger.info('[EventQueueFactory] Creating event consumer', {\n type: config.type,\n url: config.url,\n stream: config.stream,\n consumer: config.consumer,\n });\n\n if (config.type === QueueType.NATS) {\n return new NatsEventConsumer(config);\n }\n\n // Future implementations can be added here\n // if (config.type === QueueType.RABBITMQ) {\n // return new RabbitMQEventConsumer(config);\n // }\n // if (config.type === QueueType.KAFKA) {\n // return new KafkaEventConsumer(config);\n // }\n // if (config.type === QueueType.SQS) {\n // return new SQSEventConsumer(config);\n // }\n\n throw new Error(`Unsupported queue type: ${config.type}`);\n }\n\n /**\n * Create a publisher from environment variables\n */\n static createPublisherFromEnv(): IEventPublisher {\n const config: PublisherConfig = {\n type: (process.env['QUEUE_TYPE'] as QueueType) || QueueType.NATS,\n url: process.env['NATS_URL'] || 'nats://localhost:4222',\n user: process.env['NATS_USER'],\n password: process.env['NATS_PASSWORD'],\n token: process.env['NATS_TOKEN'],\n creds: process.env['NATS_CREDS'],\n credsFile: process.env['NATS_CREDS_FILE'],\n name: process.env['QUEUE_CLIENT_NAME'] || 'workspaces-backend-publisher',\n maxReconnectAttempts: process.env['NATS_MAX_RECONNECT_ATTEMPTS']\n ? parseInt(process.env['NATS_MAX_RECONNECT_ATTEMPTS'], 10)\n : -1,\n reconnectTimeWait: process.env['NATS_RECONNECT_TIME_WAIT']\n ? parseInt(process.env['NATS_RECONNECT_TIME_WAIT'], 10)\n : 2000,\n enableDeduplication: process.env['QUEUE_ENABLE_DEDUPLICATION'] === 'true',\n defaultPriority: (process.env['QUEUE_DEFAULT_PRIORITY'] as 'low' | 'normal' | 'high') || 'normal',\n defaultTTL: process.env['QUEUE_DEFAULT_TTL'] ? parseInt(process.env['QUEUE_DEFAULT_TTL'], 10) : undefined,\n };\n\n return EventQueueFactory.createPublisher(config);\n }\n\n /**\n * Create a consumer from environment variables\n */\n static createConsumerFromEnv(stream: string, consumer: string): IEventConsumer {\n const config: ConsumerConfig = {\n type: (process.env['QUEUE_TYPE'] as QueueType) || QueueType.NATS,\n url: process.env['NATS_URL'] || 'nats://localhost:4222',\n user: process.env['NATS_USER'],\n password: process.env['NATS_PASSWORD'],\n token: process.env['NATS_TOKEN'],\n creds: process.env['NATS_CREDS'],\n credsFile: process.env['NATS_CREDS_FILE'],\n name: process.env['QUEUE_CLIENT_NAME'] || 'workspaces-workers-consumer',\n maxReconnectAttempts: process.env['NATS_MAX_RECONNECT_ATTEMPTS']\n ? parseInt(process.env['NATS_MAX_RECONNECT_ATTEMPTS'], 10)\n : -1,\n reconnectTimeWait: process.env['NATS_RECONNECT_TIME_WAIT']\n ? parseInt(process.env['NATS_RECONNECT_TIME_WAIT'], 10)\n : 2000,\n stream,\n consumer,\n maxConcurrent: process.env['QUEUE_MAX_CONCURRENT'] ? parseInt(process.env['QUEUE_MAX_CONCURRENT'], 10) : 5,\n maxDeliver: process.env['QUEUE_MAX_DELIVER'] ? parseInt(process.env['QUEUE_MAX_DELIVER'], 10) : 3,\n ackWait: process.env['QUEUE_ACK_WAIT']\n ? parseInt(process.env['QUEUE_ACK_WAIT'], 10) * 1_000_000_000 // Convert seconds to nanoseconds\n : 30_000_000_000,\n };\n\n return EventQueueFactory.createConsumer(config);\n }\n\n // ========================================================================\n // Layer-Aware Factory Methods\n // ========================================================================\n\n /**\n * Create a publisher for a specific layer\n *\n * @param layer - Service layer ('wspace' or 'global')\n * @param serviceName - Service name for identification\n * @returns Publisher configured for the layer\n *\n * @example\n * ```typescript\n * const publisher = EventQueueFactory.createPublisherForLayer('wspace', 'wspace-tags-svc');\n * await publisher.connect();\n * await publisher.publish({ subject: 'wspace.tags.created', data: { id: '123' } });\n * ```\n */\n static createPublisherForLayer(layer: ServiceLayer, serviceName: string): IEventPublisher {\n const envPrefix = layer.toUpperCase();\n const defaults = DEFAULT_LAYER_RESOURCES[layer];\n\n const config: PublisherConfig = {\n type: QueueType.NATS,\n url: process.env[`${envPrefix}_NATS_URL`] || process.env['NATS_URL'] || defaults.natsUrl,\n user: process.env['NATS_USER'],\n password: process.env['NATS_PASSWORD'],\n token: process.env['NATS_TOKEN'],\n creds: process.env['NATS_CREDS'],\n credsFile: process.env['NATS_CREDS_FILE'],\n name: serviceName,\n maxReconnectAttempts: process.env['NATS_MAX_RECONNECT_ATTEMPTS']\n ? parseInt(process.env['NATS_MAX_RECONNECT_ATTEMPTS'], 10)\n : -1,\n reconnectTimeWait: process.env['NATS_RECONNECT_TIME_WAIT']\n ? parseInt(process.env['NATS_RECONNECT_TIME_WAIT'], 10)\n : 2000,\n enableDeduplication: process.env['QUEUE_ENABLE_DEDUPLICATION'] === 'true',\n defaultPriority: (process.env['QUEUE_DEFAULT_PRIORITY'] as 'low' | 'normal' | 'high') || 'normal',\n defaultTTL: process.env['QUEUE_DEFAULT_TTL'] ? parseInt(process.env['QUEUE_DEFAULT_TTL'], 10) : undefined,\n };\n\n logger.info('[EventQueueFactory] Creating layer publisher', {\n layer,\n serviceName,\n url: config.url,\n });\n\n return EventQueueFactory.createPublisher(config);\n }\n\n /**\n * Create a consumer for a specific layer\n *\n * @param layer - Service layer ('wspace' or 'global')\n * @param serviceName - Service name for identification\n * @param stream - NATS stream name\n * @param consumer - Consumer name\n * @returns Consumer configured for the layer\n *\n * @example\n * ```typescript\n * const consumer = EventQueueFactory.createConsumerForLayer(\n * 'wspace', 'wspace-tags-svc', 'WSPACE_EVENTS', 'tags-consumer'\n * );\n * await consumer.connect();\n * await consumer.consume(async (msg) => { console.log(msg); });\n * ```\n */\n static createConsumerForLayer(\n layer: ServiceLayer,\n serviceName: string,\n stream: string,\n consumer: string\n ): IEventConsumer {\n const envPrefix = layer.toUpperCase();\n const defaults = DEFAULT_LAYER_RESOURCES[layer];\n\n const config: ConsumerConfig = {\n type: QueueType.NATS,\n url: process.env[`${envPrefix}_NATS_URL`] || process.env['NATS_URL'] || defaults.natsUrl,\n user: process.env['NATS_USER'],\n password: process.env['NATS_PASSWORD'],\n token: process.env['NATS_TOKEN'],\n creds: process.env['NATS_CREDS'],\n credsFile: process.env['NATS_CREDS_FILE'],\n name: serviceName,\n maxReconnectAttempts: process.env['NATS_MAX_RECONNECT_ATTEMPTS']\n ? parseInt(process.env['NATS_MAX_RECONNECT_ATTEMPTS'], 10)\n : -1,\n reconnectTimeWait: process.env['NATS_RECONNECT_TIME_WAIT']\n ? parseInt(process.env['NATS_RECONNECT_TIME_WAIT'], 10)\n : 2000,\n stream,\n consumer,\n maxConcurrent: process.env['QUEUE_MAX_CONCURRENT'] ? parseInt(process.env['QUEUE_MAX_CONCURRENT'], 10) : 5,\n maxDeliver: process.env['QUEUE_MAX_DELIVER'] ? parseInt(process.env['QUEUE_MAX_DELIVER'], 10) : 3,\n ackWait: process.env['QUEUE_ACK_WAIT']\n ? parseInt(process.env['QUEUE_ACK_WAIT'], 10) * 1_000_000_000\n : 30_000_000_000,\n };\n\n logger.info('[EventQueueFactory] Creating layer consumer', {\n layer,\n serviceName,\n stream,\n consumer,\n url: config.url,\n });\n\n return EventQueueFactory.createConsumer(config);\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/graphql/index.ts","../src/graphql/nats-event-target.ts"],"names":["createNatsEventTarget","options","natsUrl","connectionOptions","serializer","stringify","data","JSON","parse","message","subjectPrefix","sc","StringCodec","defaultConnectionOptions","name","maxReconnectAttempts","reconnectTimeWait","pingInterval","maxPingOut","timeout","mergedConnectionOptions","effectiveUser","user","process","env","effectivePass","pass","password","connectionConfig","type","url","Array","isArray","token","creds","credsFile","connectionManager","connection","NatsConnectionManager","connect","getNatsConnection","logger","info","error","Error","callbacks","Map","subscriptions","getSubject","eventType","subscribeToNats","has","subject","subscription","subscribe","set","debug","msg","messageData","decode","payload","eventCallbacks","get","size","event","CustomEvent","detail","callback","from","callbackError","messageError","subscriptionError","unsubscribeFromNats","unsubscribe","delete","eventTarget","addEventListener","listener","Set","add","listenerCount","removeEventListener","remainingListeners","dispatchEvent","encode","publish","serializeError","close","entries","clear","disconnect","isHealthy","isClosed"],"mappings":"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","file":"chunk-NUZZRJNN.js","sourcesContent":["/**\n * GraphQL Utilities Module\n *\n * Provides GraphQL-related utilities for Burdenoff products.\n *\n * @module graphql\n */\n\nexport { createNatsEventTarget } from './nats-event-target.js';\nexport type { NatsEventTarget, NatsEventTargetOptions, MessageSerializer } from './nats-event-target.js';\n\n// Injectable services for GraphQL Modules\nexport { Logger, createDatabaseService } from './services/index.js';\nexport type { DatabaseService, PrismaTransactionClient } from './services/index.js';\n","/**\n * NATS-based EventTarget Implementation for GraphQL Yoga Distributed PubSub\n *\n * Provides NATS pub/sub infrastructure for GraphQL subscriptions across multiple server instances.\n * This enables horizontal scaling of GraphQL servers while maintaining real-time subscription functionality.\n *\n * Uses event queue abstraction's NatsConnectionManager for connection management\n * while maintaining Core NATS pub/sub for low-latency GraphQL subscriptions\n *\n * Architecture:\n * - Uses NATS Core NATS (not JetStream) for low-latency pub/sub\n * - Implements DOM EventTarget interface required by graphql-yoga's createPubSub\n * - Handles message serialization/deserialization with JSON (customizable)\n * - Manages NATS subscriptions and publishing lifecycle\n * - Includes error handling and reconnection logic\n *\n * Features:\n * - Automatic subscription management per event type\n * - Multiple listener support per event type\n * - Custom serialization support (e.g., SuperJSON for complex types)\n * - Graceful connection handling and cleanup\n * - TypeScript type safety\n *\n * @example\n * ```typescript\n * import { createNatsEventTarget } from '@burdenoff/be-sdk';\n * import { createPubSub } from 'graphql-yoga';\n *\n * const eventTarget = await createNatsEventTarget({\n * natsUrl: 'nats://localhost:4222',\n * });\n *\n * const pubsub = createPubSub({ eventTarget });\n * ```\n *\n * Reference Implementation:\n * Based on @graphql-yoga/redis-event-target pattern\n * https://github.com/graphql-hive/graphql-yoga/tree/main/packages/event-target/redis-event-target\n */\n\nimport type { NatsConnection, Subscription } from 'nats';\nimport { StringCodec } from 'nats';\nimport { logger } from '../logger/index.js';\nimport { NatsConnectionManager } from '../event-queue/implementations/nats/NatsConnection.js';\nimport type { BaseQueueConfig } from '../event-queue/types/config.js';\n\n/**\n * Message Serializer Interface\n *\n * Allows custom serialization for event payloads.\n * Useful for handling non-JSON-serializable data (Dates, BigInts, etc.)\n *\n * @example\n * ```typescript\n * import superjson from 'superjson';\n *\n * const eventTarget = await createNatsEventTarget({\n * natsUrl: 'nats://localhost:4222',\n * serializer: {\n * stringify: (data) => superjson.stringify(data),\n * parse: (message) => superjson.parse(message),\n * }\n * });\n * ```\n */\nexport interface MessageSerializer {\n /**\n * Serialize data to string for transmission over NATS\n */\n stringify: (data: unknown) => string | Promise<string>;\n\n /**\n * Deserialize string message from NATS back to original type\n */\n parse: (message: string) => unknown | Promise<unknown>;\n}\n\n/**\n * NATS EventTarget Options\n */\nexport interface NatsEventTargetOptions {\n /**\n * NATS server URL(s)\n * Examples:\n * - Single server: 'nats://localhost:4222'\n * - Multiple servers: ['nats://server1:4222', 'nats://server2:4222']\n * - With credentials: 'nats://user:password@localhost:4222'\n */\n natsUrl: string | string[];\n\n /**\n * Optional NATS connection options\n * See: https://github.com/nats-io/nats.js#connection-options\n */\n connectionOptions?: {\n /**\n * Connection name for debugging\n * @default 'graphql-pubsub'\n */\n name?: string;\n\n /**\n * Maximum reconnection attempts (-1 for infinite)\n * @default -1\n */\n maxReconnectAttempts?: number;\n\n /**\n * Time to wait between reconnection attempts (ms)\n * @default 2000\n */\n reconnectTimeWait?: number;\n\n /**\n * Ping interval (ms)\n * @default 20000\n */\n pingInterval?: number;\n\n /**\n * Maximum outstanding pings\n * @default 2\n */\n maxPingOut?: number;\n\n /**\n * Connection timeout (ms)\n * @default 20000\n */\n timeout?: number;\n\n /**\n * NATS credentials file contents (JWT + NKEY seed)\n */\n creds?: string;\n\n /**\n * Path to a NATS credentials file\n */\n credsFile?: string;\n };\n\n /**\n * Custom message serializer\n * Defaults to JSON.stringify/parse\n */\n serializer?: MessageSerializer;\n\n /**\n * Subject prefix for all GraphQL subscription topics\n * Useful for namespacing in multi-tenant or multi-app environments\n *\n * @default 'graphql.pubsub'\n *\n * Example: With prefix 'myapp.gql', a subscription to 'MESSAGE_ADDED'\n * will use NATS subject 'myapp.gql.MESSAGE_ADDED'\n */\n subjectPrefix?: string;\n}\n\n/**\n * Event Listener Type\n * Compatible with DOM EventListener interface\n */\ntype EventListener = (event: Event) => void;\n\n/**\n * NATS EventTarget Implementation\n *\n * Implements the EventTarget interface required by graphql-yoga's createPubSub.\n * Uses NATS Core NATS for pub/sub messaging across distributed GraphQL servers.\n */\nexport interface NatsEventTarget {\n /**\n * Subscribe to events of a specific type\n *\n * @param type - Event type (GraphQL subscription trigger)\n * @param listener - Callback function to invoke when event is received\n */\n addEventListener(type: string, listener: EventListener): void;\n\n /**\n * Unsubscribe from events of a specific type\n *\n * @param type - Event type (GraphQL subscription trigger)\n * @param listener - Callback function to remove\n */\n removeEventListener(type: string, listener: EventListener): void;\n\n /**\n * Publish an event to all subscribers\n *\n * @param event - Event to dispatch (must have 'type' and 'detail' properties)\n * @returns Always returns true (EventTarget interface requirement)\n */\n dispatchEvent(event: Event): boolean;\n\n /**\n * Close the NATS connection and cleanup resources\n * Should be called on application shutdown\n */\n close(): Promise<void>;\n\n /**\n * Check if the NATS connection is healthy\n */\n isHealthy(): boolean;\n}\n\n/**\n * Create NATS-based EventTarget for GraphQL Yoga Distributed PubSub\n *\n * This function creates an EventTarget implementation that uses NATS for\n * distributed publish-subscribe across multiple GraphQL server instances.\n *\n * @param options - NATS connection and configuration options\n * @returns Promise resolving to NatsEventTarget instance\n *\n * @example\n * ```typescript\n * // Basic usage\n * const eventTarget = await createNatsEventTarget({\n * natsUrl: 'nats://localhost:4222',\n * });\n *\n * const pubsub = createPubSub({ eventTarget });\n * ```\n *\n * @example\n * ```typescript\n * // With custom configuration\n * const eventTarget = await createNatsEventTarget({\n * natsUrl: ['nats://server1:4222', 'nats://server2:4222'],\n * connectionOptions: {\n * name: 'my-graphql-server',\n * maxReconnectAttempts: 10,\n * reconnectTimeWait: 1000,\n * },\n * subjectPrefix: 'myapp.graphql',\n * serializer: {\n * stringify: (data) => JSON.stringify(data),\n * parse: (msg) => JSON.parse(msg),\n * },\n * });\n * ```\n *\n * @throws {Error} If connection to NATS server fails\n */\nexport async function createNatsEventTarget(options: NatsEventTargetOptions): Promise<NatsEventTarget> {\n const {\n natsUrl,\n connectionOptions = {},\n serializer = {\n stringify: async (data: unknown): Promise<string> => JSON.stringify(data),\n parse: async (message: string): Promise<unknown> => JSON.parse(message),\n },\n subjectPrefix = 'graphql.pubsub',\n } = options;\n\n // NATS StringCodec for encoding/decoding messages\n const sc = StringCodec();\n\n // Default connection options\n const defaultConnectionOptions = {\n name: 'graphql-pubsub',\n maxReconnectAttempts: -1, // Infinite reconnects\n reconnectTimeWait: 2000, // 2 seconds\n pingInterval: 20000, // 20 seconds\n maxPingOut: 2,\n timeout: 20000, // 20 seconds\n };\n\n const mergedConnectionOptions = {\n ...defaultConnectionOptions,\n ...connectionOptions,\n };\n\n // Create connection manager config. Auth is sourced from\n // connectionOptions.user/pass first, then falls back to NATS_USER /\n // NATS_PASSWORD env vars. Required because the bun-bundled `nats`\n // 2.29.x client mis-parses URL-embedded credentials, so the URL must\n // be credential-free and auth must arrive as separate ConnectionOptions.\n const effectiveUser = (mergedConnectionOptions as { user?: string }).user ?? process.env['NATS_USER'];\n const effectivePass =\n (mergedConnectionOptions as { pass?: string; password?: string }).pass ??\n (mergedConnectionOptions as { pass?: string; password?: string }).password ??\n process.env['NATS_PASSWORD'];\n const connectionConfig: BaseQueueConfig = {\n type: 'nats',\n url: Array.isArray(natsUrl) ? (natsUrl[0] ?? 'nats://localhost:4222') : natsUrl,\n name: mergedConnectionOptions.name,\n user: effectiveUser,\n password: effectivePass,\n token: (mergedConnectionOptions as { token?: string }).token ?? process.env['NATS_TOKEN'],\n creds: (mergedConnectionOptions as { creds?: string }).creds ?? process.env['NATS_CREDS'],\n credsFile: (mergedConnectionOptions as { credsFile?: string }).credsFile ?? process.env['NATS_CREDS_FILE'],\n maxReconnectAttempts: mergedConnectionOptions.maxReconnectAttempts,\n reconnectTimeWait: mergedConnectionOptions.reconnectTimeWait,\n };\n\n // Connect to NATS using connection manager\n let connectionManager: NatsConnectionManager;\n let connection: NatsConnection;\n try {\n connectionManager = new NatsConnectionManager(connectionConfig);\n await connectionManager.connect();\n connection = connectionManager.getNatsConnection();\n\n logger.info('[NatsEventTarget] Connected to NATS', {\n url: connectionConfig.url,\n name: connectionConfig.name,\n });\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to connect to NATS', {\n error: error instanceof Error ? error.message : 'Unknown error',\n url: connectionConfig.url,\n });\n throw error;\n }\n\n // Track callbacks per event type\n // Map<eventType, Set<listener>>\n const callbacks = new Map<string, Set<EventListener>>();\n\n // Track NATS subscriptions per event type\n // Map<eventType, Subscription>\n const subscriptions = new Map<string, Subscription>();\n\n /**\n * Get NATS subject for an event type\n * Prefixes the event type with the configured subject prefix\n */\n const getSubject = (eventType: string): string => {\n return `${subjectPrefix}.${eventType}`;\n };\n\n /**\n * Subscribe to NATS subject for an event type\n * Creates a new NATS subscription if one doesn't exist\n */\n const subscribeToNats = (eventType: string): void => {\n // Check if already subscribed\n if (subscriptions.has(eventType)) {\n return;\n }\n\n const subject = getSubject(eventType);\n\n try {\n // Create NATS subscription\n const subscription = connection.subscribe(subject);\n\n // Store subscription\n subscriptions.set(eventType, subscription);\n\n logger.debug('[NatsEventTarget] Subscribed to NATS subject', {\n eventType,\n subject,\n });\n\n // Process messages asynchronously\n void (async (): Promise<void> => {\n try {\n for await (const msg of subscription) {\n try {\n // Decode and deserialize message\n const messageData = sc.decode(msg.data);\n const payload = await serializer.parse(messageData);\n\n // Get callbacks for this event type\n const eventCallbacks = callbacks.get(eventType);\n\n if (eventCallbacks && eventCallbacks.size > 0) {\n // Create CustomEvent with payload\n const event = new CustomEvent(eventType, {\n detail: payload,\n });\n\n // Dispatch to all registered callbacks\n for (const callback of Array.from(eventCallbacks)) {\n try {\n callback(event);\n } catch (callbackError) {\n logger.error('[NatsEventTarget] Error in event callback', {\n eventType,\n error: callbackError instanceof Error ? callbackError.message : 'Unknown error',\n });\n }\n }\n }\n } catch (messageError) {\n logger.error('[NatsEventTarget] Error processing NATS message', {\n eventType,\n subject,\n error: messageError instanceof Error ? messageError.message : 'Unknown error',\n });\n }\n }\n } catch (subscriptionError) {\n logger.error('[NatsEventTarget] Error in NATS subscription loop', {\n eventType,\n subject,\n error: subscriptionError instanceof Error ? subscriptionError.message : 'Unknown error',\n });\n }\n })();\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to subscribe to NATS subject', {\n eventType,\n subject,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n };\n\n /**\n * Unsubscribe from NATS subject for an event type\n * Only unsubscribes if no more callbacks are registered\n */\n const unsubscribeFromNats = (eventType: string): void => {\n const subscription = subscriptions.get(eventType);\n\n if (subscription) {\n try {\n subscription.unsubscribe();\n subscriptions.delete(eventType);\n\n logger.debug('[NatsEventTarget] Unsubscribed from NATS subject', {\n eventType,\n subject: getSubject(eventType),\n });\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to unsubscribe from NATS subject', {\n eventType,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n };\n\n /**\n * EventTarget Implementation\n */\n const eventTarget: NatsEventTarget = {\n /**\n * Add event listener (subscribe)\n */\n addEventListener(type: string, listener: EventListener): void {\n try {\n // Get or create callback set for this event type\n let eventCallbacks = callbacks.get(type);\n\n if (!eventCallbacks) {\n eventCallbacks = new Set();\n callbacks.set(type, eventCallbacks);\n\n // First listener for this event type - subscribe to NATS\n subscribeToNats(type);\n }\n\n // Add listener to set\n eventCallbacks.add(listener);\n\n logger.debug('[NatsEventTarget] Event listener added', {\n eventType: type,\n listenerCount: eventCallbacks.size,\n });\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to add event listener', {\n eventType: type,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n\n /**\n * Remove event listener (unsubscribe)\n */\n removeEventListener(type: string, listener: EventListener): void {\n try {\n const eventCallbacks = callbacks.get(type);\n\n if (eventCallbacks) {\n // Remove listener from set\n eventCallbacks.delete(listener);\n\n const remainingListeners = eventCallbacks.size;\n\n logger.debug('[NatsEventTarget] Event listener removed', {\n eventType: type,\n remainingListeners,\n });\n\n // If no more listeners, unsubscribe from NATS and cleanup\n if (remainingListeners === 0) {\n callbacks.delete(type);\n unsubscribeFromNats(type);\n }\n }\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to remove event listener', {\n eventType: type,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n\n /**\n * Dispatch event (publish)\n */\n dispatchEvent(event: Event): boolean {\n try {\n const eventType = event.type;\n const subject = getSubject(eventType);\n\n // Extract payload from CustomEvent detail or use event itself\n const payload = 'detail' in event ? (event as CustomEvent).detail : event;\n\n // Serialize payload (fire and forget for async serializers)\n void (async (): Promise<void> => {\n try {\n const message = await serializer.stringify(payload);\n\n // Encode and publish to NATS\n const data = sc.encode(message);\n connection.publish(subject, data);\n\n logger.debug('[NatsEventTarget] Event dispatched to NATS', {\n eventType,\n subject,\n });\n } catch (serializeError) {\n logger.error('[NatsEventTarget] Failed to serialize event for dispatch', {\n eventType,\n error: serializeError instanceof Error ? serializeError.message : 'Unknown error',\n });\n }\n })();\n\n return true;\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to dispatch event', {\n eventType: event.type,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n\n /**\n * Close NATS connection and cleanup\n */\n async close(): Promise<void> {\n try {\n logger.info('[NatsEventTarget] Closing NATS connection...');\n\n // Unsubscribe from all subjects\n for (const [eventType, subscription] of Array.from(subscriptions.entries())) {\n try {\n subscription.unsubscribe();\n logger.debug('[NatsEventTarget] Unsubscribed from subject', {\n eventType,\n });\n } catch (error) {\n logger.error('[NatsEventTarget] Error unsubscribing from subject', {\n eventType,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n // Clear all subscriptions and callbacks\n subscriptions.clear();\n callbacks.clear();\n\n // Disconnect using connection manager\n await connectionManager.disconnect();\n\n logger.info('[NatsEventTarget] NATS connection closed successfully');\n } catch (error) {\n logger.error('[NatsEventTarget] Failed to close NATS connection', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n\n /**\n * Check if connection is healthy\n */\n isHealthy(): boolean {\n return !connection.isClosed();\n },\n };\n\n return eventTarget;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event-queue/types/config.ts"],"names":["QueueType"],"mappings":";AAOO,IAAKA,SAAAA,6BAAAA,UAAAA,EAAAA;;;;;AAAAA,EAAAA,OAAAA,UAAAA","file":"chunk-VOFKF27Q.js","sourcesContent":["/**\n * Event Queue Configuration Types\n */\n\n/**\n * Queue type enum\n */\nexport enum QueueType {\n NATS = 'nats',\n RABBITMQ = 'rabbitmq',\n KAFKA = 'kafka',\n SQS = 'sqs',\n}\n\n/**\n * Base configuration for event queue\n */\nexport interface BaseQueueConfig {\n /** Queue type */\n type: QueueType | string;\n /** Connection URL */\n url: string;\n /** Optional username */\n user?: string;\n /** Optional password */\n password?: string;\n /** Optional auth token */\n token?: string;\n /** Optional NATS credentials file contents (JWT + NKEY seed) */\n creds?: string;\n /** Optional path to a NATS credentials file */\n credsFile?: string;\n /** Maximum reconnection attempts (-1 for infinite) */\n maxReconnectAttempts?: number;\n /** Time to wait between reconnection attempts (ms) */\n reconnectTimeWait?: number;\n /** Connection timeout (ms) */\n connectionTimeout?: number;\n /** Connection name/identifier */\n name?: string;\n}\n\n/**\n * Publisher-specific configuration\n */\nexport interface PublisherConfig extends BaseQueueConfig {\n /** Default message TTL (ms) */\n defaultTTL?: number;\n /** Enable message deduplication */\n enableDeduplication?: boolean;\n /** Default priority for messages */\n defaultPriority?: 'low' | 'normal' | 'high';\n}\n\n/**\n * Consumer-specific configuration\n */\nexport interface ConsumerConfig extends Partial<BaseQueueConfig> {\n /** Stream name to consume from */\n stream: string;\n /** Consumer name (durable) */\n consumer: string;\n /** Subject filter pattern */\n filterSubject?: string;\n /** Maximum concurrent message processing */\n maxConcurrent?: number;\n /** Maximum delivery attempts */\n maxDeliver?: number;\n /** Acknowledgment wait time (nanoseconds) */\n ackWait?: number;\n /** Acknowledgment policy */\n ackPolicy?: 'explicit' | 'all' | 'none';\n /** Delivery policy */\n deliverPolicy?: 'all' | 'last' | 'new' | 'byStartSequence' | 'byStartTime';\n /** Maximum pending acknowledgments */\n maxAckPending?: number;\n}\n\n/**\n * Health check result\n */\nexport interface EventQueueHealthCheckResult {\n /** Overall health status */\n status: 'healthy' | 'unhealthy' | 'degraded';\n /** Timestamp of health check */\n timestamp: string;\n /** Connection status */\n connected?: boolean;\n /** Latency in milliseconds */\n latencyMs?: number;\n /** Additional details */\n details?: Record<string, unknown>;\n /** Error message if unhealthy */\n error?: string;\n}\n\n/**\n * Statistics\n */\nexport interface QueueStatistics {\n /** Total messages published */\n messagesPublished?: number;\n /** Total messages consumed */\n messagesConsumed?: number;\n /** Messages currently pending */\n messagesPending?: number;\n /** Messages in queue */\n queueSize?: number;\n /** Failed message count */\n messagesFailed?: number;\n /** Active consumers count */\n activeConsumers?: number;\n /** Active publishers count */\n activePublishers?: number;\n /** Average processing time (ms) */\n avgProcessingTimeMs?: number;\n /** Last activity timestamp */\n lastActivity?: string | null;\n /** Custom metrics */\n details?: Record<string, unknown>;\n}\n"]}
|