/* eslint-disable @typescript-eslint/no-shadow */ /* eslint-disable guard-for-in */ /* eslint-disable spaced-comment */ import type { MaybePromise } from 'viem/types/utils' type Callback = ((...args: any[]) => any) | undefined type Callbacks = Record export const listenersCache = /*#__PURE__*/ new Map() export const cleanupCache = /*#__PURE__*/ new Map void>() type EmitFunction = ( emit: TCallbacks, // biome-ignore lint/suspicious/noConfusingVoidType: ) => MaybePromise void)> let callbackCount = 0 /** * @description Sets up an observer for a given function. If another function * is set up under the same observer id, the function will only be called once * for both instances of the observer. */ export function observe( observerId: string, callbacks: TCallbacks, fn: EmitFunction, ) { const callbackId = ++callbackCount const getListeners = () => listenersCache.get(observerId) || [] const unsubscribe = () => { const listeners = getListeners() listenersCache.set( observerId, listeners.filter((cb: any) => cb.id !== callbackId), ) } const unwatch = () => { const cleanup = cleanupCache.get(observerId) if (getListeners().length === 1 && cleanup) cleanup() unsubscribe() } const listeners = getListeners() listenersCache.set(observerId, [...listeners, { id: callbackId, fns: callbacks }]) if (listeners && listeners.length > 0) return unwatch const emit: TCallbacks = {} as TCallbacks for (const key in callbacks) { emit[key] = ((...args: Parameters>) => { const listeners = getListeners() if (listeners.length === 0) return for (const listener of listeners) { listener.fns[key]?.(...args) } }) as TCallbacks[Extract] } const cleanup = fn(emit) if (typeof cleanup === 'function') cleanupCache.set(observerId, cleanup) return unwatch }