Skip to content

Commit 08a4fe3

Browse files
committed
feat: add optional event emission to current event target and fix up memory leak
1 parent 946bfb2 commit 08a4fe3

2 files changed

Lines changed: 69 additions & 10 deletions

File tree

packages/event-bus-client/src/plugin.ts

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export class EventClient<
3030
#retryCount = 0
3131
#maxRetries = 5
3232
#connecting = false
33+
#internalEventTarget: EventTarget | null = null
3334

3435
#onConnected = () => {
3536
this.debugLog('Connected to event bus')
@@ -112,6 +113,7 @@ export class EventClient<
112113
}
113114
clearInterval(this.#connectIntervalId)
114115
this.#connectIntervalId = null
116+
this.#queuedEvents = []
115117
this.debugLog('Stopped connect loop')
116118
}
117119

@@ -189,6 +191,23 @@ export class EventClient<
189191
this.dispatchCustomEvent('tanstack-dispatch-event', event)
190192
}
191193

194+
createEventPayload<
195+
TSuffix extends Extract<
196+
keyof TEventMap,
197+
`${TPluginId & string}:${string}`
198+
> extends `${TPluginId & string}:${infer S}`
199+
? S
200+
: never,
201+
>(
202+
eventSuffix: TSuffix,
203+
payload: TEventMap[`${TPluginId & string}:${TSuffix}`],
204+
) {
205+
return {
206+
type: `${this.#pluginId}:${eventSuffix}`,
207+
payload,
208+
pluginId: this.#pluginId,
209+
}
210+
}
192211
emit<
193212
TSuffix extends Extract<
194213
keyof TEventMap,
@@ -200,6 +219,18 @@ export class EventClient<
200219
eventSuffix: TSuffix,
201220
payload: TEventMap[`${TPluginId & string}:${TSuffix}`],
202221
) {
222+
if (this.#internalEventTarget) {
223+
this.debugLog(
224+
'Emitting event to internal event target',
225+
eventSuffix,
226+
payload,
227+
)
228+
this.#internalEventTarget.dispatchEvent(
229+
new CustomEvent(`${this.#pluginId}:${eventSuffix}`, {
230+
detail: this.createEventPayload(eventSuffix, payload),
231+
}),
232+
)
233+
}
203234
if (!this.#enabled) {
204235
this.debugLog(
205236
'Event bus client is disabled, not emitting event',
@@ -211,11 +242,7 @@ export class EventClient<
211242
// wait to connect to the bus
212243
if (!this.#connected) {
213244
this.debugLog('Bus not available, will be pushed as soon as connected')
214-
this.#queuedEvents.push({
215-
type: `${this.#pluginId}:${eventSuffix}`,
216-
payload,
217-
pluginId: this.#pluginId,
218-
})
245+
this.#queuedEvents.push(this.createEventPayload(eventSuffix, payload))
219246
// start connection to event bus
220247
if (typeof CustomEvent !== 'undefined' && !this.#connecting) {
221248
this.#connectFunction()
@@ -224,11 +251,7 @@ export class EventClient<
224251
return
225252
}
226253
// emit right now
227-
return this.emitEventToBus({
228-
type: `${this.#pluginId}:${eventSuffix}`,
229-
payload,
230-
pluginId: this.#pluginId,
231-
})
254+
return this.emitEventToBus(this.createEventPayload(eventSuffix, payload))
232255
}
233256

234257
on<
@@ -246,8 +269,20 @@ export class EventClient<
246269
TEventMap[`${TPluginId & string}:${TSuffix}`]
247270
>,
248271
) => void,
272+
options?: {
273+
withEventTarget?: boolean
274+
},
249275
) {
276+
const withEventTarget = options?.withEventTarget ?? false
250277
const eventName = `${this.#pluginId}:${eventSuffix}` as const
278+
if (withEventTarget) {
279+
if (!this.#internalEventTarget) {
280+
this.#internalEventTarget = new EventTarget()
281+
}
282+
this.#internalEventTarget.addEventListener(eventName, (e) => {
283+
cb((e as CustomEvent).detail)
284+
})
285+
}
251286
if (!this.#enabled) {
252287
this.debugLog(
253288
'Event bus client is disabled, not registering event',
@@ -262,6 +297,9 @@ export class EventClient<
262297
this.#eventTarget().addEventListener(eventName, handler)
263298
this.debugLog('Registered event to bus', eventName)
264299
return () => {
300+
if (withEventTarget) {
301+
this.#internalEventTarget?.removeEventListener(eventName, handler)
302+
}
265303
this.#eventTarget().removeEventListener(eventName, handler)
266304
}
267305
}

packages/event-bus-client/tests/index.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,27 @@ describe('EventClient', () => {
284284
})
285285
})
286286

287+
describe('emitting to internal event target', () => {
288+
it('should initialize and dispatch events to the internal event target', () => {
289+
const client = new EventClient({
290+
debug: false,
291+
pluginId: 'test-internal',
292+
})
293+
const internalEventHandler = vi.fn()
294+
client.on('event', internalEventHandler, {
295+
withEventTarget: true,
296+
})
297+
client.emit('event', { foo: 'bar' })
298+
expect(internalEventHandler).toHaveBeenCalledWith(
299+
expect.objectContaining({
300+
type: 'test-internal:event',
301+
payload: { foo: 'bar' },
302+
pluginId: 'test-internal',
303+
}),
304+
)
305+
})
306+
})
307+
287308
describe('connecting behavior', () => {
288309
it('should only attempt connection once when #connecting flag is set', async () => {
289310
bus.stop()

0 commit comments

Comments
 (0)