@vielzeug/herald 26.10.0 → 26.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,4 +38,4 @@ stop();
38
38
 
39
39
  ## License
40
40
 
41
- MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
41
+ MIT © [Helmuth Saatkamp](https://github.com/helmuthdu): part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
package/dist/bus.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bus.cjs","names":[],"sources":["../src/bus.ts"],"sourcesContent":["import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop — shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bus.cjs","names":[],"sources":["../src/bus.ts"],"sourcesContent":["import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop: shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
package/dist/bus.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bus.js","names":[],"sources":["../src/bus.ts"],"sourcesContent":["import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop — shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bus.js","names":[],"sources":["../src/bus.ts"],"sourcesContent":["import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop: shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"herald.cjs","names":[],"sources":["../src/_dev.ts","../src/errors.ts","../src/bus.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n","/** Base class for all herald errors. Use `instanceof HeraldError` to catch any herald-originated error. */\nexport class HeraldError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed event bus. */\nexport class BusDisposedError extends HeraldError {\n constructor(busName?: string) {\n super(busName ? `Bus \"${busName}\" is disposed` : 'Bus is disposed');\n }\n}\n","import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop — shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"herald.cjs","names":[],"sources":["../src/_dev.ts","../src/errors.ts","../src/bus.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n","/** Base class for all herald errors. Use `instanceof HeraldError` to catch any herald-originated error. */\nexport class HeraldError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed event bus. */\nexport class BusDisposedError extends HeraldError {\n constructor(busName?: string) {\n super(busName ? `Bus \"${busName}\" is disposed` : 'Bus is disposed');\n }\n}\n","import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop: shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"herald.iife.js","names":[],"sources":["../src/_dev.ts","../src/errors.ts","../src/bus.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n","/** Base class for all herald errors. Use `instanceof HeraldError` to catch any herald-originated error. */\nexport class HeraldError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed event bus. */\nexport class BusDisposedError extends HeraldError {\n constructor(busName?: string) {\n super(busName ? `Bus \"${busName}\" is disposed` : 'Bus is disposed');\n }\n}\n","import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop — shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"qFCCA,IAAa,YAAb,cAAiC,KAAM,CACrC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,iBAAb,cAAsC,WAAY,CAChD,YAAY,EAAkB,CAC5B,MAAM,EAAU,QAAQ,EAAQ,eAAiB,iBAAiB,CACpE,CACF,ECEa,SAAa,CAAC,EAY3B,SAAgB,UAAwD,EAA8B,CACpG,IAAM,EAAY,IAAI,IAChB,EAAY,IAAI,IAChB,EAAU,IAAI,IACd,EAAoB,IAAI,gBACxB,EAAU,GAAS,KACnB,EAAe,GAAS,aACxB,EAAS,EAAU,KAAK,EAAQ,GAAK,GAE3C,SAAS,QAAQ,EAA6B,CACxC,KAAQ,OAAS,EACrB,IAAK,IAAM,KAAU,EACnB,GAAI,CACF,EAAO,CAAK,CACd,MAAQ,CAER,CAEJ,CAMA,SAAS,wBAAwB,EAAmC,CAClE,OAAO,EAAS,YAAY,IAAI,CAAC,EAAkB,OAAQ,CAAM,CAAC,EAAI,EAAkB,MAC1F,CAEA,SAAS,cACP,EACA,EACA,EACA,CAAE,QAAO,QAAO,WAAU,YACd,CACZ,GAAI,EAAO,QAAS,OAAO,KAE3B,IAAI,EAAS,GAEb,SAAS,OAAQ,CACX,IAEJ,EAAS,GACT,EAAU,OAAO,CAAK,EACtB,IAAW,EACX,EAAO,oBAAoB,QAAS,KAAK,EAErC,IAAU,IAAA,GACL,GAAU,QAAQ,CAAE,KAAM,iBAAkB,CAAC,EAD7B,QAAQ,CAAE,QAAO,KAAM,aAAc,CAAC,EAEjE,CAEA,IAAM,EAAQ,EAAU,KAAK,EAc7B,OAZA,EAAU,IAAI,CAAK,EACnB,EAAO,iBAAiB,QAAS,MAAO,CAAE,KAAM,EAAK,CAAC,EAElD,IAAU,IAAA,GACL,GAAU,QAAQ,CAAE,KAAM,eAAgB,CAAC,EAD3B,QAAQ,CAAE,QAAO,KAAM,WAAY,CAAC,EAGzD,IAAiB,IAAA,IAAa,EAAU,KAAO,GAE/C,GAAG,EAAH,EAAgB,EAAU,KAA1B,EAAqE,EAArE,EAA4G,EAA5G,EAIG,KACT,CAEA,SAAS,aACP,EACA,EACA,EACA,EACY,CACZ,IAAI,EAAM,EAAU,IAAI,CAAK,EAExB,IACH,EAAM,IAAI,IACV,EAAU,IAAI,EAAO,CAAG,GAG1B,IAAM,EAAc,EAEpB,OAAO,cAAc,EAAc,IAAW,CAAE,GAAI,EAA+B,OAAM,GAAI,EAAQ,CACnG,QACA,MAAO,OAAO,EAAM,IACpB,aAAgB,CACV,EAAY,OAAS,GAAG,EAAU,OAAO,CAAK,EAElD,IAAW,CACb,CACF,CAAC,CACH,CAEA,SAAS,gBACP,EACA,EACA,EACY,CACZ,OAAO,cACL,EACC,IAAW,CAAE,GAAI,EAAuD,OAAM,GAC/E,EACA,CAAE,MAAO,QAAS,WAAU,SAAU,EAAK,CAC7C,CACF,CAEA,SAAS,eACP,EACA,EACA,EACA,EACY,CACZ,IAAM,EAAM,CAAE,MAAO,IAAoB,EAYzC,MAVA,GAAI,MAAQ,aACV,EACC,GAAY,CACX,EAAI,MAAM,EACV,EAAS,CAAO,CAClB,EACA,EACA,CACF,EAEO,EAAI,KACb,CAEA,SAAS,GAA0B,EAAU,EAA0B,EAAqC,CAC1G,OAAO,aAAa,EAAO,EAAU,wBAAwB,GAAM,MAAM,CAAC,CAC5E,CAEA,SAAS,KACP,EACA,EACA,EACY,CAGZ,OAAO,eAAe,EAAO,EAFd,wBAAwB,GAAM,MAEN,CAAM,CAC/C,CAEA,SAAS,MAAM,EAA0D,EAAqC,CAC5G,OAAO,gBAAgB,EAAU,wBAAwB,GAAM,MAAM,CAAC,CACxE,CAEA,SAAS,KAA4B,EAAU,EAAgD,CAC7F,IAAM,EAAS,wBAAwB,GAAM,MAAM,EAInD,OAFI,EAAO,QAAgB,QAAQ,OAAO,EAAO,MAAM,EAEhD,IAAI,SAAe,EAAS,IAAW,CAC5C,IAAM,YAAgB,CACpB,EAAO,EAAO,MAAM,CACtB,EAEA,eACE,EACC,GAAY,CACX,EAAO,oBAAoB,QAAS,OAAO,EAC3C,EAAQ,CAAO,CACjB,EACA,CACF,EAEA,EAAO,iBAAiB,QAAS,QAAS,CAAE,KAAM,EAAK,CAAC,CAC1D,CAAC,CACH,CAEA,SAAS,SAAS,EAAoB,EAAwB,CAC5D,IAAI,EAAQ,EACR,EACE,EAAM,EAAU,IAAI,CAAK,EAE/B,GAAI,GAAK,KACP,IAAK,IAAM,IAAS,CAAC,GAAG,CAAG,EAAG,CAC5B,GAAI,CACF,EAAM,GAAG,CAAO,CAClB,OAAS,EAAK,CACZ,IAAe,CAAE,MAAO,CAAI,EAC5B,QAAQ,CAAE,MAAO,EAAK,QAAO,KAAM,OAAQ,CAAC,CAC9C,CAEA,GACF,CAGF,GAAI,EAAU,KACZ,IAAK,IAAM,IAAS,CAAC,GAAG,CAAS,EAAG,CAClC,GAAI,CACF,EAAM,GAAG,EAAO,CAAO,CACzB,OAAS,EAAK,CACZ,IAAe,CAAE,MAAO,CAAI,EAC5B,QAAQ,CAAE,MAAO,EAAK,QAAO,KAAM,OAAQ,CAAC,CAC9C,CAEA,GACF,CAKF,GAFA,QAAQ,CAAE,QAAO,UAAW,EAAO,UAAS,KAAM,MAAO,CAAC,EAEtD,EAAY,MAAM,EAAW,KACnC,CAEA,SAAS,KAA4B,EAAU,GAAG,EAAsD,CACtG,GAAI,EAAkB,OAAO,QAAS,OAEtC,IAAM,EAAW,EAAmB,GAEpC,SAAS,EAAO,CAAO,CACzB,CAEA,SAAS,cAAc,EAA6B,CAClD,GAAI,IAAU,IAAA,GAAW,OAAO,EAAU,IAAI,CAAK,CAAC,EAAE,MAAQ,EAE9D,IAAI,EAAQ,EAEZ,IAAK,IAAM,KAAO,EAAU,OAAO,EAAG,GAAS,EAAI,KAEnD,OAAO,CACT,CAEA,SAAS,eAAwB,CAC/B,OAAO,EAAU,IACnB,CAEA,SAAS,YAA4B,CACnC,MAAO,CAAC,GAAG,EAAU,KAAK,CAAC,CAC7B,CAEA,SAAS,IAAI,EAA0C,EAA6C,CAClG,GAAI,EAAkB,OAAO,QAAS,OAAO,KAE7C,IAAM,EAAS,wBAAwB,GAAM,MAAM,EAEnD,GAAI,EAAO,QAAS,OAAO,KAE3B,EAAQ,IAAI,CAAO,EAEnB,IAAM,YAAgB,EAAQ,OAAO,CAAO,EAI5C,OAFA,EAAO,iBAAiB,QAAS,QAAS,CAAE,KAAM,EAAK,CAAC,MAE3C,CACX,EAAQ,OAAO,CAAO,EACtB,EAAO,oBAAoB,QAAS,OAAO,CAC7C,CACF,CAEA,SAAS,QACP,EACA,EAC8B,CAC9B,IAAM,EAAe,wBAAwB,GAAM,MAAM,EAIzD,OAFI,EAAa,QAAgB,QAAQ,OAAO,EAAa,MAAM,EAE5D,IAAI,SAA8B,EAAS,IAAW,CAC3D,IAAM,EAAiB,IAAI,gBACrB,EAAa,YAAY,IAAI,CAAC,EAAc,EAAe,MAAM,CAAC,EAClE,EAAwB,CAAC,EAC3B,EAAU,GAEd,SAAS,SAAgB,CACvB,EAAa,oBAAoB,QAAS,OAAO,EACjD,EAAe,MAAM,EACrB,IAAK,IAAM,KAAS,EAAQ,EAAM,CACpC,CAEA,SAAS,SAAgB,CACnB,IAEJ,EAAU,GACV,QAAQ,EACR,EAAO,EAAa,MAAM,EAC5B,CAEA,EAAa,iBAAiB,QAAS,QAAS,CAAE,KAAM,EAAK,CAAC,EAE9D,IAAK,IAAM,KAAS,EAClB,EAAO,KACL,eACE,EACC,GAAY,CACP,IAEJ,EAAU,GACV,QAAQ,EACR,EAAQ,CAAE,QAAO,SAAQ,CAAwB,EACnD,EACA,CACF,CACF,CAEJ,CAAC,CACH,CAEA,SAAS,SAAgB,CACnB,EAAkB,OAAO,UAE7B,QAAQ,CAAE,KAAM,SAAU,CAAC,EAC3B,EAAkB,MAAM,IAAI,iBAAiB,CAAO,CAAC,EACrD,EAAU,MAAM,EAChB,EAAU,MAAM,EAChB,EAAQ,MAAM,EAChB,CAEA,MAAO,CACL,IAAI,gBAAiB,CACnB,OAAO,EAAkB,MAC3B,EACA,QACA,IAAI,UAAW,CACb,OAAO,EAAkB,OAAO,OAClC,EACA,KACA,WACA,cACA,GACA,MACA,MACC,OAAO,SAAU,QAClB,IACA,KACA,QACA,aACF,CACF"}
1
+ {"version":3,"file":"herald.iife.js","names":[],"sources":["../src/_dev.ts","../src/errors.ts","../src/bus.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n","/** Base class for all herald errors. Use `instanceof HeraldError` to catch any herald-originated error. */\nexport class HeraldError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed event bus. */\nexport class BusDisposedError extends HeraldError {\n constructor(busName?: string) {\n super(busName ? `Bus \"${busName}\" is disposed` : 'Bus is disposed');\n }\n}\n","import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop: shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"herald.js","names":[],"sources":["../src/_dev.ts","../src/errors.ts","../src/bus.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n","/** Base class for all herald errors. Use `instanceof HeraldError` to catch any herald-originated error. */\nexport class HeraldError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed event bus. */\nexport class BusDisposedError extends HeraldError {\n constructor(busName?: string) {\n super(busName ? `Bus \"${busName}\" is disposed` : 'Bus is disposed');\n }\n}\n","import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop — shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"herald.js","names":[],"sources":["../src/_dev.ts","../src/errors.ts","../src/bus.ts"],"sourcesContent":["const isDev = !(globalThis as { __HERALD_PROD__?: boolean }).__HERALD_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/herald] ${msg}`);\n}\n","/** Base class for all herald errors. Use `instanceof HeraldError` to catch any herald-originated error. */\nexport class HeraldError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed event bus. */\nexport class BusDisposedError extends HeraldError {\n constructor(busName?: string) {\n super(busName ? `Bus \"${busName}\" is disposed` : 'Bus is disposed');\n }\n}\n","import { warn as _internalWarn } from './_dev';\nimport { BusDisposedError } from './errors';\nimport type {\n Bus,\n BusOptions,\n EventKey,\n EventMap,\n HeraldEvent,\n Listener,\n SubscribeOptions,\n Unsubscribe,\n WaitAnyResult,\n} from './types';\n\n// Module-scoped noop: shared across all bus instances to avoid per-bus allocation.\n/** @internal */\nexport const noop = () => {};\n\ntype Entry = { fn: Listener<unknown>; unsub: () => void };\ntype WildcardEntry = { fn: (event: string, payload: unknown) => void; unsub: () => void };\n\ntype RegisterEntryOpts<T extends EventMap> = {\n event?: EventKey<T>;\n onLog: string;\n onRemove?: () => void;\n wildcard?: boolean;\n};\n\nexport function createBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): Bus<T> {\n const listeners = new Map<string, Set<Entry>>();\n const wildcards = new Set<WildcardEntry>();\n const tappers = new Set<(event: HeraldEvent<T>) => void>();\n const disposeController = new AbortController();\n const busName = options?.name;\n const maxListeners = options?.maxListeners;\n const busTag = busName ? ` (${busName})` : '';\n\n function emitTap(event: HeraldEvent<T>): void {\n if (tappers.size === 0) return;\n for (const tapper of tappers) {\n try {\n tapper(event);\n } catch {\n // Observability must not affect bus behavior.\n }\n }\n }\n\n function doWarn(msg: string): void {\n _internalWarn(msg);\n }\n\n function createSubscriptionScope(signal?: AbortSignal): AbortSignal {\n return signal ? AbortSignal.any([disposeController.signal, signal]) : disposeController.signal;\n }\n\n function registerEntry<E extends { unsub: () => void }>(\n container: Set<E>,\n makeEntry: (unsub: () => void) => E,\n signal: AbortSignal,\n { event, onLog, onRemove, wildcard }: RegisterEntryOpts<T>,\n ): () => void {\n if (signal.aborted) return noop;\n\n let called = false;\n\n function unsub() {\n if (called) return;\n\n called = true;\n container.delete(entry);\n onRemove?.();\n signal.removeEventListener('abort', unsub);\n\n if (event !== undefined) emitTap({ event, type: 'unsubscribe' });\n else if (wildcard) emitTap({ type: 'unsubscribe-any' });\n }\n\n const entry = makeEntry(unsub);\n\n container.add(entry);\n signal.addEventListener('abort', unsub, { once: true });\n\n if (event !== undefined) emitTap({ event, type: 'subscribe' });\n else if (wildcard) emitTap({ type: 'subscribe-any' });\n\n if (maxListeners !== undefined && container.size > maxListeners) {\n doWarn(\n `${onLog} has ${container.size} listeners, exceeding maxListeners (${maxListeners}). Possible memory leak.${busTag}`,\n );\n }\n\n return unsub;\n }\n\n function onWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n let set = listeners.get(event);\n\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n\n const capturedSet = set;\n\n return registerEntry(capturedSet, (unsub) => ({ fn: listener as Listener<unknown>, unsub }), signal, {\n event,\n onLog: `on(\"${event}\")`,\n onRemove: () => {\n if (capturedSet.size === 0) listeners.delete(event);\n\n onRemove?.();\n },\n });\n }\n\n function onAnyWithSignal(\n listener: (event: EventKey<T>, payload: unknown) => void,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n return registerEntry(\n wildcards,\n (unsub) => ({ fn: listener as (event: string, payload: unknown) => void, unsub }),\n signal,\n { onLog: 'onAny', onRemove, wildcard: true },\n );\n }\n\n function onceWithSignal<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n signal: AbortSignal,\n onRemove?: () => void,\n ): () => void {\n const ref = { unsub: noop as Unsubscribe };\n\n ref.unsub = onWithSignal(\n event,\n (payload) => {\n ref.unsub();\n listener(payload);\n },\n signal,\n onRemove,\n );\n\n return ref.unsub;\n }\n\n function on<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: SubscribeOptions): () => void {\n return onWithSignal(event, listener, createSubscriptionScope(opts?.signal));\n }\n\n function once<K extends EventKey<T>>(\n event: K,\n listener: Listener<T[K]>,\n opts?: { signal?: AbortSignal },\n ): () => void {\n const signal = createSubscriptionScope(opts?.signal);\n\n return onceWithSignal(event, listener, signal);\n }\n\n function onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): () => void {\n return onAnyWithSignal(listener, createSubscriptionScope(opts?.signal));\n }\n\n function wait<K extends EventKey<T>>(event: K, opts?: { signal?: AbortSignal }): Promise<T[K]> {\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return Promise.reject(signal.reason);\n\n return new Promise<T[K]>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason);\n };\n\n onceWithSignal(\n event,\n (payload) => {\n signal.removeEventListener('abort', onAbort);\n resolve(payload);\n },\n signal,\n );\n\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n function dispatch(event: EventKey<T>, payload: unknown): void {\n let count = 0;\n let firstError: { value: unknown } | undefined;\n const set = listeners.get(event);\n\n if (set?.size) {\n for (const entry of [...set]) {\n try {\n entry.fn(payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n if (wildcards.size) {\n for (const entry of [...wildcards]) {\n try {\n entry.fn(event, payload);\n } catch (err) {\n firstError ??= { value: err };\n emitTap({ error: err, event, type: 'error' });\n }\n\n count++;\n }\n }\n\n emitTap({ event, listeners: count, payload, type: 'emit' });\n\n if (firstError) throw firstError.value;\n }\n\n function emit<K extends EventKey<T>>(event: K, ...args: T[K] extends void ? [] : [payload: T[K]]): void {\n if (disposeController.signal.aborted) return;\n\n const payload = (args as unknown[])[0];\n\n dispatch(event, payload);\n }\n\n function listenerCount(event?: EventKey<T>): number {\n if (event !== undefined) return listeners.get(event)?.size ?? 0;\n\n let total = 0;\n\n for (const set of listeners.values()) total += set.size;\n\n return total;\n }\n\n function wildcardCount(): number {\n return wildcards.size;\n }\n\n function eventNames(): EventKey<T>[] {\n return [...listeners.keys()] as EventKey<T>[];\n }\n\n function tap(handler: (event: HeraldEvent<T>) => void, opts?: { signal?: AbortSignal }): () => void {\n if (disposeController.signal.aborted) return noop;\n\n const signal = createSubscriptionScope(opts?.signal);\n\n if (signal.aborted) return noop;\n\n tappers.add(handler);\n\n const onAbort = () => tappers.delete(handler);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n return () => {\n tappers.delete(handler);\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n function waitAny<K extends readonly EventKey<T>[]>(\n eventList: K,\n opts?: { signal?: AbortSignal },\n ): Promise<WaitAnyResult<T, K>> {\n const activeSignal = createSubscriptionScope(opts?.signal);\n\n if (activeSignal.aborted) return Promise.reject(activeSignal.reason);\n\n return new Promise<WaitAnyResult<T, K>>((resolve, reject) => {\n const raceController = new AbortController();\n const raceSignal = AbortSignal.any([activeSignal, raceController.signal]);\n const unsubs: Unsubscribe[] = [];\n let settled = false;\n\n function cleanup(): void {\n activeSignal.removeEventListener('abort', onAbort);\n raceController.abort();\n for (const unsub of unsubs) unsub();\n }\n\n function onAbort(): void {\n if (settled) return;\n\n settled = true;\n cleanup();\n reject(activeSignal.reason);\n }\n\n activeSignal.addEventListener('abort', onAbort, { once: true });\n\n for (const event of eventList) {\n unsubs.push(\n onceWithSignal(\n event as EventKey<T>,\n (payload) => {\n if (settled) return;\n\n settled = true;\n cleanup();\n resolve({ event, payload } as WaitAnyResult<T, K>);\n },\n raceSignal,\n ),\n );\n }\n });\n }\n\n function dispose(): void {\n if (disposeController.signal.aborted) return;\n\n emitTap({ type: 'dispose' });\n disposeController.abort(new BusDisposedError(busName));\n listeners.clear();\n wildcards.clear();\n tappers.clear();\n }\n\n return {\n get disposalSignal() {\n return disposeController.signal;\n },\n dispose,\n get disposed() {\n return disposeController.signal.aborted;\n },\n emit,\n eventNames,\n listenerCount,\n on,\n onAny,\n once,\n [Symbol.dispose]: dispose,\n tap,\n wait,\n waitAny,\n wildcardCount,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.cjs","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import type { Bus, BusOptions, EventKey, EventMap, HeraldEvent } from '..';\nimport { createBus } from '../bus';\n\n// Property names that must never be used as a bracket-assignment key on a plain object literal —\n// `obj[key] = value` for `key === '__proto__'` invokes `Object.prototype`'s `__proto__` accessor\n// and reassigns `obj`'s own prototype instead of setting an own property. `constructor` and\n// `prototype` are excluded defensively for the same class of risk.\n// Event names come from a caller-supplied `EventMap` type, but nothing prevents a caller from\n// wiring in a dynamically-determined (e.g. user-supplied) event name at runtime.\nconst UNSAFE_OBJECT_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** A test bus is a regular bus with typed emission recording on top. */\nexport type TestBus<T extends EventMap> = Bus<T> & {\n /** Returns a snapshot of all payloads dispatched across every recorded event, keyed by event name. */\n allEmitted(): { [K in EventKey<T>]?: T[K][] };\n /** Snapshot of all payloads that were successfully dispatched for the given event key, in order. */\n emitted<K extends EventKey<T>>(event: K): T[K][];\n /** Number of times the given event was successfully dispatched. Shorthand for `emitted(event).length`. */\n emittedCount<K extends EventKey<T>>(event: K): number;\n /** Clear emitted records without disposing the bus. */\n reset(): void;\n};\n\nexport function createTestBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): TestBus<T> {\n const records = new Map<string, unknown[]>();\n const bus = createBus<T>(options);\n const disposeBus = bus.dispose;\n\n // Pure observer over the public tap channel: the `emit` event is traced after every\n // listener has run, so a dispatch whose listener throws still records its payload.\n bus.tap((event: HeraldEvent<T>) => {\n if (event.type !== 'emit') return;\n\n const list = records.get(event.event);\n\n if (list) list.push(event.payload);\n else records.set(event.event, [event.payload]);\n });\n\n function allEmitted(): { [K in EventKey<T>]?: T[K][] } {\n const result: { [K in EventKey<T>]?: T[K][] } = {};\n\n for (const [key, list] of records) {\n if (UNSAFE_OBJECT_KEYS.has(key)) continue;\n\n (result as Record<string, unknown[]>)[key] = [...list];\n }\n\n return result;\n }\n\n function emitted<K extends EventKey<T>>(event: K): T[K][] {\n return [...(records.get(event) ?? [])] as T[K][];\n }\n\n function emittedCount<K extends EventKey<T>>(event: K): number {\n return records.get(event)?.length ?? 0;\n }\n\n function dispose(): void {\n disposeBus();\n records.clear();\n }\n\n return Object.assign(bus, {\n allEmitted,\n dispose,\n emitted,\n emittedCount,\n reset: () => records.clear(),\n [Symbol.dispose]: dispose,\n }) as TestBus<T>;\n}\n"],"mappings":"8BASA,IAAM,EAAqB,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAc5E,SAAgB,cAA4D,EAAkC,CAC5G,IAAM,EAAU,IAAI,IACd,EAAM,EAAA,UAAa,CAAO,EAC1B,EAAa,EAAI,QAIvB,EAAI,IAAK,GAA0B,CACjC,GAAI,EAAM,OAAS,OAAQ,OAE3B,IAAM,EAAO,EAAQ,IAAI,EAAM,KAAK,EAEhC,EAAM,EAAK,KAAK,EAAM,OAAO,EAC5B,EAAQ,IAAI,EAAM,MAAO,CAAC,EAAM,OAAO,CAAC,CAC/C,CAAC,EAED,SAAS,YAA8C,CACrD,IAAM,EAA0C,CAAC,EAEjD,IAAK,GAAM,CAAC,EAAK,KAAS,EACpB,EAAmB,IAAI,CAAG,IAE9B,EAAsC,GAAO,CAAC,GAAG,CAAI,GAGvD,OAAO,CACT,CAEA,SAAS,QAA+B,EAAkB,CACxD,MAAO,CAAC,GAAI,EAAQ,IAAI,CAAK,GAAK,CAAC,CAAE,CACvC,CAEA,SAAS,aAAoC,EAAkB,CAC7D,OAAO,EAAQ,IAAI,CAAK,CAAC,EAAE,QAAU,CACvC,CAEA,SAAS,SAAgB,CACvB,EAAW,EACX,EAAQ,MAAM,CAChB,CAEA,OAAO,OAAO,OAAO,EAAK,CACxB,WACA,QACA,QACA,aACA,UAAa,EAAQ,MAAM,GAC1B,OAAO,SAAU,OACpB,CAAC,CACH"}
1
+ {"version":3,"file":"testing.cjs","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import type { Bus, BusOptions, EventKey, EventMap, HeraldEvent } from '..';\nimport { createBus } from '../bus';\n\n// Property names that must never be used as a bracket-assignment key on a plain object literal :\n// `obj[key] = value` for `key === '__proto__'` invokes `Object.prototype`'s `__proto__` accessor\n// and reassigns `obj`'s own prototype instead of setting an own property. `constructor` and\n// `prototype` are excluded defensively for the same class of risk.\n// Event names come from a caller-supplied `EventMap` type, but nothing prevents a caller from\n// wiring in a dynamically-determined (e.g. user-supplied) event name at runtime.\nconst UNSAFE_OBJECT_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** A test bus is a regular bus with typed emission recording on top. */\nexport type TestBus<T extends EventMap> = Bus<T> & {\n /** Returns a snapshot of all payloads dispatched across every recorded event, keyed by event name. */\n allEmitted(): { [K in EventKey<T>]?: T[K][] };\n /** Snapshot of all payloads that were successfully dispatched for the given event key, in order. */\n emitted<K extends EventKey<T>>(event: K): T[K][];\n /** Number of times the given event was successfully dispatched. Shorthand for `emitted(event).length`. */\n emittedCount<K extends EventKey<T>>(event: K): number;\n /** Clear emitted records without disposing the bus. */\n reset(): void;\n};\n\nexport function createTestBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): TestBus<T> {\n const records = new Map<string, unknown[]>();\n const bus = createBus<T>(options);\n const disposeBus = bus.dispose;\n\n // Pure observer over the public tap channel: the `emit` event is traced after every\n // listener has run, so a dispatch whose listener throws still records its payload.\n bus.tap((event: HeraldEvent<T>) => {\n if (event.type !== 'emit') return;\n\n const list = records.get(event.event);\n\n if (list) list.push(event.payload);\n else records.set(event.event, [event.payload]);\n });\n\n function allEmitted(): { [K in EventKey<T>]?: T[K][] } {\n const result: { [K in EventKey<T>]?: T[K][] } = {};\n\n for (const [key, list] of records) {\n if (UNSAFE_OBJECT_KEYS.has(key)) continue;\n\n (result as Record<string, unknown[]>)[key] = [...list];\n }\n\n return result;\n }\n\n function emitted<K extends EventKey<T>>(event: K): T[K][] {\n return [...(records.get(event) ?? [])] as T[K][];\n }\n\n function emittedCount<K extends EventKey<T>>(event: K): number {\n return records.get(event)?.length ?? 0;\n }\n\n function dispose(): void {\n disposeBus();\n records.clear();\n }\n\n return Object.assign(bus, {\n allEmitted,\n dispose,\n emitted,\n emittedCount,\n reset: () => records.clear(),\n [Symbol.dispose]: dispose,\n }) as TestBus<T>;\n}\n"],"mappings":"8BASA,IAAM,EAAqB,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAc5E,SAAgB,cAA4D,EAAkC,CAC5G,IAAM,EAAU,IAAI,IACd,EAAM,EAAA,UAAa,CAAO,EAC1B,EAAa,EAAI,QAIvB,EAAI,IAAK,GAA0B,CACjC,GAAI,EAAM,OAAS,OAAQ,OAE3B,IAAM,EAAO,EAAQ,IAAI,EAAM,KAAK,EAEhC,EAAM,EAAK,KAAK,EAAM,OAAO,EAC5B,EAAQ,IAAI,EAAM,MAAO,CAAC,EAAM,OAAO,CAAC,CAC/C,CAAC,EAED,SAAS,YAA8C,CACrD,IAAM,EAA0C,CAAC,EAEjD,IAAK,GAAM,CAAC,EAAK,KAAS,EACpB,EAAmB,IAAI,CAAG,IAE9B,EAAsC,GAAO,CAAC,GAAG,CAAI,GAGvD,OAAO,CACT,CAEA,SAAS,QAA+B,EAAkB,CACxD,MAAO,CAAC,GAAI,EAAQ,IAAI,CAAK,GAAK,CAAC,CAAE,CACvC,CAEA,SAAS,aAAoC,EAAkB,CAC7D,OAAO,EAAQ,IAAI,CAAK,CAAC,EAAE,QAAU,CACvC,CAEA,SAAS,SAAgB,CACvB,EAAW,EACX,EAAQ,MAAM,CAChB,CAEA,OAAO,OAAO,OAAO,EAAK,CACxB,WACA,QACA,QACA,aACA,UAAa,EAAQ,MAAM,GAC1B,OAAO,SAAU,OACpB,CAAC,CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import type { Bus, BusOptions, EventKey, EventMap, HeraldEvent } from '..';\nimport { createBus } from '../bus';\n\n// Property names that must never be used as a bracket-assignment key on a plain object literal —\n// `obj[key] = value` for `key === '__proto__'` invokes `Object.prototype`'s `__proto__` accessor\n// and reassigns `obj`'s own prototype instead of setting an own property. `constructor` and\n// `prototype` are excluded defensively for the same class of risk.\n// Event names come from a caller-supplied `EventMap` type, but nothing prevents a caller from\n// wiring in a dynamically-determined (e.g. user-supplied) event name at runtime.\nconst UNSAFE_OBJECT_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** A test bus is a regular bus with typed emission recording on top. */\nexport type TestBus<T extends EventMap> = Bus<T> & {\n /** Returns a snapshot of all payloads dispatched across every recorded event, keyed by event name. */\n allEmitted(): { [K in EventKey<T>]?: T[K][] };\n /** Snapshot of all payloads that were successfully dispatched for the given event key, in order. */\n emitted<K extends EventKey<T>>(event: K): T[K][];\n /** Number of times the given event was successfully dispatched. Shorthand for `emitted(event).length`. */\n emittedCount<K extends EventKey<T>>(event: K): number;\n /** Clear emitted records without disposing the bus. */\n reset(): void;\n};\n\nexport function createTestBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): TestBus<T> {\n const records = new Map<string, unknown[]>();\n const bus = createBus<T>(options);\n const disposeBus = bus.dispose;\n\n // Pure observer over the public tap channel: the `emit` event is traced after every\n // listener has run, so a dispatch whose listener throws still records its payload.\n bus.tap((event: HeraldEvent<T>) => {\n if (event.type !== 'emit') return;\n\n const list = records.get(event.event);\n\n if (list) list.push(event.payload);\n else records.set(event.event, [event.payload]);\n });\n\n function allEmitted(): { [K in EventKey<T>]?: T[K][] } {\n const result: { [K in EventKey<T>]?: T[K][] } = {};\n\n for (const [key, list] of records) {\n if (UNSAFE_OBJECT_KEYS.has(key)) continue;\n\n (result as Record<string, unknown[]>)[key] = [...list];\n }\n\n return result;\n }\n\n function emitted<K extends EventKey<T>>(event: K): T[K][] {\n return [...(records.get(event) ?? [])] as T[K][];\n }\n\n function emittedCount<K extends EventKey<T>>(event: K): number {\n return records.get(event)?.length ?? 0;\n }\n\n function dispose(): void {\n disposeBus();\n records.clear();\n }\n\n return Object.assign(bus, {\n allEmitted,\n dispose,\n emitted,\n emittedCount,\n reset: () => records.clear(),\n [Symbol.dispose]: dispose,\n }) as TestBus<T>;\n}\n"],"mappings":"sCASA,IAAM,EAAqB,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAc5E,SAAgB,cAA4D,EAAkC,CAC5G,IAAM,EAAU,IAAI,IACd,EAAM,EAAa,CAAO,EAC1B,EAAa,EAAI,QAIvB,EAAI,IAAK,GAA0B,CACjC,GAAI,EAAM,OAAS,OAAQ,OAE3B,IAAM,EAAO,EAAQ,IAAI,EAAM,KAAK,EAEhC,EAAM,EAAK,KAAK,EAAM,OAAO,EAC5B,EAAQ,IAAI,EAAM,MAAO,CAAC,EAAM,OAAO,CAAC,CAC/C,CAAC,EAED,SAAS,YAA8C,CACrD,IAAM,EAA0C,CAAC,EAEjD,IAAK,GAAM,CAAC,EAAK,KAAS,EACpB,EAAmB,IAAI,CAAG,IAE9B,EAAsC,GAAO,CAAC,GAAG,CAAI,GAGvD,OAAO,CACT,CAEA,SAAS,QAA+B,EAAkB,CACxD,MAAO,CAAC,GAAI,EAAQ,IAAI,CAAK,GAAK,CAAC,CAAE,CACvC,CAEA,SAAS,aAAoC,EAAkB,CAC7D,OAAO,EAAQ,IAAI,CAAK,CAAC,EAAE,QAAU,CACvC,CAEA,SAAS,SAAgB,CACvB,EAAW,EACX,EAAQ,MAAM,CAChB,CAEA,OAAO,OAAO,OAAO,EAAK,CACxB,WACA,QACA,QACA,aACA,UAAa,EAAQ,MAAM,GAC1B,OAAO,SAAU,OACpB,CAAC,CACH"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import type { Bus, BusOptions, EventKey, EventMap, HeraldEvent } from '..';\nimport { createBus } from '../bus';\n\n// Property names that must never be used as a bracket-assignment key on a plain object literal :\n// `obj[key] = value` for `key === '__proto__'` invokes `Object.prototype`'s `__proto__` accessor\n// and reassigns `obj`'s own prototype instead of setting an own property. `constructor` and\n// `prototype` are excluded defensively for the same class of risk.\n// Event names come from a caller-supplied `EventMap` type, but nothing prevents a caller from\n// wiring in a dynamically-determined (e.g. user-supplied) event name at runtime.\nconst UNSAFE_OBJECT_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** A test bus is a regular bus with typed emission recording on top. */\nexport type TestBus<T extends EventMap> = Bus<T> & {\n /** Returns a snapshot of all payloads dispatched across every recorded event, keyed by event name. */\n allEmitted(): { [K in EventKey<T>]?: T[K][] };\n /** Snapshot of all payloads that were successfully dispatched for the given event key, in order. */\n emitted<K extends EventKey<T>>(event: K): T[K][];\n /** Number of times the given event was successfully dispatched. Shorthand for `emitted(event).length`. */\n emittedCount<K extends EventKey<T>>(event: K): number;\n /** Clear emitted records without disposing the bus. */\n reset(): void;\n};\n\nexport function createTestBus<T extends EventMap = Record<string, unknown>>(options?: BusOptions): TestBus<T> {\n const records = new Map<string, unknown[]>();\n const bus = createBus<T>(options);\n const disposeBus = bus.dispose;\n\n // Pure observer over the public tap channel: the `emit` event is traced after every\n // listener has run, so a dispatch whose listener throws still records its payload.\n bus.tap((event: HeraldEvent<T>) => {\n if (event.type !== 'emit') return;\n\n const list = records.get(event.event);\n\n if (list) list.push(event.payload);\n else records.set(event.event, [event.payload]);\n });\n\n function allEmitted(): { [K in EventKey<T>]?: T[K][] } {\n const result: { [K in EventKey<T>]?: T[K][] } = {};\n\n for (const [key, list] of records) {\n if (UNSAFE_OBJECT_KEYS.has(key)) continue;\n\n (result as Record<string, unknown[]>)[key] = [...list];\n }\n\n return result;\n }\n\n function emitted<K extends EventKey<T>>(event: K): T[K][] {\n return [...(records.get(event) ?? [])] as T[K][];\n }\n\n function emittedCount<K extends EventKey<T>>(event: K): number {\n return records.get(event)?.length ?? 0;\n }\n\n function dispose(): void {\n disposeBus();\n records.clear();\n }\n\n return Object.assign(bus, {\n allEmitted,\n dispose,\n emitted,\n emittedCount,\n reset: () => records.clear(),\n [Symbol.dispose]: dispose,\n }) as TestBus<T>;\n}\n"],"mappings":"sCASA,IAAM,EAAqB,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAc5E,SAAgB,cAA4D,EAAkC,CAC5G,IAAM,EAAU,IAAI,IACd,EAAM,EAAa,CAAO,EAC1B,EAAa,EAAI,QAIvB,EAAI,IAAK,GAA0B,CACjC,GAAI,EAAM,OAAS,OAAQ,OAE3B,IAAM,EAAO,EAAQ,IAAI,EAAM,KAAK,EAEhC,EAAM,EAAK,KAAK,EAAM,OAAO,EAC5B,EAAQ,IAAI,EAAM,MAAO,CAAC,EAAM,OAAO,CAAC,CAC/C,CAAC,EAED,SAAS,YAA8C,CACrD,IAAM,EAA0C,CAAC,EAEjD,IAAK,GAAM,CAAC,EAAK,KAAS,EACpB,EAAmB,IAAI,CAAG,IAE9B,EAAsC,GAAO,CAAC,GAAG,CAAI,GAGvD,OAAO,CACT,CAEA,SAAS,QAA+B,EAAkB,CACxD,MAAO,CAAC,GAAI,EAAQ,IAAI,CAAK,GAAK,CAAC,CAAE,CACvC,CAEA,SAAS,aAAoC,EAAkB,CAC7D,OAAO,EAAQ,IAAI,CAAK,CAAC,EAAE,QAAU,CACvC,CAEA,SAAS,SAAgB,CACvB,EAAW,EACX,EAAQ,MAAM,CAChB,CAEA,OAAO,OAAO,OAAO,EAAK,CACxB,WACA,QACA,QACA,aACA,UAAa,EAAQ,MAAM,GAC1B,OAAO,SAAU,OACpB,CAAC,CACH"}
package/dist/types.d.ts CHANGED
@@ -11,7 +11,7 @@ export type SubscribeOptions = {
11
11
  };
12
12
  /**
13
13
  * Runtime events emitted by {@link Bus.tap}.
14
- * Subscribe via `bus.tap(handler)` — handler errors are swallowed.
14
+ * Subscribe via `bus.tap(handler)`: handler errors are swallowed.
15
15
  */
16
16
  export type HeraldEvent<T extends EventMap = EventMap> = {
17
17
  readonly event: EventKey<T>;
@@ -55,14 +55,14 @@ export type WaitAnyResult<T extends EventMap, K extends readonly EventKey<T>[]>
55
55
  } : never;
56
56
  }[number];
57
57
  export type Bus<T extends EventMap> = {
58
- /** Alias for dispose() — enables the `using` keyword for automatic cleanup. */
58
+ /** Alias for dispose(): enables the `using` keyword for automatic cleanup. */
59
59
  [Symbol.dispose](): void;
60
60
  /**
61
61
  * Signal that fires when the bus is disposed.
62
62
  * Use to tie other lifecycles (subscriptions, pipes, timers) to this bus's lifetime.
63
63
  */
64
64
  readonly disposalSignal: AbortSignal;
65
- /** Permanently dispose the bus — clears all listeners; pending waits are rejected. Idempotent. */
65
+ /** Permanently dispose the bus: clears all listeners; pending waits are rejected. Idempotent. */
66
66
  dispose(): void;
67
67
  /** Whether the bus has been permanently disposed. */
68
68
  readonly disposed: boolean;
@@ -76,7 +76,7 @@ export type Bus<T extends EventMap> = {
76
76
  eventNames(): EventKey<T>[];
77
77
  /**
78
78
  * Number of active specific-event listeners for a given event key.
79
- * Does not include wildcard (`onAny`) listeners — use `wildcardCount()` for those.
79
+ * Does not include wildcard (`onAny`) listeners: use `wildcardCount()` for those.
80
80
  * When called without an argument, returns the total across all specific-event listeners.
81
81
  */
82
82
  listenerCount(event?: EventKey<T>): number;
@@ -91,7 +91,7 @@ export type Bus<T extends EventMap> = {
91
91
  */
92
92
  onAny(listener: (event: EventKey<T>, payload: unknown) => void, opts?: SubscribeOptions): Unsubscribe;
93
93
  /**
94
- * Subscribe once — auto-unsubscribes after the first emit. Stops early when the signal aborts.
94
+ * Subscribe once: auto-unsubscribes after the first emit. Stops early when the signal aborts.
95
95
  */
96
96
  once<K extends EventKey<T>>(event: K, listener: Listener<T[K]>, opts?: {
97
97
  signal?: AbortSignal;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/herald",
3
- "version": "26.10.0",
3
+ "version": "26.10.1",
4
4
  "description": "Typed synchronous event bus with wildcard subscriptions, one-shot waits, and lifecycle tracing",
5
5
  "repository": {
6
6
  "type": "git",