59 lines
1.2 KiB
TypeScript
59 lines
1.2 KiB
TypeScript
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
import { RequestContext } from './request-context.type';
|
|
|
|
@Injectable()
|
|
/**
|
|
* RequestContext holds per-request metadata including:
|
|
* - HTTP request
|
|
* - Auth payload (decoded JWT, optional)
|
|
* - Prisma transaction client (optional)
|
|
* - Correlation ID and other future cross-cutting concerns
|
|
*/
|
|
export class RequestContextService {
|
|
private readonly als = new AsyncLocalStorage<RequestContext>();
|
|
|
|
run(context: RequestContext, fn: () => void) {
|
|
this.als.run(context, fn);
|
|
}
|
|
|
|
get(): RequestContext {
|
|
const store = this.als.getStore();
|
|
if (!store) {
|
|
throw new Error('RequestContext not initialized');
|
|
}
|
|
return store;
|
|
}
|
|
|
|
set<K extends keyof RequestContext>(key: K, value: RequestContext[K]) {
|
|
this.get()[key] = value;
|
|
}
|
|
|
|
// Helpers
|
|
get user() {
|
|
const user = this.get().user;
|
|
if (!user) throw new UnauthorizedException();
|
|
return user;
|
|
}
|
|
|
|
get tx() {
|
|
return this.get().tx;
|
|
}
|
|
|
|
set tx(tx) {
|
|
this.set('tx', tx);
|
|
}
|
|
|
|
get isTransaction(): boolean {
|
|
return !!this.get().tx;
|
|
}
|
|
|
|
get orgId(): string {
|
|
return this.orgId
|
|
}
|
|
|
|
set orgId(id: string) {
|
|
this.set('orgId', id)
|
|
}
|
|
}
|