@vritti/api-sdk 0.3.16 → 0.4.0
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/auth.cjs +178 -152
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +25 -43
- package/dist/auth.d.ts +25 -43
- package/dist/auth.js +101 -72
- package/dist/auth.js.map +1 -1
- package/dist/data-table.cjs +4 -5
- package/dist/data-table.cjs.map +1 -1
- package/dist/data-table.js +4 -5
- package/dist/data-table.js.map +1 -1
- package/dist/index.d.cts +15 -9
- package/dist/index.d.ts +15 -9
- package/dist/nats.cjs +30 -36
- package/dist/nats.cjs.map +1 -1
- package/dist/nats.d.cts +20 -9
- package/dist/nats.d.ts +20 -9
- package/dist/nats.js +30 -36
- package/dist/nats.js.map +1 -1
- package/dist/root.cjs +15 -4
- package/dist/root.cjs.map +1 -1
- package/dist/root.js +15 -4
- package/dist/root.js.map +1 -1
- package/package.json +1 -1
package/dist/nats.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nats.ts","../src/filters/rpc-problem-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/nats/decorators/nats-headers.decorator.ts","../src/nats/nats-context.ts","../src/nats/nats-client.module.ts","../src/nats/constants.ts","../src/nats/nats-client.service.ts","../src/context/resolve-request.ts","../src/nats/nats-microservice-client.service.ts"],"sourcesContent":["// NATS + microservice exports — kept out of the main barrel so non-NATS consumers never load @nestjs/microservices\n\n// RPC exception filter (microservice side) — moved out of the main filters barrel\nexport { RpcProblemExceptionFilter } from './filters/rpc-problem-exception.filter';\nexport { RpcSiteCurrencyCode, RpcSiteId, RpcNatsHeaders } from './nats/decorators/nats-headers.decorator';\nexport type {\n ContextResolverFn,\n NatsHeaders,\n NatsMicroserviceModuleAsyncOptions,\n NatsRootModuleAsyncOptions,\n NatsServiceConfig,\n} from './nats/index';\nexport { NatsClientModule } from './nats/nats-client.module';\nexport { NatsClientService } from './nats/nats-client.service';\nexport { NATS_HEADER_KEYS, parseNatsHeaders } from './nats/nats-context';\nexport { NatsMicroserviceClientService } from './nats/nats-microservice-client.service';\n","import { type ArgumentsHost, Catch, type HttpException, HttpStatus, Logger } from '@nestjs/common';\nimport { RpcException } from '@nestjs/microservices';\nimport { type Observable, throwError } from 'rxjs';\nimport { tryTranslatePgError } from './pg-error.translator';\n\ninterface FieldError {\n field: string;\n message: string;\n}\n\ninterface ProblemPayload {\n type: string;\n label?: string;\n detail: string;\n message: string;\n errors: FieldError[];\n status: number;\n statusCode: number;\n}\n\n@Catch()\nexport class RpcProblemExceptionFilter {\n private readonly logger = new Logger(RpcProblemExceptionFilter.name);\n\n catch(exception: unknown, _host: ArgumentsHost): Observable<never> {\n // Translate raw Postgres errors into a ConflictException before the rest of the filter handles them.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n if (exception instanceof RpcException) {\n return throwError(() => exception.getError());\n }\n\n if (this.isHttpException(exception)) {\n const status = exception.getStatus();\n const response = exception.getResponse();\n const payload = this.toProblemPayload(response, status);\n // Log 4xx/5xx so the microservice terminal shows what actually failed (previously silent)\n const log = status >= HttpStatus.INTERNAL_SERVER_ERROR ? this.logger.error : this.logger.warn;\n log.call(this.logger, `RPC ${status}: ${payload.detail}`);\n return throwError(() => payload);\n }\n\n if (exception instanceof Error) {\n const cause = (exception as { cause?: unknown }).cause;\n const causeMessage = cause instanceof Error ? cause.message : undefined;\n const causeStack = cause instanceof Error ? cause.stack : undefined;\n this.logger.error(causeMessage ?? exception.message, causeStack ?? exception.stack);\n if (cause && cause !== exception) {\n this.logger.error(`Wrapped by: ${exception.message}`);\n }\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: causeMessage ?? exception.message,\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n this.logger.error(`Unhandled non-error exception: ${JSON.stringify(exception)}`);\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: 'An unexpected error occurred',\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n private toProblemPayload(response: unknown, status: number): ProblemPayload {\n if (typeof response === 'string') {\n return {\n type: 'about:blank',\n detail: response,\n message: response,\n errors: [],\n status,\n statusCode: status,\n };\n }\n\n const obj = (response ?? {}) as Record<string, unknown>;\n // Prefer RFC 9457 `detail`, then Nest/@nestjs-common's `message` (string or class-validator array),\n // so exceptions thrown as `@nestjs/common` errors still surface their real message across NATS.\n const detail =\n typeof obj.detail === 'string'\n ? obj.detail\n : typeof obj.message === 'string'\n ? obj.message\n : Array.isArray(obj.message)\n ? obj.message.join(', ')\n : 'Request failed';\n return {\n type: typeof obj.type === 'string' ? obj.type : 'about:blank',\n label: typeof obj.label === 'string' ? obj.label : undefined,\n detail,\n message: detail,\n errors: Array.isArray(obj.errors) ? (obj.errors as FieldError[]) : [],\n status,\n statusCode: status,\n };\n }\n\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { createParamDecorator, type ExecutionContext, InternalServerErrorException } from '@nestjs/common';\nimport { NatsContext } from '@nestjs/microservices';\nimport { parseNatsHeaders } from '../nats-context';\n\n// Extracts parsed NatsContext from NATS message headers\nexport const RpcNatsHeaders = createParamDecorator((_data: unknown, ctx: ExecutionContext) => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n return parseNatsHeaders(rpcCtx.getHeaders());\n});\n\n// Extracts siteId from NATS headers — throws if missing or empty\nexport const RpcSiteId = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteId) throw new InternalServerErrorException('Missing siteId in NATS headers.');\n return headers.siteId;\n});\n\n// Extracts siteCurrencyCode from NATS headers — throws if missing or empty\nexport const RpcSiteCurrencyCode = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteCurrencyCode) throw new InternalServerErrorException('Missing siteCurrencyCode in NATS headers.');\n return headers.siteCurrencyCode;\n});\n","export interface NatsHeaders {\n orgId: string;\n userId: string;\n siteId: string;\n legalEntityId: string;\n siteGroupId: string;\n siteTimezone: string;\n siteCurrencyCode: string;\n}\n\n// Header keys for NATS context transport\nexport const NATS_HEADER_KEYS = {\n ORG_ID: 'x-org-id',\n USER_ID: 'x-user-id',\n SITE_ID: 'x-site-id',\n LE_ID: 'x-le-id',\n SITE_GROUP_ID: 'x-sg-id',\n SITE_TIMEZONE: 'x-site-timezone',\n SITE_CURRENCY_CODE: 'x-site-currency-code',\n} as const;\n\n// Reads a header value from either a plain object or a NATS MsgHdrsImpl\nfunction getHeader(headers: unknown, key: string): string | undefined {\n if (!headers) return undefined;\n // MsgHdrsImpl uses .get(), plain objects use bracket access\n if (typeof (headers as { get?: unknown }).get === 'function') {\n const val = (headers as { get(key: string): string[] }).get(key);\n return Array.isArray(val) ? val[0] : (val as string | undefined);\n }\n return (headers as Record<string, string>)[key];\n}\n\n// Parses NATS message headers into a NatsHeaders object — siteId is optional (empty for org-level contexts)\nexport function parseNatsHeaders(headers: unknown): NatsHeaders | null {\n if (!headers) return null;\n\n const orgId = getHeader(headers, NATS_HEADER_KEYS.ORG_ID);\n const userId = getHeader(headers, NATS_HEADER_KEYS.USER_ID);\n\n if (!orgId || !userId) return null;\n\n return {\n orgId,\n userId,\n siteId: getHeader(headers, NATS_HEADER_KEYS.SITE_ID) || '',\n legalEntityId: getHeader(headers, NATS_HEADER_KEYS.LE_ID) || '',\n siteGroupId: getHeader(headers, NATS_HEADER_KEYS.SITE_GROUP_ID) || '',\n siteTimezone: getHeader(headers, NATS_HEADER_KEYS.SITE_TIMEZONE) || 'UTC',\n siteCurrencyCode: getHeader(headers, NATS_HEADER_KEYS.SITE_CURRENCY_CODE) || '',\n };\n}\n","import { type DynamicModule, Global, Logger, Module, type OnModuleDestroy, type Provider } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { ClientProxyFactory, Transport } from '@nestjs/microservices';\nimport { NATS_CONTEXT_RESOLVER, NATS_MODULE_OPTIONS } from './constants';\nimport type {\n NatsMicroserviceModuleAsyncOptions,\n NatsModuleBaseOptions,\n NatsRootModuleAsyncOptions,\n NatsRootModuleOptions,\n} from './nats-client.interfaces';\nimport { NATS_CLIENTS, NatsClientService } from './nats-client.service';\nimport { NATS_MS_CLIENTS, NatsMicroserviceClientService } from './nats-microservice-client.service';\n\nconst NATS_MS_OPTIONS = Symbol('NATS_MS_OPTIONS');\n\n@Global()\n@Module({})\nexport class NatsClientModule implements OnModuleDestroy {\n private static readonly logger = new Logger(NatsClientModule.name);\n private static allClients: ClientProxy[] = [];\n\n async onModuleDestroy() {\n await Promise.all(NatsClientModule.allClients.map((c) => c.close()));\n NatsClientModule.allClients = [];\n }\n\n // Builds a Map of named NATS ClientProxy instances\n private static buildClients(options: NatsModuleBaseOptions, natsUrl: string): Map<string, ClientProxy> {\n const clients = new Map<string, ClientProxy>();\n\n for (const svc of options.services) {\n const proxy = ClientProxyFactory.create({\n transport: Transport.NATS,\n options: { servers: [natsUrl] },\n });\n clients.set(svc.name, proxy);\n NatsClientModule.allClients.push(proxy);\n NatsClientModule.logger.log(`Registered NATS client: ${svc.name} → ${natsUrl}`);\n }\n\n return clients;\n }\n\n // Gateway mode — request-scoped, resolves context from sessionInfo via callback\n static forRoot(asyncOptions: NatsRootModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const resolverProvider: Provider = {\n provide: NATS_CONTEXT_RESOLVER,\n useFactory: (options: NatsRootModuleOptions) => options.contextResolver,\n inject: [NATS_MODULE_OPTIONS],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_CLIENTS,\n useFactory: (options: NatsRootModuleOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MODULE_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, resolverProvider, clientsProvider, NatsClientService],\n exports: [NatsClientService],\n };\n }\n\n // Microservice mode — singleton, forwards context from incoming NATS payload\n static forMicroservice(asyncOptions: NatsMicroserviceModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MS_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_MS_CLIENTS,\n useFactory: (options: NatsModuleBaseOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MS_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, clientsProvider, NatsMicroserviceClientService],\n exports: [NatsMicroserviceClientService],\n };\n }\n}\n","export const NATS_MODULE_OPTIONS = Symbol('NATS_MODULE_OPTIONS');\nexport const NATS_CONTEXT_RESOLVER = Symbol('NATS_CONTEXT_RESOLVER');\n","// Pulls the fastify module augmentation into this entry's dts graph — tsup builds each entry in isolation\nimport '../types/fastify-augmentation';\nimport { Inject, Injectable, Scope } from '@nestjs/common';\nimport { REQUEST } from '@nestjs/core';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport type { FastifyRequest } from 'fastify';\nimport { headers as natsHeaders } from 'nats';\nimport { resolveInjectedRequest } from '../context/resolve-request';\nimport { NATS_CONTEXT_RESOLVER } from './constants';\nimport type { ContextResolverFn } from './nats-client.interfaces';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_CLIENTS = Symbol('NATS_CLIENTS');\n\n@Injectable({ scope: Scope.REQUEST })\nexport class NatsClientService {\n private cachedContext: NatsHeaders | null = null;\n\n constructor(\n @Inject(REQUEST) private readonly injectedRequest: FastifyRequest,\n @Inject(NATS_CONTEXT_RESOLVER) private readonly contextResolver: ContextResolverFn,\n @Inject(NATS_CLIENTS) private readonly clients: Map<string, ClientProxy>,\n ) {}\n\n // Unwraps the GraphQL { req, reply } context wrapper so sessionInfo is visible across both transports\n private get request(): FastifyRequest {\n return resolveInjectedRequest(this.injectedRequest);\n }\n\n // Sends a message to a named microservice with NatsHeaders as NATS headers\n async send<T>(service: string, cmd: string, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n if (!this.cachedContext) {\n const sessionInfo = this.request.sessionInfo;\n if (!sessionInfo) {\n throw new Error('No sessionInfo on request — is the auth guard active?');\n }\n this.cachedContext = await this.contextResolver(sessionInfo);\n }\n\n const headers = contextToHeaders(this.cachedContext);\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n\n// Converts NatsHeaders to a NATS MsgHdrs object for NATS transport\nfunction contextToHeaders(ctx: NatsHeaders): import('nats').MsgHdrs {\n const hdrs = natsHeaders();\n hdrs.set(NATS_HEADER_KEYS.ORG_ID, ctx.orgId);\n hdrs.set(NATS_HEADER_KEYS.USER_ID, ctx.userId);\n if (ctx.siteId) hdrs.set(NATS_HEADER_KEYS.SITE_ID, ctx.siteId);\n if (ctx.legalEntityId) hdrs.set(NATS_HEADER_KEYS.LE_ID, ctx.legalEntityId);\n if (ctx.siteGroupId) hdrs.set(NATS_HEADER_KEYS.SITE_GROUP_ID, ctx.siteGroupId);\n if (ctx.siteTimezone) hdrs.set(NATS_HEADER_KEYS.SITE_TIMEZONE, ctx.siteTimezone);\n if (ctx.siteCurrencyCode) hdrs.set(NATS_HEADER_KEYS.SITE_CURRENCY_CODE, ctx.siteCurrencyCode);\n return hdrs;\n}\n","import type { FastifyRequest } from 'fastify';\n\n// Unwraps the @Inject(REQUEST) value to the real Fastify request (GraphQL injects a { req, reply } context).\nexport function resolveInjectedRequest(injected: FastifyRequest): FastifyRequest {\n const candidate = injected as unknown as { headers?: unknown; req?: FastifyRequest };\n if (candidate && candidate.headers === undefined && candidate.req) {\n return candidate.req;\n }\n return injected;\n}\n","import { Inject, Injectable } from '@nestjs/common';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_MS_CLIENTS = Symbol('NATS_MS_CLIENTS');\n\n@Injectable()\nexport class NatsMicroserviceClientService {\n constructor(@Inject(NATS_MS_CLIENTS) private readonly clients: Map<string, ClientProxy>) {}\n\n // Forwards a message to another microservice with NatsHeaders\n async send<T>(service: string, cmd: string, natsHeaders: NatsHeaders, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n const headers: Record<string, string> = {\n [NATS_HEADER_KEYS.ORG_ID]: natsHeaders.orgId,\n [NATS_HEADER_KEYS.USER_ID]: natsHeaders.userId,\n [NATS_HEADER_KEYS.SITE_ID]: natsHeaders.siteId,\n [NATS_HEADER_KEYS.SITE_TIMEZONE]: natsHeaders.siteTimezone,\n };\n\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n"],"mappings":"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","names":["import_common","import_common","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","RpcProblemExceptionFilter","logger","Logger","name","catch","exception","_host","translatedPgError","tryTranslatePgError","RpcException","throwError","getError","isHttpException","status","getStatus","response","getResponse","payload","toProblemPayload","log","HttpStatus","INTERNAL_SERVER_ERROR","error","warn","call","detail","Error","cause","causeMessage","message","undefined","causeStack","stack","type","errors","JSON","stringify","statusCode","obj","Array","isArray","join","label","import_common","NATS_HEADER_KEYS","ORG_ID","USER_ID","SITE_ID","LE_ID","SITE_GROUP_ID","SITE_TIMEZONE","SITE_CURRENCY_CODE","getHeader","headers","key","undefined","get","val","Array","isArray","parseNatsHeaders","orgId","userId","siteId","legalEntityId","siteGroupId","siteTimezone","siteCurrencyCode","RpcNatsHeaders","createParamDecorator","_data","ctx","rpcCtx","switchToRpc","getContext","parseNatsHeaders","getHeaders","RpcSiteId","headers","siteId","InternalServerErrorException","RpcSiteCurrencyCode","siteCurrencyCode","import_common","import_microservices","NATS_MODULE_OPTIONS","Symbol","NATS_CONTEXT_RESOLVER","import_common","import_microservices","resolveInjectedRequest","injected","candidate","headers","undefined","req","NATS_CLIENTS","Symbol","NatsClientService","cachedContext","injectedRequest","contextResolver","clients","request","resolveInjectedRequest","send","service","cmd","data","client","get","Error","keys","join","sessionInfo","headers","contextToHeaders","record","NatsRecordBuilder","setHeaders","build","toPromise","scope","Scope","REQUEST","ctx","hdrs","natsHeaders","set","NATS_HEADER_KEYS","ORG_ID","orgId","USER_ID","userId","siteId","SITE_ID","legalEntityId","LE_ID","siteGroupId","SITE_GROUP_ID","siteTimezone","SITE_TIMEZONE","siteCurrencyCode","SITE_CURRENCY_CODE","import_common","import_microservices","NATS_MS_CLIENTS","Symbol","NatsMicroserviceClientService","clients","send","service","cmd","natsHeaders","data","client","get","Error","keys","join","headers","NATS_HEADER_KEYS","ORG_ID","orgId","USER_ID","userId","SITE_ID","siteId","SITE_TIMEZONE","siteTimezone","record","NatsRecordBuilder","setHeaders","build","toPromise","NATS_MS_OPTIONS","Symbol","NatsClientModule","logger","Logger","name","allClients","onModuleDestroy","Promise","all","map","c","close","buildClients","options","natsUrl","clients","Map","svc","services","proxy","ClientProxyFactory","create","transport","Transport","NATS","servers","set","push","log","forRoot","asyncOptions","optionsProvider","provide","NATS_MODULE_OPTIONS","useFactory","inject","resolverProvider","NATS_CONTEXT_RESOLVER","contextResolver","clientsProvider","NATS_CLIENTS","config","get","ConfigService","module","imports","ConfigModule","providers","NatsClientService","exports","forMicroservice","NATS_MS_CLIENTS","NatsMicroserviceClientService"]}
|
|
1
|
+
{"version":3,"sources":["../src/nats.ts","../src/filters/rpc-problem-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/nats/decorators/nats-headers.decorator.ts","../src/nats/nats-context.ts","../src/nats/nats-client.module.ts","../src/nats/constants.ts","../src/nats/nats-client.service.ts","../src/context/resolve-request.ts","../src/nats/nats-microservice-client.service.ts"],"sourcesContent":["// NATS + microservice exports — kept out of the main barrel so non-NATS consumers never load @nestjs/microservices\n\n// RPC exception filter (microservice side) — moved out of the main filters barrel\nexport { RpcProblemExceptionFilter } from './filters/rpc-problem-exception.filter';\nexport { RpcSiteCurrencyCode, RpcSiteId, RpcNatsHeaders } from './nats/decorators/nats-headers.decorator';\nexport type {\n ContextResolverFn,\n NatsHeaders,\n NatsMicroserviceModuleAsyncOptions,\n NatsRootModuleAsyncOptions,\n NatsServiceConfig,\n} from './nats/index';\nexport { NatsClientModule } from './nats/nats-client.module';\nexport { NatsClientService } from './nats/nats-client.service';\nexport { NATS_HEADER_KEYS, parseNatsHeaders } from './nats/nats-context';\nexport { NatsMicroserviceClientService } from './nats/nats-microservice-client.service';\n","import { type ArgumentsHost, Catch, type HttpException, HttpStatus, Logger } from '@nestjs/common';\nimport { RpcException } from '@nestjs/microservices';\nimport { type Observable, throwError } from 'rxjs';\nimport { tryTranslatePgError } from './pg-error.translator';\n\ninterface FieldError {\n field: string;\n message: string;\n}\n\ninterface ProblemPayload {\n type: string;\n label?: string;\n detail: string;\n message: string;\n errors: FieldError[];\n status: number;\n statusCode: number;\n}\n\n@Catch()\nexport class RpcProblemExceptionFilter {\n private readonly logger = new Logger(RpcProblemExceptionFilter.name);\n\n catch(exception: unknown, _host: ArgumentsHost): Observable<never> {\n // Translate raw Postgres errors into a ConflictException before the rest of the filter handles them.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n if (exception instanceof RpcException) {\n return throwError(() => exception.getError());\n }\n\n if (this.isHttpException(exception)) {\n const status = exception.getStatus();\n const response = exception.getResponse();\n const payload = this.toProblemPayload(response, status);\n // Log 4xx/5xx so the microservice terminal shows what actually failed (previously silent)\n const log = status >= HttpStatus.INTERNAL_SERVER_ERROR ? this.logger.error : this.logger.warn;\n log.call(this.logger, `RPC ${status}: ${payload.detail}`);\n return throwError(() => payload);\n }\n\n if (exception instanceof Error) {\n const cause = (exception as { cause?: unknown }).cause;\n const causeMessage = cause instanceof Error ? cause.message : undefined;\n const causeStack = cause instanceof Error ? cause.stack : undefined;\n this.logger.error(causeMessage ?? exception.message, causeStack ?? exception.stack);\n if (cause && cause !== exception) {\n this.logger.error(`Wrapped by: ${exception.message}`);\n }\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: causeMessage ?? exception.message,\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n this.logger.error(`Unhandled non-error exception: ${JSON.stringify(exception)}`);\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: 'An unexpected error occurred',\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n private toProblemPayload(response: unknown, status: number): ProblemPayload {\n if (typeof response === 'string') {\n return {\n type: 'about:blank',\n detail: response,\n message: response,\n errors: [],\n status,\n statusCode: status,\n };\n }\n\n const obj = (response ?? {}) as Record<string, unknown>;\n // Prefer RFC 9457 `detail`, then Nest/@nestjs-common's `message` (string or class-validator array),\n // so exceptions thrown as `@nestjs/common` errors still surface their real message across NATS.\n const detail =\n typeof obj.detail === 'string'\n ? obj.detail\n : typeof obj.message === 'string'\n ? obj.message\n : Array.isArray(obj.message)\n ? obj.message.join(', ')\n : 'Request failed';\n return {\n type: typeof obj.type === 'string' ? obj.type : 'about:blank',\n label: typeof obj.label === 'string' ? obj.label : undefined,\n detail,\n message: detail,\n errors: Array.isArray(obj.errors) ? (obj.errors as FieldError[]) : [],\n status,\n statusCode: status,\n };\n }\n\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { createParamDecorator, type ExecutionContext, InternalServerErrorException } from '@nestjs/common';\nimport { NatsContext } from '@nestjs/microservices';\nimport { parseNatsHeaders } from '../nats-context';\n\n// Extracts parsed NatsContext from NATS message headers\nexport const RpcNatsHeaders = createParamDecorator((_data: unknown, ctx: ExecutionContext) => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n return parseNatsHeaders(rpcCtx.getHeaders());\n});\n\n// Extracts siteId from NATS headers — throws if missing or empty\nexport const RpcSiteId = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteId) throw new InternalServerErrorException('Missing siteId in NATS headers.');\n return headers.siteId;\n});\n\n// Extracts siteCurrencyCode from NATS headers — throws if missing or empty\nexport const RpcSiteCurrencyCode = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteCurrencyCode) throw new InternalServerErrorException('Missing siteCurrencyCode in NATS headers.');\n return headers.siteCurrencyCode;\n});\n","export interface NatsHeaders {\n orgId: string;\n userId: string;\n siteId: string;\n legalEntityId: string;\n siteGroupId: string;\n siteTimezone: string;\n siteCurrencyCode: string;\n}\n\n// The single source of truth for context transport, both directions. Adding a field means\n// adding one entry here plus one on NatsHeaders — encode and parse both pick it up.\nexport const NATS_HEADER_KEYS = {\n orgId: 'x-org-id',\n userId: 'x-user-id',\n siteId: 'x-site-id',\n legalEntityId: 'x-le-id',\n siteGroupId: 'x-sg-id',\n siteTimezone: 'x-site-timezone',\n siteCurrencyCode: 'x-site-currency-code',\n} as const satisfies Record<keyof NatsHeaders, string>;\n\n// Applied when a header is absent, so a missing optional field lands on the same value the\n// producing side would have sent for \"not set\"\nconst HEADER_FALLBACKS: Partial<Record<keyof NatsHeaders, string>> = {\n siteTimezone: 'UTC',\n};\n\n// Reads a header value from either a plain object or a NATS MsgHdrsImpl\nfunction getHeader(headers: unknown, key: string): string | undefined {\n if (!headers) return undefined;\n // MsgHdrsImpl uses .get(), plain objects use bracket access\n if (typeof (headers as { get?: unknown }).get === 'function') {\n const val = (headers as { get(key: string): string[] }).get(key);\n return Array.isArray(val) ? val[0] : (val as string | undefined);\n }\n return (headers as Record<string, string>)[key];\n}\n\n/**\n * Parses NATS message headers into a NatsHeaders object.\n *\n * Only `orgId` is required. It is what scopes every row the receiving service will read, so\n * without it there is no safe way to run — the caller returns null and the interceptor decides.\n *\n * `userId` is deliberately NOT required. A control-plane call has no user behind it, and an\n * earlier version rejected the whole context when it was blank — which meant the receiving\n * service skipped RLS entirely, ran with `app.org_id` unset, and matched no rows. Losing the\n * tenant because there was no user is a far worse failure than an empty acting principal.\n */\nexport function parseNatsHeaders(headers: unknown): NatsHeaders | null {\n if (!headers) return null;\n\n const orgId = getHeader(headers, NATS_HEADER_KEYS.orgId);\n if (!orgId) return null;\n\n const parsed = {} as NatsHeaders;\n for (const [field, key] of Object.entries(NATS_HEADER_KEYS) as [keyof NatsHeaders, string][]) {\n parsed[field] = getHeader(headers, key) || HEADER_FALLBACKS[field] || '';\n }\n return parsed;\n}\n","import { type DynamicModule, Global, Logger, Module, type OnModuleDestroy, type Provider } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { ClientProxyFactory, Transport } from '@nestjs/microservices';\nimport { NATS_CONTEXT_RESOLVER, NATS_MODULE_OPTIONS } from './constants';\nimport type {\n NatsMicroserviceModuleAsyncOptions,\n NatsModuleBaseOptions,\n NatsRootModuleAsyncOptions,\n NatsRootModuleOptions,\n} from './nats-client.interfaces';\nimport { NATS_CLIENTS, NatsClientService } from './nats-client.service';\nimport { NATS_MS_CLIENTS, NatsMicroserviceClientService } from './nats-microservice-client.service';\n\nconst NATS_MS_OPTIONS = Symbol('NATS_MS_OPTIONS');\n\n@Global()\n@Module({})\nexport class NatsClientModule implements OnModuleDestroy {\n private static readonly logger = new Logger(NatsClientModule.name);\n private static allClients: ClientProxy[] = [];\n\n async onModuleDestroy() {\n await Promise.all(NatsClientModule.allClients.map((c) => c.close()));\n NatsClientModule.allClients = [];\n }\n\n // Builds a Map of named NATS ClientProxy instances\n private static buildClients(options: NatsModuleBaseOptions, natsUrl: string): Map<string, ClientProxy> {\n const clients = new Map<string, ClientProxy>();\n\n for (const svc of options.services) {\n const proxy = ClientProxyFactory.create({\n transport: Transport.NATS,\n options: { servers: [natsUrl] },\n });\n clients.set(svc.name, proxy);\n NatsClientModule.allClients.push(proxy);\n NatsClientModule.logger.log(`Registered NATS client: ${svc.name} → ${natsUrl}`);\n }\n\n return clients;\n }\n\n // Gateway mode — request-scoped, resolves context from the request via callback\n static forRoot(asyncOptions: NatsRootModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const resolverProvider: Provider = {\n provide: NATS_CONTEXT_RESOLVER,\n useFactory: (options: NatsRootModuleOptions) => options.contextResolver,\n inject: [NATS_MODULE_OPTIONS],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_CLIENTS,\n useFactory: (options: NatsRootModuleOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MODULE_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, resolverProvider, clientsProvider, NatsClientService],\n exports: [NatsClientService],\n };\n }\n\n // Microservice mode — singleton, forwards context from incoming NATS payload\n static forMicroservice(asyncOptions: NatsMicroserviceModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MS_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_MS_CLIENTS,\n useFactory: (options: NatsModuleBaseOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MS_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, clientsProvider, NatsMicroserviceClientService],\n exports: [NatsMicroserviceClientService],\n };\n }\n}\n","export const NATS_MODULE_OPTIONS = Symbol('NATS_MODULE_OPTIONS');\nexport const NATS_CONTEXT_RESOLVER = Symbol('NATS_CONTEXT_RESOLVER');\n","// Pulls the fastify module augmentation into this entry's dts graph — tsup builds each entry in isolation\nimport '../types/fastify-augmentation';\nimport { Inject, Injectable, Scope } from '@nestjs/common';\nimport { REQUEST } from '@nestjs/core';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport type { FastifyRequest } from 'fastify';\nimport { headers as natsHeaders } from 'nats';\nimport { resolveInjectedRequest } from '../context/resolve-request';\nimport { NATS_CONTEXT_RESOLVER } from './constants';\nimport type { ContextResolverFn } from './nats-client.interfaces';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_CLIENTS = Symbol('NATS_CLIENTS');\n\n@Injectable({ scope: Scope.REQUEST })\nexport class NatsClientService {\n private cachedContext: NatsHeaders | null = null;\n\n constructor(\n @Inject(REQUEST) private readonly injectedRequest: FastifyRequest,\n @Inject(NATS_CONTEXT_RESOLVER) private readonly contextResolver: ContextResolverFn,\n @Inject(NATS_CLIENTS) private readonly clients: Map<string, ClientProxy>,\n ) {}\n\n // Unwraps the GraphQL { req, reply } context wrapper so auth is visible across both transports\n private get request(): FastifyRequest {\n return resolveInjectedRequest(this.injectedRequest);\n }\n\n // Sends a message to a named microservice with NatsHeaders as NATS headers\n async send<T>(service: string, cmd: string, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n if (!this.cachedContext) {\n // The resolver takes the whole request rather than one auth field: which caller kinds\n // exist, and what each contributes, is the consuming server's model — this side only\n // knows that something has to produce headers.\n const context = await this.contextResolver(this.request);\n if (!context) {\n throw new Error('No auth context on request — is the auth guard active for this route?');\n }\n this.cachedContext = context;\n }\n\n const headers = contextToHeaders(this.cachedContext);\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n\n// Converts NatsHeaders to a NATS MsgHdrs object for NATS transport.\n//\n// Driven by the key map rather than a field-per-line, so a new context field travels the\n// moment it is added to NATS_HEADER_KEYS. Empty values are omitted — parseNatsHeaders applies\n// the same defaults on the way back, so sending a blank would just restate them.\nfunction contextToHeaders(ctx: NatsHeaders): import('nats').MsgHdrs {\n const hdrs = natsHeaders();\n for (const [field, key] of Object.entries(NATS_HEADER_KEYS) as [keyof NatsHeaders, string][]) {\n if (ctx[field]) hdrs.set(key, ctx[field]);\n }\n return hdrs;\n}\n","import type { FastifyRequest } from 'fastify';\n\n// Unwraps the @Inject(REQUEST) value to the real Fastify request (GraphQL injects a { req, reply } context).\nexport function resolveInjectedRequest(injected: FastifyRequest): FastifyRequest {\n const candidate = injected as unknown as { headers?: unknown; req?: FastifyRequest };\n if (candidate && candidate.headers === undefined && candidate.req) {\n return candidate.req;\n }\n return injected;\n}\n","import { Inject, Injectable } from '@nestjs/common';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_MS_CLIENTS = Symbol('NATS_MS_CLIENTS');\n\n@Injectable()\nexport class NatsMicroserviceClientService {\n constructor(@Inject(NATS_MS_CLIENTS) private readonly clients: Map<string, ClientProxy>) {}\n\n // Forwards a message to another microservice with NatsHeaders\n async send<T>(service: string, cmd: string, natsHeaders: NatsHeaders, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n const headers: Record<string, string> = {\n [NATS_HEADER_KEYS.orgId]: natsHeaders.orgId,\n [NATS_HEADER_KEYS.userId]: natsHeaders.userId,\n [NATS_HEADER_KEYS.siteId]: natsHeaders.siteId,\n [NATS_HEADER_KEYS.siteTimezone]: natsHeaders.siteTimezone,\n };\n\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n"],"mappings":"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","names":["import_common","import_common","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","RpcProblemExceptionFilter","logger","Logger","name","catch","exception","_host","translatedPgError","tryTranslatePgError","RpcException","throwError","getError","isHttpException","status","getStatus","response","getResponse","payload","toProblemPayload","log","HttpStatus","INTERNAL_SERVER_ERROR","error","warn","call","detail","Error","cause","causeMessage","message","undefined","causeStack","stack","type","errors","JSON","stringify","statusCode","obj","Array","isArray","join","label","import_common","NATS_HEADER_KEYS","orgId","userId","siteId","legalEntityId","siteGroupId","siteTimezone","siteCurrencyCode","HEADER_FALLBACKS","getHeader","headers","key","undefined","get","val","Array","isArray","parseNatsHeaders","parsed","field","Object","entries","RpcNatsHeaders","createParamDecorator","_data","ctx","rpcCtx","switchToRpc","getContext","parseNatsHeaders","getHeaders","RpcSiteId","headers","siteId","InternalServerErrorException","RpcSiteCurrencyCode","siteCurrencyCode","import_common","import_microservices","NATS_MODULE_OPTIONS","Symbol","NATS_CONTEXT_RESOLVER","import_common","import_microservices","resolveInjectedRequest","injected","candidate","headers","undefined","req","NATS_CLIENTS","Symbol","NatsClientService","cachedContext","injectedRequest","contextResolver","clients","request","resolveInjectedRequest","send","service","cmd","data","client","get","Error","keys","join","context","headers","contextToHeaders","record","NatsRecordBuilder","setHeaders","build","toPromise","scope","Scope","REQUEST","ctx","hdrs","natsHeaders","field","key","Object","entries","NATS_HEADER_KEYS","set","import_common","import_microservices","NATS_MS_CLIENTS","Symbol","NatsMicroserviceClientService","clients","send","service","cmd","natsHeaders","data","client","get","Error","keys","join","headers","NATS_HEADER_KEYS","orgId","userId","siteId","siteTimezone","record","NatsRecordBuilder","setHeaders","build","toPromise","NATS_MS_OPTIONS","Symbol","NatsClientModule","logger","Logger","name","allClients","onModuleDestroy","Promise","all","map","c","close","buildClients","options","natsUrl","clients","Map","svc","services","proxy","ClientProxyFactory","create","transport","Transport","NATS","servers","set","push","log","forRoot","asyncOptions","optionsProvider","provide","NATS_MODULE_OPTIONS","useFactory","inject","resolverProvider","NATS_CONTEXT_RESOLVER","contextResolver","clientsProvider","NATS_CLIENTS","config","get","ConfigService","module","imports","ConfigModule","providers","NatsClientService","exports","forMicroservice","NATS_MS_CLIENTS","NatsMicroserviceClientService"]}
|
package/dist/nats.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ArgumentsHost, ModuleMetadata, InjectionToken, OnModuleDestroy, DynamicModule } from '@nestjs/common';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
|
-
import {
|
|
3
|
+
import { FastifyRequest } from 'fastify';
|
|
4
4
|
import './index.cjs';
|
|
5
5
|
import { ClientProxy } from '@nestjs/microservices';
|
|
6
6
|
|
|
@@ -25,17 +25,28 @@ interface NatsHeaders {
|
|
|
25
25
|
siteCurrencyCode: string;
|
|
26
26
|
}
|
|
27
27
|
declare const NATS_HEADER_KEYS: {
|
|
28
|
-
readonly
|
|
29
|
-
readonly
|
|
30
|
-
readonly
|
|
31
|
-
readonly
|
|
32
|
-
readonly
|
|
33
|
-
readonly
|
|
34
|
-
readonly
|
|
28
|
+
readonly orgId: "x-org-id";
|
|
29
|
+
readonly userId: "x-user-id";
|
|
30
|
+
readonly siteId: "x-site-id";
|
|
31
|
+
readonly legalEntityId: "x-le-id";
|
|
32
|
+
readonly siteGroupId: "x-sg-id";
|
|
33
|
+
readonly siteTimezone: "x-site-timezone";
|
|
34
|
+
readonly siteCurrencyCode: "x-site-currency-code";
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Parses NATS message headers into a NatsHeaders object.
|
|
38
|
+
*
|
|
39
|
+
* Only `orgId` is required. It is what scopes every row the receiving service will read, so
|
|
40
|
+
* without it there is no safe way to run — the caller returns null and the interceptor decides.
|
|
41
|
+
*
|
|
42
|
+
* `userId` is deliberately NOT required. A control-plane call has no user behind it, and an
|
|
43
|
+
* earlier version rejected the whole context when it was blank — which meant the receiving
|
|
44
|
+
* service skipped RLS entirely, ran with `app.org_id` unset, and matched no rows. Losing the
|
|
45
|
+
* tenant because there was no user is a far worse failure than an empty acting principal.
|
|
46
|
+
*/
|
|
36
47
|
declare function parseNatsHeaders(headers: unknown): NatsHeaders | null;
|
|
37
48
|
|
|
38
|
-
type ContextResolverFn = (
|
|
49
|
+
type ContextResolverFn = (request: FastifyRequest) => Promise<NatsHeaders | null>;
|
|
39
50
|
interface NatsServiceConfig {
|
|
40
51
|
name: string;
|
|
41
52
|
}
|
package/dist/nats.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ArgumentsHost, ModuleMetadata, InjectionToken, OnModuleDestroy, DynamicModule } from '@nestjs/common';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
|
-
import {
|
|
3
|
+
import { FastifyRequest } from 'fastify';
|
|
4
4
|
import './index.js';
|
|
5
5
|
import { ClientProxy } from '@nestjs/microservices';
|
|
6
6
|
|
|
@@ -25,17 +25,28 @@ interface NatsHeaders {
|
|
|
25
25
|
siteCurrencyCode: string;
|
|
26
26
|
}
|
|
27
27
|
declare const NATS_HEADER_KEYS: {
|
|
28
|
-
readonly
|
|
29
|
-
readonly
|
|
30
|
-
readonly
|
|
31
|
-
readonly
|
|
32
|
-
readonly
|
|
33
|
-
readonly
|
|
34
|
-
readonly
|
|
28
|
+
readonly orgId: "x-org-id";
|
|
29
|
+
readonly userId: "x-user-id";
|
|
30
|
+
readonly siteId: "x-site-id";
|
|
31
|
+
readonly legalEntityId: "x-le-id";
|
|
32
|
+
readonly siteGroupId: "x-sg-id";
|
|
33
|
+
readonly siteTimezone: "x-site-timezone";
|
|
34
|
+
readonly siteCurrencyCode: "x-site-currency-code";
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Parses NATS message headers into a NatsHeaders object.
|
|
38
|
+
*
|
|
39
|
+
* Only `orgId` is required. It is what scopes every row the receiving service will read, so
|
|
40
|
+
* without it there is no safe way to run — the caller returns null and the interceptor decides.
|
|
41
|
+
*
|
|
42
|
+
* `userId` is deliberately NOT required. A control-plane call has no user behind it, and an
|
|
43
|
+
* earlier version rejected the whole context when it was blank — which meant the receiving
|
|
44
|
+
* service skipped RLS entirely, ran with `app.org_id` unset, and matched no rows. Losing the
|
|
45
|
+
* tenant because there was no user is a far worse failure than an empty acting principal.
|
|
46
|
+
*/
|
|
36
47
|
declare function parseNatsHeaders(headers: unknown): NatsHeaders | null;
|
|
37
48
|
|
|
38
|
-
type ContextResolverFn = (
|
|
49
|
+
type ContextResolverFn = (request: FastifyRequest) => Promise<NatsHeaders | null>;
|
|
39
50
|
interface NatsServiceConfig {
|
|
40
51
|
name: string;
|
|
41
52
|
}
|
package/dist/nats.js
CHANGED
|
@@ -150,13 +150,16 @@ import { createParamDecorator, InternalServerErrorException } from "@nestjs/comm
|
|
|
150
150
|
|
|
151
151
|
// src/nats/nats-context.ts
|
|
152
152
|
var NATS_HEADER_KEYS = {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
orgId: "x-org-id",
|
|
154
|
+
userId: "x-user-id",
|
|
155
|
+
siteId: "x-site-id",
|
|
156
|
+
legalEntityId: "x-le-id",
|
|
157
|
+
siteGroupId: "x-sg-id",
|
|
158
|
+
siteTimezone: "x-site-timezone",
|
|
159
|
+
siteCurrencyCode: "x-site-currency-code"
|
|
160
|
+
};
|
|
161
|
+
var HEADER_FALLBACKS = {
|
|
162
|
+
siteTimezone: "UTC"
|
|
160
163
|
};
|
|
161
164
|
function getHeader(headers, key) {
|
|
162
165
|
if (!headers) return void 0;
|
|
@@ -169,18 +172,13 @@ function getHeader(headers, key) {
|
|
|
169
172
|
__name(getHeader, "getHeader");
|
|
170
173
|
function parseNatsHeaders(headers) {
|
|
171
174
|
if (!headers) return null;
|
|
172
|
-
const orgId = getHeader(headers, NATS_HEADER_KEYS.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
legalEntityId: getHeader(headers, NATS_HEADER_KEYS.LE_ID) || "",
|
|
180
|
-
siteGroupId: getHeader(headers, NATS_HEADER_KEYS.SITE_GROUP_ID) || "",
|
|
181
|
-
siteTimezone: getHeader(headers, NATS_HEADER_KEYS.SITE_TIMEZONE) || "UTC",
|
|
182
|
-
siteCurrencyCode: getHeader(headers, NATS_HEADER_KEYS.SITE_CURRENCY_CODE) || ""
|
|
183
|
-
};
|
|
175
|
+
const orgId = getHeader(headers, NATS_HEADER_KEYS.orgId);
|
|
176
|
+
if (!orgId) return null;
|
|
177
|
+
const parsed = {};
|
|
178
|
+
for (const [field, key] of Object.entries(NATS_HEADER_KEYS)) {
|
|
179
|
+
parsed[field] = getHeader(headers, key) || HEADER_FALLBACKS[field] || "";
|
|
180
|
+
}
|
|
181
|
+
return parsed;
|
|
184
182
|
}
|
|
185
183
|
__name(parseNatsHeaders, "parseNatsHeaders");
|
|
186
184
|
|
|
@@ -259,7 +257,7 @@ var NatsClientService = class {
|
|
|
259
257
|
this.contextResolver = contextResolver;
|
|
260
258
|
this.clients = clients;
|
|
261
259
|
}
|
|
262
|
-
// Unwraps the GraphQL { req, reply } context wrapper so
|
|
260
|
+
// Unwraps the GraphQL { req, reply } context wrapper so auth is visible across both transports
|
|
263
261
|
get request() {
|
|
264
262
|
return resolveInjectedRequest(this.injectedRequest);
|
|
265
263
|
}
|
|
@@ -272,11 +270,11 @@ var NatsClientService = class {
|
|
|
272
270
|
].join(", ")}]`);
|
|
273
271
|
}
|
|
274
272
|
if (!this.cachedContext) {
|
|
275
|
-
const
|
|
276
|
-
if (!
|
|
277
|
-
throw new Error("No
|
|
273
|
+
const context = await this.contextResolver(this.request);
|
|
274
|
+
if (!context) {
|
|
275
|
+
throw new Error("No auth context on request \u2014 is the auth guard active for this route?");
|
|
278
276
|
}
|
|
279
|
-
this.cachedContext =
|
|
277
|
+
this.cachedContext = context;
|
|
280
278
|
}
|
|
281
279
|
const headers = contextToHeaders(this.cachedContext);
|
|
282
280
|
const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();
|
|
@@ -301,13 +299,9 @@ NatsClientService = _ts_decorate2([
|
|
|
301
299
|
], NatsClientService);
|
|
302
300
|
function contextToHeaders(ctx) {
|
|
303
301
|
const hdrs = natsHeaders();
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (ctx.legalEntityId) hdrs.set(NATS_HEADER_KEYS.LE_ID, ctx.legalEntityId);
|
|
308
|
-
if (ctx.siteGroupId) hdrs.set(NATS_HEADER_KEYS.SITE_GROUP_ID, ctx.siteGroupId);
|
|
309
|
-
if (ctx.siteTimezone) hdrs.set(NATS_HEADER_KEYS.SITE_TIMEZONE, ctx.siteTimezone);
|
|
310
|
-
if (ctx.siteCurrencyCode) hdrs.set(NATS_HEADER_KEYS.SITE_CURRENCY_CODE, ctx.siteCurrencyCode);
|
|
302
|
+
for (const [field, key] of Object.entries(NATS_HEADER_KEYS)) {
|
|
303
|
+
if (ctx[field]) hdrs.set(key, ctx[field]);
|
|
304
|
+
}
|
|
311
305
|
return hdrs;
|
|
312
306
|
}
|
|
313
307
|
__name(contextToHeaders, "contextToHeaders");
|
|
@@ -350,10 +344,10 @@ var NatsMicroserviceClientService = class {
|
|
|
350
344
|
].join(", ")}]`);
|
|
351
345
|
}
|
|
352
346
|
const headers = {
|
|
353
|
-
[NATS_HEADER_KEYS.
|
|
354
|
-
[NATS_HEADER_KEYS.
|
|
355
|
-
[NATS_HEADER_KEYS.
|
|
356
|
-
[NATS_HEADER_KEYS.
|
|
347
|
+
[NATS_HEADER_KEYS.orgId]: natsHeaders2.orgId,
|
|
348
|
+
[NATS_HEADER_KEYS.userId]: natsHeaders2.userId,
|
|
349
|
+
[NATS_HEADER_KEYS.siteId]: natsHeaders2.siteId,
|
|
350
|
+
[NATS_HEADER_KEYS.siteTimezone]: natsHeaders2.siteTimezone
|
|
357
351
|
};
|
|
358
352
|
const record = new NatsRecordBuilder2(data ?? {}).setHeaders(headers).build();
|
|
359
353
|
return client.send({
|
|
@@ -407,7 +401,7 @@ var NatsClientModule = class _NatsClientModule {
|
|
|
407
401
|
}
|
|
408
402
|
return clients;
|
|
409
403
|
}
|
|
410
|
-
// Gateway mode — request-scoped, resolves context from
|
|
404
|
+
// Gateway mode — request-scoped, resolves context from the request via callback
|
|
411
405
|
static forRoot(asyncOptions) {
|
|
412
406
|
const optionsProvider = {
|
|
413
407
|
provide: NATS_MODULE_OPTIONS,
|
package/dist/nats.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/filters/rpc-problem-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/nats/decorators/nats-headers.decorator.ts","../src/nats/nats-context.ts","../src/nats/nats-client.module.ts","../src/nats/constants.ts","../src/nats/nats-client.service.ts","../src/context/resolve-request.ts","../src/nats/nats-microservice-client.service.ts"],"sourcesContent":["import { type ArgumentsHost, Catch, type HttpException, HttpStatus, Logger } from '@nestjs/common';\nimport { RpcException } from '@nestjs/microservices';\nimport { type Observable, throwError } from 'rxjs';\nimport { tryTranslatePgError } from './pg-error.translator';\n\ninterface FieldError {\n field: string;\n message: string;\n}\n\ninterface ProblemPayload {\n type: string;\n label?: string;\n detail: string;\n message: string;\n errors: FieldError[];\n status: number;\n statusCode: number;\n}\n\n@Catch()\nexport class RpcProblemExceptionFilter {\n private readonly logger = new Logger(RpcProblemExceptionFilter.name);\n\n catch(exception: unknown, _host: ArgumentsHost): Observable<never> {\n // Translate raw Postgres errors into a ConflictException before the rest of the filter handles them.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n if (exception instanceof RpcException) {\n return throwError(() => exception.getError());\n }\n\n if (this.isHttpException(exception)) {\n const status = exception.getStatus();\n const response = exception.getResponse();\n const payload = this.toProblemPayload(response, status);\n // Log 4xx/5xx so the microservice terminal shows what actually failed (previously silent)\n const log = status >= HttpStatus.INTERNAL_SERVER_ERROR ? this.logger.error : this.logger.warn;\n log.call(this.logger, `RPC ${status}: ${payload.detail}`);\n return throwError(() => payload);\n }\n\n if (exception instanceof Error) {\n const cause = (exception as { cause?: unknown }).cause;\n const causeMessage = cause instanceof Error ? cause.message : undefined;\n const causeStack = cause instanceof Error ? cause.stack : undefined;\n this.logger.error(causeMessage ?? exception.message, causeStack ?? exception.stack);\n if (cause && cause !== exception) {\n this.logger.error(`Wrapped by: ${exception.message}`);\n }\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: causeMessage ?? exception.message,\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n this.logger.error(`Unhandled non-error exception: ${JSON.stringify(exception)}`);\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: 'An unexpected error occurred',\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n private toProblemPayload(response: unknown, status: number): ProblemPayload {\n if (typeof response === 'string') {\n return {\n type: 'about:blank',\n detail: response,\n message: response,\n errors: [],\n status,\n statusCode: status,\n };\n }\n\n const obj = (response ?? {}) as Record<string, unknown>;\n // Prefer RFC 9457 `detail`, then Nest/@nestjs-common's `message` (string or class-validator array),\n // so exceptions thrown as `@nestjs/common` errors still surface their real message across NATS.\n const detail =\n typeof obj.detail === 'string'\n ? obj.detail\n : typeof obj.message === 'string'\n ? obj.message\n : Array.isArray(obj.message)\n ? obj.message.join(', ')\n : 'Request failed';\n return {\n type: typeof obj.type === 'string' ? obj.type : 'about:blank',\n label: typeof obj.label === 'string' ? obj.label : undefined,\n detail,\n message: detail,\n errors: Array.isArray(obj.errors) ? (obj.errors as FieldError[]) : [],\n status,\n statusCode: status,\n };\n }\n\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { createParamDecorator, type ExecutionContext, InternalServerErrorException } from '@nestjs/common';\nimport { NatsContext } from '@nestjs/microservices';\nimport { parseNatsHeaders } from '../nats-context';\n\n// Extracts parsed NatsContext from NATS message headers\nexport const RpcNatsHeaders = createParamDecorator((_data: unknown, ctx: ExecutionContext) => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n return parseNatsHeaders(rpcCtx.getHeaders());\n});\n\n// Extracts siteId from NATS headers — throws if missing or empty\nexport const RpcSiteId = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteId) throw new InternalServerErrorException('Missing siteId in NATS headers.');\n return headers.siteId;\n});\n\n// Extracts siteCurrencyCode from NATS headers — throws if missing or empty\nexport const RpcSiteCurrencyCode = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteCurrencyCode) throw new InternalServerErrorException('Missing siteCurrencyCode in NATS headers.');\n return headers.siteCurrencyCode;\n});\n","export interface NatsHeaders {\n orgId: string;\n userId: string;\n siteId: string;\n legalEntityId: string;\n siteGroupId: string;\n siteTimezone: string;\n siteCurrencyCode: string;\n}\n\n// Header keys for NATS context transport\nexport const NATS_HEADER_KEYS = {\n ORG_ID: 'x-org-id',\n USER_ID: 'x-user-id',\n SITE_ID: 'x-site-id',\n LE_ID: 'x-le-id',\n SITE_GROUP_ID: 'x-sg-id',\n SITE_TIMEZONE: 'x-site-timezone',\n SITE_CURRENCY_CODE: 'x-site-currency-code',\n} as const;\n\n// Reads a header value from either a plain object or a NATS MsgHdrsImpl\nfunction getHeader(headers: unknown, key: string): string | undefined {\n if (!headers) return undefined;\n // MsgHdrsImpl uses .get(), plain objects use bracket access\n if (typeof (headers as { get?: unknown }).get === 'function') {\n const val = (headers as { get(key: string): string[] }).get(key);\n return Array.isArray(val) ? val[0] : (val as string | undefined);\n }\n return (headers as Record<string, string>)[key];\n}\n\n// Parses NATS message headers into a NatsHeaders object — siteId is optional (empty for org-level contexts)\nexport function parseNatsHeaders(headers: unknown): NatsHeaders | null {\n if (!headers) return null;\n\n const orgId = getHeader(headers, NATS_HEADER_KEYS.ORG_ID);\n const userId = getHeader(headers, NATS_HEADER_KEYS.USER_ID);\n\n if (!orgId || !userId) return null;\n\n return {\n orgId,\n userId,\n siteId: getHeader(headers, NATS_HEADER_KEYS.SITE_ID) || '',\n legalEntityId: getHeader(headers, NATS_HEADER_KEYS.LE_ID) || '',\n siteGroupId: getHeader(headers, NATS_HEADER_KEYS.SITE_GROUP_ID) || '',\n siteTimezone: getHeader(headers, NATS_HEADER_KEYS.SITE_TIMEZONE) || 'UTC',\n siteCurrencyCode: getHeader(headers, NATS_HEADER_KEYS.SITE_CURRENCY_CODE) || '',\n };\n}\n","import { type DynamicModule, Global, Logger, Module, type OnModuleDestroy, type Provider } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { ClientProxyFactory, Transport } from '@nestjs/microservices';\nimport { NATS_CONTEXT_RESOLVER, NATS_MODULE_OPTIONS } from './constants';\nimport type {\n NatsMicroserviceModuleAsyncOptions,\n NatsModuleBaseOptions,\n NatsRootModuleAsyncOptions,\n NatsRootModuleOptions,\n} from './nats-client.interfaces';\nimport { NATS_CLIENTS, NatsClientService } from './nats-client.service';\nimport { NATS_MS_CLIENTS, NatsMicroserviceClientService } from './nats-microservice-client.service';\n\nconst NATS_MS_OPTIONS = Symbol('NATS_MS_OPTIONS');\n\n@Global()\n@Module({})\nexport class NatsClientModule implements OnModuleDestroy {\n private static readonly logger = new Logger(NatsClientModule.name);\n private static allClients: ClientProxy[] = [];\n\n async onModuleDestroy() {\n await Promise.all(NatsClientModule.allClients.map((c) => c.close()));\n NatsClientModule.allClients = [];\n }\n\n // Builds a Map of named NATS ClientProxy instances\n private static buildClients(options: NatsModuleBaseOptions, natsUrl: string): Map<string, ClientProxy> {\n const clients = new Map<string, ClientProxy>();\n\n for (const svc of options.services) {\n const proxy = ClientProxyFactory.create({\n transport: Transport.NATS,\n options: { servers: [natsUrl] },\n });\n clients.set(svc.name, proxy);\n NatsClientModule.allClients.push(proxy);\n NatsClientModule.logger.log(`Registered NATS client: ${svc.name} → ${natsUrl}`);\n }\n\n return clients;\n }\n\n // Gateway mode — request-scoped, resolves context from sessionInfo via callback\n static forRoot(asyncOptions: NatsRootModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const resolverProvider: Provider = {\n provide: NATS_CONTEXT_RESOLVER,\n useFactory: (options: NatsRootModuleOptions) => options.contextResolver,\n inject: [NATS_MODULE_OPTIONS],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_CLIENTS,\n useFactory: (options: NatsRootModuleOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MODULE_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, resolverProvider, clientsProvider, NatsClientService],\n exports: [NatsClientService],\n };\n }\n\n // Microservice mode — singleton, forwards context from incoming NATS payload\n static forMicroservice(asyncOptions: NatsMicroserviceModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MS_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_MS_CLIENTS,\n useFactory: (options: NatsModuleBaseOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MS_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, clientsProvider, NatsMicroserviceClientService],\n exports: [NatsMicroserviceClientService],\n };\n }\n}\n","export const NATS_MODULE_OPTIONS = Symbol('NATS_MODULE_OPTIONS');\nexport const NATS_CONTEXT_RESOLVER = Symbol('NATS_CONTEXT_RESOLVER');\n","// Pulls the fastify module augmentation into this entry's dts graph — tsup builds each entry in isolation\nimport '../types/fastify-augmentation';\nimport { Inject, Injectable, Scope } from '@nestjs/common';\nimport { REQUEST } from '@nestjs/core';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport type { FastifyRequest } from 'fastify';\nimport { headers as natsHeaders } from 'nats';\nimport { resolveInjectedRequest } from '../context/resolve-request';\nimport { NATS_CONTEXT_RESOLVER } from './constants';\nimport type { ContextResolverFn } from './nats-client.interfaces';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_CLIENTS = Symbol('NATS_CLIENTS');\n\n@Injectable({ scope: Scope.REQUEST })\nexport class NatsClientService {\n private cachedContext: NatsHeaders | null = null;\n\n constructor(\n @Inject(REQUEST) private readonly injectedRequest: FastifyRequest,\n @Inject(NATS_CONTEXT_RESOLVER) private readonly contextResolver: ContextResolverFn,\n @Inject(NATS_CLIENTS) private readonly clients: Map<string, ClientProxy>,\n ) {}\n\n // Unwraps the GraphQL { req, reply } context wrapper so sessionInfo is visible across both transports\n private get request(): FastifyRequest {\n return resolveInjectedRequest(this.injectedRequest);\n }\n\n // Sends a message to a named microservice with NatsHeaders as NATS headers\n async send<T>(service: string, cmd: string, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n if (!this.cachedContext) {\n const sessionInfo = this.request.sessionInfo;\n if (!sessionInfo) {\n throw new Error('No sessionInfo on request — is the auth guard active?');\n }\n this.cachedContext = await this.contextResolver(sessionInfo);\n }\n\n const headers = contextToHeaders(this.cachedContext);\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n\n// Converts NatsHeaders to a NATS MsgHdrs object for NATS transport\nfunction contextToHeaders(ctx: NatsHeaders): import('nats').MsgHdrs {\n const hdrs = natsHeaders();\n hdrs.set(NATS_HEADER_KEYS.ORG_ID, ctx.orgId);\n hdrs.set(NATS_HEADER_KEYS.USER_ID, ctx.userId);\n if (ctx.siteId) hdrs.set(NATS_HEADER_KEYS.SITE_ID, ctx.siteId);\n if (ctx.legalEntityId) hdrs.set(NATS_HEADER_KEYS.LE_ID, ctx.legalEntityId);\n if (ctx.siteGroupId) hdrs.set(NATS_HEADER_KEYS.SITE_GROUP_ID, ctx.siteGroupId);\n if (ctx.siteTimezone) hdrs.set(NATS_HEADER_KEYS.SITE_TIMEZONE, ctx.siteTimezone);\n if (ctx.siteCurrencyCode) hdrs.set(NATS_HEADER_KEYS.SITE_CURRENCY_CODE, ctx.siteCurrencyCode);\n return hdrs;\n}\n","import type { FastifyRequest } from 'fastify';\n\n// Unwraps the @Inject(REQUEST) value to the real Fastify request (GraphQL injects a { req, reply } context).\nexport function resolveInjectedRequest(injected: FastifyRequest): FastifyRequest {\n const candidate = injected as unknown as { headers?: unknown; req?: FastifyRequest };\n if (candidate && candidate.headers === undefined && candidate.req) {\n return candidate.req;\n }\n return injected;\n}\n","import { Inject, Injectable } from '@nestjs/common';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_MS_CLIENTS = Symbol('NATS_MS_CLIENTS');\n\n@Injectable()\nexport class NatsMicroserviceClientService {\n constructor(@Inject(NATS_MS_CLIENTS) private readonly clients: Map<string, ClientProxy>) {}\n\n // Forwards a message to another microservice with NatsHeaders\n async send<T>(service: string, cmd: string, natsHeaders: NatsHeaders, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n const headers: Record<string, string> = {\n [NATS_HEADER_KEYS.ORG_ID]: natsHeaders.orgId,\n [NATS_HEADER_KEYS.USER_ID]: natsHeaders.userId,\n [NATS_HEADER_KEYS.SITE_ID]: natsHeaders.siteId,\n [NATS_HEADER_KEYS.SITE_TIMEZONE]: natsHeaders.siteTimezone,\n };\n\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n"],"mappings":"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","names":["Catch","HttpStatus","Logger","RpcException","throwError","HttpStatus","HttpException","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","RpcProblemExceptionFilter","logger","Logger","name","catch","exception","_host","translatedPgError","tryTranslatePgError","RpcException","throwError","getError","isHttpException","status","getStatus","response","getResponse","payload","toProblemPayload","log","HttpStatus","INTERNAL_SERVER_ERROR","error","warn","call","detail","Error","cause","causeMessage","message","undefined","causeStack","stack","type","errors","JSON","stringify","statusCode","obj","Array","isArray","join","label","createParamDecorator","InternalServerErrorException","NATS_HEADER_KEYS","ORG_ID","USER_ID","SITE_ID","LE_ID","SITE_GROUP_ID","SITE_TIMEZONE","SITE_CURRENCY_CODE","getHeader","headers","key","undefined","get","val","Array","isArray","parseNatsHeaders","orgId","userId","siteId","legalEntityId","siteGroupId","siteTimezone","siteCurrencyCode","RpcNatsHeaders","createParamDecorator","_data","ctx","rpcCtx","switchToRpc","getContext","parseNatsHeaders","getHeaders","RpcSiteId","headers","siteId","InternalServerErrorException","RpcSiteCurrencyCode","siteCurrencyCode","Global","Logger","Module","ConfigModule","ConfigService","ClientProxyFactory","Transport","NATS_MODULE_OPTIONS","Symbol","NATS_CONTEXT_RESOLVER","Inject","Injectable","Scope","REQUEST","NatsRecordBuilder","headers","natsHeaders","resolveInjectedRequest","injected","candidate","headers","undefined","req","NATS_CLIENTS","Symbol","NatsClientService","cachedContext","injectedRequest","contextResolver","clients","request","resolveInjectedRequest","send","service","cmd","data","client","get","Error","keys","join","sessionInfo","headers","contextToHeaders","record","NatsRecordBuilder","setHeaders","build","toPromise","scope","Scope","REQUEST","ctx","hdrs","natsHeaders","set","NATS_HEADER_KEYS","ORG_ID","orgId","USER_ID","userId","siteId","SITE_ID","legalEntityId","LE_ID","siteGroupId","SITE_GROUP_ID","siteTimezone","SITE_TIMEZONE","siteCurrencyCode","SITE_CURRENCY_CODE","Inject","Injectable","NatsRecordBuilder","NATS_MS_CLIENTS","Symbol","NatsMicroserviceClientService","clients","send","service","cmd","natsHeaders","data","client","get","Error","keys","join","headers","NATS_HEADER_KEYS","ORG_ID","orgId","USER_ID","userId","SITE_ID","siteId","SITE_TIMEZONE","siteTimezone","record","NatsRecordBuilder","setHeaders","build","toPromise","NATS_MS_OPTIONS","Symbol","NatsClientModule","logger","Logger","name","allClients","onModuleDestroy","Promise","all","map","c","close","buildClients","options","natsUrl","clients","Map","svc","services","proxy","ClientProxyFactory","create","transport","Transport","NATS","servers","set","push","log","forRoot","asyncOptions","optionsProvider","provide","NATS_MODULE_OPTIONS","useFactory","inject","resolverProvider","NATS_CONTEXT_RESOLVER","contextResolver","clientsProvider","NATS_CLIENTS","config","get","ConfigService","module","imports","ConfigModule","providers","NatsClientService","exports","forMicroservice","NATS_MS_CLIENTS","NatsMicroserviceClientService"]}
|
|
1
|
+
{"version":3,"sources":["../src/filters/rpc-problem-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/nats/decorators/nats-headers.decorator.ts","../src/nats/nats-context.ts","../src/nats/nats-client.module.ts","../src/nats/constants.ts","../src/nats/nats-client.service.ts","../src/context/resolve-request.ts","../src/nats/nats-microservice-client.service.ts"],"sourcesContent":["import { type ArgumentsHost, Catch, type HttpException, HttpStatus, Logger } from '@nestjs/common';\nimport { RpcException } from '@nestjs/microservices';\nimport { type Observable, throwError } from 'rxjs';\nimport { tryTranslatePgError } from './pg-error.translator';\n\ninterface FieldError {\n field: string;\n message: string;\n}\n\ninterface ProblemPayload {\n type: string;\n label?: string;\n detail: string;\n message: string;\n errors: FieldError[];\n status: number;\n statusCode: number;\n}\n\n@Catch()\nexport class RpcProblemExceptionFilter {\n private readonly logger = new Logger(RpcProblemExceptionFilter.name);\n\n catch(exception: unknown, _host: ArgumentsHost): Observable<never> {\n // Translate raw Postgres errors into a ConflictException before the rest of the filter handles them.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n if (exception instanceof RpcException) {\n return throwError(() => exception.getError());\n }\n\n if (this.isHttpException(exception)) {\n const status = exception.getStatus();\n const response = exception.getResponse();\n const payload = this.toProblemPayload(response, status);\n // Log 4xx/5xx so the microservice terminal shows what actually failed (previously silent)\n const log = status >= HttpStatus.INTERNAL_SERVER_ERROR ? this.logger.error : this.logger.warn;\n log.call(this.logger, `RPC ${status}: ${payload.detail}`);\n return throwError(() => payload);\n }\n\n if (exception instanceof Error) {\n const cause = (exception as { cause?: unknown }).cause;\n const causeMessage = cause instanceof Error ? cause.message : undefined;\n const causeStack = cause instanceof Error ? cause.stack : undefined;\n this.logger.error(causeMessage ?? exception.message, causeStack ?? exception.stack);\n if (cause && cause !== exception) {\n this.logger.error(`Wrapped by: ${exception.message}`);\n }\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: causeMessage ?? exception.message,\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n this.logger.error(`Unhandled non-error exception: ${JSON.stringify(exception)}`);\n return throwError(() =>\n this.toProblemPayload(\n {\n type: 'about:blank',\n detail: 'An unexpected error occurred',\n errors: [],\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n ),\n );\n }\n\n private toProblemPayload(response: unknown, status: number): ProblemPayload {\n if (typeof response === 'string') {\n return {\n type: 'about:blank',\n detail: response,\n message: response,\n errors: [],\n status,\n statusCode: status,\n };\n }\n\n const obj = (response ?? {}) as Record<string, unknown>;\n // Prefer RFC 9457 `detail`, then Nest/@nestjs-common's `message` (string or class-validator array),\n // so exceptions thrown as `@nestjs/common` errors still surface their real message across NATS.\n const detail =\n typeof obj.detail === 'string'\n ? obj.detail\n : typeof obj.message === 'string'\n ? obj.message\n : Array.isArray(obj.message)\n ? obj.message.join(', ')\n : 'Request failed';\n return {\n type: typeof obj.type === 'string' ? obj.type : 'about:blank',\n label: typeof obj.label === 'string' ? obj.label : undefined,\n detail,\n message: detail,\n errors: Array.isArray(obj.errors) ? (obj.errors as FieldError[]) : [],\n status,\n statusCode: status,\n };\n }\n\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { createParamDecorator, type ExecutionContext, InternalServerErrorException } from '@nestjs/common';\nimport { NatsContext } from '@nestjs/microservices';\nimport { parseNatsHeaders } from '../nats-context';\n\n// Extracts parsed NatsContext from NATS message headers\nexport const RpcNatsHeaders = createParamDecorator((_data: unknown, ctx: ExecutionContext) => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n return parseNatsHeaders(rpcCtx.getHeaders());\n});\n\n// Extracts siteId from NATS headers — throws if missing or empty\nexport const RpcSiteId = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteId) throw new InternalServerErrorException('Missing siteId in NATS headers.');\n return headers.siteId;\n});\n\n// Extracts siteCurrencyCode from NATS headers — throws if missing or empty\nexport const RpcSiteCurrencyCode = createParamDecorator((_data: unknown, ctx: ExecutionContext): string => {\n const rpcCtx = ctx.switchToRpc().getContext<NatsContext>();\n const headers = parseNatsHeaders(rpcCtx.getHeaders());\n if (!headers?.siteCurrencyCode) throw new InternalServerErrorException('Missing siteCurrencyCode in NATS headers.');\n return headers.siteCurrencyCode;\n});\n","export interface NatsHeaders {\n orgId: string;\n userId: string;\n siteId: string;\n legalEntityId: string;\n siteGroupId: string;\n siteTimezone: string;\n siteCurrencyCode: string;\n}\n\n// The single source of truth for context transport, both directions. Adding a field means\n// adding one entry here plus one on NatsHeaders — encode and parse both pick it up.\nexport const NATS_HEADER_KEYS = {\n orgId: 'x-org-id',\n userId: 'x-user-id',\n siteId: 'x-site-id',\n legalEntityId: 'x-le-id',\n siteGroupId: 'x-sg-id',\n siteTimezone: 'x-site-timezone',\n siteCurrencyCode: 'x-site-currency-code',\n} as const satisfies Record<keyof NatsHeaders, string>;\n\n// Applied when a header is absent, so a missing optional field lands on the same value the\n// producing side would have sent for \"not set\"\nconst HEADER_FALLBACKS: Partial<Record<keyof NatsHeaders, string>> = {\n siteTimezone: 'UTC',\n};\n\n// Reads a header value from either a plain object or a NATS MsgHdrsImpl\nfunction getHeader(headers: unknown, key: string): string | undefined {\n if (!headers) return undefined;\n // MsgHdrsImpl uses .get(), plain objects use bracket access\n if (typeof (headers as { get?: unknown }).get === 'function') {\n const val = (headers as { get(key: string): string[] }).get(key);\n return Array.isArray(val) ? val[0] : (val as string | undefined);\n }\n return (headers as Record<string, string>)[key];\n}\n\n/**\n * Parses NATS message headers into a NatsHeaders object.\n *\n * Only `orgId` is required. It is what scopes every row the receiving service will read, so\n * without it there is no safe way to run — the caller returns null and the interceptor decides.\n *\n * `userId` is deliberately NOT required. A control-plane call has no user behind it, and an\n * earlier version rejected the whole context when it was blank — which meant the receiving\n * service skipped RLS entirely, ran with `app.org_id` unset, and matched no rows. Losing the\n * tenant because there was no user is a far worse failure than an empty acting principal.\n */\nexport function parseNatsHeaders(headers: unknown): NatsHeaders | null {\n if (!headers) return null;\n\n const orgId = getHeader(headers, NATS_HEADER_KEYS.orgId);\n if (!orgId) return null;\n\n const parsed = {} as NatsHeaders;\n for (const [field, key] of Object.entries(NATS_HEADER_KEYS) as [keyof NatsHeaders, string][]) {\n parsed[field] = getHeader(headers, key) || HEADER_FALLBACKS[field] || '';\n }\n return parsed;\n}\n","import { type DynamicModule, Global, Logger, Module, type OnModuleDestroy, type Provider } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { ClientProxyFactory, Transport } from '@nestjs/microservices';\nimport { NATS_CONTEXT_RESOLVER, NATS_MODULE_OPTIONS } from './constants';\nimport type {\n NatsMicroserviceModuleAsyncOptions,\n NatsModuleBaseOptions,\n NatsRootModuleAsyncOptions,\n NatsRootModuleOptions,\n} from './nats-client.interfaces';\nimport { NATS_CLIENTS, NatsClientService } from './nats-client.service';\nimport { NATS_MS_CLIENTS, NatsMicroserviceClientService } from './nats-microservice-client.service';\n\nconst NATS_MS_OPTIONS = Symbol('NATS_MS_OPTIONS');\n\n@Global()\n@Module({})\nexport class NatsClientModule implements OnModuleDestroy {\n private static readonly logger = new Logger(NatsClientModule.name);\n private static allClients: ClientProxy[] = [];\n\n async onModuleDestroy() {\n await Promise.all(NatsClientModule.allClients.map((c) => c.close()));\n NatsClientModule.allClients = [];\n }\n\n // Builds a Map of named NATS ClientProxy instances\n private static buildClients(options: NatsModuleBaseOptions, natsUrl: string): Map<string, ClientProxy> {\n const clients = new Map<string, ClientProxy>();\n\n for (const svc of options.services) {\n const proxy = ClientProxyFactory.create({\n transport: Transport.NATS,\n options: { servers: [natsUrl] },\n });\n clients.set(svc.name, proxy);\n NatsClientModule.allClients.push(proxy);\n NatsClientModule.logger.log(`Registered NATS client: ${svc.name} → ${natsUrl}`);\n }\n\n return clients;\n }\n\n // Gateway mode — request-scoped, resolves context from the request via callback\n static forRoot(asyncOptions: NatsRootModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const resolverProvider: Provider = {\n provide: NATS_CONTEXT_RESOLVER,\n useFactory: (options: NatsRootModuleOptions) => options.contextResolver,\n inject: [NATS_MODULE_OPTIONS],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_CLIENTS,\n useFactory: (options: NatsRootModuleOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MODULE_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, resolverProvider, clientsProvider, NatsClientService],\n exports: [NatsClientService],\n };\n }\n\n // Microservice mode — singleton, forwards context from incoming NATS payload\n static forMicroservice(asyncOptions: NatsMicroserviceModuleAsyncOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: NATS_MS_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n };\n\n const clientsProvider: Provider = {\n provide: NATS_MS_CLIENTS,\n useFactory: (options: NatsModuleBaseOptions, config: ConfigService): Map<string, ClientProxy> => {\n const natsUrl = options.natsUrl ?? config.get<string>('NATS_URL', 'nats://localhost:4222');\n return NatsClientModule.buildClients(options, natsUrl);\n },\n inject: [NATS_MS_OPTIONS, ConfigService],\n };\n\n return {\n module: NatsClientModule,\n imports: [ConfigModule, ...(asyncOptions.imports ?? [])],\n providers: [optionsProvider, clientsProvider, NatsMicroserviceClientService],\n exports: [NatsMicroserviceClientService],\n };\n }\n}\n","export const NATS_MODULE_OPTIONS = Symbol('NATS_MODULE_OPTIONS');\nexport const NATS_CONTEXT_RESOLVER = Symbol('NATS_CONTEXT_RESOLVER');\n","// Pulls the fastify module augmentation into this entry's dts graph — tsup builds each entry in isolation\nimport '../types/fastify-augmentation';\nimport { Inject, Injectable, Scope } from '@nestjs/common';\nimport { REQUEST } from '@nestjs/core';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport type { FastifyRequest } from 'fastify';\nimport { headers as natsHeaders } from 'nats';\nimport { resolveInjectedRequest } from '../context/resolve-request';\nimport { NATS_CONTEXT_RESOLVER } from './constants';\nimport type { ContextResolverFn } from './nats-client.interfaces';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_CLIENTS = Symbol('NATS_CLIENTS');\n\n@Injectable({ scope: Scope.REQUEST })\nexport class NatsClientService {\n private cachedContext: NatsHeaders | null = null;\n\n constructor(\n @Inject(REQUEST) private readonly injectedRequest: FastifyRequest,\n @Inject(NATS_CONTEXT_RESOLVER) private readonly contextResolver: ContextResolverFn,\n @Inject(NATS_CLIENTS) private readonly clients: Map<string, ClientProxy>,\n ) {}\n\n // Unwraps the GraphQL { req, reply } context wrapper so auth is visible across both transports\n private get request(): FastifyRequest {\n return resolveInjectedRequest(this.injectedRequest);\n }\n\n // Sends a message to a named microservice with NatsHeaders as NATS headers\n async send<T>(service: string, cmd: string, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n if (!this.cachedContext) {\n // The resolver takes the whole request rather than one auth field: which caller kinds\n // exist, and what each contributes, is the consuming server's model — this side only\n // knows that something has to produce headers.\n const context = await this.contextResolver(this.request);\n if (!context) {\n throw new Error('No auth context on request — is the auth guard active for this route?');\n }\n this.cachedContext = context;\n }\n\n const headers = contextToHeaders(this.cachedContext);\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n\n// Converts NatsHeaders to a NATS MsgHdrs object for NATS transport.\n//\n// Driven by the key map rather than a field-per-line, so a new context field travels the\n// moment it is added to NATS_HEADER_KEYS. Empty values are omitted — parseNatsHeaders applies\n// the same defaults on the way back, so sending a blank would just restate them.\nfunction contextToHeaders(ctx: NatsHeaders): import('nats').MsgHdrs {\n const hdrs = natsHeaders();\n for (const [field, key] of Object.entries(NATS_HEADER_KEYS) as [keyof NatsHeaders, string][]) {\n if (ctx[field]) hdrs.set(key, ctx[field]);\n }\n return hdrs;\n}\n","import type { FastifyRequest } from 'fastify';\n\n// Unwraps the @Inject(REQUEST) value to the real Fastify request (GraphQL injects a { req, reply } context).\nexport function resolveInjectedRequest(injected: FastifyRequest): FastifyRequest {\n const candidate = injected as unknown as { headers?: unknown; req?: FastifyRequest };\n if (candidate && candidate.headers === undefined && candidate.req) {\n return candidate.req;\n }\n return injected;\n}\n","import { Inject, Injectable } from '@nestjs/common';\nimport type { ClientProxy } from '@nestjs/microservices';\nimport { NatsRecordBuilder } from '@nestjs/microservices';\nimport { NATS_HEADER_KEYS, type NatsHeaders } from './nats-context';\n\nexport const NATS_MS_CLIENTS = Symbol('NATS_MS_CLIENTS');\n\n@Injectable()\nexport class NatsMicroserviceClientService {\n constructor(@Inject(NATS_MS_CLIENTS) private readonly clients: Map<string, ClientProxy>) {}\n\n // Forwards a message to another microservice with NatsHeaders\n async send<T>(service: string, cmd: string, natsHeaders: NatsHeaders, data?: object): Promise<T> {\n const client = this.clients.get(service);\n if (!client) {\n throw new Error(\n `NATS service \"${service}\" is not registered. Available: [${[...this.clients.keys()].join(', ')}]`,\n );\n }\n\n const headers: Record<string, string> = {\n [NATS_HEADER_KEYS.orgId]: natsHeaders.orgId,\n [NATS_HEADER_KEYS.userId]: natsHeaders.userId,\n [NATS_HEADER_KEYS.siteId]: natsHeaders.siteId,\n [NATS_HEADER_KEYS.siteTimezone]: natsHeaders.siteTimezone,\n };\n\n const record = new NatsRecordBuilder(data ?? {}).setHeaders(headers).build();\n return client.send<T>({ cmd }, record).toPromise() as Promise<T>;\n }\n}\n"],"mappings":";;;;AAAA,SAA6BA,OAA2BC,cAAAA,aAAYC,cAAc;AAClF,SAASC,oBAAoB;AAC7B,SAA0BC,kBAAkB;;;ACF5C,SAASC,kBAAkB;;;ACA3B,SAASC,qBAAiC;AAanC,IAAeC,uBAAf,cAA4CC,cAAAA;EAbnD,OAamDA;;;EACjD,YAAYC,iBAA0CC,YAAwB;AAC5E,UAAMC,UAAU,OAAOF,oBAAoB,WAAW;MAAEG,QAAQH;IAAgB,IAAIA;AAEpF,UACE;MACEI,MAAMF,QAAQE,QAAQ;MACtBC,OAAOH,QAAQG;MACfF,QAAQD,QAAQC;MAChBG,QAAQJ,QAAQI,UAAU,CAAA;IAC5B,GACAL,UAAAA;EAEJ;AACF;;;ADxBO,IAAMM,oBAAN,cAAgCC,qBAAAA;EAHvC,OAGuCA;;;EACrC,YAAYC,iBAA2C;AACrD,UAAMA,mBAAmB,YAAYC,WAAWC,QAAQ;EAC1D;AACF;;;AELA,IAAMC,sBAAsB;AAcrB,SAASC,oBAAoBC,OAAc;AAChD,QAAMC,UAAUC,YAAYF,KAAAA;AAC5B,MAAI,CAACC,QAAS,QAAOE;AACrB,QAAM,EAAEC,MAAMC,YAAYC,OAAOC,OAAM,IAAKN;AAC5C,MAAIG,SAASN,oBAAqB,QAAOK;AACzC,SAAO,IAAIK,kBAAkB;IAC3BC,OAAO;IACPF,QAAQA,QAAQG,KAAAA,KAAU;IAC1BC,QAAQ,CAAA;IACR,GAAIN,cAAcC,QAAQ;MAAEM,MAAM;QAAEP;QAAYC;MAAM;IAAE,IAAI,CAAC;EAC/D,CAAA;AACF;AAXgBP;AAcT,SAASG,YAAYF,OAAgBa,QAAQ,GAAC;AACnD,MAAI,CAACb,SAAS,OAAOA,UAAU,YAAYa,QAAQ,EAAG,QAAOV;AAC7D,QAAMW,YAAYd;AAClB,MAAI,OAAOc,UAAUV,SAAS,SAAU,QAAOU;AAC/C,SAAOZ,YAAYY,UAAUC,OAAOF,QAAQ,CAAA;AAC9C;AALgBX;;;;;;;;;;AHTT,IAAMc,4BAAN,MAAMA,2BAAAA;SAAAA;;;EACMC,SAAS,IAAIC,OAAOF,2BAA0BG,IAAI;EAEnEC,MAAMC,WAAoBC,OAAyC;AAEjE,UAAMC,oBAAoBC,oBAAoBH,SAAAA;AAC9C,QAAIE,kBAAmBF,aAAYE;AAEnC,QAAIF,qBAAqBI,cAAc;AACrC,aAAOC,WAAW,MAAML,UAAUM,SAAQ,CAAA;IAC5C;AAEA,QAAI,KAAKC,gBAAgBP,SAAAA,GAAY;AACnC,YAAMQ,SAASR,UAAUS,UAAS;AAClC,YAAMC,WAAWV,UAAUW,YAAW;AACtC,YAAMC,UAAU,KAAKC,iBAAiBH,UAAUF,MAAAA;AAEhD,YAAMM,MAAMN,UAAUO,YAAWC,wBAAwB,KAAKpB,OAAOqB,QAAQ,KAAKrB,OAAOsB;AACzFJ,UAAIK,KAAK,KAAKvB,QAAQ,OAAOY,MAAAA,KAAWI,QAAQQ,MAAM,EAAE;AACxD,aAAOf,WAAW,MAAMO,OAAAA;IAC1B;AAEA,QAAIZ,qBAAqBqB,OAAO;AAC9B,YAAMC,QAAStB,UAAkCsB;AACjD,YAAMC,eAAeD,iBAAiBD,QAAQC,MAAME,UAAUC;AAC9D,YAAMC,aAAaJ,iBAAiBD,QAAQC,MAAMK,QAAQF;AAC1D,WAAK7B,OAAOqB,MAAMM,gBAAgBvB,UAAUwB,SAASE,cAAc1B,UAAU2B,KAAK;AAClF,UAAIL,SAASA,UAAUtB,WAAW;AAChC,aAAKJ,OAAOqB,MAAM,eAAejB,UAAUwB,OAAO,EAAE;MACtD;AACA,aAAOnB,WAAW,MAChB,KAAKQ,iBACH;QACEe,MAAM;QACNR,QAAQG,gBAAgBvB,UAAUwB;QAClCK,QAAQ,CAAA;MACV,GACAd,YAAWC,qBAAqB,CAAA;IAGtC;AAEA,SAAKpB,OAAOqB,MAAM,kCAAkCa,KAAKC,UAAU/B,SAAAA,CAAAA,EAAY;AAC/E,WAAOK,WAAW,MAChB,KAAKQ,iBACH;MACEe,MAAM;MACNR,QAAQ;MACRS,QAAQ,CAAA;IACV,GACAd,YAAWC,qBAAqB,CAAA;EAGtC;EAEQH,iBAAiBH,UAAmBF,QAAgC;AAC1E,QAAI,OAAOE,aAAa,UAAU;AAChC,aAAO;QACLkB,MAAM;QACNR,QAAQV;QACRc,SAASd;QACTmB,QAAQ,CAAA;QACRrB;QACAwB,YAAYxB;MACd;IACF;AAEA,UAAMyB,MAAOvB,YAAY,CAAC;AAG1B,UAAMU,SACJ,OAAOa,IAAIb,WAAW,WAClBa,IAAIb,SACJ,OAAOa,IAAIT,YAAY,WACrBS,IAAIT,UACJU,MAAMC,QAAQF,IAAIT,OAAO,IACvBS,IAAIT,QAAQY,KAAK,IAAA,IACjB;AACV,WAAO;MACLR,MAAM,OAAOK,IAAIL,SAAS,WAAWK,IAAIL,OAAO;MAChDS,OAAO,OAAOJ,IAAII,UAAU,WAAWJ,IAAII,QAAQZ;MACnDL;MACAI,SAASJ;MACTS,QAAQK,MAAMC,QAAQF,IAAIJ,MAAM,IAAKI,IAAIJ,SAA0B,CAAA;MACnErB;MACAwB,YAAYxB;IACd;EACF;EAEQD,gBAAgBU,OAAwC;AAC9D,WACEA,iBAAiBI,SACjB,OAAQJ,MAAkCR,cAAc,cACxD,OAAQQ,MAAoCN,gBAAgB;EAEhE;AACF;;;;;;AIrHA,SAAS2B,sBAA6CC,oCAAoC;;;ACYnF,IAAMC,mBAAmB;EAC9BC,OAAO;EACPC,QAAQ;EACRC,QAAQ;EACRC,eAAe;EACfC,aAAa;EACbC,cAAc;EACdC,kBAAkB;AACpB;AAIA,IAAMC,mBAA+D;EACnEF,cAAc;AAChB;AAGA,SAASG,UAAUC,SAAkBC,KAAW;AAC9C,MAAI,CAACD,QAAS,QAAOE;AAErB,MAAI,OAAQF,QAA8BG,QAAQ,YAAY;AAC5D,UAAMC,MAAOJ,QAA2CG,IAAIF,GAAAA;AAC5D,WAAOI,MAAMC,QAAQF,GAAAA,IAAOA,IAAI,CAAA,IAAMA;EACxC;AACA,SAAQJ,QAAmCC,GAAAA;AAC7C;AARSF;AAqBF,SAASQ,iBAAiBP,SAAgB;AAC/C,MAAI,CAACA,QAAS,QAAO;AAErB,QAAMT,QAAQQ,UAAUC,SAASV,iBAAiBC,KAAK;AACvD,MAAI,CAACA,MAAO,QAAO;AAEnB,QAAMiB,SAAS,CAAC;AAChB,aAAW,CAACC,OAAOR,GAAAA,KAAQS,OAAOC,QAAQrB,gBAAAA,GAAoD;AAC5FkB,WAAOC,KAAAA,IAASV,UAAUC,SAASC,GAAAA,KAAQH,iBAAiBW,KAAAA,KAAU;EACxE;AACA,SAAOD;AACT;AAXgBD;;;AD7CT,IAAMK,iBAAiBC,qBAAqB,CAACC,OAAgBC,QAAAA;AAClE,QAAMC,SAASD,IAAIE,YAAW,EAAGC,WAAU;AAC3C,SAAOC,iBAAiBH,OAAOI,WAAU,CAAA;AAC3C,CAAA;AAGO,IAAMC,YAAYR,qBAAqB,CAACC,OAAgBC,QAAAA;AAC7D,QAAMC,SAASD,IAAIE,YAAW,EAAGC,WAAU;AAC3C,QAAMI,UAAUH,iBAAiBH,OAAOI,WAAU,CAAA;AAClD,MAAI,CAACE,SAASC,OAAQ,OAAM,IAAIC,6BAA6B,iCAAA;AAC7D,SAAOF,QAAQC;AACjB,CAAA;AAGO,IAAME,sBAAsBZ,qBAAqB,CAACC,OAAgBC,QAAAA;AACvE,QAAMC,SAASD,IAAIE,YAAW,EAAGC,WAAU;AAC3C,QAAMI,UAAUH,iBAAiBH,OAAOI,WAAU,CAAA;AAClD,MAAI,CAACE,SAASI,iBAAkB,OAAM,IAAIF,6BAA6B,2CAAA;AACvE,SAAOF,QAAQI;AACjB,CAAA;;;AExBA,SAA6BC,QAAQC,UAAAA,SAAQC,cAAmD;AAChG,SAASC,cAAcC,qBAAqB;AAE5C,SAASC,oBAAoBC,iBAAiB;;;ACHvC,IAAMC,sBAAsBC,OAAO,qBAAA;AACnC,IAAMC,wBAAwBD,OAAO,uBAAA;;;ACC5C,SAASE,QAAQC,YAAYC,aAAa;AAC1C,SAASC,eAAe;AAExB,SAASC,yBAAyB;AAElC,SAASC,WAAWC,mBAAmB;;;ACJhC,SAASC,uBAAuBC,UAAwB;AAC7D,QAAMC,YAAYD;AAClB,MAAIC,aAAaA,UAAUC,YAAYC,UAAaF,UAAUG,KAAK;AACjE,WAAOH,UAAUG;EACnB;AACA,SAAOJ;AACT;AANgBD;;;;;;;;;;;;;;;;;;;;ADUT,IAAMM,eAAeC,OAAO,cAAA;AAG5B,IAAMC,oBAAN,MAAMA;EAhBb,OAgBaA;;;;;;EACHC,gBAAoC;EAE5C,YACoCC,iBACcC,iBACTC,SACvC;SAHkCF,kBAAAA;SACcC,kBAAAA;SACTC,UAAAA;EACtC;;EAGH,IAAYC,UAA0B;AACpC,WAAOC,uBAAuB,KAAKJ,eAAe;EACpD;;EAGA,MAAMK,KAAQC,SAAiBC,KAAaC,MAA2B;AACrE,UAAMC,SAAS,KAAKP,QAAQQ,IAAIJ,OAAAA;AAChC,QAAI,CAACG,QAAQ;AACX,YAAM,IAAIE,MACR,iBAAiBL,OAAAA,oCAA2C;WAAI,KAAKJ,QAAQU,KAAI;QAAIC,KAAK,IAAA,CAAA,GAAQ;IAEtG;AAEA,QAAI,CAAC,KAAKd,eAAe;AAIvB,YAAMe,UAAU,MAAM,KAAKb,gBAAgB,KAAKE,OAAO;AACvD,UAAI,CAACW,SAAS;AACZ,cAAM,IAAIH,MAAM,4EAAA;MAClB;AACA,WAAKZ,gBAAgBe;IACvB;AAEA,UAAMC,UAAUC,iBAAiB,KAAKjB,aAAa;AACnD,UAAMkB,SAAS,IAAIC,kBAAkBV,QAAQ,CAAC,CAAA,EAAGW,WAAWJ,OAAAA,EAASK,MAAK;AAE1E,WAAOX,OAAOJ,KAAQ;MAAEE;IAAI,GAAGU,MAAAA,EAAQI,UAAS;EAClD;AACF;;;IAxCcC,OAAOC,MAAMC;;;;;;;;;;;;AA+C3B,SAASR,iBAAiBS,KAAgB;AACxC,QAAMC,OAAOC,YAAAA;AACb,aAAW,CAACC,OAAOC,GAAAA,KAAQC,OAAOC,QAAQC,gBAAAA,GAAoD;AAC5F,QAAIP,IAAIG,KAAAA,EAAQF,MAAKO,IAAIJ,KAAKJ,IAAIG,KAAAA,CAAM;EAC1C;AACA,SAAOF;AACT;AANSV;;;AE9DT,SAASkB,UAAAA,SAAQC,cAAAA,mBAAkB;AAEnC,SAASC,qBAAAA,0BAAyB;;;;;;;;;;;;;;;;;;AAG3B,IAAMC,kBAAkBC,OAAO,iBAAA;AAG/B,IAAMC,gCAAN,MAAMA;SAAAA;;;;EACX,YAAsDC,SAAmC;SAAnCA,UAAAA;EAAoC;;EAG1F,MAAMC,KAAQC,SAAiBC,KAAaC,cAA0BC,MAA2B;AAC/F,UAAMC,SAAS,KAAKN,QAAQO,IAAIL,OAAAA;AAChC,QAAI,CAACI,QAAQ;AACX,YAAM,IAAIE,MACR,iBAAiBN,OAAAA,oCAA2C;WAAI,KAAKF,QAAQS,KAAI;QAAIC,KAAK,IAAA,CAAA,GAAQ;IAEtG;AAEA,UAAMC,UAAkC;MACtC,CAACC,iBAAiBC,KAAK,GAAGT,aAAYS;MACtC,CAACD,iBAAiBE,MAAM,GAAGV,aAAYU;MACvC,CAACF,iBAAiBG,MAAM,GAAGX,aAAYW;MACvC,CAACH,iBAAiBI,YAAY,GAAGZ,aAAYY;IAC/C;AAEA,UAAMC,SAAS,IAAIC,mBAAkBb,QAAQ,CAAC,CAAA,EAAGc,WAAWR,OAAAA,EAASS,MAAK;AAC1E,WAAOd,OAAOL,KAAQ;MAAEE;IAAI,GAAGc,MAAAA,EAAQI,UAAS;EAClD;AACF;;;;;;;;;;;;;;;;;;AJhBA,IAAMC,kBAAkBC,OAAO,iBAAA;AAIxB,IAAMC,mBAAN,MAAMA,kBAAAA;SAAAA;;;EACX,OAAwBC,SAAS,IAAIC,QAAOF,kBAAiBG,IAAI;EACjE,OAAeC,aAA4B,CAAA;EAE3C,MAAMC,kBAAkB;AACtB,UAAMC,QAAQC,IAAIP,kBAAiBI,WAAWI,IAAI,CAACC,MAAMA,EAAEC,MAAK,CAAA,CAAA;AAChEV,sBAAiBI,aAAa,CAAA;EAChC;;EAGA,OAAeO,aAAaC,SAAgCC,SAA2C;AACrG,UAAMC,UAAU,oBAAIC,IAAAA;AAEpB,eAAWC,OAAOJ,QAAQK,UAAU;AAClC,YAAMC,QAAQC,mBAAmBC,OAAO;QACtCC,WAAWC,UAAUC;QACrBX,SAAS;UAAEY,SAAS;YAACX;;QAAS;MAChC,CAAA;AACAC,cAAQW,IAAIT,IAAIb,MAAMe,KAAAA;AACtBlB,wBAAiBI,WAAWsB,KAAKR,KAAAA;AACjClB,wBAAiBC,OAAO0B,IAAI,2BAA2BX,IAAIb,IAAI,WAAMU,OAAAA,EAAS;IAChF;AAEA,WAAOC;EACT;;EAGA,OAAOc,QAAQC,cAAyD;AACtE,UAAMC,kBAA4B;MAChCC,SAASC;MACTC,YAAYJ,aAAaI;MACzBC,QAAQL,aAAaK,UAAU,CAAA;IACjC;AAEA,UAAMC,mBAA6B;MACjCJ,SAASK;MACTH,YAAY,wBAACrB,YAAmCA,QAAQyB,iBAA5C;MACZH,QAAQ;QAACF;;IACX;AAEA,UAAMM,kBAA4B;MAChCP,SAASQ;MACTN,YAAY,wBAACrB,SAAgC4B,WAAAA;AAC3C,cAAM3B,UAAUD,QAAQC,WAAW2B,OAAOC,IAAY,YAAY,uBAAA;AAClE,eAAOzC,kBAAiBW,aAAaC,SAASC,OAAAA;MAChD,GAHY;MAIZqB,QAAQ;QAACF;QAAqBU;;IAChC;AAEA,WAAO;MACLC,QAAQ3C;MACR4C,SAAS;QAACC;WAAkBhB,aAAae,WAAW,CAAA;;MACpDE,WAAW;QAAChB;QAAiBK;QAAkBG;QAAiBS;;MAChEC,SAAS;QAACD;;IACZ;EACF;;EAGA,OAAOE,gBAAgBpB,cAAiE;AACtF,UAAMC,kBAA4B;MAChCC,SAASjC;MACTmC,YAAYJ,aAAaI;MACzBC,QAAQL,aAAaK,UAAU,CAAA;IACjC;AAEA,UAAMI,kBAA4B;MAChCP,SAASmB;MACTjB,YAAY,wBAACrB,SAAgC4B,WAAAA;AAC3C,cAAM3B,UAAUD,QAAQC,WAAW2B,OAAOC,IAAY,YAAY,uBAAA;AAClE,eAAOzC,kBAAiBW,aAAaC,SAASC,OAAAA;MAChD,GAHY;MAIZqB,QAAQ;QAACpC;QAAiB4C;;IAC5B;AAEA,WAAO;MACLC,QAAQ3C;MACR4C,SAAS;QAACC;WAAkBhB,aAAae,WAAW,CAAA;;MACpDE,WAAW;QAAChB;QAAiBQ;QAAiBa;;MAC9CH,SAAS;QAACG;;IACZ;EACF;AACF;;;;;","names":["Catch","HttpStatus","Logger","RpcException","throwError","HttpStatus","HttpException","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","RpcProblemExceptionFilter","logger","Logger","name","catch","exception","_host","translatedPgError","tryTranslatePgError","RpcException","throwError","getError","isHttpException","status","getStatus","response","getResponse","payload","toProblemPayload","log","HttpStatus","INTERNAL_SERVER_ERROR","error","warn","call","detail","Error","cause","causeMessage","message","undefined","causeStack","stack","type","errors","JSON","stringify","statusCode","obj","Array","isArray","join","label","createParamDecorator","InternalServerErrorException","NATS_HEADER_KEYS","orgId","userId","siteId","legalEntityId","siteGroupId","siteTimezone","siteCurrencyCode","HEADER_FALLBACKS","getHeader","headers","key","undefined","get","val","Array","isArray","parseNatsHeaders","parsed","field","Object","entries","RpcNatsHeaders","createParamDecorator","_data","ctx","rpcCtx","switchToRpc","getContext","parseNatsHeaders","getHeaders","RpcSiteId","headers","siteId","InternalServerErrorException","RpcSiteCurrencyCode","siteCurrencyCode","Global","Logger","Module","ConfigModule","ConfigService","ClientProxyFactory","Transport","NATS_MODULE_OPTIONS","Symbol","NATS_CONTEXT_RESOLVER","Inject","Injectable","Scope","REQUEST","NatsRecordBuilder","headers","natsHeaders","resolveInjectedRequest","injected","candidate","headers","undefined","req","NATS_CLIENTS","Symbol","NatsClientService","cachedContext","injectedRequest","contextResolver","clients","request","resolveInjectedRequest","send","service","cmd","data","client","get","Error","keys","join","context","headers","contextToHeaders","record","NatsRecordBuilder","setHeaders","build","toPromise","scope","Scope","REQUEST","ctx","hdrs","natsHeaders","field","key","Object","entries","NATS_HEADER_KEYS","set","Inject","Injectable","NatsRecordBuilder","NATS_MS_CLIENTS","Symbol","NatsMicroserviceClientService","clients","send","service","cmd","natsHeaders","data","client","get","Error","keys","join","headers","NATS_HEADER_KEYS","orgId","userId","siteId","siteTimezone","record","NatsRecordBuilder","setHeaders","build","toPromise","NATS_MS_OPTIONS","Symbol","NatsClientModule","logger","Logger","name","allClients","onModuleDestroy","Promise","all","map","c","close","buildClients","options","natsUrl","clients","Map","svc","services","proxy","ClientProxyFactory","create","transport","Transport","NATS","servers","set","push","log","forRoot","asyncOptions","optionsProvider","provide","NATS_MODULE_OPTIONS","useFactory","inject","resolverProvider","NATS_CONTEXT_RESOLVER","contextResolver","clientsProvider","NATS_CLIENTS","config","get","ConfigService","module","imports","ConfigModule","providers","NatsClientService","exports","forMicroservice","NATS_MS_CLIENTS","NatsMicroserviceClientService"]}
|
package/dist/root.cjs
CHANGED
|
@@ -32,9 +32,20 @@ var import_common7 = require("@nestjs/common");
|
|
|
32
32
|
var import_common4 = require("@nestjs/common");
|
|
33
33
|
var import_swagger2 = require("@nestjs/swagger");
|
|
34
34
|
|
|
35
|
-
// src/auth/decorators/
|
|
35
|
+
// src/auth/decorators/require.decorator.ts
|
|
36
36
|
var import_common = require("@nestjs/common");
|
|
37
|
-
var
|
|
37
|
+
var REQUIRE_AUTH_KEY = "requireAuth";
|
|
38
|
+
var AuthType = /* @__PURE__ */ (function(AuthType2) {
|
|
39
|
+
AuthType2["Session"] = "session";
|
|
40
|
+
AuthType2["App"] = "app";
|
|
41
|
+
AuthType2["Cloud"] = "cloud";
|
|
42
|
+
AuthType2["Public"] = "public";
|
|
43
|
+
return AuthType2;
|
|
44
|
+
})({});
|
|
45
|
+
var Require = /* @__PURE__ */ __name((type, ...subtypes) => (0, import_common.SetMetadata)(REQUIRE_AUTH_KEY, {
|
|
46
|
+
type,
|
|
47
|
+
subtypes
|
|
48
|
+
}), "Require");
|
|
38
49
|
|
|
39
50
|
// src/root/docs/app.docs.ts
|
|
40
51
|
var import_common2 = require("@nestjs/common");
|
|
@@ -99,7 +110,7 @@ var AppController = class {
|
|
|
99
110
|
};
|
|
100
111
|
_ts_decorate2([
|
|
101
112
|
(0, import_common4.Get)(),
|
|
102
|
-
Public
|
|
113
|
+
Require(AuthType.Public),
|
|
103
114
|
ApiHealthCheck(),
|
|
104
115
|
_ts_metadata("design:type", Function),
|
|
105
116
|
_ts_metadata("design:paramtypes", []),
|
|
@@ -177,7 +188,7 @@ var CsrfController = class {
|
|
|
177
188
|
};
|
|
178
189
|
_ts_decorate3([
|
|
179
190
|
(0, import_common6.Get)("token"),
|
|
180
|
-
Public
|
|
191
|
+
Require(AuthType.Public),
|
|
181
192
|
(0, import_common6.HttpCode)(import_common6.HttpStatus.OK),
|
|
182
193
|
ApiGetCsrfToken(),
|
|
183
194
|
_ts_param(0, (0, import_common6.Res)({
|