UNPKG

msw

Version:

Seamless REST/GraphQL API mocking library for browser and Node.js.

88 lines (76 loc) 2.79 kB
import { AsyncLocalStorage } from 'node:async_hooks' import type { HttpRequestEventMap, Interceptor } from '@mswjs/interceptors' 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>, interceptors: Array<Interceptor<HttpRequestEventMap>> = [ new ClientRequestInterceptor(), new XMLHttpRequestInterceptor(), new FetchInterceptor(), ], ) { super(interceptors, 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() } }