import { AsyncLocalStorage } from 'async_hooks' ; import type { EntityManager } from '../EntityManager' ; /**
 * Uses `AsyncLocalStorage` to create async context that holds current EM fork.
 */ export class RequestContext { private static storage = new AsyncLocalStorage < RequestContext > ( ) ; private static counter = 1 ; readonly id = RequestContext . counter ++ ; constructor ( readonly map ) { } /**
     * Returns default EntityManager.
     */ get em ( ) : EntityManager | undefined { return this . map . get ( 'default' ) ; } /**
     * Creates new RequestContext instance and runs the code inside its domain.
     */ static create ( em , next ) { const ctx = this . createContext ( em ) ; this . storage . run ( ctx , next ) ; } /**
     * Creates new RequestContext instance and runs the code inside its domain.
     * Async variant, when the `next` handler needs to be awaited (like in Koa).
     */ static async createAsync < T > ( em , next ) { const ctx = this . createContext ( em ) ; return new Promise ( ( resolve , reject ) => { this . storage . run ( ctx , ( ) => next ( ) . then ( resolve ) . catch ( reject ) ) ; } ) ; } /**
     * Returns current RequestContext (if available).
     */ static currentRequestContext ( ) { return this . storage . getStore ( ) ; } /**
     * Returns current EntityManager (if available).
     */ static getEntityManager ( name = 'default' ) { const context = RequestContext . currentRequestContext ( ) ; return context ? context . map . get ( name ) : undefined ; } private static createContext ( em ) { const forks = new Map < string , EntityManager > ( ) ; if ( Array . isArray ( em ) ) { em . forEach ( em => forks . set ( em . name , em . fork ( { clear : true , useContext : true } ) ) ) ; } else { forks . set ( em . name , em . fork ( { clear : true , useContext : true } ) ) ; } return new RequestContext ( forks ) ; } }