Spaces:
Running
Running
import { AsyncLocalStorage } from 'node:async_hooks' | |
import { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest' | |
import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest' | |
import { FetchInterceptor } from '@mswjs/interceptors/fetch' | |
import { HandlersController } from '~/core/SetupApi' | |
import type { RequestHandler } from '~/core/handlers/RequestHandler' | |
import type { WebSocketHandler } from '~/core/handlers/WebSocketHandler' | |
import type { SetupServer } from './glossary' | |
import { SetupServerCommonApi } from './SetupServerCommonApi' | |
const store = new AsyncLocalStorage<RequestHandlersContext>() | |
type RequestHandlersContext = { | |
initialHandlers: Array<RequestHandler | WebSocketHandler> | |
handlers: Array<RequestHandler | WebSocketHandler> | |
} | |
/** | |
* A handlers controller that utilizes `AsyncLocalStorage` in Node.js | |
* to prevent the request handlers list from being a shared state | |
* across mutliple tests. | |
*/ | |
class AsyncHandlersController implements HandlersController { | |
private rootContext: RequestHandlersContext | |
constructor(initialHandlers: Array<RequestHandler | WebSocketHandler>) { | |
this.rootContext = { initialHandlers, handlers: [] } | |
} | |
get context(): RequestHandlersContext { | |
return store.getStore() || this.rootContext | |
} | |
public prepend(runtimeHandlers: Array<RequestHandler | WebSocketHandler>) { | |
this.context.handlers.unshift(...runtimeHandlers) | |
} | |
public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>) { | |
const context = this.context | |
context.handlers = [] | |
context.initialHandlers = | |
nextHandlers.length > 0 ? nextHandlers : context.initialHandlers | |
} | |
public currentHandlers(): Array<RequestHandler | WebSocketHandler> { | |
const { initialHandlers, handlers } = this.context | |
return handlers.concat(initialHandlers) | |
} | |
} | |
export class SetupServerApi | |
extends SetupServerCommonApi | |
implements SetupServer | |
{ | |
constructor(handlers: Array<RequestHandler | WebSocketHandler>) { | |
super( | |
[ClientRequestInterceptor, XMLHttpRequestInterceptor, FetchInterceptor], | |
handlers, | |
) | |
this.handlersController = new AsyncHandlersController(handlers) | |
} | |
public boundary<Args extends Array<any>, R>( | |
callback: (...args: Args) => R, | |
): (...args: Args) => R { | |
return (...args: Args): R => { | |
return store.run<any, any>( | |
{ | |
initialHandlers: this.handlersController.currentHandlers(), | |
handlers: [], | |
}, | |
callback, | |
...args, | |
) | |
} | |
} | |
public close(): void { | |
super.close() | |
store.disable() | |
} | |
} | |