@dafengzhen/event-bus 0.1.4 → 0.1.6
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["<anon>","src/index.ts","src/event-bus.ts","src/types.ts"],"sourcesContent":["\nfunction $parcel$export(e, n, v, s) {\n Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});\n}\nvar $54a742859ac4854f$exports = {};\n\n$parcel$export($54a742859ac4854f$exports, \"EventBus\", function () { return $54a742859ac4854f$export$5087227eb54526; });\nclass $54a742859ac4854f$export$5087227eb54526 {\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */ clear(event) {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */ on(event, listener) {\n this.getListenerSet(event).add(listener);\n return ()=>this.off(event, listener);\n }\n /**\n * Remove an exact event listener (no-op if missing).\n */ off(event, listener) {\n const set = this.listenersByEvent.get(event);\n if (!set) return;\n set.delete(listener);\n if (set.size === 0) this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ once(event, listener) {\n const wrapper = (payload)=>{\n listener(payload);\n this.off(event, wrapper);\n };\n return this.on(event, wrapper);\n }\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */ onAny(listener) {\n this.anyListeners.add(listener);\n return ()=>this.anyListeners.delete(listener);\n }\n /**\n * Remove a global (any) listener (no-op if missing).\n */ offAny(listener) {\n this.anyListeners.delete(listener);\n }\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ onceAny(listener) {\n const wrapper = (event, payload)=>{\n listener(event, payload);\n this.offAny(wrapper);\n };\n return this.onAny(wrapper);\n }\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */ use(mw) {\n this.middlewares.push(mw);\n return ()=>this.removeFromArray(this.middlewares, mw);\n }\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */ usePattern(mw) {\n this.patternMiddlewares.push(mw);\n return ()=>this.removeFromArray(this.patternMiddlewares, mw);\n }\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */ onPattern(pattern, handler, options) {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n const entry = {\n pattern: pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler\n };\n this.insertPatternByPriority(entry);\n return ()=>this.removeFromArray(this.patternListeners, entry);\n }\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */ oncePattern(pattern, handler, options) {\n return this.onPattern(pattern, handler, {\n ...options,\n once: true\n });\n }\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */ listenerCount(event) {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners)if (p.match(event) !== null) count++;\n }\n return count;\n }\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */ emit(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n this._emit(event, ...args).catch((err)=>this.rethrowAsync(err));\n }\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */ async emitAsync(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n await this._emit(event, ...args);\n }\n async _emit(event, ...args) {\n const payload = args[0];\n let blocked = false;\n const ctx = {\n get blocked () {\n return blocked;\n },\n event: event,\n payload: payload,\n matched: [],\n meta: {},\n block () {\n blocked = true;\n }\n };\n await this.runMiddlewares(ctx);\n }\n async runMiddlewares(ctx) {\n const mws = this.middlewares;\n let i = 0;\n const next = async ()=>{\n if (ctx.blocked) return;\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n const mw = mws[i++];\n let nextCalled = false;\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n await next();\n });\n };\n await next();\n }\n async invokeUnifiedDispatch(ctx) {\n const { event: event, payload: payload } = ctx;\n const matched = typeof event === 'string' && this.patternListeners.length ? this.matchPatternListeners(event) : [];\n // expose matched info for middleware / debugging\n ctx.matched = Object.freeze(matched.map(({ entry: entry, params: params })=>({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({\n ...params\n }),\n handler: entry.handler\n })));\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) for(let i = 0; i < this.patternMiddlewares.length; i++){\n if (ctx.blocked) return;\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n });\n // guard: if not calling next, stop dispatch\n if (!nextCalled) return;\n }\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n // pattern handlers by priority\n for (const { entry: entry, params: params } of matched){\n if (ctx.blocked) return;\n this.safeCall(()=>entry.handler(event, payload, params));\n if (entry.once) this.removeFromArray(this.patternListeners, entry);\n }\n }\n matchPatternListeners(event) {\n const matches = [];\n for (const entry of this.patternListeners){\n const params = entry.match(event);\n if (params !== null) matches.push({\n entry: entry,\n params: params\n });\n }\n return matches;\n }\n invokeExactAndAnyListeners(event, payload) {\n const set = this.listenersByEvent.get(event);\n if (set) for (const fn of set)this.safeCall(()=>fn(payload));\n for (const fn of this.anyListeners)this.safeCall(()=>fn(event, payload));\n }\n getListenerSet(event) {\n let set = this.listenersByEvent.get(event);\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n insertPatternByPriority(entry) {\n const arr = this.patternListeners;\n const { priority: priority } = entry;\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n while(lo < hi){\n const mid = lo + hi >>> 1;\n if (arr[mid].priority >= priority) lo = mid + 1;\n else hi = mid;\n }\n arr.splice(lo, 0, entry);\n }\n removeFromArray(arr, item) {\n const i = arr.indexOf(item);\n if (i >= 0) arr.splice(i, 1);\n }\n safeCall(fn) {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n rethrowAsync(err) {\n queueMicrotask(()=>{\n throw err;\n });\n }\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */ compilePattern(pattern, sep) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') return {\n kind: 'wildcard',\n priority: -100,\n match: ()=>({})\n };\n const pSegs = pattern.split(sep);\n const keys = [];\n let score = 0;\n const compiled = pSegs.map((seg)=>{\n if (seg === '**') {\n score -= 5;\n return {\n type: 'deepWildcard'\n };\n }\n if (seg === '*') {\n score -= 1;\n return {\n type: 'wildcard'\n };\n }\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return {\n type: 'param',\n key: key\n };\n }\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp('^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$');\n score += 5;\n return {\n type: 'regex',\n re: re\n };\n }\n score += 100;\n return {\n type: 'exact',\n value: seg\n };\n });\n let kind = 'exact';\n if (keys.length) kind = 'param';\n else if (compiled.some((s)=>s.type !== 'exact')) kind = 'wildcard';\n function match(event) {\n const eSegs = event.split(sep);\n const params = {};\n let i = 0; // pattern index\n let j = 0; // event index\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n while(j < eSegs.length){\n const p = compiled[i];\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n // one segment match\n if (p.type === 'wildcard' || p.type === 'exact' && p.value === eSegs[j] || p.type === 'regex' && p.re.test(eSegs[j]) || p.type === 'param' && (params[p.key] = eSegs[j], true)) {\n i++;\n j++;\n continue;\n }\n }\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n return null;\n }\n // event ended; remaining pattern segments must be ** to match empty\n while(compiled[i]?.type === 'deepWildcard')i++;\n return i === compiled.length ? params : null;\n }\n return {\n kind: kind,\n priority: score,\n match: match\n };\n }\n constructor(){\n /** Listeners that receive all events */ this.anyListeners = new Set();\n /** Exact listeners mapped by event name */ this.listenersByEvent = new Map();\n /** Global middleware chain (runs on every emit) */ this.middlewares = [];\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */ this.patternMiddlewares = [];\n /** Compiled pattern listeners, sorted by priority (descending) */ this.patternListeners = [];\n /** Cache for compiled patterns (pattern + separator) */ this.patternCache = new Map();\n }\n}\n\n\nvar $50402f782971a62d$exports = {};\n/**\n * Event map definition.\n *\n * A mapping from **event name** to **payload type**.\n *\n * - **Key**: event name (string literal recommended)\n * - **Value**: payload type for that event\n *\n * Notes:\n * - Event names are typically namespaced strings, e.g. `user:login`, `order:created`.\n * - Payload can be `void` for events without payload.\n *\n * @example\n * ```ts\n * type MyEvents = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n * ```\n */ \n\n\n\nexport {$54a742859ac4854f$export$5087227eb54526 as EventBus};\n//# sourceMappingURL=index.js.map\n","export * from './event-bus.ts';\nexport * from './types.ts';\n","import type {\n AnyListener,\n CompiledPatternListener,\n CompiledSeg,\n EmitContext,\n EventMap,\n Listener,\n Middleware,\n PatternKind,\n PatternListenerInfo,\n PatternMiddleware,\n PatternOptions,\n} from './types.ts';\n\n/**\n * A strongly-typed EventBus supporting:\n *\n * - Exact event listeners (`on`, `once`)\n * - Global listeners (`onAny`)\n * - Pattern listeners (`onPattern`, `oncePattern`)\n * - Global middleware & pattern middleware\n *\n * Pattern syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{name}` → named parameter segment\n * - `?` → single-character wildcard within a segment (regex-like)\n *\n * Error handling:\n * - Listener errors are rethrown asynchronously via `queueMicrotask`,\n * so they don't break the current emit loop.\n *\n * Emit modes:\n * - `emit()` : fire-and-forget (async errors rethrown)\n * - `emitAsync()`: await completion of middleware + listeners\n *\n * @example\n * ```ts\n * type Events = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n *\n * const bus = new EventBus<Events>();\n *\n * bus.on('user:login', (p) => console.log(p.id));\n * bus.onPattern('user:{action}', (evt, payload, params) => {\n * console.log(evt, params?.action);\n * });\n *\n * bus.emit('user:login', { id: '42' });\n * ```\n *\n * @author dafengzhen\n */\nexport class EventBus<E extends EventMap> {\n /** Listeners that receive all events */\n private anyListeners = new Set<AnyListener<E>>();\n\n /** Exact listeners mapped by event name */\n private listenersByEvent = new Map<keyof E, Set<Listener<any>>>();\n\n /** Global middleware chain (runs on every emit) */\n private middlewares: Middleware<E>[] = [];\n\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */\n private patternMiddlewares: PatternMiddleware<E>[] = [];\n\n /** Compiled pattern listeners, sorted by priority (descending) */\n private patternListeners: CompiledPatternListener<E>[] = [];\n\n /** Cache for compiled patterns (pattern + separator) */\n private patternCache = new Map<string, ReturnType<EventBus<E>['compilePattern']>>();\n\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */\n clear(event?: keyof E): void {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */\n on<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n this.getListenerSet(event).add(listener);\n return () => this.off(event, listener);\n }\n\n /**\n * Remove an exact event listener (no-op if missing).\n */\n off<K extends keyof E>(event: K, listener: Listener<E[K]>): void {\n const set = this.listenersByEvent.get(event);\n if (!set) {\n return;\n }\n\n set.delete(listener);\n if (set.size === 0) {\n this.listenersByEvent.delete(event);\n }\n }\n\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n once<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n const wrapper = ((payload: E[K]) => {\n listener(payload);\n this.off(event, wrapper);\n }) as Listener<E[K]>;\n\n return this.on(event, wrapper);\n }\n\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */\n onAny(listener: AnyListener<E>): () => void {\n this.anyListeners.add(listener);\n return () => this.anyListeners.delete(listener);\n }\n\n /**\n * Remove a global (any) listener (no-op if missing).\n */\n offAny(listener: AnyListener<E>): void {\n this.anyListeners.delete(listener);\n }\n\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n onceAny(listener: AnyListener<E>): () => void {\n const wrapper: AnyListener<E> = (event, payload) => {\n listener(event, payload);\n this.offAny(wrapper);\n };\n\n return this.onAny(wrapper);\n }\n\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */\n use(mw: Middleware<E>): () => void {\n this.middlewares.push(mw);\n return () => this.removeFromArray(this.middlewares, mw);\n }\n\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */\n usePattern(mw: PatternMiddleware<E>): () => void {\n this.patternMiddlewares.push(mw);\n return () => this.removeFromArray(this.patternMiddlewares, mw);\n }\n\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */\n onPattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: PatternOptions,\n ): () => void {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n\n const entry: CompiledPatternListener<E> = {\n pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler as any,\n };\n\n this.insertPatternByPriority(entry);\n return () => this.removeFromArray(this.patternListeners, entry);\n }\n\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */\n oncePattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: Omit<PatternOptions, 'once'>,\n ): () => void {\n return this.onPattern(pattern, handler, { ...options, once: true });\n }\n\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */\n listenerCount(event: keyof E): number {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners) {\n if (p.match(event) !== null) {\n count++;\n }\n }\n }\n\n return count;\n }\n\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */\n emit<K extends keyof E>(event: K, ...args: E[K] extends void ? [] : [payload: E[K]]): void {\n if (this.listenerCount(event) === 0) {\n return;\n }\n\n this._emit(event, ...args).catch((err) => this.rethrowAsync(err));\n }\n\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */\n async emitAsync<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n if (this.listenerCount(event) === 0) {\n return;\n }\n await this._emit(event, ...args);\n }\n\n private async _emit<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n const payload = args[0] as E[K];\n let blocked = false;\n\n const ctx: EmitContext<E, K> = {\n get blocked() {\n return blocked;\n },\n event,\n payload,\n matched: [],\n meta: {},\n block() {\n blocked = true;\n },\n };\n\n await this.runMiddlewares(ctx);\n }\n\n private async runMiddlewares<K extends keyof E>(ctx: EmitContext<E, K>): Promise<void> {\n const mws = this.middlewares;\n let i = 0;\n\n const next = async (): Promise<void> => {\n if (ctx.blocked) {\n return;\n }\n\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n\n const mw = mws[i++];\n let nextCalled = false;\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n await next();\n });\n };\n\n await next();\n }\n\n private async invokeUnifiedDispatch(ctx: EmitContext<E, keyof E>): Promise<void> {\n const { event, payload } = ctx;\n\n const matched =\n typeof event === 'string' && this.patternListeners.length\n ? this.matchPatternListeners(event)\n : [];\n\n // expose matched info for middleware / debugging\n (ctx as any).matched = Object.freeze(\n matched.map(\n ({ entry, params }): PatternListenerInfo<E> => ({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({ ...params }),\n handler: entry.handler,\n }),\n ),\n );\n\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) {\n for (let i = 0; i < this.patternMiddlewares.length; i++) {\n if (ctx.blocked) {\n return;\n }\n\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n });\n\n // guard: if not calling next, stop dispatch\n if (!nextCalled) {\n return;\n }\n }\n }\n\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n\n // pattern handlers by priority\n for (const { entry, params } of matched) {\n if (ctx.blocked) {\n return;\n }\n\n this.safeCall(() => entry.handler(event, payload, params));\n\n if (entry.once) {\n this.removeFromArray(this.patternListeners, entry);\n }\n }\n }\n\n private matchPatternListeners(event: string) {\n const matches: Array<{ entry: CompiledPatternListener<E>; params: Record<string, string> }> =\n [];\n\n for (const entry of this.patternListeners) {\n const params = entry.match(event);\n if (params !== null) {\n matches.push({ entry, params });\n }\n }\n\n return matches;\n }\n\n private invokeExactAndAnyListeners<K extends keyof E>(event: K, payload: E[K]): void {\n const set = this.listenersByEvent.get(event);\n if (set) {\n for (const fn of set) {\n this.safeCall(() => fn(payload));\n }\n }\n\n for (const fn of this.anyListeners) {\n this.safeCall(() => fn(event, payload));\n }\n }\n\n private getListenerSet<K extends keyof E>(event: K): Set<Listener<E[K]>> {\n let set = this.listenersByEvent.get(event) as Set<Listener<E[K]>> | undefined;\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n\n private insertPatternByPriority(entry: CompiledPatternListener<E>): void {\n const arr = this.patternListeners;\n const { priority } = entry;\n\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (arr[mid].priority >= priority) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n arr.splice(lo, 0, entry);\n }\n\n private removeFromArray<T>(arr: T[], item: T): void {\n const i = arr.indexOf(item);\n if (i >= 0) {\n arr.splice(i, 1);\n }\n }\n\n private safeCall(fn: () => void): void {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n\n private rethrowAsync(err: unknown): void {\n queueMicrotask(() => {\n throw err;\n });\n }\n\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */\n private compilePattern(pattern: string, sep: string) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') {\n return {\n kind: 'wildcard' as const,\n priority: -100,\n match: () => ({}) as Record<string, string>,\n };\n }\n\n const pSegs = pattern.split(sep);\n const keys: string[] = [];\n let score = 0;\n\n const compiled: CompiledSeg[] = pSegs.map((seg) => {\n if (seg === '**') {\n score -= 5;\n return { type: 'deepWildcard' as const };\n }\n\n if (seg === '*') {\n score -= 1;\n return { type: 'wildcard' as const };\n }\n\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return { type: 'param' as const, key };\n }\n\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp(\n '^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$',\n );\n score += 5;\n return { type: 'regex' as const, re };\n }\n\n score += 100;\n return { type: 'exact' as const, value: seg };\n });\n\n let kind: PatternKind = 'exact';\n if (keys.length) {\n kind = 'param';\n } else if (compiled.some((s) => s.type !== 'exact')) {\n kind = 'wildcard';\n }\n\n function match(event: string) {\n const eSegs = event.split(sep);\n const params: Record<string, string> = {};\n\n let i = 0; // pattern index\n let j = 0; // event index\n\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n\n while (j < eSegs.length) {\n const p = compiled[i];\n\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n\n // one segment match\n if (\n p.type === 'wildcard' ||\n (p.type === 'exact' && p.value === eSegs[j]) ||\n (p.type === 'regex' && p.re.test(eSegs[j])) ||\n (p.type === 'param' && ((params[p.key] = eSegs[j]), true))\n ) {\n i++;\n j++;\n continue;\n }\n }\n\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n\n return null;\n }\n\n // event ended; remaining pattern segments must be ** to match empty\n while (compiled[i]?.type === 'deepWildcard') {\n i++;\n }\n\n return i === compiled.length ? params : null;\n }\n\n return {\n kind,\n priority: score,\n match,\n };\n }\n}\n","/**\n * Event map definition.\n *\n * A mapping from **event name** to **payload type**.\n *\n * - **Key**: event name (string literal recommended)\n * - **Value**: payload type for that event\n *\n * Notes:\n * - Event names are typically namespaced strings, e.g. `user:login`, `order:created`.\n * - Payload can be `void` for events without payload.\n *\n * @example\n * ```ts\n * type MyEvents = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n * ```\n */\nexport type EventMap = Record<string, unknown>;\n\n/**\n * Listener type for a specific payload.\n *\n * If the payload is `void`, the listener receives **no arguments**.\n * Otherwise, it receives **exactly one argument**: the payload.\n *\n * This enables strict typing for both forms:\n *\n * @example\n * ```ts\n * on('ready', () => {});\n * on('data', (payload) => {\n * console.log(payload);\n * });\n * ```\n */\nexport type Listener<Payload> = Payload extends void ? () => void : (payload: Payload) => void;\n\n/**\n * Listener that receives **all emitted events**.\n *\n * It receives:\n * - `event`: the event name\n * - `payload`: the payload associated with that event\n *\n * Typical use cases:\n * - logging / debugging\n * - analytics / tracing\n * - building devtools\n *\n * @example\n * ```ts\n * const off = bus.onAny((event, payload) => {\n * console.log('event=', event, 'payload=', payload);\n * });\n * off();\n * ```\n */\nexport type AnyListener<E extends EventMap> = <K extends keyof E>(event: K, payload: E[K]) => void;\n\n/**\n * Pattern matching strategy used by a pattern listener.\n *\n * - `exact` → exact segment match (no wildcards / params)\n * - `wildcard` → contains wildcards (e.g. `*`, `**`, `?`)\n * - `param` → contains named params (e.g. `{id}`)\n *\n * Notes:\n * - These are informational categories; the actual matching is implemented by the EventBus.\n */\nexport type PatternKind = 'exact' | 'wildcard' | 'param';\n\n/**\n * Context object passed through the emit lifecycle.\n *\n * This context is shared across:\n * - global middleware\n * - pattern middleware\n * - dispatch logic\n *\n * It allows middleware to:\n * - observe the event and payload\n * - attach metadata (`meta`)\n * - stop propagation (`block()`)\n */\nexport type EmitContext<E extends EventMap, K extends keyof E> = {\n /**\n * Whether propagation has been blocked.\n *\n * Once `true`, dispatch stops and no further middleware/listeners should run.\n */\n readonly blocked: boolean;\n\n /**\n * Current emitted event name.\n */\n readonly event: K;\n\n /**\n * Payload associated with the event.\n *\n * If the event's payload type is `void`, this value is typically `undefined`\n * (depending on the emitter implementation).\n */\n readonly payload: E[K];\n\n /**\n * Information about matched pattern listeners for this emit cycle.\n *\n * - Ordered by priority (highest first).\n * - Empty if no pattern listeners matched (or pattern matching not applicable).\n *\n * Useful for middleware that wants to inspect or audit matches.\n */\n readonly matched: readonly PatternListenerInfo<E>[];\n\n /**\n * Free-form metadata container shared across middleware.\n *\n * Use this to pass state between middleware, e.g.:\n * - correlation IDs\n * - timing info\n * - auth decisions\n *\n * Note: Consumers should avoid putting large objects here in hot paths.\n */\n readonly meta: Record<string, unknown>;\n\n /**\n * Stop further propagation of this event.\n *\n * Once called:\n * - remaining middleware is skipped\n * - remaining listeners are not executed\n */\n block(): void;\n};\n\n/**\n * Middleware executed for **every emit call**.\n *\n * Middleware can:\n * - inspect event/payload/matches\n * - read/write `ctx.meta`\n * - block propagation via `ctx.block()`\n * - perform async work\n *\n * Chain semantics:\n * - Middlewares are executed sequentially in registration order.\n * - `next()` must be called exactly once to continue the chain (depending on implementation).\n */\nexport type Middleware<E extends EventMap> = <K extends keyof E>(\n ctx: EmitContext<E, K>,\n next: () => Promise<void>,\n) => Promise<void> | void;\n\n/**\n * Middleware executed **only when pattern listeners are involved**.\n *\n * Typical uses:\n * - logging pattern matches & params\n * - permission checks / gating\n * - validating extracted params\n *\n * Chain semantics depend on the EventBus implementation.\n * In your EventBus, pattern middleware acts as a guard:\n * - if it does not call `next()`, dispatch stops\n * - `next()` must not be called more than once\n */\nexport type PatternMiddleware<E extends EventMap> = (\n ctx: EmitContext<E, keyof E>,\n next: () => Promise<void>,\n) => Promise<void> | void;\n\n/**\n * Public information of a matched pattern listener.\n *\n * Exposed to middleware and user-land code through `ctx.matched`.\n */\nexport interface PatternListenerInfo<E extends EventMap> {\n /**\n * Original pattern string.\n *\n * @example\n * ```ts\n * 'user:{id}'\n * 'order:*'\n * '**'\n * ```\n */\n readonly pattern: string;\n\n /**\n * Matching strategy classification.\n */\n readonly kind: PatternKind;\n\n /**\n * Listener priority. Higher values run earlier.\n */\n readonly priority: number;\n\n /**\n * Whether this listener was registered with `once`.\n */\n readonly once?: boolean;\n\n /**\n * Extracted params from the event name.\n *\n * Example (separator `:`):\n * - pattern: `user:{id}`\n * - event: `user:42`\n * - params: `{ id: '42' }`\n */\n readonly params: Readonly<Record<string, string>>;\n\n /**\n * The actual handler function.\n *\n * Note:\n * - Kept here mainly for introspection/debugging.\n * - Middleware should generally not call handlers directly.\n */\n readonly handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void;\n}\n\n/**\n * Internal compiled representation of a pattern listener.\n *\n * Not exposed publicly.\n * Contains precompiled matching logic for performance.\n */\nexport interface CompiledPatternListener<E extends EventMap> {\n /**\n * Original pattern string (uncompiled).\n */\n pattern: string;\n\n /**\n * Matching strategy classification.\n */\n kind: PatternKind;\n\n /**\n * Listener priority. Higher values run earlier.\n */\n priority: number;\n\n /**\n * Whether the listener should auto-remove after first run.\n */\n once?: boolean;\n\n /**\n * Match function produced by the compiler.\n *\n * @param event - Emitted event name\n * @returns\n * - `null` if no match\n * - params record if matched (possibly empty)\n */\n match(event: string): null | Record<string, string>;\n\n /**\n * Listener handler.\n *\n * @param event - Emitted event name\n * @param payload - Payload associated with event\n * @param params - Extracted params from pattern (if any)\n */\n handler(event: keyof E, payload: E[keyof E], params?: Record<string, string>): void;\n}\n\n/**\n * Options for registering a pattern listener.\n */\nexport type PatternOptions = {\n /**\n * Invoke the listener only once.\n *\n * After the first successful match, it is automatically removed.\n */\n once?: boolean;\n\n /**\n * Listener priority.\n *\n * Higher values run earlier.\n * If omitted, EventBus will derive a priority from pattern specificity.\n */\n priority?: number;\n\n /**\n * Segment separator used when splitting patterns and events.\n *\n * IMPORTANT:\n * - This default should match your EventBus implementation.\n * - In the current EventBus code you posted, the default is `':'`.\n */\n separator?: string;\n};\n\n/**\n * Internal compiled segment representation produced by the pattern compiler.\n *\n * - `exact` → exact segment match\n * - `wildcard` → `*` matches exactly one segment\n * - `deepWildcard` → `**` matches 0..n segments (backtracking)\n * - `param` → `{key}` captures a segment into params\n * - `regex` → per-segment regex (used for `?` patterns)\n */\nexport type CompiledSeg =\n | { type: 'exact'; value: string }\n | { type: 'wildcard' }\n | { type: 'deepWildcard' }\n | { type: 'param'; key: string }\n | { type: 'regex'; re: RegExp };\n"],"names":["Object","defineProperty","get","$54a742859ac4854f$export$5087227eb54526","set","s","enumerable","configurable","clear","event","undefined","listenersByEvent","anyListeners","patternListeners","length","middlewares","patternMiddlewares","patternCache","delete","on","listener","getListenerSet","add","off","size","once","wrapper","payload","onAny","offAny","onceAny","use","mw","push","removeFromArray","usePattern","onPattern","pattern","handler","options","sep","separator","cacheKey","compiled","compilePattern","entry","kind","match","priority","insertPatternByPriority","oncePattern","listenerCount","count","p","emit","args","_emit","catch","err","rethrowAsync","emitAsync","blocked","runMiddlewares","matched","meta","block","ctx","mws","i","next","invokeUnifiedDispatch","nextCalled","Error","matchPatternListeners","freeze","map","params","invokeExactAndAnyListeners","safeCall","matches","fn","Set","arr","lo","hi","mid","splice","item","indexOf","queueMicrotask","pSegs","split","keys","score","seg","type","startsWith","endsWith","key","slice","includes","re","RegExp","replace","value","some","eSegs","j","starI","starJ","test","Map","EventBus"],"version":3,"file":"index.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["<anon>","src/index.ts","src/event-bus.ts"],"sourcesContent":["\nfunction $parcel$export(e, n, v, s) {\n Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});\n}\nvar $54a742859ac4854f$exports = {};\n\n$parcel$export($54a742859ac4854f$exports, \"EventBus\", function () { return $54a742859ac4854f$export$5087227eb54526; });\nclass $54a742859ac4854f$export$5087227eb54526 {\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */ clear(event) {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */ on(event, listener) {\n this.getListenerSet(event).add(listener);\n return ()=>this.off(event, listener);\n }\n /**\n * Remove an exact event listener (no-op if missing).\n */ off(event, listener) {\n const set = this.listenersByEvent.get(event);\n if (!set) return;\n set.delete(listener);\n if (set.size === 0) this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ once(event, listener) {\n const wrapper = (payload)=>{\n listener(payload);\n this.off(event, wrapper);\n };\n return this.on(event, wrapper);\n }\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */ onAny(listener) {\n this.anyListeners.add(listener);\n return ()=>this.anyListeners.delete(listener);\n }\n /**\n * Remove a global (any) listener (no-op if missing).\n */ offAny(listener) {\n this.anyListeners.delete(listener);\n }\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ onceAny(listener) {\n const wrapper = (event, payload)=>{\n listener(event, payload);\n this.offAny(wrapper);\n };\n return this.onAny(wrapper);\n }\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */ use(mw) {\n this.middlewares.push(mw);\n return ()=>this.removeFromArray(this.middlewares, mw);\n }\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */ usePattern(mw) {\n this.patternMiddlewares.push(mw);\n return ()=>this.removeFromArray(this.patternMiddlewares, mw);\n }\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */ onPattern(pattern, handler, options) {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n const entry = {\n pattern: pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler\n };\n this.insertPatternByPriority(entry);\n return ()=>this.removeFromArray(this.patternListeners, entry);\n }\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */ oncePattern(pattern, handler, options) {\n return this.onPattern(pattern, handler, {\n ...options,\n once: true\n });\n }\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */ listenerCount(event) {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners)if (p.match(event) !== null) count++;\n }\n return count;\n }\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */ emit(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n this._emit(event, ...args).catch((err)=>this.rethrowAsync(err));\n }\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */ async emitAsync(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n await this._emit(event, ...args);\n }\n async _emit(event, ...args) {\n const payload = args[0];\n let blocked = false;\n const ctx = {\n get blocked () {\n return blocked;\n },\n event: event,\n payload: payload,\n matched: [],\n meta: {},\n block () {\n blocked = true;\n }\n };\n await this.runMiddlewares(ctx);\n }\n async runMiddlewares(ctx) {\n const mws = this.middlewares;\n let i = 0;\n const next = async ()=>{\n if (ctx.blocked) return;\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n const mw = mws[i++];\n let nextCalled = false;\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n await next();\n });\n };\n await next();\n }\n async invokeUnifiedDispatch(ctx) {\n const { event: event, payload: payload } = ctx;\n const matched = typeof event === 'string' && this.patternListeners.length ? this.matchPatternListeners(event) : [];\n // expose matched info for middleware / debugging\n ctx.matched = Object.freeze(matched.map(({ entry: entry, params: params })=>({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({\n ...params\n }),\n handler: entry.handler\n })));\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) for(let i = 0; i < this.patternMiddlewares.length; i++){\n if (ctx.blocked) return;\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n });\n // guard: if not calling next, stop dispatch\n if (!nextCalled) return;\n }\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n // pattern handlers by priority\n for (const { entry: entry, params: params } of matched){\n if (ctx.blocked) return;\n this.safeCall(()=>entry.handler(event, payload, params));\n if (entry.once) this.removeFromArray(this.patternListeners, entry);\n }\n }\n matchPatternListeners(event) {\n const matches = [];\n for (const entry of this.patternListeners){\n const params = entry.match(event);\n if (params !== null) matches.push({\n entry: entry,\n params: params\n });\n }\n return matches;\n }\n invokeExactAndAnyListeners(event, payload) {\n const set = this.listenersByEvent.get(event);\n if (set) for (const fn of set)this.safeCall(()=>fn(payload));\n for (const fn of this.anyListeners)this.safeCall(()=>fn(event, payload));\n }\n getListenerSet(event) {\n let set = this.listenersByEvent.get(event);\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n insertPatternByPriority(entry) {\n const arr = this.patternListeners;\n const { priority: priority } = entry;\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n while(lo < hi){\n const mid = lo + hi >>> 1;\n if (arr[mid].priority >= priority) lo = mid + 1;\n else hi = mid;\n }\n arr.splice(lo, 0, entry);\n }\n removeFromArray(arr, item) {\n const i = arr.indexOf(item);\n if (i >= 0) arr.splice(i, 1);\n }\n safeCall(fn) {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n rethrowAsync(err) {\n queueMicrotask(()=>{\n throw err;\n });\n }\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */ compilePattern(pattern, sep) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') return {\n kind: 'wildcard',\n priority: -100,\n match: ()=>({})\n };\n const pSegs = pattern.split(sep);\n const keys = [];\n let score = 0;\n const compiled = pSegs.map((seg)=>{\n if (seg === '**') {\n score -= 5;\n return {\n type: 'deepWildcard'\n };\n }\n if (seg === '*') {\n score -= 1;\n return {\n type: 'wildcard'\n };\n }\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return {\n type: 'param',\n key: key\n };\n }\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp('^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$');\n score += 5;\n return {\n type: 'regex',\n re: re\n };\n }\n score += 100;\n return {\n type: 'exact',\n value: seg\n };\n });\n let kind = 'exact';\n if (keys.length) kind = 'param';\n else if (compiled.some((s)=>s.type !== 'exact')) kind = 'wildcard';\n function match(event) {\n const eSegs = event.split(sep);\n const params = {};\n let i = 0; // pattern index\n let j = 0; // event index\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n while(j < eSegs.length){\n const p = compiled[i];\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n // one segment match\n if (p.type === 'wildcard' || p.type === 'exact' && p.value === eSegs[j] || p.type === 'regex' && p.re.test(eSegs[j]) || p.type === 'param' && (params[p.key] = eSegs[j], true)) {\n i++;\n j++;\n continue;\n }\n }\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n return null;\n }\n // event ended; remaining pattern segments must be ** to match empty\n while(compiled[i]?.type === 'deepWildcard')i++;\n return i === compiled.length ? params : null;\n }\n return {\n kind: kind,\n priority: score,\n match: match\n };\n }\n constructor(){\n /** Listeners that receive all events */ this.anyListeners = new Set();\n /** Exact listeners mapped by event name */ this.listenersByEvent = new Map();\n /** Global middleware chain (runs on every emit) */ this.middlewares = [];\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */ this.patternMiddlewares = [];\n /** Compiled pattern listeners, sorted by priority (descending) */ this.patternListeners = [];\n /** Cache for compiled patterns (pattern + separator) */ this.patternCache = new Map();\n }\n}\n\n\n\n\nexport {$54a742859ac4854f$export$5087227eb54526 as EventBus};\n//# sourceMappingURL=index.js.map\n","export type * from './types.ts';\nexport * from './event-bus.ts';\n","import type {\n AnyListener,\n CompiledPatternListener,\n CompiledSeg,\n EmitContext,\n EventMap,\n Listener,\n Middleware,\n PatternKind,\n PatternListenerInfo,\n PatternMiddleware,\n PatternOptions,\n} from './types.ts';\n\n/**\n * A strongly-typed EventBus supporting:\n *\n * - Exact event listeners (`on`, `once`)\n * - Global listeners (`onAny`)\n * - Pattern listeners (`onPattern`, `oncePattern`)\n * - Global middleware & pattern middleware\n *\n * Pattern syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{name}` → named parameter segment\n * - `?` → single-character wildcard within a segment (regex-like)\n *\n * Error handling:\n * - Listener errors are rethrown asynchronously via `queueMicrotask`,\n * so they don't break the current emit loop.\n *\n * Emit modes:\n * - `emit()` : fire-and-forget (async errors rethrown)\n * - `emitAsync()`: await completion of middleware + listeners\n *\n * @example\n * ```ts\n * type Events = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n *\n * const bus = new EventBus<Events>();\n *\n * bus.on('user:login', (p) => console.log(p.id));\n * bus.onPattern('user:{action}', (evt, payload, params) => {\n * console.log(evt, params?.action);\n * });\n *\n * bus.emit('user:login', { id: '42' });\n * ```\n *\n * @author dafengzhen\n */\nexport class EventBus<E extends EventMap> {\n /** Listeners that receive all events */\n private anyListeners = new Set<AnyListener<E>>();\n\n /** Exact listeners mapped by event name */\n private listenersByEvent = new Map<keyof E, Set<Listener<any>>>();\n\n /** Global middleware chain (runs on every emit) */\n private middlewares: Middleware<E>[] = [];\n\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */\n private patternMiddlewares: PatternMiddleware<E>[] = [];\n\n /** Compiled pattern listeners, sorted by priority (descending) */\n private patternListeners: CompiledPatternListener<E>[] = [];\n\n /** Cache for compiled patterns (pattern + separator) */\n private patternCache = new Map<string, ReturnType<EventBus<E>['compilePattern']>>();\n\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */\n clear(event?: keyof E): void {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */\n on<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n this.getListenerSet(event).add(listener);\n return () => this.off(event, listener);\n }\n\n /**\n * Remove an exact event listener (no-op if missing).\n */\n off<K extends keyof E>(event: K, listener: Listener<E[K]>): void {\n const set = this.listenersByEvent.get(event);\n if (!set) {\n return;\n }\n\n set.delete(listener);\n if (set.size === 0) {\n this.listenersByEvent.delete(event);\n }\n }\n\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n once<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n const wrapper = ((payload: E[K]) => {\n listener(payload);\n this.off(event, wrapper);\n }) as Listener<E[K]>;\n\n return this.on(event, wrapper);\n }\n\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */\n onAny(listener: AnyListener<E>): () => void {\n this.anyListeners.add(listener);\n return () => this.anyListeners.delete(listener);\n }\n\n /**\n * Remove a global (any) listener (no-op if missing).\n */\n offAny(listener: AnyListener<E>): void {\n this.anyListeners.delete(listener);\n }\n\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n onceAny(listener: AnyListener<E>): () => void {\n const wrapper: AnyListener<E> = (event, payload) => {\n listener(event, payload);\n this.offAny(wrapper);\n };\n\n return this.onAny(wrapper);\n }\n\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */\n use(mw: Middleware<E>): () => void {\n this.middlewares.push(mw);\n return () => this.removeFromArray(this.middlewares, mw);\n }\n\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */\n usePattern(mw: PatternMiddleware<E>): () => void {\n this.patternMiddlewares.push(mw);\n return () => this.removeFromArray(this.patternMiddlewares, mw);\n }\n\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */\n onPattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: PatternOptions,\n ): () => void {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n\n const entry: CompiledPatternListener<E> = {\n pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler as any,\n };\n\n this.insertPatternByPriority(entry);\n return () => this.removeFromArray(this.patternListeners, entry);\n }\n\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */\n oncePattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: Omit<PatternOptions, 'once'>,\n ): () => void {\n return this.onPattern(pattern, handler, { ...options, once: true });\n }\n\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */\n listenerCount(event: keyof E): number {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners) {\n if (p.match(event) !== null) {\n count++;\n }\n }\n }\n\n return count;\n }\n\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */\n emit<K extends keyof E>(event: K, ...args: E[K] extends void ? [] : [payload: E[K]]): void {\n if (this.listenerCount(event) === 0) {\n return;\n }\n\n this._emit(event, ...args).catch((err) => this.rethrowAsync(err));\n }\n\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */\n async emitAsync<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n if (this.listenerCount(event) === 0) {\n return;\n }\n await this._emit(event, ...args);\n }\n\n private async _emit<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n const payload = args[0] as E[K];\n let blocked = false;\n\n const ctx: EmitContext<E, K> = {\n get blocked() {\n return blocked;\n },\n event,\n payload,\n matched: [],\n meta: {},\n block() {\n blocked = true;\n },\n };\n\n await this.runMiddlewares(ctx);\n }\n\n private async runMiddlewares<K extends keyof E>(ctx: EmitContext<E, K>): Promise<void> {\n const mws = this.middlewares;\n let i = 0;\n\n const next = async (): Promise<void> => {\n if (ctx.blocked) {\n return;\n }\n\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n\n const mw = mws[i++];\n let nextCalled = false;\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n await next();\n });\n };\n\n await next();\n }\n\n private async invokeUnifiedDispatch(ctx: EmitContext<E, keyof E>): Promise<void> {\n const { event, payload } = ctx;\n\n const matched =\n typeof event === 'string' && this.patternListeners.length\n ? this.matchPatternListeners(event)\n : [];\n\n // expose matched info for middleware / debugging\n (ctx as any).matched = Object.freeze(\n matched.map(\n ({ entry, params }): PatternListenerInfo<E> => ({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({ ...params }),\n handler: entry.handler,\n }),\n ),\n );\n\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) {\n for (let i = 0; i < this.patternMiddlewares.length; i++) {\n if (ctx.blocked) {\n return;\n }\n\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n });\n\n // guard: if not calling next, stop dispatch\n if (!nextCalled) {\n return;\n }\n }\n }\n\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n\n // pattern handlers by priority\n for (const { entry, params } of matched) {\n if (ctx.blocked) {\n return;\n }\n\n this.safeCall(() => entry.handler(event, payload, params));\n\n if (entry.once) {\n this.removeFromArray(this.patternListeners, entry);\n }\n }\n }\n\n private matchPatternListeners(event: string) {\n const matches: Array<{ entry: CompiledPatternListener<E>; params: Record<string, string> }> =\n [];\n\n for (const entry of this.patternListeners) {\n const params = entry.match(event);\n if (params !== null) {\n matches.push({ entry, params });\n }\n }\n\n return matches;\n }\n\n private invokeExactAndAnyListeners<K extends keyof E>(event: K, payload: E[K]): void {\n const set = this.listenersByEvent.get(event);\n if (set) {\n for (const fn of set) {\n this.safeCall(() => fn(payload));\n }\n }\n\n for (const fn of this.anyListeners) {\n this.safeCall(() => fn(event, payload));\n }\n }\n\n private getListenerSet<K extends keyof E>(event: K): Set<Listener<E[K]>> {\n let set = this.listenersByEvent.get(event) as Set<Listener<E[K]>> | undefined;\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n\n private insertPatternByPriority(entry: CompiledPatternListener<E>): void {\n const arr = this.patternListeners;\n const { priority } = entry;\n\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (arr[mid].priority >= priority) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n arr.splice(lo, 0, entry);\n }\n\n private removeFromArray<T>(arr: T[], item: T): void {\n const i = arr.indexOf(item);\n if (i >= 0) {\n arr.splice(i, 1);\n }\n }\n\n private safeCall(fn: () => void): void {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n\n private rethrowAsync(err: unknown): void {\n queueMicrotask(() => {\n throw err;\n });\n }\n\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */\n private compilePattern(pattern: string, sep: string) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') {\n return {\n kind: 'wildcard' as const,\n priority: -100,\n match: () => ({}) as Record<string, string>,\n };\n }\n\n const pSegs = pattern.split(sep);\n const keys: string[] = [];\n let score = 0;\n\n const compiled: CompiledSeg[] = pSegs.map((seg) => {\n if (seg === '**') {\n score -= 5;\n return { type: 'deepWildcard' as const };\n }\n\n if (seg === '*') {\n score -= 1;\n return { type: 'wildcard' as const };\n }\n\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return { type: 'param' as const, key };\n }\n\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp(\n '^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$',\n );\n score += 5;\n return { type: 'regex' as const, re };\n }\n\n score += 100;\n return { type: 'exact' as const, value: seg };\n });\n\n let kind: PatternKind = 'exact';\n if (keys.length) {\n kind = 'param';\n } else if (compiled.some((s) => s.type !== 'exact')) {\n kind = 'wildcard';\n }\n\n function match(event: string) {\n const eSegs = event.split(sep);\n const params: Record<string, string> = {};\n\n let i = 0; // pattern index\n let j = 0; // event index\n\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n\n while (j < eSegs.length) {\n const p = compiled[i];\n\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n\n // one segment match\n if (\n p.type === 'wildcard' ||\n (p.type === 'exact' && p.value === eSegs[j]) ||\n (p.type === 'regex' && p.re.test(eSegs[j])) ||\n (p.type === 'param' && ((params[p.key] = eSegs[j]), true))\n ) {\n i++;\n j++;\n continue;\n }\n }\n\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n\n return null;\n }\n\n // event ended; remaining pattern segments must be ** to match empty\n while (compiled[i]?.type === 'deepWildcard') {\n i++;\n }\n\n return i === compiled.length ? params : null;\n }\n\n return {\n kind,\n priority: score,\n match,\n };\n }\n}\n"],"names":["Object","defineProperty","get","$54a742859ac4854f$export$5087227eb54526","set","s","enumerable","configurable","clear","event","undefined","listenersByEvent","anyListeners","patternListeners","length","middlewares","patternMiddlewares","patternCache","delete","on","listener","getListenerSet","add","off","size","once","wrapper","payload","onAny","offAny","onceAny","use","mw","push","removeFromArray","usePattern","onPattern","pattern","handler","options","sep","separator","cacheKey","compiled","compilePattern","entry","kind","match","priority","insertPatternByPriority","oncePattern","listenerCount","count","p","emit","args","_emit","catch","err","rethrowAsync","emitAsync","blocked","runMiddlewares","matched","meta","block","ctx","mws","i","next","invokeUnifiedDispatch","nextCalled","Error","matchPatternListeners","freeze","map","params","invokeExactAndAnyListeners","safeCall","matches","fn","Set","arr","lo","hi","mid","splice","item","indexOf","queueMicrotask","pSegs","split","keys","score","seg","type","startsWith","endsWith","key","slice","includes","re","RegExp","replace","value","some","eSegs","j","starI","starJ","test","Map","EventBus"],"version":3,"file":"index.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["<anon>","src/index.ts","src/event-bus.ts","src/types.ts"],"sourcesContent":["\nfunction $parcel$export(e, n, v, s) {\n Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});\n}\nvar $ca382ab219d0caba$exports = {};\n\n$parcel$export($ca382ab219d0caba$exports, \"EventBus\", () => $ca382ab219d0caba$export$5087227eb54526);\nclass $ca382ab219d0caba$export$5087227eb54526 {\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */ clear(event) {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */ on(event, listener) {\n this.getListenerSet(event).add(listener);\n return ()=>this.off(event, listener);\n }\n /**\n * Remove an exact event listener (no-op if missing).\n */ off(event, listener) {\n const set = this.listenersByEvent.get(event);\n if (!set) return;\n set.delete(listener);\n if (set.size === 0) this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ once(event, listener) {\n const wrapper = (payload)=>{\n listener(payload);\n this.off(event, wrapper);\n };\n return this.on(event, wrapper);\n }\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */ onAny(listener) {\n this.anyListeners.add(listener);\n return ()=>this.anyListeners.delete(listener);\n }\n /**\n * Remove a global (any) listener (no-op if missing).\n */ offAny(listener) {\n this.anyListeners.delete(listener);\n }\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ onceAny(listener) {\n const wrapper = (event, payload)=>{\n listener(event, payload);\n this.offAny(wrapper);\n };\n return this.onAny(wrapper);\n }\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */ use(mw) {\n this.middlewares.push(mw);\n return ()=>this.removeFromArray(this.middlewares, mw);\n }\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */ usePattern(mw) {\n this.patternMiddlewares.push(mw);\n return ()=>this.removeFromArray(this.patternMiddlewares, mw);\n }\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */ onPattern(pattern, handler, options) {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n const entry = {\n pattern: pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler\n };\n this.insertPatternByPriority(entry);\n return ()=>this.removeFromArray(this.patternListeners, entry);\n }\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */ oncePattern(pattern, handler, options) {\n return this.onPattern(pattern, handler, {\n ...options,\n once: true\n });\n }\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */ listenerCount(event) {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners)if (p.match(event) !== null) count++;\n }\n return count;\n }\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */ emit(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n this._emit(event, ...args).catch((err)=>this.rethrowAsync(err));\n }\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */ async emitAsync(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n await this._emit(event, ...args);\n }\n async _emit(event, ...args) {\n const payload = args[0];\n let blocked = false;\n const ctx = {\n get blocked () {\n return blocked;\n },\n event: event,\n payload: payload,\n matched: [],\n meta: {},\n block () {\n blocked = true;\n }\n };\n await this.runMiddlewares(ctx);\n }\n async runMiddlewares(ctx) {\n const mws = this.middlewares;\n let i = 0;\n const next = async ()=>{\n if (ctx.blocked) return;\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n const mw = mws[i++];\n let nextCalled = false;\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n await next();\n });\n };\n await next();\n }\n async invokeUnifiedDispatch(ctx) {\n const { event: event, payload: payload } = ctx;\n const matched = typeof event === 'string' && this.patternListeners.length ? this.matchPatternListeners(event) : [];\n // expose matched info for middleware / debugging\n ctx.matched = Object.freeze(matched.map(({ entry: entry, params: params })=>({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({\n ...params\n }),\n handler: entry.handler\n })));\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) for(let i = 0; i < this.patternMiddlewares.length; i++){\n if (ctx.blocked) return;\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n });\n // guard: if not calling next, stop dispatch\n if (!nextCalled) return;\n }\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n // pattern handlers by priority\n for (const { entry: entry, params: params } of matched){\n if (ctx.blocked) return;\n this.safeCall(()=>entry.handler(event, payload, params));\n if (entry.once) this.removeFromArray(this.patternListeners, entry);\n }\n }\n matchPatternListeners(event) {\n const matches = [];\n for (const entry of this.patternListeners){\n const params = entry.match(event);\n if (params !== null) matches.push({\n entry: entry,\n params: params\n });\n }\n return matches;\n }\n invokeExactAndAnyListeners(event, payload) {\n const set = this.listenersByEvent.get(event);\n if (set) for (const fn of set)this.safeCall(()=>fn(payload));\n for (const fn of this.anyListeners)this.safeCall(()=>fn(event, payload));\n }\n getListenerSet(event) {\n let set = this.listenersByEvent.get(event);\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n insertPatternByPriority(entry) {\n const arr = this.patternListeners;\n const { priority: priority } = entry;\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n while(lo < hi){\n const mid = lo + hi >>> 1;\n if (arr[mid].priority >= priority) lo = mid + 1;\n else hi = mid;\n }\n arr.splice(lo, 0, entry);\n }\n removeFromArray(arr, item) {\n const i = arr.indexOf(item);\n if (i >= 0) arr.splice(i, 1);\n }\n safeCall(fn) {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n rethrowAsync(err) {\n queueMicrotask(()=>{\n throw err;\n });\n }\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */ compilePattern(pattern, sep) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') return {\n kind: 'wildcard',\n priority: -100,\n match: ()=>({})\n };\n const pSegs = pattern.split(sep);\n const keys = [];\n let score = 0;\n const compiled = pSegs.map((seg)=>{\n if (seg === '**') {\n score -= 5;\n return {\n type: 'deepWildcard'\n };\n }\n if (seg === '*') {\n score -= 1;\n return {\n type: 'wildcard'\n };\n }\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return {\n type: 'param',\n key: key\n };\n }\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp('^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$');\n score += 5;\n return {\n type: 'regex',\n re: re\n };\n }\n score += 100;\n return {\n type: 'exact',\n value: seg\n };\n });\n let kind = 'exact';\n if (keys.length) kind = 'param';\n else if (compiled.some((s)=>s.type !== 'exact')) kind = 'wildcard';\n function match(event) {\n const eSegs = event.split(sep);\n const params = {};\n let i = 0; // pattern index\n let j = 0; // event index\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n while(j < eSegs.length){\n const p = compiled[i];\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n // one segment match\n if (p.type === 'wildcard' || p.type === 'exact' && p.value === eSegs[j] || p.type === 'regex' && p.re.test(eSegs[j]) || p.type === 'param' && (params[p.key] = eSegs[j], true)) {\n i++;\n j++;\n continue;\n }\n }\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n return null;\n }\n // event ended; remaining pattern segments must be ** to match empty\n while(compiled[i]?.type === 'deepWildcard')i++;\n return i === compiled.length ? params : null;\n }\n return {\n kind: kind,\n priority: score,\n match: match\n };\n }\n constructor(){\n /** Listeners that receive all events */ this.anyListeners = new Set();\n /** Exact listeners mapped by event name */ this.listenersByEvent = new Map();\n /** Global middleware chain (runs on every emit) */ this.middlewares = [];\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */ this.patternMiddlewares = [];\n /** Compiled pattern listeners, sorted by priority (descending) */ this.patternListeners = [];\n /** Cache for compiled patterns (pattern + separator) */ this.patternCache = new Map();\n }\n}\n\n\nvar $539f4cbe7d2addb7$exports = {};\n/**\n * Event map definition.\n *\n * A mapping from **event name** to **payload type**.\n *\n * - **Key**: event name (string literal recommended)\n * - **Value**: payload type for that event\n *\n * Notes:\n * - Event names are typically namespaced strings, e.g. `user:login`, `order:created`.\n * - Payload can be `void` for events without payload.\n *\n * @example\n * ```ts\n * type MyEvents = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n * ```\n */ \n\n\n\nexport {$ca382ab219d0caba$export$5087227eb54526 as EventBus};\n//# sourceMappingURL=index.js.map\n","export * from './event-bus.ts';\nexport * from './types.ts';\n","import type {\n AnyListener,\n CompiledPatternListener,\n CompiledSeg,\n EmitContext,\n EventMap,\n Listener,\n Middleware,\n PatternKind,\n PatternListenerInfo,\n PatternMiddleware,\n PatternOptions,\n} from './types.ts';\n\n/**\n * A strongly-typed EventBus supporting:\n *\n * - Exact event listeners (`on`, `once`)\n * - Global listeners (`onAny`)\n * - Pattern listeners (`onPattern`, `oncePattern`)\n * - Global middleware & pattern middleware\n *\n * Pattern syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{name}` → named parameter segment\n * - `?` → single-character wildcard within a segment (regex-like)\n *\n * Error handling:\n * - Listener errors are rethrown asynchronously via `queueMicrotask`,\n * so they don't break the current emit loop.\n *\n * Emit modes:\n * - `emit()` : fire-and-forget (async errors rethrown)\n * - `emitAsync()`: await completion of middleware + listeners\n *\n * @example\n * ```ts\n * type Events = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n *\n * const bus = new EventBus<Events>();\n *\n * bus.on('user:login', (p) => console.log(p.id));\n * bus.onPattern('user:{action}', (evt, payload, params) => {\n * console.log(evt, params?.action);\n * });\n *\n * bus.emit('user:login', { id: '42' });\n * ```\n *\n * @author dafengzhen\n */\nexport class EventBus<E extends EventMap> {\n /** Listeners that receive all events */\n private anyListeners = new Set<AnyListener<E>>();\n\n /** Exact listeners mapped by event name */\n private listenersByEvent = new Map<keyof E, Set<Listener<any>>>();\n\n /** Global middleware chain (runs on every emit) */\n private middlewares: Middleware<E>[] = [];\n\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */\n private patternMiddlewares: PatternMiddleware<E>[] = [];\n\n /** Compiled pattern listeners, sorted by priority (descending) */\n private patternListeners: CompiledPatternListener<E>[] = [];\n\n /** Cache for compiled patterns (pattern + separator) */\n private patternCache = new Map<string, ReturnType<EventBus<E>['compilePattern']>>();\n\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */\n clear(event?: keyof E): void {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */\n on<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n this.getListenerSet(event).add(listener);\n return () => this.off(event, listener);\n }\n\n /**\n * Remove an exact event listener (no-op if missing).\n */\n off<K extends keyof E>(event: K, listener: Listener<E[K]>): void {\n const set = this.listenersByEvent.get(event);\n if (!set) {\n return;\n }\n\n set.delete(listener);\n if (set.size === 0) {\n this.listenersByEvent.delete(event);\n }\n }\n\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n once<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n const wrapper = ((payload: E[K]) => {\n listener(payload);\n this.off(event, wrapper);\n }) as Listener<E[K]>;\n\n return this.on(event, wrapper);\n }\n\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */\n onAny(listener: AnyListener<E>): () => void {\n this.anyListeners.add(listener);\n return () => this.anyListeners.delete(listener);\n }\n\n /**\n * Remove a global (any) listener (no-op if missing).\n */\n offAny(listener: AnyListener<E>): void {\n this.anyListeners.delete(listener);\n }\n\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n onceAny(listener: AnyListener<E>): () => void {\n const wrapper: AnyListener<E> = (event, payload) => {\n listener(event, payload);\n this.offAny(wrapper);\n };\n\n return this.onAny(wrapper);\n }\n\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */\n use(mw: Middleware<E>): () => void {\n this.middlewares.push(mw);\n return () => this.removeFromArray(this.middlewares, mw);\n }\n\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */\n usePattern(mw: PatternMiddleware<E>): () => void {\n this.patternMiddlewares.push(mw);\n return () => this.removeFromArray(this.patternMiddlewares, mw);\n }\n\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */\n onPattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: PatternOptions,\n ): () => void {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n\n const entry: CompiledPatternListener<E> = {\n pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler as any,\n };\n\n this.insertPatternByPriority(entry);\n return () => this.removeFromArray(this.patternListeners, entry);\n }\n\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */\n oncePattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: Omit<PatternOptions, 'once'>,\n ): () => void {\n return this.onPattern(pattern, handler, { ...options, once: true });\n }\n\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */\n listenerCount(event: keyof E): number {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners) {\n if (p.match(event) !== null) {\n count++;\n }\n }\n }\n\n return count;\n }\n\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */\n emit<K extends keyof E>(event: K, ...args: E[K] extends void ? [] : [payload: E[K]]): void {\n if (this.listenerCount(event) === 0) {\n return;\n }\n\n this._emit(event, ...args).catch((err) => this.rethrowAsync(err));\n }\n\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */\n async emitAsync<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n if (this.listenerCount(event) === 0) {\n return;\n }\n await this._emit(event, ...args);\n }\n\n private async _emit<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n const payload = args[0] as E[K];\n let blocked = false;\n\n const ctx: EmitContext<E, K> = {\n get blocked() {\n return blocked;\n },\n event,\n payload,\n matched: [],\n meta: {},\n block() {\n blocked = true;\n },\n };\n\n await this.runMiddlewares(ctx);\n }\n\n private async runMiddlewares<K extends keyof E>(ctx: EmitContext<E, K>): Promise<void> {\n const mws = this.middlewares;\n let i = 0;\n\n const next = async (): Promise<void> => {\n if (ctx.blocked) {\n return;\n }\n\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n\n const mw = mws[i++];\n let nextCalled = false;\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n await next();\n });\n };\n\n await next();\n }\n\n private async invokeUnifiedDispatch(ctx: EmitContext<E, keyof E>): Promise<void> {\n const { event, payload } = ctx;\n\n const matched =\n typeof event === 'string' && this.patternListeners.length\n ? this.matchPatternListeners(event)\n : [];\n\n // expose matched info for middleware / debugging\n (ctx as any).matched = Object.freeze(\n matched.map(\n ({ entry, params }): PatternListenerInfo<E> => ({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({ ...params }),\n handler: entry.handler,\n }),\n ),\n );\n\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) {\n for (let i = 0; i < this.patternMiddlewares.length; i++) {\n if (ctx.blocked) {\n return;\n }\n\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n });\n\n // guard: if not calling next, stop dispatch\n if (!nextCalled) {\n return;\n }\n }\n }\n\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n\n // pattern handlers by priority\n for (const { entry, params } of matched) {\n if (ctx.blocked) {\n return;\n }\n\n this.safeCall(() => entry.handler(event, payload, params));\n\n if (entry.once) {\n this.removeFromArray(this.patternListeners, entry);\n }\n }\n }\n\n private matchPatternListeners(event: string) {\n const matches: Array<{ entry: CompiledPatternListener<E>; params: Record<string, string> }> =\n [];\n\n for (const entry of this.patternListeners) {\n const params = entry.match(event);\n if (params !== null) {\n matches.push({ entry, params });\n }\n }\n\n return matches;\n }\n\n private invokeExactAndAnyListeners<K extends keyof E>(event: K, payload: E[K]): void {\n const set = this.listenersByEvent.get(event);\n if (set) {\n for (const fn of set) {\n this.safeCall(() => fn(payload));\n }\n }\n\n for (const fn of this.anyListeners) {\n this.safeCall(() => fn(event, payload));\n }\n }\n\n private getListenerSet<K extends keyof E>(event: K): Set<Listener<E[K]>> {\n let set = this.listenersByEvent.get(event) as Set<Listener<E[K]>> | undefined;\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n\n private insertPatternByPriority(entry: CompiledPatternListener<E>): void {\n const arr = this.patternListeners;\n const { priority } = entry;\n\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (arr[mid].priority >= priority) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n arr.splice(lo, 0, entry);\n }\n\n private removeFromArray<T>(arr: T[], item: T): void {\n const i = arr.indexOf(item);\n if (i >= 0) {\n arr.splice(i, 1);\n }\n }\n\n private safeCall(fn: () => void): void {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n\n private rethrowAsync(err: unknown): void {\n queueMicrotask(() => {\n throw err;\n });\n }\n\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */\n private compilePattern(pattern: string, sep: string) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') {\n return {\n kind: 'wildcard' as const,\n priority: -100,\n match: () => ({}) as Record<string, string>,\n };\n }\n\n const pSegs = pattern.split(sep);\n const keys: string[] = [];\n let score = 0;\n\n const compiled: CompiledSeg[] = pSegs.map((seg) => {\n if (seg === '**') {\n score -= 5;\n return { type: 'deepWildcard' as const };\n }\n\n if (seg === '*') {\n score -= 1;\n return { type: 'wildcard' as const };\n }\n\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return { type: 'param' as const, key };\n }\n\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp(\n '^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$',\n );\n score += 5;\n return { type: 'regex' as const, re };\n }\n\n score += 100;\n return { type: 'exact' as const, value: seg };\n });\n\n let kind: PatternKind = 'exact';\n if (keys.length) {\n kind = 'param';\n } else if (compiled.some((s) => s.type !== 'exact')) {\n kind = 'wildcard';\n }\n\n function match(event: string) {\n const eSegs = event.split(sep);\n const params: Record<string, string> = {};\n\n let i = 0; // pattern index\n let j = 0; // event index\n\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n\n while (j < eSegs.length) {\n const p = compiled[i];\n\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n\n // one segment match\n if (\n p.type === 'wildcard' ||\n (p.type === 'exact' && p.value === eSegs[j]) ||\n (p.type === 'regex' && p.re.test(eSegs[j])) ||\n (p.type === 'param' && ((params[p.key] = eSegs[j]), true))\n ) {\n i++;\n j++;\n continue;\n }\n }\n\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n\n return null;\n }\n\n // event ended; remaining pattern segments must be ** to match empty\n while (compiled[i]?.type === 'deepWildcard') {\n i++;\n }\n\n return i === compiled.length ? params : null;\n }\n\n return {\n kind,\n priority: score,\n match,\n };\n }\n}\n","/**\n * Event map definition.\n *\n * A mapping from **event name** to **payload type**.\n *\n * - **Key**: event name (string literal recommended)\n * - **Value**: payload type for that event\n *\n * Notes:\n * - Event names are typically namespaced strings, e.g. `user:login`, `order:created`.\n * - Payload can be `void` for events without payload.\n *\n * @example\n * ```ts\n * type MyEvents = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n * ```\n */\nexport type EventMap = Record<string, unknown>;\n\n/**\n * Listener type for a specific payload.\n *\n * If the payload is `void`, the listener receives **no arguments**.\n * Otherwise, it receives **exactly one argument**: the payload.\n *\n * This enables strict typing for both forms:\n *\n * @example\n * ```ts\n * on('ready', () => {});\n * on('data', (payload) => {\n * console.log(payload);\n * });\n * ```\n */\nexport type Listener<Payload> = Payload extends void ? () => void : (payload: Payload) => void;\n\n/**\n * Listener that receives **all emitted events**.\n *\n * It receives:\n * - `event`: the event name\n * - `payload`: the payload associated with that event\n *\n * Typical use cases:\n * - logging / debugging\n * - analytics / tracing\n * - building devtools\n *\n * @example\n * ```ts\n * const off = bus.onAny((event, payload) => {\n * console.log('event=', event, 'payload=', payload);\n * });\n * off();\n * ```\n */\nexport type AnyListener<E extends EventMap> = <K extends keyof E>(event: K, payload: E[K]) => void;\n\n/**\n * Pattern matching strategy used by a pattern listener.\n *\n * - `exact` → exact segment match (no wildcards / params)\n * - `wildcard` → contains wildcards (e.g. `*`, `**`, `?`)\n * - `param` → contains named params (e.g. `{id}`)\n *\n * Notes:\n * - These are informational categories; the actual matching is implemented by the EventBus.\n */\nexport type PatternKind = 'exact' | 'wildcard' | 'param';\n\n/**\n * Context object passed through the emit lifecycle.\n *\n * This context is shared across:\n * - global middleware\n * - pattern middleware\n * - dispatch logic\n *\n * It allows middleware to:\n * - observe the event and payload\n * - attach metadata (`meta`)\n * - stop propagation (`block()`)\n */\nexport type EmitContext<E extends EventMap, K extends keyof E> = {\n /**\n * Whether propagation has been blocked.\n *\n * Once `true`, dispatch stops and no further middleware/listeners should run.\n */\n readonly blocked: boolean;\n\n /**\n * Current emitted event name.\n */\n readonly event: K;\n\n /**\n * Payload associated with the event.\n *\n * If the event's payload type is `void`, this value is typically `undefined`\n * (depending on the emitter implementation).\n */\n readonly payload: E[K];\n\n /**\n * Information about matched pattern listeners for this emit cycle.\n *\n * - Ordered by priority (highest first).\n * - Empty if no pattern listeners matched (or pattern matching not applicable).\n *\n * Useful for middleware that wants to inspect or audit matches.\n */\n readonly matched: readonly PatternListenerInfo<E>[];\n\n /**\n * Free-form metadata container shared across middleware.\n *\n * Use this to pass state between middleware, e.g.:\n * - correlation IDs\n * - timing info\n * - auth decisions\n *\n * Note: Consumers should avoid putting large objects here in hot paths.\n */\n readonly meta: Record<string, unknown>;\n\n /**\n * Stop further propagation of this event.\n *\n * Once called:\n * - remaining middleware is skipped\n * - remaining listeners are not executed\n */\n block(): void;\n};\n\n/**\n * Middleware executed for **every emit call**.\n *\n * Middleware can:\n * - inspect event/payload/matches\n * - read/write `ctx.meta`\n * - block propagation via `ctx.block()`\n * - perform async work\n *\n * Chain semantics:\n * - Middlewares are executed sequentially in registration order.\n * - `next()` must be called exactly once to continue the chain (depending on implementation).\n */\nexport type Middleware<E extends EventMap> = <K extends keyof E>(\n ctx: EmitContext<E, K>,\n next: () => Promise<void>,\n) => Promise<void> | void;\n\n/**\n * Middleware executed **only when pattern listeners are involved**.\n *\n * Typical uses:\n * - logging pattern matches & params\n * - permission checks / gating\n * - validating extracted params\n *\n * Chain semantics depend on the EventBus implementation.\n * In your EventBus, pattern middleware acts as a guard:\n * - if it does not call `next()`, dispatch stops\n * - `next()` must not be called more than once\n */\nexport type PatternMiddleware<E extends EventMap> = (\n ctx: EmitContext<E, keyof E>,\n next: () => Promise<void>,\n) => Promise<void> | void;\n\n/**\n * Public information of a matched pattern listener.\n *\n * Exposed to middleware and user-land code through `ctx.matched`.\n */\nexport interface PatternListenerInfo<E extends EventMap> {\n /**\n * Original pattern string.\n *\n * @example\n * ```ts\n * 'user:{id}'\n * 'order:*'\n * '**'\n * ```\n */\n readonly pattern: string;\n\n /**\n * Matching strategy classification.\n */\n readonly kind: PatternKind;\n\n /**\n * Listener priority. Higher values run earlier.\n */\n readonly priority: number;\n\n /**\n * Whether this listener was registered with `once`.\n */\n readonly once?: boolean;\n\n /**\n * Extracted params from the event name.\n *\n * Example (separator `:`):\n * - pattern: `user:{id}`\n * - event: `user:42`\n * - params: `{ id: '42' }`\n */\n readonly params: Readonly<Record<string, string>>;\n\n /**\n * The actual handler function.\n *\n * Note:\n * - Kept here mainly for introspection/debugging.\n * - Middleware should generally not call handlers directly.\n */\n readonly handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void;\n}\n\n/**\n * Internal compiled representation of a pattern listener.\n *\n * Not exposed publicly.\n * Contains precompiled matching logic for performance.\n */\nexport interface CompiledPatternListener<E extends EventMap> {\n /**\n * Original pattern string (uncompiled).\n */\n pattern: string;\n\n /**\n * Matching strategy classification.\n */\n kind: PatternKind;\n\n /**\n * Listener priority. Higher values run earlier.\n */\n priority: number;\n\n /**\n * Whether the listener should auto-remove after first run.\n */\n once?: boolean;\n\n /**\n * Match function produced by the compiler.\n *\n * @param event - Emitted event name\n * @returns\n * - `null` if no match\n * - params record if matched (possibly empty)\n */\n match(event: string): null | Record<string, string>;\n\n /**\n * Listener handler.\n *\n * @param event - Emitted event name\n * @param payload - Payload associated with event\n * @param params - Extracted params from pattern (if any)\n */\n handler(event: keyof E, payload: E[keyof E], params?: Record<string, string>): void;\n}\n\n/**\n * Options for registering a pattern listener.\n */\nexport type PatternOptions = {\n /**\n * Invoke the listener only once.\n *\n * After the first successful match, it is automatically removed.\n */\n once?: boolean;\n\n /**\n * Listener priority.\n *\n * Higher values run earlier.\n * If omitted, EventBus will derive a priority from pattern specificity.\n */\n priority?: number;\n\n /**\n * Segment separator used when splitting patterns and events.\n *\n * IMPORTANT:\n * - This default should match your EventBus implementation.\n * - In the current EventBus code you posted, the default is `':'`.\n */\n separator?: string;\n};\n\n/**\n * Internal compiled segment representation produced by the pattern compiler.\n *\n * - `exact` → exact segment match\n * - `wildcard` → `*` matches exactly one segment\n * - `deepWildcard` → `**` matches 0..n segments (backtracking)\n * - `param` → `{key}` captures a segment into params\n * - `regex` → per-segment regex (used for `?` patterns)\n */\nexport type CompiledSeg =\n | { type: 'exact'; value: string }\n | { type: 'wildcard' }\n | { type: 'deepWildcard' }\n | { type: 'param'; key: string }\n | { type: 'regex'; re: RegExp };\n"],"names":["Object","defineProperty","get","$ca382ab219d0caba$export$5087227eb54526","set","s","enumerable","configurable","clear","event","undefined","listenersByEvent","anyListeners","patternListeners","length","middlewares","patternMiddlewares","patternCache","delete","on","listener","getListenerSet","add","off","size","once","wrapper","payload","onAny","offAny","onceAny","use","mw","push","removeFromArray","usePattern","onPattern","pattern","handler","options","sep","separator","cacheKey","compiled","compilePattern","entry","kind","match","priority","insertPatternByPriority","oncePattern","listenerCount","count","p","emit","args","_emit","catch","err","rethrowAsync","emitAsync","blocked","runMiddlewares","matched","meta","block","ctx","mws","i","next","invokeUnifiedDispatch","nextCalled","Error","matchPatternListeners","freeze","map","params","invokeExactAndAnyListeners","safeCall","matches","fn","Set","arr","lo","hi","mid","splice","item","indexOf","queueMicrotask","pSegs","split","keys","score","seg","type","startsWith","endsWith","key","slice","includes","re","RegExp","replace","value","some","eSegs","j","starI","starJ","test","Map","EventBus"],"version":3,"file":"index.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["<anon>","src/index.ts","src/event-bus.ts"],"sourcesContent":["\nfunction $parcel$export(e, n, v, s) {\n Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});\n}\nvar $ca382ab219d0caba$exports = {};\n\n$parcel$export($ca382ab219d0caba$exports, \"EventBus\", () => $ca382ab219d0caba$export$5087227eb54526);\nclass $ca382ab219d0caba$export$5087227eb54526 {\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */ clear(event) {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */ on(event, listener) {\n this.getListenerSet(event).add(listener);\n return ()=>this.off(event, listener);\n }\n /**\n * Remove an exact event listener (no-op if missing).\n */ off(event, listener) {\n const set = this.listenersByEvent.get(event);\n if (!set) return;\n set.delete(listener);\n if (set.size === 0) this.listenersByEvent.delete(event);\n }\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ once(event, listener) {\n const wrapper = (payload)=>{\n listener(payload);\n this.off(event, wrapper);\n };\n return this.on(event, wrapper);\n }\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */ onAny(listener) {\n this.anyListeners.add(listener);\n return ()=>this.anyListeners.delete(listener);\n }\n /**\n * Remove a global (any) listener (no-op if missing).\n */ offAny(listener) {\n this.anyListeners.delete(listener);\n }\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */ onceAny(listener) {\n const wrapper = (event, payload)=>{\n listener(event, payload);\n this.offAny(wrapper);\n };\n return this.onAny(wrapper);\n }\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */ use(mw) {\n this.middlewares.push(mw);\n return ()=>this.removeFromArray(this.middlewares, mw);\n }\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */ usePattern(mw) {\n this.patternMiddlewares.push(mw);\n return ()=>this.removeFromArray(this.patternMiddlewares, mw);\n }\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */ onPattern(pattern, handler, options) {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n const entry = {\n pattern: pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler\n };\n this.insertPatternByPriority(entry);\n return ()=>this.removeFromArray(this.patternListeners, entry);\n }\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */ oncePattern(pattern, handler, options) {\n return this.onPattern(pattern, handler, {\n ...options,\n once: true\n });\n }\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */ listenerCount(event) {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners)if (p.match(event) !== null) count++;\n }\n return count;\n }\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */ emit(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n this._emit(event, ...args).catch((err)=>this.rethrowAsync(err));\n }\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */ async emitAsync(event, ...args) {\n if (this.listenerCount(event) === 0) return;\n await this._emit(event, ...args);\n }\n async _emit(event, ...args) {\n const payload = args[0];\n let blocked = false;\n const ctx = {\n get blocked () {\n return blocked;\n },\n event: event,\n payload: payload,\n matched: [],\n meta: {},\n block () {\n blocked = true;\n }\n };\n await this.runMiddlewares(ctx);\n }\n async runMiddlewares(ctx) {\n const mws = this.middlewares;\n let i = 0;\n const next = async ()=>{\n if (ctx.blocked) return;\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n const mw = mws[i++];\n let nextCalled = false;\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n await next();\n });\n };\n await next();\n }\n async invokeUnifiedDispatch(ctx) {\n const { event: event, payload: payload } = ctx;\n const matched = typeof event === 'string' && this.patternListeners.length ? this.matchPatternListeners(event) : [];\n // expose matched info for middleware / debugging\n ctx.matched = Object.freeze(matched.map(({ entry: entry, params: params })=>({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({\n ...params\n }),\n handler: entry.handler\n })));\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) for(let i = 0; i < this.patternMiddlewares.length; i++){\n if (ctx.blocked) return;\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n await mw(ctx, async ()=>{\n if (nextCalled) throw new Error('next() called multiple times.');\n nextCalled = true;\n });\n // guard: if not calling next, stop dispatch\n if (!nextCalled) return;\n }\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n // pattern handlers by priority\n for (const { entry: entry, params: params } of matched){\n if (ctx.blocked) return;\n this.safeCall(()=>entry.handler(event, payload, params));\n if (entry.once) this.removeFromArray(this.patternListeners, entry);\n }\n }\n matchPatternListeners(event) {\n const matches = [];\n for (const entry of this.patternListeners){\n const params = entry.match(event);\n if (params !== null) matches.push({\n entry: entry,\n params: params\n });\n }\n return matches;\n }\n invokeExactAndAnyListeners(event, payload) {\n const set = this.listenersByEvent.get(event);\n if (set) for (const fn of set)this.safeCall(()=>fn(payload));\n for (const fn of this.anyListeners)this.safeCall(()=>fn(event, payload));\n }\n getListenerSet(event) {\n let set = this.listenersByEvent.get(event);\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n insertPatternByPriority(entry) {\n const arr = this.patternListeners;\n const { priority: priority } = entry;\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n while(lo < hi){\n const mid = lo + hi >>> 1;\n if (arr[mid].priority >= priority) lo = mid + 1;\n else hi = mid;\n }\n arr.splice(lo, 0, entry);\n }\n removeFromArray(arr, item) {\n const i = arr.indexOf(item);\n if (i >= 0) arr.splice(i, 1);\n }\n safeCall(fn) {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n rethrowAsync(err) {\n queueMicrotask(()=>{\n throw err;\n });\n }\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */ compilePattern(pattern, sep) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') return {\n kind: 'wildcard',\n priority: -100,\n match: ()=>({})\n };\n const pSegs = pattern.split(sep);\n const keys = [];\n let score = 0;\n const compiled = pSegs.map((seg)=>{\n if (seg === '**') {\n score -= 5;\n return {\n type: 'deepWildcard'\n };\n }\n if (seg === '*') {\n score -= 1;\n return {\n type: 'wildcard'\n };\n }\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return {\n type: 'param',\n key: key\n };\n }\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp('^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$');\n score += 5;\n return {\n type: 'regex',\n re: re\n };\n }\n score += 100;\n return {\n type: 'exact',\n value: seg\n };\n });\n let kind = 'exact';\n if (keys.length) kind = 'param';\n else if (compiled.some((s)=>s.type !== 'exact')) kind = 'wildcard';\n function match(event) {\n const eSegs = event.split(sep);\n const params = {};\n let i = 0; // pattern index\n let j = 0; // event index\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n while(j < eSegs.length){\n const p = compiled[i];\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n // one segment match\n if (p.type === 'wildcard' || p.type === 'exact' && p.value === eSegs[j] || p.type === 'regex' && p.re.test(eSegs[j]) || p.type === 'param' && (params[p.key] = eSegs[j], true)) {\n i++;\n j++;\n continue;\n }\n }\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n return null;\n }\n // event ended; remaining pattern segments must be ** to match empty\n while(compiled[i]?.type === 'deepWildcard')i++;\n return i === compiled.length ? params : null;\n }\n return {\n kind: kind,\n priority: score,\n match: match\n };\n }\n constructor(){\n /** Listeners that receive all events */ this.anyListeners = new Set();\n /** Exact listeners mapped by event name */ this.listenersByEvent = new Map();\n /** Global middleware chain (runs on every emit) */ this.middlewares = [];\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */ this.patternMiddlewares = [];\n /** Compiled pattern listeners, sorted by priority (descending) */ this.patternListeners = [];\n /** Cache for compiled patterns (pattern + separator) */ this.patternCache = new Map();\n }\n}\n\n\n\n\nexport {$ca382ab219d0caba$export$5087227eb54526 as EventBus};\n//# sourceMappingURL=index.js.map\n","export type * from './types.ts';\nexport * from './event-bus.ts';\n","import type {\n AnyListener,\n CompiledPatternListener,\n CompiledSeg,\n EmitContext,\n EventMap,\n Listener,\n Middleware,\n PatternKind,\n PatternListenerInfo,\n PatternMiddleware,\n PatternOptions,\n} from './types.ts';\n\n/**\n * A strongly-typed EventBus supporting:\n *\n * - Exact event listeners (`on`, `once`)\n * - Global listeners (`onAny`)\n * - Pattern listeners (`onPattern`, `oncePattern`)\n * - Global middleware & pattern middleware\n *\n * Pattern syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{name}` → named parameter segment\n * - `?` → single-character wildcard within a segment (regex-like)\n *\n * Error handling:\n * - Listener errors are rethrown asynchronously via `queueMicrotask`,\n * so they don't break the current emit loop.\n *\n * Emit modes:\n * - `emit()` : fire-and-forget (async errors rethrown)\n * - `emitAsync()`: await completion of middleware + listeners\n *\n * @example\n * ```ts\n * type Events = {\n * 'user:login': { id: string };\n * 'user:logout': void;\n * };\n *\n * const bus = new EventBus<Events>();\n *\n * bus.on('user:login', (p) => console.log(p.id));\n * bus.onPattern('user:{action}', (evt, payload, params) => {\n * console.log(evt, params?.action);\n * });\n *\n * bus.emit('user:login', { id: '42' });\n * ```\n *\n * @author dafengzhen\n */\nexport class EventBus<E extends EventMap> {\n /** Listeners that receive all events */\n private anyListeners = new Set<AnyListener<E>>();\n\n /** Exact listeners mapped by event name */\n private listenersByEvent = new Map<keyof E, Set<Listener<any>>>();\n\n /** Global middleware chain (runs on every emit) */\n private middlewares: Middleware<E>[] = [];\n\n /**\n * Pattern-specific middleware chain.\n * Only runs when there is at least one matched pattern listener for the emitted event.\n */\n private patternMiddlewares: PatternMiddleware<E>[] = [];\n\n /** Compiled pattern listeners, sorted by priority (descending) */\n private patternListeners: CompiledPatternListener<E>[] = [];\n\n /** Cache for compiled patterns (pattern + separator) */\n private patternCache = new Map<string, ReturnType<EventBus<E>['compilePattern']>>();\n\n /**\n * Clear listeners and middleware.\n * - If `event` is omitted, clears everything (exact/any/pattern listeners + middleware + cache).\n * - If `event` is provided, only clears exact listeners of that event.\n */\n clear(event?: keyof E): void {\n if (event === undefined) {\n this.listenersByEvent.clear();\n this.anyListeners.clear();\n this.patternListeners.length = 0;\n this.middlewares.length = 0;\n this.patternMiddlewares.length = 0;\n this.patternCache.clear();\n return;\n }\n this.listenersByEvent.delete(event);\n }\n\n /**\n * Register an exact listener for a specific event.\n * @returns Unsubscribe function\n */\n on<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n this.getListenerSet(event).add(listener);\n return () => this.off(event, listener);\n }\n\n /**\n * Remove an exact event listener (no-op if missing).\n */\n off<K extends keyof E>(event: K, listener: Listener<E[K]>): void {\n const set = this.listenersByEvent.get(event);\n if (!set) {\n return;\n }\n\n set.delete(listener);\n if (set.size === 0) {\n this.listenersByEvent.delete(event);\n }\n }\n\n /**\n * Register an exact listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n once<K extends keyof E>(event: K, listener: Listener<E[K]>): () => void {\n const wrapper = ((payload: E[K]) => {\n listener(payload);\n this.off(event, wrapper);\n }) as Listener<E[K]>;\n\n return this.on(event, wrapper);\n }\n\n /**\n * Register a listener that receives all events.\n * @returns Unsubscribe function\n */\n onAny(listener: AnyListener<E>): () => void {\n this.anyListeners.add(listener);\n return () => this.anyListeners.delete(listener);\n }\n\n /**\n * Remove a global (any) listener (no-op if missing).\n */\n offAny(listener: AnyListener<E>): void {\n this.anyListeners.delete(listener);\n }\n\n /**\n * Register a global (any) listener that runs only once.\n * @returns Unsubscribe function (still works before the first run)\n */\n onceAny(listener: AnyListener<E>): () => void {\n const wrapper: AnyListener<E> = (event, payload) => {\n listener(event, payload);\n this.offAny(wrapper);\n };\n\n return this.onAny(wrapper);\n }\n\n /**\n * Register a global middleware (runs on every emit).\n *\n * Middleware must call `next()` exactly once to continue.\n * If it never calls `next()`, dispatch stops.\n *\n * @returns Unsubscribe function\n */\n use(mw: Middleware<E>): () => void {\n this.middlewares.push(mw);\n return () => this.removeFromArray(this.middlewares, mw);\n }\n\n /**\n * Register a pattern-specific middleware.\n *\n * Only invoked when there is at least one matched pattern listener.\n *\n * Gate semantics:\n * - If a pattern middleware does not call `next()`, dispatch stops (acts like a guard).\n * - `next()` must be called exactly once.\n *\n * @returns Unsubscribe function\n */\n usePattern(mw: PatternMiddleware<E>): () => void {\n this.patternMiddlewares.push(mw);\n return () => this.removeFromArray(this.patternMiddlewares, mw);\n }\n\n /**\n * Register a pattern listener.\n *\n * Supported syntax (separator defaults to `:`):\n * - `*` → single-segment wildcard\n * - `**` → deep wildcard (matches 0..n segments)\n * - `{param}`→ named parameter segment\n * - `?` → single-character wildcard inside a segment\n *\n * Priority:\n * - If `options.priority` is provided, it overrides auto-derived priority.\n * - Higher priority runs earlier.\n *\n * @param pattern Pattern string\n * @param handler Callback invoked when pattern matches\n * @param options Pattern options\n * @returns Unsubscribe function\n */\n onPattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: PatternOptions,\n ): () => void {\n const sep = options?.separator ?? ':';\n const cacheKey = `${pattern}|${sep}`;\n\n let compiled = this.patternCache.get(cacheKey);\n if (!compiled) {\n compiled = this.compilePattern(pattern, sep);\n this.patternCache.set(cacheKey, compiled);\n }\n\n const entry: CompiledPatternListener<E> = {\n pattern,\n kind: compiled.kind,\n match: compiled.match,\n priority: options?.priority ?? compiled.priority,\n once: options?.once,\n handler: handler as any,\n };\n\n this.insertPatternByPriority(entry);\n return () => this.removeFromArray(this.patternListeners, entry);\n }\n\n /**\n * Register a one-time pattern listener.\n * @returns Unsubscribe function\n */\n oncePattern(\n pattern: string,\n handler: (event: keyof E, payload: E[keyof E], params?: Record<string, string>) => void,\n options?: Omit<PatternOptions, 'once'>,\n ): () => void {\n return this.onPattern(pattern, handler, { ...options, once: true });\n }\n\n /**\n * Count listeners matching the event.\n *\n * Includes:\n * - Exact listeners for `event`\n * - Global `onAny` listeners\n * - Pattern listeners that match (only when `event` is a string)\n */\n listenerCount(event: keyof E): number {\n let count = 0;\n count += this.listenersByEvent.get(event)?.size ?? 0;\n count += this.anyListeners.size;\n\n if (typeof event === 'string' && this.patternListeners.length) {\n for (const p of this.patternListeners) {\n if (p.match(event) !== null) {\n count++;\n }\n }\n }\n\n return count;\n }\n\n /**\n * Emit an event synchronously (fire-and-forget).\n *\n * - Execution is async internally, but this method does not await.\n * - Listener errors are rethrown asynchronously.\n */\n emit<K extends keyof E>(event: K, ...args: E[K] extends void ? [] : [payload: E[K]]): void {\n if (this.listenerCount(event) === 0) {\n return;\n }\n\n this._emit(event, ...args).catch((err) => this.rethrowAsync(err));\n }\n\n /**\n * Emit an event asynchronously.\n * Resolves when middleware + listeners have finished.\n */\n async emitAsync<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n if (this.listenerCount(event) === 0) {\n return;\n }\n await this._emit(event, ...args);\n }\n\n private async _emit<K extends keyof E>(\n event: K,\n ...args: E[K] extends void ? [] : [payload: E[K]]\n ): Promise<void> {\n const payload = args[0] as E[K];\n let blocked = false;\n\n const ctx: EmitContext<E, K> = {\n get blocked() {\n return blocked;\n },\n event,\n payload,\n matched: [],\n meta: {},\n block() {\n blocked = true;\n },\n };\n\n await this.runMiddlewares(ctx);\n }\n\n private async runMiddlewares<K extends keyof E>(ctx: EmitContext<E, K>): Promise<void> {\n const mws = this.middlewares;\n let i = 0;\n\n const next = async (): Promise<void> => {\n if (ctx.blocked) {\n return;\n }\n\n if (i >= mws.length) {\n await this.invokeUnifiedDispatch(ctx);\n return;\n }\n\n const mw = mws[i++];\n let nextCalled = false;\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n await next();\n });\n };\n\n await next();\n }\n\n private async invokeUnifiedDispatch(ctx: EmitContext<E, keyof E>): Promise<void> {\n const { event, payload } = ctx;\n\n const matched =\n typeof event === 'string' && this.patternListeners.length\n ? this.matchPatternListeners(event)\n : [];\n\n // expose matched info for middleware / debugging\n (ctx as any).matched = Object.freeze(\n matched.map(\n ({ entry, params }): PatternListenerInfo<E> => ({\n pattern: entry.pattern,\n kind: entry.kind,\n once: entry.once,\n priority: entry.priority,\n params: Object.freeze({ ...params }),\n handler: entry.handler,\n }),\n ),\n );\n\n // pattern middleware only runs if there are matches\n if (matched.length && this.patternMiddlewares.length) {\n for (let i = 0; i < this.patternMiddlewares.length; i++) {\n if (ctx.blocked) {\n return;\n }\n\n let nextCalled = false;\n const mw = this.patternMiddlewares[i];\n\n await mw(ctx, async () => {\n if (nextCalled) {\n throw new Error('next() called multiple times.');\n }\n nextCalled = true;\n });\n\n // guard: if not calling next, stop dispatch\n if (!nextCalled) {\n return;\n }\n }\n }\n\n // exact + any first\n this.invokeExactAndAnyListeners(event, payload);\n\n // pattern handlers by priority\n for (const { entry, params } of matched) {\n if (ctx.blocked) {\n return;\n }\n\n this.safeCall(() => entry.handler(event, payload, params));\n\n if (entry.once) {\n this.removeFromArray(this.patternListeners, entry);\n }\n }\n }\n\n private matchPatternListeners(event: string) {\n const matches: Array<{ entry: CompiledPatternListener<E>; params: Record<string, string> }> =\n [];\n\n for (const entry of this.patternListeners) {\n const params = entry.match(event);\n if (params !== null) {\n matches.push({ entry, params });\n }\n }\n\n return matches;\n }\n\n private invokeExactAndAnyListeners<K extends keyof E>(event: K, payload: E[K]): void {\n const set = this.listenersByEvent.get(event);\n if (set) {\n for (const fn of set) {\n this.safeCall(() => fn(payload));\n }\n }\n\n for (const fn of this.anyListeners) {\n this.safeCall(() => fn(event, payload));\n }\n }\n\n private getListenerSet<K extends keyof E>(event: K): Set<Listener<E[K]>> {\n let set = this.listenersByEvent.get(event) as Set<Listener<E[K]>> | undefined;\n if (!set) {\n set = new Set();\n this.listenersByEvent.set(event, set);\n }\n return set;\n }\n\n private insertPatternByPriority(entry: CompiledPatternListener<E>): void {\n const arr = this.patternListeners;\n const { priority } = entry;\n\n // binary insert (descending)\n let lo = 0;\n let hi = arr.length;\n\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (arr[mid].priority >= priority) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n arr.splice(lo, 0, entry);\n }\n\n private removeFromArray<T>(arr: T[], item: T): void {\n const i = arr.indexOf(item);\n if (i >= 0) {\n arr.splice(i, 1);\n }\n }\n\n private safeCall(fn: () => void): void {\n try {\n fn();\n } catch (err) {\n this.rethrowAsync(err);\n }\n }\n\n private rethrowAsync(err: unknown): void {\n queueMicrotask(() => {\n throw err;\n });\n }\n\n /**\n * Compile a pattern into a matcher.\n *\n * Notes:\n * - `**` as a segment means \"match 0..n segments\" (deep wildcard).\n * - `*` as a segment means \"match exactly 1 segment\".\n * - If the whole pattern is exactly `\"**\"`, it matches any event (including empty params).\n */\n private compilePattern(pattern: string, sep: string) {\n // Whole-pattern deep wildcard: match everything\n if (pattern === '**') {\n return {\n kind: 'wildcard' as const,\n priority: -100,\n match: () => ({}) as Record<string, string>,\n };\n }\n\n const pSegs = pattern.split(sep);\n const keys: string[] = [];\n let score = 0;\n\n const compiled: CompiledSeg[] = pSegs.map((seg) => {\n if (seg === '**') {\n score -= 5;\n return { type: 'deepWildcard' as const };\n }\n\n if (seg === '*') {\n score -= 1;\n return { type: 'wildcard' as const };\n }\n\n if (seg.startsWith('{') && seg.endsWith('}')) {\n const key = seg.slice(1, -1);\n keys.push(key);\n score += 10;\n return { type: 'param' as const, key };\n }\n\n if (seg.includes('?')) {\n // escape then replace ? with single-char wildcard\n const re = new RegExp(\n '^' + seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\?/g, '.') + '$',\n );\n score += 5;\n return { type: 'regex' as const, re };\n }\n\n score += 100;\n return { type: 'exact' as const, value: seg };\n });\n\n let kind: PatternKind = 'exact';\n if (keys.length) {\n kind = 'param';\n } else if (compiled.some((s) => s.type !== 'exact')) {\n kind = 'wildcard';\n }\n\n function match(event: string) {\n const eSegs = event.split(sep);\n const params: Record<string, string> = {};\n\n let i = 0; // pattern index\n let j = 0; // event index\n\n // backtracking position for deepWildcard (**)\n let starI = -1;\n let starJ = -1;\n\n while (j < eSegs.length) {\n const p = compiled[i];\n\n if (p) {\n if (p.type === 'deepWildcard') {\n // ** can match empty; remember and advance pattern\n starI = i++;\n starJ = j;\n continue;\n }\n\n // one segment match\n if (\n p.type === 'wildcard' ||\n (p.type === 'exact' && p.value === eSegs[j]) ||\n (p.type === 'regex' && p.re.test(eSegs[j])) ||\n (p.type === 'param' && ((params[p.key] = eSegs[j]), true))\n ) {\n i++;\n j++;\n continue;\n }\n }\n\n // mismatch: if we had a ** before, backtrack to let ** consume one more segment\n if (starI !== -1) {\n i = starI + 1;\n j = ++starJ;\n continue;\n }\n\n return null;\n }\n\n // event ended; remaining pattern segments must be ** to match empty\n while (compiled[i]?.type === 'deepWildcard') {\n i++;\n }\n\n return i === compiled.length ? params : null;\n }\n\n return {\n kind,\n priority: score,\n match,\n };\n }\n}\n"],"names":["Object","defineProperty","get","$ca382ab219d0caba$export$5087227eb54526","set","s","enumerable","configurable","clear","event","undefined","listenersByEvent","anyListeners","patternListeners","length","middlewares","patternMiddlewares","patternCache","delete","on","listener","getListenerSet","add","off","size","once","wrapper","payload","onAny","offAny","onceAny","use","mw","push","removeFromArray","usePattern","onPattern","pattern","handler","options","sep","separator","cacheKey","compiled","compilePattern","entry","kind","match","priority","insertPatternByPriority","oncePattern","listenerCount","count","p","emit","args","_emit","catch","err","rethrowAsync","emitAsync","blocked","runMiddlewares","matched","meta","block","ctx","mws","i","next","invokeUnifiedDispatch","nextCalled","Error","matchPatternListeners","freeze","map","params","invokeExactAndAnyListeners","safeCall","matches","fn","Set","arr","lo","hi","mid","splice","item","indexOf","queueMicrotask","pSegs","split","keys","score","seg","type","startsWith","endsWith","key","slice","includes","re","RegExp","replace","value","some","eSegs","j","starI","starJ","test","Map","EventBus"],"version":3,"file":"index.js.map"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,uBAAuB,MAAM,CAAC,MAAM,EAAE,
|
|
1
|
+
{"mappings":"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","sources":["src/src/types.ts","src/src/event-bus.ts","src/src/index.ts","src/index.ts"],"sourcesContent":[null,null,null,"export type * from './types.ts';\nexport * from './event-bus.ts';\n"],"names":[],"version":3,"file":"index.d.ts.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dafengzhen/event-bus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A lightweight TypeScript event bus with strong typing, middleware pipeline, and pattern-based event listeners.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"event-bus",
|
|
@@ -31,12 +31,9 @@
|
|
|
31
31
|
"types": "./dist/types/index.d.ts",
|
|
32
32
|
"exports": {
|
|
33
33
|
".": {
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"require": {
|
|
38
|
-
"default": "./dist/cjs/modern/index.js"
|
|
39
|
-
}
|
|
34
|
+
"types": "./dist/types/index.d.ts",
|
|
35
|
+
"import": "./dist/esm/modern/index.js",
|
|
36
|
+
"require": "./dist/cjs/modern/index.js"
|
|
40
37
|
}
|
|
41
38
|
},
|
|
42
39
|
"scripts": {
|