diff --git a/package.json b/package.json index 703417b42..95e77835f 100644 --- a/package.json +++ b/package.json @@ -252,7 +252,7 @@ "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", - "strict-event-emitter": "^0.5.1", + "rettime": "^0.6.2", "type-fest": "^4.26.1", "yargs": "^17.7.2" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfba973f6..a81b9db0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,9 +53,9 @@ importers: picocolors: specifier: ^1.1.1 version: 1.1.1 - strict-event-emitter: - specifier: ^0.5.1 - version: 0.5.1 + rettime: + specifier: ^0.6.2 + version: 0.6.2 type-fest: specifier: ^4.26.1 version: 4.29.0 @@ -4291,6 +4291,9 @@ packages: resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} engines: {node: '>=10'} + rettime@0.6.2: + resolution: {integrity: sha512-0mHwLbBt6kLnt5UOiJWWcq0LiCSrBRpyANgIBP4CPE1pkbutGACXvLtdIjcltV4B0C3DffB7T1YN07gw2iEbag==} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -9623,6 +9626,8 @@ snapshots: ret@0.4.3: {} + rettime@0.6.2: {} + reusify@1.0.4: {} rfdc@1.3.1: {} diff --git a/src/browser/setupWorker/glossary.ts b/src/browser/setupWorker/glossary.ts index 38ad656bf..176d95f06 100644 --- a/src/browser/setupWorker/glossary.ts +++ b/src/browser/setupWorker/glossary.ts @@ -1,4 +1,4 @@ -import { Emitter } from 'strict-event-emitter' +import { Emitter } from 'rettime' import { LifeCycleEventEmitter, LifeCycleEventsMap, @@ -95,7 +95,7 @@ export interface SetupWorkerInternalContext { /** * Adds a Service Worker event listener. */ - on( + on: ( eventType: EventType, callback: ( event: MessageEvent, @@ -104,10 +104,10 @@ export interface SetupWorkerInternalContext { ServiceWorkerIncomingEventsMap[EventType] >, ) => void, - ): void - send( + ) => void + send: ( eventType: EventType, - ): void + ) => void } events: { /** @@ -122,13 +122,13 @@ export interface SetupWorkerInternalContext { /** * Removes all currently attached listeners. */ - removeAllListeners(): void + removeAllListeners: () => void /** * Awaits a given message type from the Service Worker. */ - once( + once: ( eventType: EventType, - ): Promise< + ) => Promise< ServiceWorkerMessage > } @@ -235,7 +235,7 @@ export interface SetupWorker { * * @see {@link https://mswjs.io/docs/api/setup-worker/list-handlers `worker.listHandlers()` API reference} */ - listHandlers(): ReadonlyArray + listHandlers: () => ReadonlyArray /** * Life-cycle events. diff --git a/src/core/SetupApi.ts b/src/core/SetupApi.ts index e908e5994..fba8942ef 100644 --- a/src/core/SetupApi.ts +++ b/src/core/SetupApi.ts @@ -1,5 +1,5 @@ import { invariant } from 'outvariant' -import { EventMap, Emitter } from 'strict-event-emitter' +import { Emitter, type DefaultEventMap } from 'rettime' import { RequestHandler } from './handlers/RequestHandler' import { LifeCycleEventEmitter } from './sharedOptions' import { devUtils } from './utils/internal/devUtils' @@ -12,8 +12,10 @@ export abstract class HandlersController { abstract prepend( runtimeHandlers: Array, ): void - abstract reset(nextHandles: Array): void - abstract currentHandlers(): Array + abstract reset: ( + nextHandles: Array, + ) => void + abstract currentHandlers: () => Array } export class InMemoryHandlersController implements HandlersController { @@ -44,12 +46,14 @@ export class InMemoryHandlersController implements HandlersController { /** * Generic class for the mock API setup. */ -export abstract class SetupApi extends Disposable { +export abstract class SetupApi< + EventMap extends DefaultEventMap, +> extends Disposable { protected handlersController: HandlersController - protected readonly emitter: Emitter - protected readonly publicEmitter: Emitter + protected readonly emitter: Emitter + protected readonly publicEmitter: Emitter - public readonly events: LifeCycleEventEmitter + public readonly events: LifeCycleEventEmitter constructor(...initialHandlers: Array) { super() @@ -63,8 +67,8 @@ export abstract class SetupApi extends Disposable { this.handlersController = new InMemoryHandlersController(initialHandlers) - this.emitter = new Emitter() - this.publicEmitter = new Emitter() + this.emitter = new Emitter() + this.publicEmitter = new Emitter() pipeEvents(this.emitter, this.publicEmitter) this.events = this.createLifeCycleEvents() @@ -111,17 +115,15 @@ export abstract class SetupApi extends Disposable { return toReadonlyArray(this.handlersController.currentHandlers()) } - private createLifeCycleEvents(): LifeCycleEventEmitter { + private createLifeCycleEvents(): LifeCycleEventEmitter { return { - on: (...args: any[]) => { - return (this.publicEmitter.on as any)(...args) - }, - removeListener: (...args: any[]) => { - return (this.publicEmitter.removeListener as any)(...args) - }, - removeAllListeners: (...args: any[]) => { - return this.publicEmitter.removeAllListeners(...args) - }, + on: this.publicEmitter.on.bind(this.publicEmitter), + removeListener: this.publicEmitter.removeListener.bind( + this.publicEmitter, + ), + removeAllListeners: this.publicEmitter.removeAllListeners.bind( + this.publicEmitter, + ), } } } diff --git a/src/core/handlers/WebSocketHandler.ts b/src/core/handlers/WebSocketHandler.ts index 22ea65f6e..49ae53494 100644 --- a/src/core/handlers/WebSocketHandler.ts +++ b/src/core/handlers/WebSocketHandler.ts @@ -1,4 +1,4 @@ -import { Emitter } from 'strict-event-emitter' +import { type DefaultEventMap, Emitter, TypedEvent } from 'rettime' import { createRequestId } from '@mswjs/interceptors' import type { WebSocketClientConnectionProtocol, @@ -18,8 +18,8 @@ type WebSocketHandlerParsedResult = { match: Match } -export type WebSocketHandlerEventMap = { - connection: [args: WebSocketHandlerConnection] +export interface WebSocketHandlerEventMap extends DefaultEventMap { + connection: TypedEvent } export interface WebSocketHandlerConnection { @@ -136,7 +136,9 @@ export class WebSocketHandler { // Emit the connection event on the handler. // This is what the developer adds listeners for. - return this[kEmitter].emit('connection', connection) + return this[kEmitter].emit( + new TypedEvent('connection', { data: connection }), + ) } } diff --git a/src/core/sharedOptions.ts b/src/core/sharedOptions.ts index ad7f151a2..30d1f2d40 100644 --- a/src/core/sharedOptions.ts +++ b/src/core/sharedOptions.ts @@ -1,4 +1,4 @@ -import type { Emitter } from 'strict-event-emitter' +import type { Emitter, DefaultEventMap } from 'rettime' import type { UnhandledRequestStrategy } from './utils/request/onUnhandledRequest' export interface SharedOptions { @@ -13,7 +13,7 @@ export interface SharedOptions { onUnhandledRequest?: UnhandledRequestStrategy } -export type LifeCycleEventsMap = { +export interface LifeCycleEventsMap extends DefaultEventMap { 'request:start': [ args: { request: Request @@ -61,6 +61,7 @@ export type LifeCycleEventsMap = { ] } -export type LifeCycleEventEmitter< - EventsMap extends Record, -> = Pick, 'on' | 'removeListener' | 'removeAllListeners'> +export type LifeCycleEventEmitter = Pick< + Emitter, + 'on' | 'removeListener' | 'removeAllListeners' +> diff --git a/src/core/utils/handleRequest.test.ts b/src/core/utils/handleRequest.test.ts index 932276450..7e7148bd4 100644 --- a/src/core/utils/handleRequest.test.ts +++ b/src/core/utils/handleRequest.test.ts @@ -1,5 +1,5 @@ // @vitest-environment jsdom -import { Emitter } from 'strict-event-emitter' +import { Emitter } from 'rettime' import { createRequestId } from '@mswjs/interceptors' import { LifeCycleEventsMap, SharedOptions } from '../sharedOptions' import { RequestHandler } from '../handlers/RequestHandler' diff --git a/src/core/utils/handleRequest.ts b/src/core/utils/handleRequest.ts index b7cd2599e..fe6cc9ab7 100644 --- a/src/core/utils/handleRequest.ts +++ b/src/core/utils/handleRequest.ts @@ -1,5 +1,5 @@ import { until } from '@open-draft/until' -import { Emitter } from 'strict-event-emitter' +import { Emitter } from 'rettime' import { LifeCycleEventsMap, SharedOptions } from '../sharedOptions' import { RequiredDeep } from '../typeUtils' import type { RequestHandler } from '../handlers/RequestHandler' diff --git a/src/core/utils/internal/pipeEvents.test.ts b/src/core/utils/internal/pipeEvents.test.ts index 77dff7f4f..f123af1a8 100644 --- a/src/core/utils/internal/pipeEvents.test.ts +++ b/src/core/utils/internal/pipeEvents.test.ts @@ -1,4 +1,4 @@ -import { Emitter } from 'strict-event-emitter' +import { Emitter, TypedEvent } from 'rettime' import { pipeEvents } from './pipeEvents' it('pipes events from the source emitter to the destination emitter', () => { @@ -9,6 +9,7 @@ it('pipes events from the source emitter to the destination emitter', () => { const callback = vi.fn() destination.on('hello', callback) - source.emit('hello', 'world', { data: true }) - expect(callback).toHaveBeenNthCalledWith(1, 'world', { data: true }) + const event = new TypedEvent('hello', { data: 'world' }) + source.emit(event) + expect(callback).toHaveBeenNthCalledWith(1, event) }) diff --git a/src/core/utils/internal/pipeEvents.ts b/src/core/utils/internal/pipeEvents.ts index 43b57cd4e..02165bd71 100644 --- a/src/core/utils/internal/pipeEvents.ts +++ b/src/core/utils/internal/pipeEvents.ts @@ -1,11 +1,11 @@ -import { Emitter, EventMap } from 'strict-event-emitter' +import type { Emitter, DefaultEventMap } from 'rettime' /** * Pipes all emitted events from one emitter to another. */ -export function pipeEvents( - source: Emitter, - destination: Emitter, +export function pipeEvents( + source: Emitter, + destination: Emitter, ): void { const rawEmit: typeof source.emit & { _isPiped?: boolean } = source.emit @@ -14,9 +14,9 @@ export function pipeEvents( } const sourceEmit: typeof source.emit & { _isPiped?: boolean } = - function sourceEmit(this: typeof source, event, ...data) { - destination.emit(event, ...data) - return rawEmit.call(this, event, ...data) + function sourceEmit(this: typeof source, event) { + destination.emit(event) + return rawEmit.call(this, event) } sourceEmit._isPiped = true diff --git a/src/core/ws.ts b/src/core/ws.ts index 745615951..c79501245 100644 --- a/src/core/ws.ts +++ b/src/core/ws.ts @@ -116,8 +116,8 @@ function createWebSocketLinkHandler(url: Path): WebSocketLink { // handler matches and emits a connection event. // When that happens, store that connection in the // set of all connections for reference. - handler[kEmitter].on('connection', async ({ client }) => { - await clientManager.addConnection(client) + handler[kEmitter].on('connection', async (event) => { + await clientManager.addConnection(event.data.client) }) // The "handleWebSocketEvent" function will invoke diff --git a/test/browser/setup/workerConsole.ts b/test/browser/setup/workerConsole.ts index 61facd836..188e7dc02 100644 --- a/test/browser/setup/workerConsole.ts +++ b/test/browser/setup/workerConsole.ts @@ -1,5 +1,5 @@ import { format } from 'outvariant' -import { Emitter } from 'strict-event-emitter' +import { type DefaultEventMap, Emitter, TypedEvent } from 'rettime' import { type Page } from '@playwright/test' type WorkerConsoleMessageType = @@ -33,8 +33,8 @@ type WorkerConsoleMessageType = | 'context' | 'memory' -type WorkerConsoleEventMap = { - [MessageType in WorkerConsoleMessageType]: [message: string] +type WorkerConsoleEventMap = DefaultEventMap & { + [MessageType in WorkerConsoleMessageType]: TypedEvent } type InternalWorkerConsoleMessageData = { @@ -85,7 +85,7 @@ export class WorkerConsole extends Emitter { const formattedMessage = format(template, ...positionals) this.addMessage(messageType, formattedMessage) - this.emit(messageType, formattedMessage) + this.emit(new TypedEvent(messageType, { data: formattedMessage })) }, ) diff --git a/test/support/WebSocketServer.ts b/test/support/WebSocketServer.ts index 8995fb8d7..e16ce6b87 100644 --- a/test/support/WebSocketServer.ts +++ b/test/support/WebSocketServer.ts @@ -1,12 +1,12 @@ import { invariant } from 'outvariant' -import { Emitter } from 'strict-event-emitter' +import { type DefaultEventMap, Emitter, TypedEvent } from 'rettime' import fastify, { FastifyInstance } from 'fastify' import fastifyWebSocket, { SocketStream } from '@fastify/websocket' type FastifySocket = SocketStream['socket'] -type WebSocketEventMap = { - connection: [client: FastifySocket] +interface WebSocketEventMap extends DefaultEventMap { + connection: TypedEvent } export class WebSocketServer extends Emitter { @@ -24,8 +24,7 @@ export class WebSocketServer extends Emitter { fastify.get('/', { websocket: true }, ({ socket }) => { this.clients.add(socket) socket.once('close', () => this.clients.delete(socket)) - - this.emit('connection', socket) + this.emit(new TypedEvent('connection', { data: socket })) }) }) }