{"version":3,"file":"HookBridge-CiRfR67f.cjs","names":[],"sources":["../../src/hooks/HookManager.ts","../../src/hooks/HookBridge.ts"],"sourcesContent":["import type {\n    HookLogEntry,\n    HookEvent,\n    HookCallback,\n    MiddlewareFn,\n    HookRegistration,\n    MiddlewareRegistration,\n    IHookManager\n} from '../types/index.js';\n\nconst MAX_ONERROR_DEPTH = 5;\n\nfunction generateId(): string {\n    return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nexport class HookManager implements IHookManager {\n    private hooks: Map<HookEvent, HookRegistration[]> = new Map();\n    private middlewares: MiddlewareRegistration[] = [];\n    /**\n     * Tracks current recursion depth for each hook event so `onError` chains\n     * that throw can't loop forever. Reset when the outer emit returns.\n     */\n    private _onErrorDepth: Map<HookEvent, number> = new Map();\n\n    constructor() {\n        this.hooks.set('beforeLog', []);\n        this.hooks.set('afterLog', []);\n        this.hooks.set('onError', []);\n    }\n\n    on(event: HookEvent, callback: HookCallback, priority: number = 50): () => void {\n        const registration: HookRegistration = {\n            id: generateId(),\n            event,\n            callback,\n            priority,\n            once: false\n        };\n\n        const hooks = this.hooks.get(event)!;\n        hooks.push(registration);\n        hooks.sort((a, b) => b.priority - a.priority);\n\n        return () => this.removeHook(event, registration.id);\n    }\n\n    once(event: HookEvent, callback: HookCallback, priority: number = 50): () => void {\n        const registration: HookRegistration = {\n            id: generateId(),\n            event,\n            callback,\n            priority,\n            once: true\n        };\n\n        const hooks = this.hooks.get(event)!;\n        hooks.push(registration);\n        hooks.sort((a, b) => b.priority - a.priority);\n\n        return () => this.removeHook(event, registration.id);\n    }\n\n    off(event: HookEvent, callback: HookCallback): boolean {\n        const hooks = this.hooks.get(event);\n        if (!hooks) return false;\n\n        const index = hooks.findIndex(h => h.callback === callback);\n        if (index >= 0) {\n            hooks.splice(index, 1);\n            return true;\n        }\n        return false;\n    }\n\n    private removeHook(event: HookEvent, id: string): void {\n        const hooks = this.hooks.get(event);\n        if (hooks) {\n            const index = hooks.findIndex(h => h.id === id);\n            if (index >= 0) {\n                hooks.splice(index, 1);\n            }\n        }\n    }\n\n    use(middleware: MiddlewareFn, priority: number = 50): () => void {\n        const registration: MiddlewareRegistration = {\n            id: generateId(),\n            fn: middleware,\n            priority\n        };\n\n        this.middlewares.push(registration);\n        this.middlewares.sort((a, b) => b.priority - a.priority);\n\n        return () => {\n            const index = this.middlewares.findIndex(m => m.id === registration.id);\n            if (index >= 0) {\n                this.middlewares.splice(index, 1);\n            }\n        };\n    }\n\n    async emit(event: HookEvent, entry: HookLogEntry): Promise<HookLogEntry> {\n        // Re-entrancy guard. Without this, an onError hook that itself throws\n        // would re-enter emit('onError', ...) and either spin forever or\n        // recurse until the stack blows. We allow a small burst (MAX_ONERROR_DEPTH)\n        // so legitimate fan-out keeps working, but break the cycle.\n        const depth = (this._onErrorDepth.get(entry.hookEvent ?? event) ?? 0);\n        if (event === 'onError' && depth >= MAX_ONERROR_DEPTH) {\n            // eslint-disable-next-line no-console\n            console.error('HookManager: onError recursion limit reached, dropping entry:', entry);\n            return entry;\n        }\n        this._onErrorDepth.set(event, depth + 1);\n\n        try {\n            const hooks = this.hooks.get(event) || [];\n            let currentEntry = { ...entry };\n            const toRemove: string[] = [];\n\n            for (const hook of hooks) {\n                try {\n                    const result = await hook.callback(currentEntry);\n                    if (result) {\n                        currentEntry = { ...currentEntry, ...result };\n                    }\n                    if (hook.once) {\n                        toRemove.push(hook.id);\n                    }\n                } catch (error) {\n                    if (event !== 'onError') {\n                        await this.emit('onError', {\n                            ...currentEntry,\n                            error: error instanceof Error ? error : new Error(String(error)),\n                            hookEvent: event\n                        });\n                    } else {\n                        // An onError hook threw — surface to console (single shot)\n                        // without dispatching another onError (which would recurse).\n                        // eslint-disable-next-line no-console\n                        console.error('HookManager: onError hook threw, swallowed to break recursion:', error);\n                    }\n                }\n            }\n\n            toRemove.forEach(id => this.removeHook(event, id));\n            return currentEntry;\n        } finally {\n            this._onErrorDepth.set(event, depth);\n        }\n    }\n\n    async process(entry: HookLogEntry): Promise<HookLogEntry> {\n        let currentEntry = { ...entry };\n\n        currentEntry = await this.emit('beforeLog', currentEntry);\n\n        if (this.middlewares.length > 0) {\n            let index = 0;\n\n            const executeNext = async (): Promise<void> => {\n                if (index < this.middlewares.length) {\n                    const middleware = this.middlewares[index++];\n                    if (middleware) {\n                        await middleware.fn(currentEntry, executeNext);\n                    }\n                }\n            };\n\n            await executeNext();\n        }\n\n        return currentEntry;\n    }\n\n    async afterProcess(entry: HookLogEntry): Promise<void> {\n        await this.emit('afterLog', entry);\n    }\n\n    clear(): void {\n        this.hooks.forEach(hooks => hooks.length = 0);\n        this.middlewares.length = 0;\n    }\n\n    getStats(): { hooks: Record<HookEvent, number>; middlewares: number } {\n        return {\n            hooks: {\n                beforeLog: this.hooks.get('beforeLog')?.length || 0,\n                afterLog: this.hooks.get('afterLog')?.length || 0,\n                onError: this.hooks.get('onError')?.length || 0\n            },\n            middlewares: this.middlewares.length\n        };\n    }\n}\n\nlet _defaultHookManager: HookManager | null = null;\n\nexport function getDefaultHookManager(): HookManager {\n    if (!_defaultHookManager) {\n        _defaultHookManager = new HookManager();\n    }\n    return _defaultHookManager;\n}\n","/**\n * @fileoverview HookBridge — HookManager facade.\n * Encapsulates hook registration, middleware pipeline, and event emission.\n */\n\nimport type { HookEvent, HookCallback, MiddlewareFn } from '../types/index.js';\nimport { HookManager } from './index.js';\n\n/**\n * Bridge for hook and middleware management.\n */\nexport interface HookBridge {\n    /** Registers a hook for an event. Returns unsubscribe function. */\n    on(event: HookEvent, callback: HookCallback, priority?: number): () => void;\n    /** Registers a one-time hook. Returns unsubscribe function. */\n    once(event: HookEvent, callback: HookCallback, priority?: number): () => void;\n    /** Removes a registered hook. Returns true if removed. */\n    off(event: HookEvent, callback: HookCallback): boolean;\n    /** Adds middleware to the pipeline. Returns unsubscribe function. */\n    use(middleware: MiddlewareFn, priority?: number): () => void;\n    /** Returns the underlying HookManager. */\n    getHookManager(): HookManager;\n}\n\n/**\n * Creates a HookBridge instance.\n */\nexport function createHookBridge(): HookBridge {\n    const hookManager = new HookManager();\n\n    return {\n        on(event: HookEvent, callback: HookCallback, priority?: number): () => void {\n            return hookManager.on(event, callback, priority);\n        },\n\n        once(event: HookEvent, callback: HookCallback, priority?: number): () => void {\n            return hookManager.once(event, callback, priority);\n        },\n\n        off(event: HookEvent, callback: HookCallback): boolean {\n            return hookManager.off(event, callback);\n        },\n\n        use(middleware: MiddlewareFn, priority?: number): () => void {\n            return hookManager.use(middleware, priority);\n        },\n\n        getHookManager(): HookManager {\n            return hookManager;\n        }\n    };\n}\n"],"mappings":"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"}