Skip to content

Commit dabc438

Browse files
committed
feat(wip): migrate setupServer to the new architecture
1 parent d427536 commit dabc438

File tree

4 files changed

+155
-1
lines changed

4 files changed

+155
-1
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { AsyncLocalStorage } from 'node:async_hooks'
2+
import { HandlersController, AnyHandler } from '~/core/new/handlers-controller'
3+
4+
export interface AsyncHandlersController<Handler extends AnyHandler>
5+
extends HandlersController<Handler> {
6+
context: AsyncLocalStorage<AsyncHandlersControllerContext<Handler>>
7+
}
8+
9+
export interface AsyncHandlersControllerContext<Handler extends AnyHandler> {
10+
initialHandlers: Array<Handler>
11+
handlers: Array<Handler>
12+
}
13+
14+
export function asyncHandlersController<Handler extends AnyHandler>(
15+
initialHandlers: Array<Handler>,
16+
): AsyncHandlersController<Handler> {
17+
const context = new AsyncLocalStorage<
18+
AsyncHandlersControllerContext<Handler>
19+
>()
20+
const fallbackContext: AsyncHandlersControllerContext<Handler> = {
21+
initialHandlers: [...initialHandlers],
22+
handlers: [],
23+
}
24+
25+
const getContext = () => {
26+
return context.getStore() || fallbackContext
27+
}
28+
29+
return {
30+
context,
31+
currentHandlers() {
32+
const { initialHandlers, handlers } = getContext()
33+
return [...initialHandlers, ...handlers]
34+
},
35+
use(nextHandlers) {
36+
getContext().handlers.unshift(...nextHandlers)
37+
},
38+
reset(nextHandlers) {
39+
const context = getContext()
40+
context.handlers = []
41+
context.initialHandlers =
42+
nextHandlers.length > 0 ? nextHandlers : context.initialHandlers
43+
},
44+
}
45+
}

src/node/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
export type { SetupServer, ListenOptions } from './glossary'
22
export { SetupServerApi } from './SetupServerApi'
3-
export { setupServer } from './setupServer'
3+
// export { setupServer } from './setupServer'
44
export {
55
setupRemoteServer,
66
SetupRemoteServer,
77
SetupRemoteServerApi,
88
} from './setup-remote-server'
9+
10+
export { setupServer } from './setup-server'
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { Interceptor } from '@mswjs/interceptors'
2+
import { defineNetwork, type NetworkApi } from '~/core/new/define-network'
3+
import type {
4+
AnyHandler,
5+
HandlersController,
6+
} from '~/core/new/handlers-controller'
7+
import { InterceptorSource } from '~/core/new/sources/interceptor-source'
8+
import type { SetupServerCommon } from './glossary'
9+
10+
export class SetupServerCommonApi implements SetupServerCommon {
11+
protected network: NetworkApi<AnyHandler>
12+
13+
public events: SetupServerCommon['events']
14+
public use: SetupServerCommon['use']
15+
public resetHandlers: SetupServerCommon['resetHandlers']
16+
public restoreHandlers: SetupServerCommon['restoreHandlers']
17+
public listHandlers: SetupServerCommon['listHandlers']
18+
19+
constructor(
20+
interceptors: Array<Interceptor<any>> = [],
21+
handlers: Array<AnyHandler>,
22+
handlersController?: HandlersController<AnyHandler>,
23+
) {
24+
this.network = defineNetwork({
25+
sources: [
26+
new InterceptorSource({
27+
interceptors,
28+
}),
29+
],
30+
handlers,
31+
handlersController,
32+
})
33+
34+
this.events = this.network.events
35+
this.use = this.network.use.bind(this.network)
36+
this.resetHandlers = this.network.resetHandlers.bind(this.network)
37+
this.restoreHandlers = this.network.restoreHandlers.bind(this.network)
38+
this.listHandlers = this.network.listHandlers.bind(this.network)
39+
}
40+
41+
public listen(): void {
42+
this.network.enable()
43+
}
44+
45+
public close(): void {
46+
this.network.disable()
47+
}
48+
}

src/node/setup-server.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { type Interceptor } from '@mswjs/interceptors'
2+
import { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest'
3+
import { FetchInterceptor } from '@mswjs/interceptors/fetch'
4+
import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'
5+
import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'
6+
import { type AnyHandler } from '~/core/new/handlers-controller'
7+
import { SetupServerCommonApi } from './setup-server-common-api'
8+
import {
9+
type AsyncHandlersController,
10+
asyncHandlersController,
11+
} from './async-handler-controller'
12+
import type { SetupServer } from './glossary'
13+
14+
export function setupServer(...handlers: Array<AnyHandler>): SetupServerApi {
15+
return new SetupServerApi(handlers)
16+
}
17+
18+
export class SetupServerApi
19+
extends SetupServerCommonApi
20+
implements SetupServer
21+
{
22+
protected handlersController: AsyncHandlersController<AnyHandler>
23+
24+
constructor(
25+
handlers: Array<AnyHandler>,
26+
interceptors: Array<Interceptor<any>> = [
27+
new ClientRequestInterceptor(),
28+
new XMLHttpRequestInterceptor(),
29+
new FetchInterceptor(),
30+
new WebSocketInterceptor(),
31+
],
32+
) {
33+
const handlersController = asyncHandlersController(handlers)
34+
super(interceptors, handlers, handlersController)
35+
36+
this.handlersController = handlersController
37+
}
38+
39+
public listen(): void {
40+
super.listen()
41+
42+
/** @todo Check for remote option. */
43+
}
44+
45+
public boundary<Args extends Array<any>, R>(
46+
callback: (...args: Args) => R,
47+
): (...args: Args) => R {
48+
return (...args: Args): R => {
49+
return this.handlersController.context.run<any, any>(
50+
{
51+
initialHandlers: this.handlersController.currentHandlers(),
52+
handlers: [],
53+
},
54+
callback,
55+
...args,
56+
)
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)