Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 19x 19x 19x 12x 19x 38x 19x 42x 19x 3x 3x | import { AsyncLocalStorage } from 'node:async_hooks';
export interface RequestContext {
requestId: string;
/** Authenticated user (JWT subject), set at the gateway after the token is
* verified and propagated to services via the x-user-id header. */
userId?: string;
}
/**
* AsyncLocalStorage keeps the request context reachable from anywhere on the
* async call path — service methods, event publishers — without threading a
* parameter through every signature or resorting to request-scoped providers
* (which would re-instantiate the whole injection subtree per request).
*/
const storage = new AsyncLocalStorage<RequestContext>();
export function runWithRequestContext<T>(
context: RequestContext,
fn: () => T,
): T {
return storage.run(context, fn);
}
export function currentRequestId(): string | undefined {
return storage.getStore()?.requestId;
}
export function currentUserId(): string | undefined {
return storage.getStore()?.userId;
}
/**
* Authentication happens after the context middleware opened the store (the
* guard runs later in the request lifecycle), so the user id is attached by
* mutating the already-open context rather than opening a new one.
*/
export function setCurrentUserId(userId: string): void {
const store = storage.getStore();
if (store) store.userId = userId;
}
|