@mks2508/better-logger 0.18.2-alpha.1 → 0.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -336
- package/dist/Logger.d.ts +356 -157
- package/dist/Logger.d.ts.map +1 -1
- package/dist/ScopedLogger.d.ts +549 -9
- package/dist/ScopedLogger.d.ts.map +1 -1
- package/dist/chunks/HookBridge-C-AvXmPD.cjs +504 -0
- package/dist/chunks/HookBridge-C-AvXmPD.cjs.map +1 -0
- package/dist/chunks/HookBridge-CI2PH79S.js +487 -0
- package/dist/chunks/HookBridge-CI2PH79S.js.map +1 -0
- package/dist/chunks/{LogContext-L7HzynFw.cjs → LogContext-BaMXleWj.cjs} +19 -4
- package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs +141 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs.map +1 -0
- package/dist/chunks/{LogContext-Cwn-1Zzb.js → LogContext-DjlITOzZ.js} +19 -4
- package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
- package/dist/chunks/LogContext-Dyzs61XG.js +136 -0
- package/dist/chunks/LogContext-Dyzs61XG.js.map +1 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
- package/dist/chunks/{StyleManager-CIpd6wbO.cjs → StyleManager-DQ6UNRB-.cjs} +37 -11
- package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
- package/dist/chunks/{core-PoT7RrTK.js → core-Blfi2klP.js} +1 -4
- package/dist/chunks/core-Blfi2klP.js.map +1 -0
- package/dist/chunks/{core-Dzz7agGa.cjs → core-CqS_UBzJ.cjs} +1 -4
- package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
- package/dist/chunks/{environment-detector-CI3TrWK_.js → environment-detector-7NvnYUfr.js} +11 -11
- package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
- package/dist/chunks/{environment-detector-Cnn6wr6O.cjs → environment-detector-D-tHkKWA.cjs} +11 -11
- package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
- package/dist/chunks/{spinner-DNvxbM9a.cjs → spinner-BHyYEXsM.cjs} +319 -37
- package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
- package/dist/chunks/{spinner-D3FsF78o.js → spinner-BtkwpzYv.js} +319 -37
- package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
- package/dist/chunks/styling-CRw3KQW4.js +1592 -0
- package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
- package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
- package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
- package/dist/chunks/transports-BGfwwakw.js +1237 -0
- package/dist/chunks/transports-BGfwwakw.js.map +1 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs +1450 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs.map +1 -0
- package/dist/chunks/transports-DvaLAeGJ.js +1403 -0
- package/dist/chunks/transports-DvaLAeGJ.js.map +1 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
- package/dist/chunks/{utils-BqlFYocD.cjs → utils-W_cxqriN.cjs} +44 -37
- package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
- package/dist/chunks/{utils-VETbVpkR.js → utils-tKfBAWUM.js} +44 -37
- package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
- package/dist/cli/CommandProcessor.d.ts +166 -19
- package/dist/cli/CommandProcessor.d.ts.map +1 -1
- package/dist/cli/commands/ConfigCommand.d.ts +36 -1
- package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/dist/cli/commands/ExportCommand.d.ts +49 -3
- package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
- package/dist/cli/commands/ThemeCommand.d.ts +62 -3
- package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
- package/dist/cli/help.d.ts +30 -2
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.d.ts +29 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +2 -2
- package/dist/context/LogContext.d.ts +167 -70
- package/dist/context/LogContext.d.ts.map +1 -1
- package/dist/context.cjs +1 -1
- package/dist/context.js +1 -1
- package/dist/core.cjs +52 -29
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +50 -27
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +52 -29
- package/dist/core.js.map +1 -1
- package/dist/hooks/HookBridge.d.ts +15 -9
- package/dist/hooks/HookBridge.d.ts.map +1 -1
- package/dist/hooks/HookManager.d.ts +295 -2
- package/dist/hooks/HookManager.d.ts.map +1 -1
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.cjs +1415 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1413 -215
- package/dist/index.js.map +1 -1
- package/dist/playground/TerminalBridge.d.ts +23 -16
- package/dist/playground/TerminalBridge.d.ts.map +1 -1
- package/dist/playground/box.d.ts +36 -5
- package/dist/playground/box.d.ts.map +1 -1
- package/dist/playground/cli-table.d.ts +41 -5
- package/dist/playground/cli-table.d.ts.map +1 -1
- package/dist/playground/divider.d.ts +22 -3
- package/dist/playground/divider.d.ts.map +1 -1
- package/dist/playground/header.d.ts +21 -4
- package/dist/playground/header.d.ts.map +1 -1
- package/dist/playground/server-fallback.d.ts +96 -9
- package/dist/playground/server-fallback.d.ts.map +1 -1
- package/dist/playground/spinner.d.ts +159 -10
- package/dist/playground/spinner.d.ts.map +1 -1
- package/dist/playground/step.d.ts +25 -6
- package/dist/playground/step.d.ts.map +1 -1
- package/dist/playground.cjs +1 -1
- package/dist/playground.js +1 -1
- package/dist/serializers/SerializerBridge.d.ts +13 -6
- package/dist/serializers/SerializerBridge.d.ts.map +1 -1
- package/dist/serializers/SerializerRegistry.d.ts +236 -0
- package/dist/serializers/SerializerRegistry.d.ts.map +1 -1
- package/dist/serializers.cjs +1 -1
- package/dist/serializers.js +1 -1
- package/dist/styles/StyleManager.d.ts +138 -31
- package/dist/styles/StyleManager.d.ts.map +1 -1
- package/dist/styles.cjs +2 -2
- package/dist/styles.js +2 -2
- package/dist/styling/SmartPresets.d.ts +100 -6
- package/dist/styling/SmartPresets.d.ts.map +1 -1
- package/dist/styling/StyleBuilder.d.ts +453 -32
- package/dist/styling/StyleBuilder.d.ts.map +1 -1
- package/dist/styling/banners.d.ts +83 -7
- package/dist/styling/banners.d.ts.map +1 -1
- package/dist/styling/themes.d.ts +41 -2
- package/dist/styling/themes.d.ts.map +1 -1
- package/dist/transports/ConsoleTransport.d.ts +95 -0
- package/dist/transports/ConsoleTransport.d.ts.map +1 -1
- package/dist/transports/FileTransport.d.ts +99 -18
- package/dist/transports/FileTransport.d.ts.map +1 -1
- package/dist/transports/HttpTransport.d.ts +135 -22
- package/dist/transports/HttpTransport.d.ts.map +1 -1
- package/dist/transports/OtlpTraceTransport.d.ts +118 -0
- package/dist/transports/OtlpTraceTransport.d.ts.map +1 -0
- package/dist/transports/OtlpTransport.d.ts +80 -37
- package/dist/transports/OtlpTransport.d.ts.map +1 -1
- package/dist/transports/SpanRuntime.d.ts +73 -0
- package/dist/transports/SpanRuntime.d.ts.map +1 -0
- package/dist/transports/TransportBridge.d.ts +19 -13
- package/dist/transports/TransportBridge.d.ts.map +1 -1
- package/dist/transports/TransportManager.d.ts +232 -10
- package/dist/transports/TransportManager.d.ts.map +1 -1
- package/dist/transports/index.d.ts +1 -0
- package/dist/transports/index.d.ts.map +1 -1
- package/dist/transports-module.d.ts +3 -1
- package/dist/transports-module.d.ts.map +1 -1
- package/dist/transports.cjs +2 -1
- package/dist/transports.js +2 -2
- package/dist/types/core.d.ts +155 -59
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +92 -14
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/serializers.d.ts +72 -0
- package/dist/types/serializers.d.ts.map +1 -1
- package/dist/types/transports.d.ts +163 -39
- package/dist/types/transports.d.ts.map +1 -1
- package/dist/utils/ansi-colors.d.ts +15 -15
- package/dist/utils/asyncLocalStorage.d.ts +33 -0
- package/dist/utils/asyncLocalStorage.d.ts.map +1 -0
- package/dist/utils/environment-detector.d.ts +11 -11
- package/dist/utils/formatting.d.ts +8 -8
- package/dist/utils/output.d.ts +9 -9
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/stackTrace.d.ts +2 -2
- package/package.json +24 -25
- package/dist/chunks/HookBridge-CiRfR67f.cjs +0 -190
- package/dist/chunks/HookBridge-CiRfR67f.cjs.map +0 -1
- package/dist/chunks/HookBridge-SgMmbXZB.js +0 -173
- package/dist/chunks/HookBridge-SgMmbXZB.js.map +0 -1
- package/dist/chunks/LogContext-Cwn-1Zzb.js.map +0 -1
- package/dist/chunks/LogContext-L7HzynFw.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs +0 -166
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BkpQu5c9.js +0 -149
- package/dist/chunks/SerializerBridge-BkpQu5c9.js.map +0 -1
- package/dist/chunks/StyleManager-CIpd6wbO.cjs.map +0 -1
- package/dist/chunks/StyleManager-LCvVlVdx.js +0 -87
- package/dist/chunks/StyleManager-LCvVlVdx.js.map +0 -1
- package/dist/chunks/core-Dzz7agGa.cjs.map +0 -1
- package/dist/chunks/core-PoT7RrTK.js.map +0 -1
- package/dist/chunks/environment-detector-CI3TrWK_.js.map +0 -1
- package/dist/chunks/environment-detector-Cnn6wr6O.cjs.map +0 -1
- package/dist/chunks/server-fallback-BUKjdLS7.cjs +0 -42
- package/dist/chunks/server-fallback-BUKjdLS7.cjs.map +0 -1
- package/dist/chunks/server-fallback-BsuWH1Dk.js +0 -37
- package/dist/chunks/server-fallback-BsuWH1Dk.js.map +0 -1
- package/dist/chunks/spinner-D3FsF78o.js.map +0 -1
- package/dist/chunks/spinner-DNvxbM9a.cjs.map +0 -1
- package/dist/chunks/styling-84N8T97t.js +0 -941
- package/dist/chunks/styling-84N8T97t.js.map +0 -1
- package/dist/chunks/styling-Cg5saQ46.cjs +0 -994
- package/dist/chunks/styling-Cg5saQ46.cjs.map +0 -1
- package/dist/chunks/transports-BiDk345e.js +0 -715
- package/dist/chunks/transports-BiDk345e.js.map +0 -1
- package/dist/chunks/transports-COPWmlF1.cjs +0 -756
- package/dist/chunks/transports-COPWmlF1.cjs.map +0 -1
- package/dist/chunks/utils-BqlFYocD.cjs.map +0 -1
- package/dist/chunks/utils-VETbVpkR.js.map +0 -1
- package/dist/example.d.ts +0 -18
- package/dist/example.d.ts.map +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScopedLogger.d.ts","sourceRoot":"","sources":["../src/ScopedLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ScopedLogger.d.ts","sourceRoot":"","sources":["../src/ScopedLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
//#region src/hooks/HookManager.ts
|
|
2
|
+
/**
|
|
3
|
+
* Profundidad máxima de reentrancia permitida para el evento `onError`.
|
|
4
|
+
*
|
|
5
|
+
* Cuando un hook registrado para `onError` lanza una excepción, el manager
|
|
6
|
+
* re-emite el error como un nuevo evento `onError`, lo que podría entrar en
|
|
7
|
+
* un bucle infinito. Este límite corta la cadena tras N niveles de anidamiento
|
|
8
|
+
* y deja caer el entry al console para no acaparar el event loop.
|
|
9
|
+
*
|
|
10
|
+
* @internal Constantante de implementación; no forma parte de la API pública.
|
|
11
|
+
*/
|
|
12
|
+
const MAX_ONERROR_DEPTH = 5;
|
|
13
|
+
/**
|
|
14
|
+
* Genera un identificador corto y único para cada registro de hook/middleware.
|
|
15
|
+
*
|
|
16
|
+
* Combina timestamp con un segmento aleatorio base36. Suficiente para
|
|
17
|
+
* desambiguar registros dentro de un mismo proceso; no es un UUID criptográfico.
|
|
18
|
+
*
|
|
19
|
+
* @internal Helper interno; no es API pública.
|
|
20
|
+
* @returns {string} ID tipo `<epoch>-<random9>`.
|
|
21
|
+
*/
|
|
22
|
+
function generateId() {
|
|
23
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Implementación por defecto de {@link IHookManager} que orquesta el ciclo de
|
|
27
|
+
* vida de los hooks del logger: `beforeLog`, `afterLog` y `onError`.
|
|
28
|
+
*
|
|
29
|
+
* Permite:
|
|
30
|
+
* - Registrar callbacks por evento con **prioridad** (mayor número = se
|
|
31
|
+
* ejecuta primero; las registraciones se ordenan descendentemente).
|
|
32
|
+
* - Encadenar middlewares sobre el entry previo al dispatch.
|
|
33
|
+
* - Propagar mutaciones: cada hook puede retornar un partial de
|
|
34
|
+
* {@link HookLogEntry} que se mergea al entry actual antes del siguiente hook.
|
|
35
|
+
* - Acotar la recursión de `onError` con un guard de profundidad
|
|
36
|
+
* ({@link MAX_ONERROR_DEPTH}) para que un hook que lanza no loopée para
|
|
37
|
+
* siempre.
|
|
38
|
+
*
|
|
39
|
+
* El flujo típico lo orquesta el logger vía {@link process} (emite `beforeLog`
|
|
40
|
+
* + ejecuta middlewares) y {@link afterProcess} (emite `afterLog`).
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const hooks = new HookManager();
|
|
45
|
+
*
|
|
46
|
+
* // Mayor prioridad => corre primero
|
|
47
|
+
* hooks.on('beforeLog', (entry) => {
|
|
48
|
+
* return { ...entry, attributes: { ...entry.attributes, traced: true } };
|
|
49
|
+
* }, 90);
|
|
50
|
+
*
|
|
51
|
+
* hooks.on('afterLog', (entry) => {
|
|
52
|
+
* metrics.increment('log_emitted', { level: entry.level });
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* hooks.on('onError', (entry) => {
|
|
56
|
+
* telemetry.capture(entry.error);
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* // Middleware que añade timestamp si falta y delega al siguiente
|
|
63
|
+
* hooks.use(async (entry, next) => {
|
|
64
|
+
* if (!entry.time) entry.time = Date.now();
|
|
65
|
+
* await next();
|
|
66
|
+
* });
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @see {@link IHookManager}
|
|
70
|
+
* @see {@link HookEvent}
|
|
71
|
+
*/
|
|
72
|
+
var HookManager = class {
|
|
73
|
+
hooks = /* @__PURE__ */ new Map();
|
|
74
|
+
middlewares = [];
|
|
75
|
+
/**
|
|
76
|
+
* Lleva el conteo de la profundidad de recursión actual por cada evento de
|
|
77
|
+
* hook, para que las cadenas de `onError` que lanzan excepciones no puedan
|
|
78
|
+
* loopéar para siempre. Se resetea cuando el `emit` externo retorna.
|
|
79
|
+
*/
|
|
80
|
+
_onErrorDepth = /* @__PURE__ */ new Map();
|
|
81
|
+
constructor() {
|
|
82
|
+
this.hooks.set("beforeLog", []);
|
|
83
|
+
this.hooks.set("afterLog", []);
|
|
84
|
+
this.hooks.set("onError", []);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Registra un callback persistente para un evento. Se ejecuta en cada
|
|
88
|
+
* emisión hasta que se cancele con la función devuelta o con {@link off}.
|
|
89
|
+
*
|
|
90
|
+
* Los hooks se ordenan por `priority` **descendente**: mayor número =
|
|
91
|
+
* se ejecuta primero. Misma prioridad respeta el orden de registro.
|
|
92
|
+
*
|
|
93
|
+
* @param event - Uno de `'beforeLog' | 'afterLog' | 'onError'`.
|
|
94
|
+
* @param callback - Función asíncrona que recibe el {@link HookLogEntry}
|
|
95
|
+
* actual y puede retornar un partial para mutar el entry que verán los
|
|
96
|
+
* hooks siguientes.
|
|
97
|
+
* @param priority - Peso de ordenamiento. Default `50`. Mayor = primero.
|
|
98
|
+
* @returns {() => void} Función de cancelación; llamarla desregistra el hook.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const off = hooks.on('beforeLog', async (entry) => {
|
|
103
|
+
* return { attributes: { ...entry.attributes, requestId: getReqId() } };
|
|
104
|
+
* }, 80);
|
|
105
|
+
*
|
|
106
|
+
* // ...en shutdown:
|
|
107
|
+
* off();
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @see {@link once} para hooks de un solo disparo.
|
|
111
|
+
* @see {@link off} para desregistro por referencia de callback.
|
|
112
|
+
*/
|
|
113
|
+
on(event, callback, priority = 50) {
|
|
114
|
+
const registration = {
|
|
115
|
+
id: generateId(),
|
|
116
|
+
event,
|
|
117
|
+
callback,
|
|
118
|
+
priority,
|
|
119
|
+
once: false
|
|
120
|
+
};
|
|
121
|
+
const hooks = this.hooks.get(event);
|
|
122
|
+
hooks.push(registration);
|
|
123
|
+
hooks.sort((a, b) => b.priority - a.priority);
|
|
124
|
+
return () => this.removeHook(event, registration.id);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Igual que {@link on}, pero el hook se auto-desregistra después del primer
|
|
128
|
+
* disparo exitoso. Útil para setup one-shot (warm-up de caché, captura del
|
|
129
|
+
* primer log, ...).
|
|
130
|
+
*
|
|
131
|
+
* Si el callback lanza, el hook NO se elimina (la excepción se deriva a
|
|
132
|
+
* `onError`); la limpieza solo ocurre cuando el callback retorna sin Throw.
|
|
133
|
+
*
|
|
134
|
+
* @param event - Evento a escuchar.
|
|
135
|
+
* @param callback - Handler que se ejecutará una sola vez.
|
|
136
|
+
* @param priority - Peso de ordenamiento (mayor = primero). Default `50`.
|
|
137
|
+
* @returns {() => void} Cancelación manual por si se quiere retirar antes
|
|
138
|
+
* del primer disparo.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* hooks.once('afterLog', async (entry) => {
|
|
143
|
+
* console.log('Primer log emitido:', entry.msg);
|
|
144
|
+
* });
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @see {@link on}
|
|
148
|
+
*/
|
|
149
|
+
once(event, callback, priority = 50) {
|
|
150
|
+
const registration = {
|
|
151
|
+
id: generateId(),
|
|
152
|
+
event,
|
|
153
|
+
callback,
|
|
154
|
+
priority,
|
|
155
|
+
once: true
|
|
156
|
+
};
|
|
157
|
+
const hooks = this.hooks.get(event);
|
|
158
|
+
hooks.push(registration);
|
|
159
|
+
hooks.sort((a, b) => b.priority - a.priority);
|
|
160
|
+
return () => this.removeHook(event, registration.id);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Desregistra un hook por referencia de callback. Solo elimina la primera
|
|
164
|
+
* coincidencia encontrada para el evento.
|
|
165
|
+
*
|
|
166
|
+
* Para hooks registrados con {@link on} o {@link once} es preferible usar
|
|
167
|
+
* la función de cancelación devuelta (que usa el id interno y es O(n) más
|
|
168
|
+
* directa). `off` es útil cuando se perdió la referencia al cancelador o
|
|
169
|
+
* cuando se integra con APIs que piden un método `removeListener(cb)`.
|
|
170
|
+
*
|
|
171
|
+
* @param event - Evento del que se quiere desregistrar.
|
|
172
|
+
* @param callback - Misma referencia de función pasada a {@link on}/{@link once}.
|
|
173
|
+
* @returns {boolean} `true` si se eliminó un hook, `false` si no había match.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* const handler = async (entry) => { /* ... *\/ };
|
|
178
|
+
* hooks.on('afterLog', handler);
|
|
179
|
+
* hooks.off('afterLog', handler); // true
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @see {@link on}
|
|
183
|
+
*/
|
|
184
|
+
off(event, callback) {
|
|
185
|
+
const hooks = this.hooks.get(event);
|
|
186
|
+
if (!hooks) return false;
|
|
187
|
+
const index = hooks.findIndex((h) => h.callback === callback);
|
|
188
|
+
if (index >= 0) {
|
|
189
|
+
hooks.splice(index, 1);
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
removeHook(event, id) {
|
|
195
|
+
const hooks = this.hooks.get(event);
|
|
196
|
+
if (hooks) {
|
|
197
|
+
const index = hooks.findIndex((h) => h.id === id);
|
|
198
|
+
if (index >= 0) hooks.splice(index, 1);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Registra un middleware que se encadena sobre el {@link HookLogEntry}
|
|
203
|
+
* **antes** de que se emita el log al resto del pipeline. Los middlewares
|
|
204
|
+
* corren después del evento `beforeLog` y se ejecutan en cascada vía `next()`.
|
|
205
|
+
*
|
|
206
|
+
* Cada middleware recibe `(entry, next)` y debe llamar a `next()` para
|
|
207
|
+
* ceder el control al siguiente. Si NO llama a `next()`, corta la cadena
|
|
208
|
+
* (patrón short-circuit).
|
|
209
|
+
*
|
|
210
|
+
* Ordenamiento: `priority` descendente (mayor = primero), igual que los
|
|
211
|
+
* hooks. La secuencia respetada es la del sort, no la del orden de
|
|
212
|
+
* llamada a `use`.
|
|
213
|
+
*
|
|
214
|
+
* @param middleware - Función `(entry, next) => Promise<void>`.
|
|
215
|
+
* @param priority - Peso de ordenamiento. Default `50`.
|
|
216
|
+
* @returns {() => void} Función de cancelación para retirar el middleware.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* // PII redaction: enmascara passwords antes de loguear
|
|
221
|
+
* hooks.use(async (entry, next) => {
|
|
222
|
+
* if (entry.attributes?.password) {
|
|
223
|
+
* entry.attributes.password = '***';
|
|
224
|
+
* }
|
|
225
|
+
* await next();
|
|
226
|
+
* }, 90);
|
|
227
|
+
*
|
|
228
|
+
* // Short-circuit: si es level=debug y env=prod, no baja
|
|
229
|
+
* const stop = hooks.use(async (entry, next) => {
|
|
230
|
+
* if (entry.level === 'debug' && ENV === 'production') return;
|
|
231
|
+
* await next();
|
|
232
|
+
* }, 100);
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* @see {@link process} para el orquestador que ejecuta la cadena.
|
|
236
|
+
*/
|
|
237
|
+
use(middleware, priority = 50) {
|
|
238
|
+
const registration = {
|
|
239
|
+
id: generateId(),
|
|
240
|
+
fn: middleware,
|
|
241
|
+
priority
|
|
242
|
+
};
|
|
243
|
+
this.middlewares.push(registration);
|
|
244
|
+
this.middlewares.sort((a, b) => b.priority - a.priority);
|
|
245
|
+
return () => {
|
|
246
|
+
const index = this.middlewares.findIndex((m) => m.id === registration.id);
|
|
247
|
+
if (index >= 0) this.middlewares.splice(index, 1);
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Emite un evento a todos sus hooks registrados, en orden de prioridad, y
|
|
252
|
+
* retorna el entry resultante tras aplicar todos los mutations.
|
|
253
|
+
*
|
|
254
|
+
* Cada hook puede retornar un partial de {@link HookLogEntry}; ese partial
|
|
255
|
+
* se mergea sobre el entry actual antes de invocar al siguiente hook, así
|
|
256
|
+
* los hooks se encadenan como una pipeline de transformaciones.
|
|
257
|
+
*
|
|
258
|
+
* Manejo de errores:
|
|
259
|
+
* - Si un hook de `beforeLog`/`afterLog` lanza, la excepción se captura y
|
|
260
|
+
* se re-emite como evento `onError` con el campo `error` poblado.
|
|
261
|
+
* - Si un hook de `onError` lanza, **NO** se re-emite (rompería el ciclo);
|
|
262
|
+
* se loguea a `console.error` y se traga.
|
|
263
|
+
* - Guard de reentrancia: si `onError` se re-entra más de
|
|
264
|
+
* {@link MAX_ONERROR_DEPTH} veces, se corta y se loguea el entry al
|
|
265
|
+
* console. Previene loops infinitos por errores en cascada.
|
|
266
|
+
*
|
|
267
|
+
* Los hooks marcados como `once` se eliminan tras un disparo exitoso.
|
|
268
|
+
*
|
|
269
|
+
* @param event - Evento a emitir.
|
|
270
|
+
* @param entry - Entry inicial; no se muta in-place (se clona por nivel).
|
|
271
|
+
* @returns {Promise<HookLogEntry>} Entry transformado tras todos los hooks.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```ts
|
|
275
|
+
* const enriched = await hooks.emit('beforeLog', rawEntry);
|
|
276
|
+
* // enriched.attributes puede traer merges de varios hooks
|
|
277
|
+
* ```
|
|
278
|
+
*
|
|
279
|
+
* @see {@link on}
|
|
280
|
+
* @see {@link once}
|
|
281
|
+
* @see {@link MAX_ONERROR_DEPTH}
|
|
282
|
+
*/
|
|
283
|
+
async emit(event, entry) {
|
|
284
|
+
const depth = this._onErrorDepth.get(entry.hookEvent ?? event) ?? 0;
|
|
285
|
+
if (event === "onError" && depth >= MAX_ONERROR_DEPTH) {
|
|
286
|
+
console.error("HookManager: onError recursion limit reached, dropping entry:", entry);
|
|
287
|
+
return entry;
|
|
288
|
+
}
|
|
289
|
+
this._onErrorDepth.set(event, depth + 1);
|
|
290
|
+
try {
|
|
291
|
+
const hooks = this.hooks.get(event) || [];
|
|
292
|
+
let currentEntry = { ...entry };
|
|
293
|
+
const toRemove = [];
|
|
294
|
+
for (const hook of hooks) try {
|
|
295
|
+
const result = await hook.callback(currentEntry);
|
|
296
|
+
if (result) currentEntry = {
|
|
297
|
+
...currentEntry,
|
|
298
|
+
...result
|
|
299
|
+
};
|
|
300
|
+
if (hook.once) toRemove.push(hook.id);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
if (event !== "onError") await this.emit("onError", {
|
|
303
|
+
...currentEntry,
|
|
304
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
305
|
+
hookEvent: event
|
|
306
|
+
});
|
|
307
|
+
else console.error("HookManager: onError hook threw, swallowed to break recursion:", error);
|
|
308
|
+
}
|
|
309
|
+
toRemove.forEach((id) => this.removeHook(event, id));
|
|
310
|
+
return currentEntry;
|
|
311
|
+
} finally {
|
|
312
|
+
this._onErrorDepth.set(event, depth);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Orquesta el pipeline pre-emit de un log. Orden de ejecución:
|
|
317
|
+
*
|
|
318
|
+
* 1. Emite `beforeLog` (todos sus hooks corren en orden de prioridad y
|
|
319
|
+
* pueden mutar el entry vía return partial).
|
|
320
|
+
* 2. Si hay middlewares registrados ({@link use}), los ejecuta en cascada
|
|
321
|
+
* sobre el entry ya enriquecido por los hooks de `beforeLog`.
|
|
322
|
+
*
|
|
323
|
+
* Es el punto de entrada que el logger invoca **antes** de despachar el
|
|
324
|
+
* record a los transports. El entry devuelto es el que finalmente se loguea.
|
|
325
|
+
*
|
|
326
|
+
* No emite `afterLog`; para eso usar {@link afterProcess} una vez que el
|
|
327
|
+
* dispatch al transport haya terminado.
|
|
328
|
+
*
|
|
329
|
+
* @param entry - Entry crudo entrante al pipeline.
|
|
330
|
+
* @returns {Promise<HookLogEntry>} Entry final listo para mandar a transports.
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```ts
|
|
334
|
+
* const processed = await hooks.process(rawEntry);
|
|
335
|
+
* await transport.write(processed);
|
|
336
|
+
* await hooks.afterProcess(processed);
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* @see {@link afterProcess}
|
|
340
|
+
* @see {@link use}
|
|
341
|
+
*/
|
|
342
|
+
async process(entry) {
|
|
343
|
+
let currentEntry = { ...entry };
|
|
344
|
+
currentEntry = await this.emit("beforeLog", currentEntry);
|
|
345
|
+
if (this.middlewares.length > 0) {
|
|
346
|
+
let index = 0;
|
|
347
|
+
const executeNext = async () => {
|
|
348
|
+
if (index < this.middlewares.length) {
|
|
349
|
+
const middleware = this.middlewares[index++];
|
|
350
|
+
if (middleware) await middleware.fn(currentEntry, executeNext);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
await executeNext();
|
|
354
|
+
}
|
|
355
|
+
return currentEntry;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Emite el evento `afterLog` con el entry ya procesado y dispatcheado a
|
|
359
|
+
* los transports. Pensado para side-effects post-log: métricas, audit
|
|
360
|
+
* trail, flush de buffers externos, etc.
|
|
361
|
+
*
|
|
362
|
+
* Los hooks de `afterLog` pueden retornar un partial pero el entry ya se
|
|
363
|
+
* ha publicado, así que la mutación no tiene efecto sobre el log emitido;
|
|
364
|
+
* solo queda disponible en el return de {@link emit}, que aquí se descarta.
|
|
365
|
+
*
|
|
366
|
+
* @param entry - Entry final (mismo objeto devuelto por {@link process}).
|
|
367
|
+
* @returns {Promise<void>} Resuelve cuando todos los hooks terminaron.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* hooks.on('afterLog', async (entry) => {
|
|
372
|
+
* metrics.increment('logs_total', { level: entry.level });
|
|
373
|
+
* });
|
|
374
|
+
*
|
|
375
|
+
* const processed = await hooks.process(rawEntry);
|
|
376
|
+
* await transport.write(processed);
|
|
377
|
+
* await hooks.afterProcess(processed); // dispara métricas
|
|
378
|
+
* ```
|
|
379
|
+
*
|
|
380
|
+
* @see {@link process}
|
|
381
|
+
*/
|
|
382
|
+
async afterProcess(entry) {
|
|
383
|
+
await this.emit("afterLog", entry);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Vacía todos los hooks y middlewares registrados. Útil para resetear el
|
|
387
|
+
* estado entre tests o en hot-reload.
|
|
388
|
+
*
|
|
389
|
+
* Afecta a los tres eventos (`beforeLog`, `afterLog`, `onError`) y a la
|
|
390
|
+
* pila de middlewares. Las funciones de cancelación devueltas por
|
|
391
|
+
* {@link on}/{@link once}/{@link use} se vuelven no-ops pero pueden
|
|
392
|
+
* llamarse sin error.
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```ts
|
|
396
|
+
* afterEach(() => hooks.clear());
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
clear() {
|
|
400
|
+
this.hooks.forEach((hooks) => hooks.length = 0);
|
|
401
|
+
this.middlewares.length = 0;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Snapshot del estado interno para observabilidad y debugging.
|
|
405
|
+
*
|
|
406
|
+
* @returns {Object} stats
|
|
407
|
+
* @returns {Record<HookEvent, number>} stats.hooks - Conteo de hooks
|
|
408
|
+
* registrados por evento (`beforeLog`, `afterLog`, `onError`).
|
|
409
|
+
* @returns {number} stats.middlewares - Total de middlewares activos.
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* ```ts
|
|
413
|
+
* const stats = hooks.getStats();
|
|
414
|
+
* // { hooks: { beforeLog: 2, afterLog: 1, onError: 3 }, middlewares: 1 }
|
|
415
|
+
* if (stats.hooks.onError === 0) {
|
|
416
|
+
* console.warn('Sin handlers onError registrados');
|
|
417
|
+
* }
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
getStats() {
|
|
421
|
+
return {
|
|
422
|
+
hooks: {
|
|
423
|
+
beforeLog: this.hooks.get("beforeLog")?.length || 0,
|
|
424
|
+
afterLog: this.hooks.get("afterLog")?.length || 0,
|
|
425
|
+
onError: this.hooks.get("onError")?.length || 0
|
|
426
|
+
},
|
|
427
|
+
middlewares: this.middlewares.length
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
let _defaultHookManager = null;
|
|
432
|
+
/**
|
|
433
|
+
* Devuelve la instancia singleton de {@link HookManager} compartida por todo
|
|
434
|
+
* el proceso. La crea perezosamente en la primera llamada.
|
|
435
|
+
*
|
|
436
|
+
* Pensada como hook manager por defecto del logger; los consumidores que
|
|
437
|
+
* necesiten aislamiento (tests, múltiples loggers con pipelines distintos)
|
|
438
|
+
* deben instanciar su propio `new HookManager()` en lugar de usar este shared.
|
|
439
|
+
*
|
|
440
|
+
* @returns {HookManager} La instancia singleton.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```ts
|
|
444
|
+
* import { getDefaultHookManager } from '@mks2508/better-logger/hooks';
|
|
445
|
+
*
|
|
446
|
+
* getDefaultHookManager().on('onError', async (entry) => {
|
|
447
|
+
* telemetry.capture(entry.error);
|
|
448
|
+
* });
|
|
449
|
+
* ```
|
|
450
|
+
*
|
|
451
|
+
* @see {@link HookManager}
|
|
452
|
+
*/
|
|
453
|
+
function getDefaultHookManager() {
|
|
454
|
+
if (!_defaultHookManager) _defaultHookManager = new HookManager();
|
|
455
|
+
return _defaultHookManager;
|
|
456
|
+
}
|
|
457
|
+
//#endregion
|
|
458
|
+
//#region src/hooks/HookBridge.ts
|
|
459
|
+
/**
|
|
460
|
+
* Crea una instancia de {@link HookBridge}.
|
|
461
|
+
*
|
|
462
|
+
* @internal
|
|
463
|
+
*/
|
|
464
|
+
function createHookBridge() {
|
|
465
|
+
const hookManager = new HookManager();
|
|
466
|
+
return {
|
|
467
|
+
on(event, callback, priority) {
|
|
468
|
+
return hookManager.on(event, callback, priority);
|
|
469
|
+
},
|
|
470
|
+
once(event, callback, priority) {
|
|
471
|
+
return hookManager.once(event, callback, priority);
|
|
472
|
+
},
|
|
473
|
+
off(event, callback) {
|
|
474
|
+
return hookManager.off(event, callback);
|
|
475
|
+
},
|
|
476
|
+
use(middleware, priority) {
|
|
477
|
+
return hookManager.use(middleware, priority);
|
|
478
|
+
},
|
|
479
|
+
getHookManager() {
|
|
480
|
+
return hookManager;
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
//#endregion
|
|
485
|
+
Object.defineProperty(exports, "HookManager", {
|
|
486
|
+
enumerable: true,
|
|
487
|
+
get: function() {
|
|
488
|
+
return HookManager;
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
Object.defineProperty(exports, "createHookBridge", {
|
|
492
|
+
enumerable: true,
|
|
493
|
+
get: function() {
|
|
494
|
+
return createHookBridge;
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
Object.defineProperty(exports, "getDefaultHookManager", {
|
|
498
|
+
enumerable: true,
|
|
499
|
+
get: function() {
|
|
500
|
+
return getDefaultHookManager;
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
//# sourceMappingURL=HookBridge-C-AvXmPD.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HookBridge-C-AvXmPD.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\n/**\n * Profundidad máxima de reentrancia permitida para el evento `onError`.\n *\n * Cuando un hook registrado para `onError` lanza una excepción, el manager\n * re-emite el error como un nuevo evento `onError`, lo que podría entrar en\n * un bucle infinito. Este límite corta la cadena tras N niveles de anidamiento\n * y deja caer el entry al console para no acaparar el event loop.\n *\n * @internal Constantante de implementación; no forma parte de la API pública.\n */\nconst MAX_ONERROR_DEPTH = 5;\n\n/**\n * Genera un identificador corto y único para cada registro de hook/middleware.\n *\n * Combina timestamp con un segmento aleatorio base36. Suficiente para\n * desambiguar registros dentro de un mismo proceso; no es un UUID criptográfico.\n *\n * @internal Helper interno; no es API pública.\n * @returns {string} ID tipo `<epoch>-<random9>`.\n */\nfunction generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * Implementación por defecto de {@link IHookManager} que orquesta el ciclo de\n * vida de los hooks del logger: `beforeLog`, `afterLog` y `onError`.\n *\n * Permite:\n * - Registrar callbacks por evento con **prioridad** (mayor número = se\n * ejecuta primero; las registraciones se ordenan descendentemente).\n * - Encadenar middlewares sobre el entry previo al dispatch.\n * - Propagar mutaciones: cada hook puede retornar un partial de\n * {@link HookLogEntry} que se mergea al entry actual antes del siguiente hook.\n * - Acotar la recursión de `onError` con un guard de profundidad\n * ({@link MAX_ONERROR_DEPTH}) para que un hook que lanza no loopée para\n * siempre.\n *\n * El flujo típico lo orquesta el logger vía {@link process} (emite `beforeLog`\n * + ejecuta middlewares) y {@link afterProcess} (emite `afterLog`).\n *\n * @example\n * ```ts\n * const hooks = new HookManager();\n *\n * // Mayor prioridad => corre primero\n * hooks.on('beforeLog', (entry) => {\n * return { ...entry, attributes: { ...entry.attributes, traced: true } };\n * }, 90);\n *\n * hooks.on('afterLog', (entry) => {\n * metrics.increment('log_emitted', { level: entry.level });\n * });\n *\n * hooks.on('onError', (entry) => {\n * telemetry.capture(entry.error);\n * });\n * ```\n *\n * @example\n * ```ts\n * // Middleware que añade timestamp si falta y delega al siguiente\n * hooks.use(async (entry, next) => {\n * if (!entry.time) entry.time = Date.now();\n * await next();\n * });\n * ```\n *\n * @see {@link IHookManager}\n * @see {@link HookEvent}\n */\nexport class HookManager implements IHookManager {\n private hooks: Map<HookEvent, HookRegistration[]> = new Map();\n private middlewares: MiddlewareRegistration[] = [];\n /**\n * Lleva el conteo de la profundidad de recursión actual por cada evento de\n * hook, para que las cadenas de `onError` que lanzan excepciones no puedan\n * loopéar para siempre. Se resetea cuando el `emit` externo retorna.\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 /**\n * Registra un callback persistente para un evento. Se ejecuta en cada\n * emisión hasta que se cancele con la función devuelta o con {@link off}.\n *\n * Los hooks se ordenan por `priority` **descendente**: mayor número =\n * se ejecuta primero. Misma prioridad respeta el orden de registro.\n *\n * @param event - Uno de `'beforeLog' | 'afterLog' | 'onError'`.\n * @param callback - Función asíncrona que recibe el {@link HookLogEntry}\n * actual y puede retornar un partial para mutar el entry que verán los\n * hooks siguientes.\n * @param priority - Peso de ordenamiento. Default `50`. Mayor = primero.\n * @returns {() => void} Función de cancelación; llamarla desregistra el hook.\n *\n * @example\n * ```ts\n * const off = hooks.on('beforeLog', async (entry) => {\n * return { attributes: { ...entry.attributes, requestId: getReqId() } };\n * }, 80);\n *\n * // ...en shutdown:\n * off();\n * ```\n *\n * @see {@link once} para hooks de un solo disparo.\n * @see {@link off} para desregistro por referencia de callback.\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 /**\n * Igual que {@link on}, pero el hook se auto-desregistra después del primer\n * disparo exitoso. Útil para setup one-shot (warm-up de caché, captura del\n * primer log, ...).\n *\n * Si el callback lanza, el hook NO se elimina (la excepción se deriva a\n * `onError`); la limpieza solo ocurre cuando el callback retorna sin Throw.\n *\n * @param event - Evento a escuchar.\n * @param callback - Handler que se ejecutará una sola vez.\n * @param priority - Peso de ordenamiento (mayor = primero). Default `50`.\n * @returns {() => void} Cancelación manual por si se quiere retirar antes\n * del primer disparo.\n *\n * @example\n * ```ts\n * hooks.once('afterLog', async (entry) => {\n * console.log('Primer log emitido:', entry.msg);\n * });\n * ```\n *\n * @see {@link on}\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 /**\n * Desregistra un hook por referencia de callback. Solo elimina la primera\n * coincidencia encontrada para el evento.\n *\n * Para hooks registrados con {@link on} o {@link once} es preferible usar\n * la función de cancelación devuelta (que usa el id interno y es O(n) más\n * directa). `off` es útil cuando se perdió la referencia al cancelador o\n * cuando se integra con APIs que piden un método `removeListener(cb)`.\n *\n * @param event - Evento del que se quiere desregistrar.\n * @param callback - Misma referencia de función pasada a {@link on}/{@link once}.\n * @returns {boolean} `true` si se eliminó un hook, `false` si no había match.\n *\n * @example\n * ```ts\n * const handler = async (entry) => { /* ... *\\/ };\n * hooks.on('afterLog', handler);\n * hooks.off('afterLog', handler); // true\n * ```\n *\n * @see {@link on}\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 /**\n * Registra un middleware que se encadena sobre el {@link HookLogEntry}\n * **antes** de que se emita el log al resto del pipeline. Los middlewares\n * corren después del evento `beforeLog` y se ejecutan en cascada vía `next()`.\n *\n * Cada middleware recibe `(entry, next)` y debe llamar a `next()` para\n * ceder el control al siguiente. Si NO llama a `next()`, corta la cadena\n * (patrón short-circuit).\n *\n * Ordenamiento: `priority` descendente (mayor = primero), igual que los\n * hooks. La secuencia respetada es la del sort, no la del orden de\n * llamada a `use`.\n *\n * @param middleware - Función `(entry, next) => Promise<void>`.\n * @param priority - Peso de ordenamiento. Default `50`.\n * @returns {() => void} Función de cancelación para retirar el middleware.\n *\n * @example\n * ```ts\n * // PII redaction: enmascara passwords antes de loguear\n * hooks.use(async (entry, next) => {\n * if (entry.attributes?.password) {\n * entry.attributes.password = '***';\n * }\n * await next();\n * }, 90);\n *\n * // Short-circuit: si es level=debug y env=prod, no baja\n * const stop = hooks.use(async (entry, next) => {\n * if (entry.level === 'debug' && ENV === 'production') return;\n * await next();\n * }, 100);\n * ```\n *\n * @see {@link process} para el orquestador que ejecuta la cadena.\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 /**\n * Emite un evento a todos sus hooks registrados, en orden de prioridad, y\n * retorna el entry resultante tras aplicar todos los mutations.\n *\n * Cada hook puede retornar un partial de {@link HookLogEntry}; ese partial\n * se mergea sobre el entry actual antes de invocar al siguiente hook, así\n * los hooks se encadenan como una pipeline de transformaciones.\n *\n * Manejo de errores:\n * - Si un hook de `beforeLog`/`afterLog` lanza, la excepción se captura y\n * se re-emite como evento `onError` con el campo `error` poblado.\n * - Si un hook de `onError` lanza, **NO** se re-emite (rompería el ciclo);\n * se loguea a `console.error` y se traga.\n * - Guard de reentrancia: si `onError` se re-entra más de\n * {@link MAX_ONERROR_DEPTH} veces, se corta y se loguea el entry al\n * console. Previene loops infinitos por errores en cascada.\n *\n * Los hooks marcados como `once` se eliminan tras un disparo exitoso.\n *\n * @param event - Evento a emitir.\n * @param entry - Entry inicial; no se muta in-place (se clona por nivel).\n * @returns {Promise<HookLogEntry>} Entry transformado tras todos los hooks.\n *\n * @example\n * ```ts\n * const enriched = await hooks.emit('beforeLog', rawEntry);\n * // enriched.attributes puede traer merges de varios hooks\n * ```\n *\n * @see {@link on}\n * @see {@link once}\n * @see {@link MAX_ONERROR_DEPTH}\n */\n async emit(event: HookEvent, entry: HookLogEntry): Promise<HookLogEntry> {\n // Guard de reentrancia. Sin esto, un hook de onError que lance\n // re-entraría a emit('onError', ...) y loopearía para siempre o\n // recursaría hasta hacer volar el stack. Permitimos un burst pequeño\n // (MAX_ONERROR_DEPTH) para que el fan-out legítimo siga funcionando,\n // pero cortamos el ciclo.\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 // Un hook de onError lanzó — se loguea al console (single shot)\n // sin emitir otro onError (lo que recursaría).\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 /**\n * Orquesta el pipeline pre-emit de un log. Orden de ejecución:\n *\n * 1. Emite `beforeLog` (todos sus hooks corren en orden de prioridad y\n * pueden mutar el entry vía return partial).\n * 2. Si hay middlewares registrados ({@link use}), los ejecuta en cascada\n * sobre el entry ya enriquecido por los hooks de `beforeLog`.\n *\n * Es el punto de entrada que el logger invoca **antes** de despachar el\n * record a los transports. El entry devuelto es el que finalmente se loguea.\n *\n * No emite `afterLog`; para eso usar {@link afterProcess} una vez que el\n * dispatch al transport haya terminado.\n *\n * @param entry - Entry crudo entrante al pipeline.\n * @returns {Promise<HookLogEntry>} Entry final listo para mandar a transports.\n *\n * @example\n * ```ts\n * const processed = await hooks.process(rawEntry);\n * await transport.write(processed);\n * await hooks.afterProcess(processed);\n * ```\n *\n * @see {@link afterProcess}\n * @see {@link use}\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 /**\n * Emite el evento `afterLog` con el entry ya procesado y dispatcheado a\n * los transports. Pensado para side-effects post-log: métricas, audit\n * trail, flush de buffers externos, etc.\n *\n * Los hooks de `afterLog` pueden retornar un partial pero el entry ya se\n * ha publicado, así que la mutación no tiene efecto sobre el log emitido;\n * solo queda disponible en el return de {@link emit}, que aquí se descarta.\n *\n * @param entry - Entry final (mismo objeto devuelto por {@link process}).\n * @returns {Promise<void>} Resuelve cuando todos los hooks terminaron.\n *\n * @example\n * ```ts\n * hooks.on('afterLog', async (entry) => {\n * metrics.increment('logs_total', { level: entry.level });\n * });\n *\n * const processed = await hooks.process(rawEntry);\n * await transport.write(processed);\n * await hooks.afterProcess(processed); // dispara métricas\n * ```\n *\n * @see {@link process}\n */\n async afterProcess(entry: HookLogEntry): Promise<void> {\n await this.emit('afterLog', entry);\n }\n\n /**\n * Vacía todos los hooks y middlewares registrados. Útil para resetear el\n * estado entre tests o en hot-reload.\n *\n * Afecta a los tres eventos (`beforeLog`, `afterLog`, `onError`) y a la\n * pila de middlewares. Las funciones de cancelación devueltas por\n * {@link on}/{@link once}/{@link use} se vuelven no-ops pero pueden\n * llamarse sin error.\n *\n * @example\n * ```ts\n * afterEach(() => hooks.clear());\n * ```\n */\n clear(): void {\n this.hooks.forEach(hooks => hooks.length = 0);\n this.middlewares.length = 0;\n }\n\n /**\n * Snapshot del estado interno para observabilidad y debugging.\n *\n * @returns {Object} stats\n * @returns {Record<HookEvent, number>} stats.hooks - Conteo de hooks\n * registrados por evento (`beforeLog`, `afterLog`, `onError`).\n * @returns {number} stats.middlewares - Total de middlewares activos.\n *\n * @example\n * ```ts\n * const stats = hooks.getStats();\n * // { hooks: { beforeLog: 2, afterLog: 1, onError: 3 }, middlewares: 1 }\n * if (stats.hooks.onError === 0) {\n * console.warn('Sin handlers onError registrados');\n * }\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\n/**\n * Devuelve la instancia singleton de {@link HookManager} compartida por todo\n * el proceso. La crea perezosamente en la primera llamada.\n *\n * Pensada como hook manager por defecto del logger; los consumidores que\n * necesiten aislamiento (tests, múltiples loggers con pipelines distintos)\n * deben instanciar su propio `new HookManager()` en lugar de usar este shared.\n *\n * @returns {HookManager} La instancia singleton.\n *\n * @example\n * ```ts\n * import { getDefaultHookManager } from '@mks2508/better-logger/hooks';\n *\n * getDefaultHookManager().on('onError', async (entry) => {\n * telemetry.capture(entry.error);\n * });\n * ```\n *\n * @see {@link HookManager}\n */\nexport function getDefaultHookManager(): HookManager {\n if (!_defaultHookManager) {\n _defaultHookManager = new HookManager();\n }\n return _defaultHookManager;\n}\n","/**\n * @fileoverview HookBridge — facade de HookManager.\n * Encapsula registro de hooks, middleware pipeline y emisión de eventos.\n *\n * @internal\n */\n\nimport type { HookEvent, HookCallback, MiddlewareFn } from '../types/index.js';\nimport { HookManager } from './index.js';\n\n/**\n * Bridge para la gestión de hooks y middleware.\n *\n * @internal\n */\nexport interface HookBridge {\n /** Registra un hook para un evento. Devuelve función de unsubscribe. */\n on(event: HookEvent, callback: HookCallback, priority?: number): () => void;\n /** Registra un hook one-time. Devuelve función de unsubscribe. */\n once(event: HookEvent, callback: HookCallback, priority?: number): () => void;\n /** Elimina un hook registrado. Devuelve `true` si se eliminó. */\n off(event: HookEvent, callback: HookCallback): boolean;\n /** Añade middleware al pipeline. Devuelve función de unsubscribe. */\n use(middleware: MiddlewareFn, priority?: number): () => void;\n /** Devuelve el HookManager subyacente. */\n getHookManager(): HookManager;\n}\n\n/**\n * Crea una instancia de {@link HookBridge}.\n *\n * @internal\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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"}
|