@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
package/dist/index.cjs
CHANGED
|
@@ -2,24 +2,64 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_core = require("./chunks/core-
|
|
6
|
-
const require_transports = require("./chunks/transports-
|
|
7
|
-
const require_utils = require("./chunks/utils-
|
|
8
|
-
const require_styling = require("./chunks/styling-
|
|
9
|
-
const require_environment_detector = require("./chunks/environment-detector-
|
|
10
|
-
const require_spinner = require("./chunks/spinner-
|
|
11
|
-
const require_LogContext = require("./chunks/LogContext-
|
|
12
|
-
const require_HookBridge = require("./chunks/HookBridge-
|
|
13
|
-
const require_SerializerBridge = require("./chunks/SerializerBridge-
|
|
14
|
-
const require_server_fallback = require("./chunks/server-fallback-
|
|
15
|
-
const require_StyleManager = require("./chunks/StyleManager-
|
|
5
|
+
const require_core = require("./chunks/core-CqS_UBzJ.cjs");
|
|
6
|
+
const require_transports = require("./chunks/transports-BZ-Mc2IT.cjs");
|
|
7
|
+
const require_utils = require("./chunks/utils-W_cxqriN.cjs");
|
|
8
|
+
const require_styling = require("./chunks/styling-Cel2wPRy.cjs");
|
|
9
|
+
const require_environment_detector = require("./chunks/environment-detector-D-tHkKWA.cjs");
|
|
10
|
+
const require_spinner = require("./chunks/spinner-BHyYEXsM.cjs");
|
|
11
|
+
const require_LogContext = require("./chunks/LogContext-DZasm_P5.cjs");
|
|
12
|
+
const require_HookBridge = require("./chunks/HookBridge-C-AvXmPD.cjs");
|
|
13
|
+
const require_SerializerBridge = require("./chunks/SerializerBridge-C4a9Z37F.cjs");
|
|
14
|
+
const require_server_fallback = require("./chunks/server-fallback-CaCPjWby.cjs");
|
|
15
|
+
const require_StyleManager = require("./chunks/StyleManager-DQ6UNRB-.cjs");
|
|
16
16
|
//#region src/ScopedLogger.ts
|
|
17
|
+
/**
|
|
18
|
+
* Logger prefijado por un scope nominal. Mantiene su propio stack de badges
|
|
19
|
+
* y contextos y delega el envío de mensajes al {@link Logger} padre a través
|
|
20
|
+
* de bindings (`{ scope, badges }`).
|
|
21
|
+
*
|
|
22
|
+
* Es la base de la jerarquía temática: {@link APILogger} y
|
|
23
|
+
* {@link ComponentLogger} extienden de ella, y {@link ContextLogger} la
|
|
24
|
+
* consume para apilar/subdesapilar sub-prefijos en el scope.
|
|
25
|
+
*
|
|
26
|
+
* No se construye directamente: se obtiene con `logger.scope('name')`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // El factory method del Logger raíz devuelve un ScopedLogger
|
|
30
|
+
* import logger from '@mks2508/better-logger';
|
|
31
|
+
*
|
|
32
|
+
* const http = logger.scope('HTTP');
|
|
33
|
+
* http.badge('OUTBOUND').info('Request enviada');
|
|
34
|
+
* // salida: [HTTP] [OUTBOUND] Request enviada
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Anidar contextos dentro de un scope (el prefijo se compone con ':')
|
|
38
|
+
* const retry = http.context('retry');
|
|
39
|
+
* retry.run(() => http.warn('Reintentando petición'));
|
|
40
|
+
* // salida: [HTTP:retry] Reintentando petición
|
|
41
|
+
*
|
|
42
|
+
* @see {@link Logger.scope}
|
|
43
|
+
* @see {@link APILogger}
|
|
44
|
+
* @see {@link ComponentLogger}
|
|
45
|
+
* @see {@link ContextLogger}
|
|
46
|
+
*/
|
|
17
47
|
var ScopedLogger = class {
|
|
18
48
|
parent;
|
|
19
49
|
scopeName;
|
|
20
50
|
badgeList = [];
|
|
21
51
|
contextStack = [];
|
|
22
52
|
_timers;
|
|
53
|
+
/**
|
|
54
|
+
* Construye un ScopedLogger vinculado a un {@link Logger} padre.
|
|
55
|
+
*
|
|
56
|
+
* Los clientes no deben llamar a este constructor directamente: usen
|
|
57
|
+
* `logger.scope(name)`, que configura correctamente la instancia.
|
|
58
|
+
*
|
|
59
|
+
* @param {Logger} parent - Logger raíz al que se delegan los mensajes.
|
|
60
|
+
* @param {string} scopeName - Etiqueta del scope; se renderiza como
|
|
61
|
+
* prefijo `[scopeName]` en cada línea.
|
|
62
|
+
*/
|
|
23
63
|
constructor(parent, scopeName) {
|
|
24
64
|
this.parent = parent;
|
|
25
65
|
this.scopeName = scopeName;
|
|
@@ -38,31 +78,125 @@ var ScopedLogger = class {
|
|
|
38
78
|
if (this.contextStack.length === 0) return this.scopeName;
|
|
39
79
|
return [this.scopeName, ...this.contextStack].join(":");
|
|
40
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Reemplaza la lista actual de badges por la pasada y la aplica a todos
|
|
83
|
+
* los mensajes posteriores de este scope.
|
|
84
|
+
*
|
|
85
|
+
* @param {string[]} badges - Etiquetas a mostrar como badges adyacentes
|
|
86
|
+
* al prefijo (p. ej. `['OUTBOUND', 'CACHED']`).
|
|
87
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* logger.scope('HTTP').badges(['OUTBOUND', 'CACHED']).info('Cache hit');
|
|
91
|
+
* // salida: [HTTP] [OUTBOUND] [CACHED] Cache hit
|
|
92
|
+
*
|
|
93
|
+
* @see {@link badge} para añadir sin reemplazar los existentes.
|
|
94
|
+
* @see {@link clearBadges} para vaciar la lista.
|
|
95
|
+
*/
|
|
41
96
|
badges(badges) {
|
|
42
97
|
this.badgeList = [...badges];
|
|
43
98
|
return this;
|
|
44
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Añade un badge al scope de forma idempotente (no lo duplica si ya existe).
|
|
102
|
+
*
|
|
103
|
+
* @param {string} badge - Etiqueta a añadir a la lista de badges.
|
|
104
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* logger.scope('API')
|
|
108
|
+
* .badge('OUTBOUND')
|
|
109
|
+
* .badge('RETRY')
|
|
110
|
+
* .warn('Reintentando');
|
|
111
|
+
* // salida: [API] [OUTBOUND] [RETRY] Reintentando
|
|
112
|
+
*/
|
|
45
113
|
badge(badge) {
|
|
46
114
|
if (!this.badgeList.includes(badge)) this.badgeList.push(badge);
|
|
47
115
|
return this;
|
|
48
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Vacía la lista de badges del scope.
|
|
119
|
+
*
|
|
120
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* const http = logger.scope('HTTP');
|
|
124
|
+
* http.badge('OUTBOUND').info('uno');
|
|
125
|
+
* http.clearBadges().info('dos');
|
|
126
|
+
* // [HTTP] [OUTBOUND] uno / [HTTP] dos
|
|
127
|
+
*/
|
|
49
128
|
clearBadges() {
|
|
50
129
|
this.badgeList = [];
|
|
51
130
|
return this;
|
|
52
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Aplica un theme preset al logger padre. El preset afecta a toda la
|
|
134
|
+
* instancia raíz (no solo a este scope) porque el style es compartido.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} presetName - Nombre del preset registrado en el StyleManager.
|
|
137
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* logger.scope('UI').style('cyberpunk').info('neon');
|
|
141
|
+
* @see {@link Logger.setTheme}
|
|
142
|
+
*/
|
|
53
143
|
style(presetName) {
|
|
54
144
|
this.parent.setTheme(presetName);
|
|
55
145
|
return this;
|
|
56
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Crea un {@link ContextLogger} vinculado a este scope. Los contextos se
|
|
149
|
+
* apilan en el prefijo separados por `:`, permitiendo agrupar bloques de
|
|
150
|
+
* logs relacionados (reintentos, sub-etapas, etc.) sin `console.group`.
|
|
151
|
+
*
|
|
152
|
+
* @param {string} contextName - Nombre del contexto a apilar.
|
|
153
|
+
* @returns {ContextLogger} Handler con `run`, `runAsync`, `start`/`end`.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* const retry = logger.scope('HTTP').context('retry');
|
|
157
|
+
* retry.run(() => logger.warn('Reintentando'));
|
|
158
|
+
* // salida: [HTTP:retry] Reintentando
|
|
159
|
+
* @see {@link ContextLogger}
|
|
160
|
+
*/
|
|
57
161
|
context(contextName) {
|
|
58
162
|
return new ContextLogger(this, contextName);
|
|
59
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Inicia un timer etiquetado bajo el namespace `<scopeName>:<label>`.
|
|
166
|
+
* El label es local a este scope, así que dos scopes pueden reutilizar el
|
|
167
|
+
* mismo nombre sin colisión.
|
|
168
|
+
*
|
|
169
|
+
* @param {string} label - Identificador del timer.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* const http = logger.scope('HTTP');
|
|
173
|
+
* http.time('request');
|
|
174
|
+
* // ... trabajo ...
|
|
175
|
+
* http.timeEnd('request'); // imprime "Timer: request - 12.34ms"
|
|
176
|
+
* @see {@link timeEnd}
|
|
177
|
+
*/
|
|
60
178
|
time(label) {
|
|
61
179
|
this.timers.set(label, {
|
|
62
180
|
label: `${this.scopeName}:${label}`,
|
|
63
181
|
startTime: performance.now()
|
|
64
182
|
});
|
|
65
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Detiene un timer previamente iniciado con {@link time} y registra la
|
|
186
|
+
* duración con nivel `success`. Si el label no existe, emite un `warn`
|
|
187
|
+
* y devuelve `undefined`.
|
|
188
|
+
*
|
|
189
|
+
* @param {string} label - Mismo label pasado a {@link time}.
|
|
190
|
+
* @returns {number | undefined} Milisegundos transcurridos, o `undefined`
|
|
191
|
+
* si el timer no estaba registrado.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* const http = logger.scope('HTTP');
|
|
195
|
+
* http.time('fetch');
|
|
196
|
+
* await fetch(url);
|
|
197
|
+
* const ms = http.timeEnd('fetch');
|
|
198
|
+
* if (ms && ms > 1000) http.warn('Latencia alta');
|
|
199
|
+
*/
|
|
66
200
|
timeEnd(label) {
|
|
67
201
|
const timer = this.timers.get(label);
|
|
68
202
|
if (!timer) {
|
|
@@ -74,118 +208,447 @@ var ScopedLogger = class {
|
|
|
74
208
|
this.success(`Timer: ${label} - ${elapsed.toFixed(2)}ms`);
|
|
75
209
|
return elapsed;
|
|
76
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Emite un mensaje a nivel `debug` con los bindings actuales del scope.
|
|
213
|
+
*
|
|
214
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales (objetos,
|
|
215
|
+
* errores, etc.) serializados igual que en el logger raíz.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* logger.scope('DB').debug('query', { sql, params });
|
|
219
|
+
*/
|
|
77
220
|
debug(...args) {
|
|
78
221
|
this.parent.logWithBindings(this.getBindings(), "debug", ...args);
|
|
79
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Emite un mensaje a nivel `info` con los bindings actuales del scope.
|
|
225
|
+
*
|
|
226
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* logger.scope('AUTH').info('Login exitoso', { userId });
|
|
230
|
+
*/
|
|
80
231
|
info(...args) {
|
|
81
232
|
this.parent.logWithBindings(this.getBindings(), "info", ...args);
|
|
82
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Emite un mensaje a nivel `warn` con los bindings actuales del scope.
|
|
236
|
+
*
|
|
237
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* logger.scope('CACHE').warn('Cache miss', { key });
|
|
241
|
+
*/
|
|
83
242
|
warn(...args) {
|
|
84
243
|
this.parent.logWithBindings(this.getBindings(), "warn", ...args);
|
|
85
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Emite un mensaje a nivel `error` con los bindings actuales del scope.
|
|
247
|
+
*
|
|
248
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales (típicamente
|
|
249
|
+
* un `Error` o contexto del fallo).
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* logger.scope('DB').error('Conexión rechazada', err);
|
|
253
|
+
*/
|
|
86
254
|
error(...args) {
|
|
87
255
|
this.parent.logWithBindings(this.getBindings(), "error", ...args);
|
|
88
256
|
}
|
|
257
|
+
/**
|
|
258
|
+
* Emite un mensaje con badge visual `SUCCESS` a nivel `info`. Úselo para
|
|
259
|
+
* hitos positivos dentro del scope (conexión establecida, sync completo,
|
|
260
|
+
* commit aplicado).
|
|
261
|
+
*
|
|
262
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* logger.scope('SYNC').success('Sincronización completa', { count: 42 });
|
|
266
|
+
*/
|
|
89
267
|
success(...args) {
|
|
90
268
|
const bindings = this.getBindings();
|
|
91
269
|
this.parent.logWithBindingsAndTag(bindings, "info", "success", ...args);
|
|
92
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Emite un mensaje a nivel `critical` con los bindings actuales del scope.
|
|
273
|
+
* Reservado para fallos que detienen el flujo de la aplicación.
|
|
274
|
+
*
|
|
275
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* logger.scope('PAY').critical('Pasarela inaccesible', err);
|
|
279
|
+
*/
|
|
93
280
|
critical(...args) {
|
|
94
281
|
this.parent.logWithBindings(this.getBindings(), "critical", ...args);
|
|
95
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Emite un mensaje a nivel `trace` (verbosidad máxima) con los bindings
|
|
285
|
+
* actuales del scope. Solo aparece si la verbosity global lo permite.
|
|
286
|
+
*
|
|
287
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* logger.scope('NET').trace('packet', { bytes });
|
|
291
|
+
*/
|
|
96
292
|
trace(...args) {
|
|
97
293
|
this.parent.logWithBindings(this.getBindings(), "trace", ...args);
|
|
98
294
|
}
|
|
99
|
-
/**
|
|
295
|
+
/**
|
|
296
|
+
* Emite un point-span con el scope de este logger como
|
|
297
|
+
* `SpanRecord.scope`. Ver {@link Logger.event}.
|
|
298
|
+
*
|
|
299
|
+
* @param {string} name - Nombre del evento.
|
|
300
|
+
* @param {SpanAttributes} [attributes] - Attributes del span.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* logger.scope('BUILD').event('step.done', { step: 'compile' });
|
|
304
|
+
*/
|
|
305
|
+
event(name, attributes) {
|
|
306
|
+
this.parent._emitSpanEvent(name, attributes, this.getScopePrefix());
|
|
307
|
+
}
|
|
308
|
+
span(name, fnOrAttributes, maybeFn) {
|
|
309
|
+
const { attributes, fn } = resolveSpanArgs(fnOrAttributes, maybeFn);
|
|
310
|
+
return this.parent._runSpan(name, attributes, this.getScopePrefix(), fn);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Inicia un span externally-ended etiquetado con el scope de este
|
|
314
|
+
* logger. Ver {@link Logger.startSpan}.
|
|
315
|
+
*
|
|
316
|
+
* @param {string} name - Nombre de la operación.
|
|
317
|
+
* @param {SpanAttributes} [attributes] - Attributes iniciales.
|
|
318
|
+
* @returns {Span} Handle con `set`/`end`/`fail`.
|
|
319
|
+
*/
|
|
320
|
+
startSpan(name, attributes) {
|
|
321
|
+
return this.parent._startSpan(name, attributes, this.getScopePrefix());
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Delegación a {@link Logger.step}: dibuja una barra de progreso discreta
|
|
325
|
+
* `current/total` para este scope.
|
|
326
|
+
*
|
|
327
|
+
* @param {number} current - Paso actual (1-indexed).
|
|
328
|
+
* @param {number} total - Total de pasos.
|
|
329
|
+
* @param {string} message - Texto mostrado junto al contador.
|
|
330
|
+
* @see {@link Logger.step}
|
|
331
|
+
*/
|
|
100
332
|
step(current, total, message) {
|
|
101
333
|
this.parent.step(current, total, message);
|
|
102
334
|
}
|
|
103
|
-
/**
|
|
335
|
+
/**
|
|
336
|
+
* Delegación a {@link Logger.header}: imprime un título con separadores visuales.
|
|
337
|
+
*
|
|
338
|
+
* @param {string} title - Texto del título.
|
|
339
|
+
* @param {string} [subtitle] - Subtítulo opcional bajo el título.
|
|
340
|
+
* @see {@link Logger.header}
|
|
341
|
+
*/
|
|
104
342
|
header(title, subtitle) {
|
|
105
343
|
this.parent.header(title, subtitle);
|
|
106
344
|
}
|
|
107
|
-
/**
|
|
345
|
+
/**
|
|
346
|
+
* Delegación a {@link Logger.divider}: imprime una línea separadora horizontal.
|
|
347
|
+
* @see {@link Logger.divider}
|
|
348
|
+
*/
|
|
108
349
|
divider() {
|
|
109
350
|
this.parent.divider();
|
|
110
351
|
}
|
|
111
|
-
/**
|
|
352
|
+
/**
|
|
353
|
+
* Delegación a {@link Logger.blank}: inserta una línea en blanco.
|
|
354
|
+
* @see {@link Logger.blank}
|
|
355
|
+
*/
|
|
112
356
|
blank() {
|
|
113
357
|
this.parent.blank();
|
|
114
358
|
}
|
|
115
|
-
/**
|
|
359
|
+
/**
|
|
360
|
+
* Delegación a {@link Logger.box}: dibuja un recuadro ANSI alrededor de `content`.
|
|
361
|
+
*
|
|
362
|
+
* @param {string} content - Texto a enmarcar.
|
|
363
|
+
* @param {IBoxOptions} [options] - Opciones de estilo del box.
|
|
364
|
+
* @see {@link Logger.box}
|
|
365
|
+
*/
|
|
116
366
|
box(content, options) {
|
|
117
367
|
this.parent.box(content, options);
|
|
118
368
|
}
|
|
119
|
-
/**
|
|
369
|
+
/**
|
|
370
|
+
* Delegación a {@link Logger.cliTable}: renderiza `rows` como tabla ASCII.
|
|
371
|
+
*
|
|
372
|
+
* @param {Record<string, unknown>[]} rows - Filas a mostrar.
|
|
373
|
+
* @param {ITableOptions} [options] - Opciones de columnas y estilo.
|
|
374
|
+
* @see {@link Logger.cliTable}
|
|
375
|
+
*/
|
|
120
376
|
cliTable(rows, options) {
|
|
121
377
|
this.parent.cliTable(rows, options);
|
|
122
378
|
}
|
|
123
|
-
/**
|
|
379
|
+
/**
|
|
380
|
+
* Delegación a {@link Logger.spinner}: arranca un spinner con `message`.
|
|
381
|
+
*
|
|
382
|
+
* @param {string} message - Texto a mostrar al lado del spinner.
|
|
383
|
+
* @returns {ISpinnerHandle} Handle para detener/actualizar el spinner.
|
|
384
|
+
* @see {@link Logger.spinner}
|
|
385
|
+
*/
|
|
124
386
|
spinner(message) {
|
|
125
387
|
return this.parent.spinner(message);
|
|
126
388
|
}
|
|
127
|
-
/**
|
|
389
|
+
/**
|
|
390
|
+
* Delegación a {@link Logger.setCLILevel}: ajusta el nivel mínimo de las
|
|
391
|
+
* primitivas CLI visibles.
|
|
392
|
+
*
|
|
393
|
+
* @param {CLILogLevel} level - Nivel CLI (`silent` … `verbose`).
|
|
394
|
+
* @see {@link Logger.setCLILevel}
|
|
395
|
+
*/
|
|
128
396
|
setCLILevel(level) {
|
|
129
397
|
this.parent.setCLILevel(level);
|
|
130
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Apila un contexto en el prefijo del scope. Invocado por
|
|
401
|
+
* {@link ContextLogger}; los clientes no deben llamarlo directamente.
|
|
402
|
+
*
|
|
403
|
+
* @param {string} context - Nombre del contexto a apilar.
|
|
404
|
+
* @internal
|
|
405
|
+
*/
|
|
131
406
|
_pushContext(context) {
|
|
132
407
|
this.contextStack.push(context);
|
|
133
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Desapila el último contexto del prefijo del scope. Invocado por
|
|
411
|
+
* {@link ContextLogger}; los clientes no deben llamarlo directamente.
|
|
412
|
+
*
|
|
413
|
+
* @internal
|
|
414
|
+
*/
|
|
134
415
|
_popContext() {
|
|
135
416
|
this.contextStack.pop();
|
|
136
417
|
}
|
|
137
418
|
};
|
|
419
|
+
/**
|
|
420
|
+
* Logger especializado para llamadas a APIs y servicios externos.
|
|
421
|
+
*
|
|
422
|
+
* Extiende {@link ScopedLogger} pre-seteando el badge `API` y exponiendo
|
|
423
|
+
* atajos para eventos típicos de integración: llamadas lentas ({@link slow}),
|
|
424
|
+
* rate limiting ({@link rateLimit}), fallos de autenticación ({@link auth}) y
|
|
425
|
+
* APIs deprecadas ({@link deprecated}).
|
|
426
|
+
*
|
|
427
|
+
* Se obtiene con `logger.api(name)` y no se construye directamente.
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* import logger from '@mks2508/better-logger';
|
|
431
|
+
*
|
|
432
|
+
* const stripe = logger.api('Stripe');
|
|
433
|
+
* stripe.info('Consultando customer', { id });
|
|
434
|
+
* // salida: [API:Stripe] [API] Consultando customer
|
|
435
|
+
*
|
|
436
|
+
* stripe.slow('customer.retrieve', 1250);
|
|
437
|
+
* // salida: [API:Stripe] [API] [SLOW] customer.retrieve (1250ms)
|
|
438
|
+
*
|
|
439
|
+
* @see {@link Logger.api}
|
|
440
|
+
* @see {@link ScopedLogger}
|
|
441
|
+
*/
|
|
138
442
|
var APILogger = class extends ScopedLogger {
|
|
443
|
+
/**
|
|
444
|
+
* Construye un APILogger con scope `API:<apiName>` y badge `API` ya aplicado.
|
|
445
|
+
*
|
|
446
|
+
* Los clientes deben usar `logger.api(name)`.
|
|
447
|
+
*
|
|
448
|
+
* @param {Logger} parent - Logger raíz al que se delegan los mensajes.
|
|
449
|
+
* @param {string} apiName - Nombre del servicio/API (se prefija con `API:`).
|
|
450
|
+
*/
|
|
139
451
|
constructor(parent, apiName) {
|
|
140
452
|
super(parent, `API:${apiName}`);
|
|
141
453
|
this.badge("API");
|
|
142
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* Registra una llamada lenta con badge `SLOW` a nivel `warn`.
|
|
457
|
+
*
|
|
458
|
+
* @param {string} message - Descripción de la operación lenta.
|
|
459
|
+
* @param {number} [duration] - Duración medida en ms; si se pasa, se
|
|
460
|
+
* anexa al mensaje como `(Nms)`.
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* const t0 = performance.now();
|
|
464
|
+
* await stripe.customers.retrieve(id);
|
|
465
|
+
* logger.api('Stripe').slow('retrieve', performance.now() - t0);
|
|
466
|
+
*/
|
|
143
467
|
slow(message, duration) {
|
|
144
468
|
this.badge("SLOW");
|
|
145
469
|
const msg = duration ? `${message} (${duration}ms)` : message;
|
|
146
470
|
this.warn(msg);
|
|
147
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Registra un evento de rate limiting (HTTP 429) con badge `RATE_LIMIT`.
|
|
474
|
+
*
|
|
475
|
+
* @param {string} message - Detalle del límite golpeado.
|
|
476
|
+
*
|
|
477
|
+
* @example
|
|
478
|
+
* logger.api('GitHub').rateLimit('Secondary rate limit on /search');
|
|
479
|
+
*/
|
|
148
480
|
rateLimit(message) {
|
|
149
481
|
this.badge("RATE_LIMIT");
|
|
150
482
|
this.warn(message);
|
|
151
483
|
}
|
|
484
|
+
/**
|
|
485
|
+
* Registra un fallo de autenticación (401/403) con badge `AUTH` a nivel
|
|
486
|
+
* `error`.
|
|
487
|
+
*
|
|
488
|
+
* @param {string} message - Detalle del fallo de credenciales/token.
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* logger.api('OAuth').auth('Token expirado');
|
|
492
|
+
*/
|
|
152
493
|
auth(message) {
|
|
153
494
|
this.badge("AUTH");
|
|
154
495
|
this.error(message);
|
|
155
496
|
}
|
|
497
|
+
/**
|
|
498
|
+
* Marca una API como deprecada con badge `DEPRECATED` a nivel `warn`.
|
|
499
|
+
*
|
|
500
|
+
* @param {string} message - Mensaje guiando a la migración (endpoint
|
|
501
|
+
* alternativo, versión retirada, etc.).
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* logger.api('Legacy').deprecated('Usar v3; v2 se retira en Q4');
|
|
505
|
+
*/
|
|
156
506
|
deprecated(message) {
|
|
157
507
|
this.badge("DEPRECATED");
|
|
158
508
|
this.warn(message);
|
|
159
509
|
}
|
|
160
510
|
};
|
|
511
|
+
/**
|
|
512
|
+
* Logger para componentes UI, módulos o cualquier unidad con ciclo de vida.
|
|
513
|
+
*
|
|
514
|
+
* Extiende {@link ScopedLogger} pre-seteando el badge `COMPONENT` y exponiendo
|
|
515
|
+
* atajos para eventos típicos: {@link lifecycle}, {@link stateChange} y
|
|
516
|
+
* {@link propsChange}.
|
|
517
|
+
*
|
|
518
|
+
* Se obtiene con `logger.component(name)` y no se construye directamente.
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* import logger from '@mks2508/better-logger';
|
|
522
|
+
*
|
|
523
|
+
* const cart = logger.component('Cart');
|
|
524
|
+
* cart.lifecycle('mount');
|
|
525
|
+
* // salida: [Cart] [COMPONENT] [LIFECYCLE] mount
|
|
526
|
+
*
|
|
527
|
+
* cart.stateChange('empty', 'has-items', { count: 3 });
|
|
528
|
+
* // salida: [Cart] [COMPONENT] [STATE] empty → has-items { count: 3 }
|
|
529
|
+
*
|
|
530
|
+
* @see {@link Logger.component}
|
|
531
|
+
* @see {@link ScopedLogger}
|
|
532
|
+
*/
|
|
161
533
|
var ComponentLogger = class extends ScopedLogger {
|
|
534
|
+
/**
|
|
535
|
+
* Construye un ComponentLogger con badge `COMPONENT` ya aplicado.
|
|
536
|
+
*
|
|
537
|
+
* Los clientes deben usar `logger.component(name)`.
|
|
538
|
+
*
|
|
539
|
+
* @param {Logger} parent - Logger raíz al que se delegan los mensajes.
|
|
540
|
+
* @param {string} componentName - Nombre del componente (scope label).
|
|
541
|
+
*/
|
|
162
542
|
constructor(parent, componentName) {
|
|
163
543
|
super(parent, componentName);
|
|
164
544
|
this.badge("COMPONENT");
|
|
165
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* Registra un evento de ciclo de vida con badge `LIFECYCLE` a nivel `info`.
|
|
548
|
+
*
|
|
549
|
+
* @param {string} event - Nombre del evento (`mount`, `unmount`,
|
|
550
|
+
* `update`, ...).
|
|
551
|
+
* @param {string} [message] - Detalle opcional; si se omite, solo se
|
|
552
|
+
* registra el nombre del evento.
|
|
553
|
+
*
|
|
554
|
+
* @example
|
|
555
|
+
* logger.component('Cart').lifecycle('mount', 'Modal abierto');
|
|
556
|
+
*/
|
|
166
557
|
lifecycle(event, message) {
|
|
167
558
|
this.badge("LIFECYCLE");
|
|
168
559
|
const msg = message ? `${event}: ${message}` : event;
|
|
169
560
|
this.info(msg);
|
|
170
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Registra una transición de estado con badge `STATE` a nivel `info`.
|
|
564
|
+
*
|
|
565
|
+
* @param {string} from - Estado previo.
|
|
566
|
+
* @param {string} to - Estado nuevo.
|
|
567
|
+
* @param {unknown} [data] - Payload opcional asociado a la transición.
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* const fsm = logger.component('FSM');
|
|
571
|
+
* fsm.stateChange('idle', 'loading');
|
|
572
|
+
* fsm.stateChange('loading', 'success', { items: 3 });
|
|
573
|
+
*/
|
|
171
574
|
stateChange(from, to, data) {
|
|
172
575
|
this.badge("STATE");
|
|
173
576
|
const msg = `${from} → ${to}`;
|
|
174
577
|
if (data) this.info(msg, data);
|
|
175
578
|
else this.info(msg);
|
|
176
579
|
}
|
|
580
|
+
/**
|
|
581
|
+
* Registra cambios de props/debug del componente con badge `PROPS` a nivel
|
|
582
|
+
* `debug`.
|
|
583
|
+
*
|
|
584
|
+
* @param {Record<string, unknown>} changes - Mapa prop → valor (típicamente
|
|
585
|
+
* el diff de props entre renders).
|
|
586
|
+
*
|
|
587
|
+
* @example
|
|
588
|
+
* logger.component('Cart').propsChange({ itemCount: 5, currency: 'EUR' });
|
|
589
|
+
*/
|
|
177
590
|
propsChange(changes) {
|
|
178
591
|
this.badge("PROPS");
|
|
179
592
|
this.debug("Props changed:", changes);
|
|
180
593
|
}
|
|
181
594
|
};
|
|
595
|
+
/**
|
|
596
|
+
* Handler de contexto apilable sobre un {@link ScopedLogger}.
|
|
597
|
+
*
|
|
598
|
+
* Permite agrupar bloques de logs bajo un sub-prefijo separado por `:`,
|
|
599
|
+
* manteniendo la correlación visual sin necesidad de `console.group`. El
|
|
600
|
+
* prefijo compuesto se forma como `<scopeName>:<contextName>`.
|
|
601
|
+
*
|
|
602
|
+
* Se crea con `scopedLogger.context(name)`. El patrón idiomático es
|
|
603
|
+
* {@link run}/{@link runAsync} (auto push/pop con try/finally); {@link start}
|
|
604
|
+
* y {@link end} permiten control manual cuando el bloque no cierra
|
|
605
|
+
* léxicamente (event handlers distribuidos, promesas de larga duración).
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* import logger from '@mks2508/better-logger';
|
|
609
|
+
*
|
|
610
|
+
* const http = logger.scope('HTTP');
|
|
611
|
+
*
|
|
612
|
+
* // Bloque síncrono auto-cerrado
|
|
613
|
+
* http.context('retry').run(() => {
|
|
614
|
+
* http.warn('Reintentando petición');
|
|
615
|
+
* });
|
|
616
|
+
* // salida: [HTTP:retry] Reintentando petición
|
|
617
|
+
*
|
|
618
|
+
* // Bloque async auto-cerrado
|
|
619
|
+
* await http.context('refresh').runAsync(async () => {
|
|
620
|
+
* await refreshToken();
|
|
621
|
+
* http.info('Token refrescado');
|
|
622
|
+
* });
|
|
623
|
+
*
|
|
624
|
+
* @see {@link ScopedLogger.context}
|
|
625
|
+
*/
|
|
182
626
|
var ContextLogger = class {
|
|
183
627
|
parentLogger;
|
|
184
628
|
contextName;
|
|
629
|
+
/**
|
|
630
|
+
* @param {ScopedLogger} parentLogger - Scope sobre el que se apila el contexto.
|
|
631
|
+
* @param {string} contextName - Sub-prefijo a apilar en el scope padre.
|
|
632
|
+
*/
|
|
185
633
|
constructor(parentLogger, contextName) {
|
|
186
634
|
this.parentLogger = parentLogger;
|
|
187
635
|
this.contextName = contextName;
|
|
188
636
|
}
|
|
637
|
+
/**
|
|
638
|
+
* Ejecuta `fn` síncrona dentro del contexto, garantizando el pop del
|
|
639
|
+
* prefijo incluso si `fn` lanza. El contexto solo está activo durante la
|
|
640
|
+
* ejecución de `fn`.
|
|
641
|
+
*
|
|
642
|
+
* @typeParam T - Tipo de retorno de `fn`.
|
|
643
|
+
* @param {() => T} fn - Función a ejecutar bajo el contexto.
|
|
644
|
+
* @returns {T} Lo que devuelva `fn`.
|
|
645
|
+
* @throws {unknown} Relanza cualquier excepción de `fn` tras desapilar.
|
|
646
|
+
*
|
|
647
|
+
* @example
|
|
648
|
+
* logger.scope('HTTP').context('warmup').run(() => {
|
|
649
|
+
* logger.info('Pre-cargando caché');
|
|
650
|
+
* });
|
|
651
|
+
*/
|
|
189
652
|
run(fn) {
|
|
190
653
|
this.parentLogger._pushContext(this.contextName);
|
|
191
654
|
try {
|
|
@@ -194,6 +657,21 @@ var ContextLogger = class {
|
|
|
194
657
|
this.parentLogger._popContext();
|
|
195
658
|
}
|
|
196
659
|
}
|
|
660
|
+
/**
|
|
661
|
+
* Variante async de {@link run}: mantiene el contexto activo mientras se
|
|
662
|
+
* awaiting la promesa de `fn`, incluyendo awaits internos.
|
|
663
|
+
*
|
|
664
|
+
* @typeParam T - Tipo resuelto por la promesa de `fn`.
|
|
665
|
+
* @param {() => Promise<T>} fn - Función async a ejecutar bajo el contexto.
|
|
666
|
+
* @returns {Promise<T>} Promesa que resuelve al valor de `fn`.
|
|
667
|
+
* @throws {unknown} Relanza cualquier rechazo de `fn` tras desapilar.
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* await logger.scope('HTTP').context('fetch').runAsync(async () => {
|
|
671
|
+
* const r = await fetch(url);
|
|
672
|
+
* logger.info('Recibido', { status: r.status });
|
|
673
|
+
* });
|
|
674
|
+
*/
|
|
197
675
|
async runAsync(fn) {
|
|
198
676
|
this.parentLogger._pushContext(this.contextName);
|
|
199
677
|
try {
|
|
@@ -202,27 +680,80 @@ var ContextLogger = class {
|
|
|
202
680
|
this.parentLogger._popContext();
|
|
203
681
|
}
|
|
204
682
|
}
|
|
683
|
+
/**
|
|
684
|
+
* Apila el contexto manualmente. Útil cuando el bloque que lo consume no
|
|
685
|
+
* cierra léxicamente (event handlers, timeouts, streams). Debe emparejarse
|
|
686
|
+
* con un {@link end} posterior; olvidarlo deja el prefijo contaminado para
|
|
687
|
+
* los logs siguientes del scope.
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* const ctx = logger.scope('WS').context('subscribe');
|
|
691
|
+
* socket.onopen = () => { ctx.start(); ctx.info('connected'); };
|
|
692
|
+
* socket.onclose = () => { ctx.info('disconnected'); ctx.end(); };
|
|
693
|
+
* @see {@link end}
|
|
694
|
+
*/
|
|
205
695
|
start() {
|
|
206
696
|
this.parentLogger._pushContext(this.contextName);
|
|
207
697
|
}
|
|
698
|
+
/**
|
|
699
|
+
* Desapila el último contexto abierto con {@link start}.
|
|
700
|
+
*
|
|
701
|
+
* @see {@link start}
|
|
702
|
+
*/
|
|
208
703
|
end() {
|
|
209
704
|
this.parentLogger._popContext();
|
|
210
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* Atajo a `scopedLogger.debug(...)`. El contexto se aplica al prefijo del
|
|
708
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
709
|
+
*
|
|
710
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
711
|
+
*/
|
|
211
712
|
debug(...args) {
|
|
212
713
|
this.parentLogger.debug(...args);
|
|
213
714
|
}
|
|
715
|
+
/**
|
|
716
|
+
* Atajo a `scopedLogger.info(...)`. El contexto se aplica al prefijo del
|
|
717
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
718
|
+
*
|
|
719
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
720
|
+
*/
|
|
214
721
|
info(...args) {
|
|
215
722
|
this.parentLogger.info(...args);
|
|
216
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Atajo a `scopedLogger.warn(...)`. El contexto se aplica al prefijo del
|
|
726
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
727
|
+
*
|
|
728
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
729
|
+
*/
|
|
217
730
|
warn(...args) {
|
|
218
731
|
this.parentLogger.warn(...args);
|
|
219
732
|
}
|
|
733
|
+
/**
|
|
734
|
+
* Atajo a `scopedLogger.error(...)`. El contexto se aplica al prefijo del
|
|
735
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
736
|
+
*
|
|
737
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
738
|
+
*/
|
|
220
739
|
error(...args) {
|
|
221
740
|
this.parentLogger.error(...args);
|
|
222
741
|
}
|
|
742
|
+
/**
|
|
743
|
+
* Atajo a `scopedLogger.success(...)`. El contexto se aplica al prefijo del
|
|
744
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
745
|
+
*
|
|
746
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
747
|
+
*/
|
|
223
748
|
success(...args) {
|
|
224
749
|
this.parentLogger.success(...args);
|
|
225
750
|
}
|
|
751
|
+
/**
|
|
752
|
+
* Atajo a `scopedLogger.critical(...)`. El contexto se aplica al prefijo
|
|
753
|
+
* del scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
754
|
+
*
|
|
755
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
756
|
+
*/
|
|
226
757
|
critical(...args) {
|
|
227
758
|
this.parentLogger.critical(...args);
|
|
228
759
|
}
|
|
@@ -230,7 +761,34 @@ var ContextLogger = class {
|
|
|
230
761
|
//#endregion
|
|
231
762
|
//#region src/cli/CommandProcessor.ts
|
|
232
763
|
/**
|
|
233
|
-
* CLI
|
|
764
|
+
* Procesador central del CLI del logger. Resuelve nombres de comando (con
|
|
765
|
+
* aliases), despacha ejecución, mantiene historial acotado (max 100 entradas)
|
|
766
|
+
* y soporta un sistema de plugins para extensión de terceros.
|
|
767
|
+
*
|
|
768
|
+
* No es un binario standalone: se invoca desde la consola del navegador vía
|
|
769
|
+
* `window.cli("<command>")` (modo interactivo habilitado por
|
|
770
|
+
* {@link enterInteractiveMode}) o desde código vía `logger.cli()`. El
|
|
771
|
+
* constructor no registra ningún comando por defecto — usar
|
|
772
|
+
* {@link createDefaultCLI} para obtener una instancia con los 8 comandos
|
|
773
|
+
* estándar ya cargados.
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```ts
|
|
777
|
+
* const cli = createDefaultCLI();
|
|
778
|
+
* await cli.processCommand('/themes', logger);
|
|
779
|
+
* await cli.processCommand('/config theme=neon', logger);
|
|
780
|
+
* ```
|
|
781
|
+
*
|
|
782
|
+
* @example
|
|
783
|
+
* ```ts
|
|
784
|
+
* // Modo interactivo: expone `window.cli` en el navegador
|
|
785
|
+
* cli.enterInteractiveMode(logger);
|
|
786
|
+
* // Desde la devtools: cli('help') → procesa '/help'
|
|
787
|
+
* ```
|
|
788
|
+
*
|
|
789
|
+
* @see {@link createDefaultCLI}
|
|
790
|
+
* @see {@link ICommand}
|
|
791
|
+
* @see {@link ICLIPlugin}
|
|
234
792
|
*/
|
|
235
793
|
var CommandProcessor = class {
|
|
236
794
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -240,14 +798,26 @@ var CommandProcessor = class {
|
|
|
240
798
|
maxHistorySize = 100;
|
|
241
799
|
isInteractiveMode = false;
|
|
242
800
|
/**
|
|
243
|
-
*
|
|
801
|
+
* Registra un comando. Si el comando declara `aliases`, también se indexan
|
|
802
|
+
* para resolución. Un comando con el mismo `name` sobreescribe al previo.
|
|
803
|
+
*
|
|
804
|
+
* @param {ICommand} command - Comando a registrar.
|
|
805
|
+
* @see {@link ICommand}
|
|
244
806
|
*/
|
|
245
807
|
registerCommand(command) {
|
|
246
808
|
this.commands.set(command.name, command);
|
|
247
809
|
if (command.aliases) for (const alias of command.aliases) this.aliases.set(alias, command.name);
|
|
248
810
|
}
|
|
249
811
|
/**
|
|
250
|
-
*
|
|
812
|
+
* Registra un plugin: indexa todos sus commands y, si el plugin define
|
|
813
|
+
* `initialize`, lo invoca con el processor y el logger. Los comandos del
|
|
814
|
+
* plugin se registran vía {@link registerCommand} y sus aliases quedan
|
|
815
|
+
* resolvibles igual que los directos.
|
|
816
|
+
*
|
|
817
|
+
* @param {ICLIPlugin} plugin - Plugin a registrar.
|
|
818
|
+
* @param {Logger} [logger] - Logger activo; requerido solo si el plugin define `initialize`.
|
|
819
|
+
* @throws {Error} Si ya existe un plugin registrado con el mismo `name`.
|
|
820
|
+
* @see {@link unregisterPlugin}
|
|
251
821
|
*/
|
|
252
822
|
registerPlugin(plugin, logger) {
|
|
253
823
|
if (this.plugins.has(plugin.name)) throw new Error(`Plugin ${plugin.name} is already registered`);
|
|
@@ -256,7 +826,12 @@ var CommandProcessor = class {
|
|
|
256
826
|
if (plugin.initialize && logger) plugin.initialize(this, logger);
|
|
257
827
|
}
|
|
258
828
|
/**
|
|
259
|
-
*
|
|
829
|
+
* Desregistra un plugin por nombre: elimina todos sus commands (y los
|
|
830
|
+
* aliases que aportasen), invoca su hook `cleanup` si existe y lo quita
|
|
831
|
+
* del registry. No-op si el nombre no existe.
|
|
832
|
+
*
|
|
833
|
+
* @param {string} pluginName - Nombre del plugin a desregistrar.
|
|
834
|
+
* @see {@link registerPlugin}
|
|
260
835
|
*/
|
|
261
836
|
unregisterPlugin(pluginName) {
|
|
262
837
|
const plugin = this.plugins.get(pluginName);
|
|
@@ -269,13 +844,20 @@ var CommandProcessor = class {
|
|
|
269
844
|
this.plugins.delete(pluginName);
|
|
270
845
|
}
|
|
271
846
|
/**
|
|
272
|
-
*
|
|
847
|
+
* Lista todos los commands registrados (directamente o vía plugins).
|
|
848
|
+
* No incluye aliases.
|
|
849
|
+
*
|
|
850
|
+
* @returns {ICommand[]} Snapshot array de los commands registrados.
|
|
273
851
|
*/
|
|
274
852
|
getCommands() {
|
|
275
853
|
return Array.from(this.commands.values());
|
|
276
854
|
}
|
|
277
855
|
/**
|
|
278
|
-
*
|
|
856
|
+
* Resuelve un comando por nombre canónico o alias. Devuelve `undefined`
|
|
857
|
+
* si no existe ninguno que matchee.
|
|
858
|
+
*
|
|
859
|
+
* @param {string} name - Nombre canónico o alias del comando.
|
|
860
|
+
* @returns {ICommand | undefined} El comando resuelto, o `undefined`.
|
|
279
861
|
*/
|
|
280
862
|
getCommand(name) {
|
|
281
863
|
let command = this.commands.get(name);
|
|
@@ -284,25 +866,38 @@ var CommandProcessor = class {
|
|
|
284
866
|
if (aliasTarget) return this.commands.get(aliasTarget);
|
|
285
867
|
}
|
|
286
868
|
/**
|
|
287
|
-
*
|
|
869
|
+
* Devuelve una copia del historial de comandos ejecutados (más recientes
|
|
870
|
+
* primero). Acotado a 100 entradas por {@link maxHistorySize}; las más
|
|
871
|
+
* viejas se descartan al insertar nuevas.
|
|
872
|
+
*
|
|
873
|
+
* @returns {HistoryEntry[]} Snapshot del historial; mutar el array devuelto
|
|
874
|
+
* no afecta al estado interno del processor.
|
|
288
875
|
*/
|
|
289
876
|
getHistory() {
|
|
290
877
|
return [...this.history];
|
|
291
878
|
}
|
|
292
879
|
/**
|
|
293
|
-
*
|
|
880
|
+
* Vacía el historial de comandos en memoria.
|
|
294
881
|
*/
|
|
295
882
|
clearHistory() {
|
|
296
883
|
this.history = [];
|
|
297
884
|
}
|
|
298
885
|
/**
|
|
299
|
-
*
|
|
886
|
+
* Lista los plugins actualmente registrados.
|
|
887
|
+
*
|
|
888
|
+
* @returns {ICLIPlugin[]} Snapshot array de plugins activos.
|
|
300
889
|
*/
|
|
301
890
|
getPlugins() {
|
|
302
891
|
return Array.from(this.plugins.values());
|
|
303
892
|
}
|
|
304
893
|
/**
|
|
305
|
-
*
|
|
894
|
+
* Activa el modo interactivo. Marca el flag interno y, si se ejecuta en
|
|
895
|
+
* navegador, expone `window.cli(command)` para invocar comandos desde la
|
|
896
|
+
* devtools sin prefijo `/` (se añade automáticamente al input).
|
|
897
|
+
*
|
|
898
|
+
* @param {Logger} logger - Logger activo (emite el mensaje de bienvenida
|
|
899
|
+
* con hint sobre `cli(...)` en browser).
|
|
900
|
+
* @see {@link exitInteractiveMode}
|
|
306
901
|
*/
|
|
307
902
|
enterInteractiveMode(logger) {
|
|
308
903
|
this.isInteractiveMode = true;
|
|
@@ -310,13 +905,22 @@ var CommandProcessor = class {
|
|
|
310
905
|
if (typeof window !== "undefined") this.setupBrowserInteractiveMode(logger);
|
|
311
906
|
}
|
|
312
907
|
/**
|
|
313
|
-
*
|
|
908
|
+
* Desactiva el flag de modo interactivo. Nota: no elimina el `window.cli`
|
|
909
|
+
* que {@link enterInteractiveMode} haya expuesto en el navegador — el
|
|
910
|
+
* handler global sigue vivo hasta reload.
|
|
911
|
+
*
|
|
912
|
+
* @see {@link enterInteractiveMode}
|
|
314
913
|
*/
|
|
315
914
|
exitInteractiveMode() {
|
|
316
915
|
this.isInteractiveMode = false;
|
|
317
916
|
}
|
|
318
917
|
/**
|
|
319
|
-
*
|
|
918
|
+
* Instala `window.cli(command)` como wrapper delgado alrededor de
|
|
919
|
+
* {@link processCommand}, prefijando `/` automáticamente. Solo se invoca
|
|
920
|
+
* desde {@link enterInteractiveMode} cuando `window` está disponible.
|
|
921
|
+
*
|
|
922
|
+
* @internal
|
|
923
|
+
* @param logger - Logger activo, reenviado a cada invocación.
|
|
320
924
|
*/
|
|
321
925
|
setupBrowserInteractiveMode(logger) {
|
|
322
926
|
window.cli = (commandString) => {
|
|
@@ -325,7 +929,20 @@ var CommandProcessor = class {
|
|
|
325
929
|
logger.info("💡 Use cli(\"command\") to execute CLI commands in browser console.");
|
|
326
930
|
}
|
|
327
931
|
/**
|
|
328
|
-
*
|
|
932
|
+
* Parsea y ejecuta un comando. El formato esperado es `/name args...`:
|
|
933
|
+
* split por espacios, primer token = nombre del comando, resto = args
|
|
934
|
+
* (re-joined con espacios). Si el comando no existe, loguea el error y
|
|
935
|
+
* sugiere similares vía {@link getSuggestions} ("Did you mean: ...?").
|
|
936
|
+
*
|
|
937
|
+
* Toda invocación (válida o no) se registra en el historial con flag de
|
|
938
|
+
* éxito/fallo según si `execute` resolvió o throweó.
|
|
939
|
+
*
|
|
940
|
+
* @param {string} commandString - Comando completo, debe empezar con `/`.
|
|
941
|
+
* @param {Logger} logger - Logger activo para output y errores.
|
|
942
|
+
* @returns {Promise<void>} Resuelve cuando el comando termina (sync o async).
|
|
943
|
+
* Nunca rechaza: los errores de `execute` se capturan y se loguean.
|
|
944
|
+
* @see {@link ICommand.execute}
|
|
945
|
+
* @see {@link getSuggestions}
|
|
329
946
|
*/
|
|
330
947
|
async processCommand(commandString, logger) {
|
|
331
948
|
if (!commandString.startsWith("/")) {
|
|
@@ -353,7 +970,12 @@ var CommandProcessor = class {
|
|
|
353
970
|
}
|
|
354
971
|
}
|
|
355
972
|
/**
|
|
356
|
-
*
|
|
973
|
+
* Inserta una entrada al frente del historial y trunca a
|
|
974
|
+
* {@link maxHistorySize} (100) si hace falta.
|
|
975
|
+
*
|
|
976
|
+
* @internal
|
|
977
|
+
* @param command - String crudo del comando ejecutado.
|
|
978
|
+
* @param success - Si la ejecución tuvo éxito.
|
|
357
979
|
*/
|
|
358
980
|
addToHistory(command, success) {
|
|
359
981
|
this.history.unshift({
|
|
@@ -364,7 +986,12 @@ var CommandProcessor = class {
|
|
|
364
986
|
if (this.history.length > this.maxHistorySize) this.history = this.history.slice(0, this.maxHistorySize);
|
|
365
987
|
}
|
|
366
988
|
/**
|
|
367
|
-
*
|
|
989
|
+
* Devuelve nombres de comando que empiezan con el prefijo dado. Alimente
|
|
990
|
+
* el hint "Did you mean" de {@link processCommand} cuando un comando no
|
|
991
|
+
* se encuentra. Match por `startsWith` (no fuzzy).
|
|
992
|
+
*
|
|
993
|
+
* @param {string} partial - Prefijo parcial tipeado por el usuario.
|
|
994
|
+
* @returns {string[]} Nombres canónicos que matchean; aliases excluidos.
|
|
368
995
|
*/
|
|
369
996
|
getSuggestions(partial) {
|
|
370
997
|
return Array.from(this.commands.keys()).filter((name) => name.startsWith(partial));
|
|
@@ -373,12 +1000,47 @@ var CommandProcessor = class {
|
|
|
373
1000
|
//#endregion
|
|
374
1001
|
//#region src/cli/commands/ConfigCommand.ts
|
|
375
1002
|
/**
|
|
376
|
-
*
|
|
1003
|
+
* Comando `/config` del CLI runtime del {@link Logger}. Inspecciona o muta
|
|
1004
|
+
* la configuración del logger en vivo desde la DevTools console.
|
|
1005
|
+
*
|
|
1006
|
+
* Acepta tres modos de invocación:
|
|
1007
|
+
* - Sin argumentos: vuelca el estado actual como tabla agrupada.
|
|
1008
|
+
* - JSON completo (empieza con `{`): aplica un objeto de configuración parcial.
|
|
1009
|
+
* - Pares `key=value` separados por coma: atajo para mutaciones puntuales.
|
|
1010
|
+
*
|
|
1011
|
+
* Solo se aplican las keys de la whitelist interna (`theme`, `verbosity`,
|
|
1012
|
+
* `enableColors`, `enableTimestamps`, `enableStackTrace`, `globalPrefix`,
|
|
1013
|
+
* `bannerType`); cualquier otra key se rechaza con un `warn` y se ignora.
|
|
1014
|
+
*
|
|
1015
|
+
* @example
|
|
1016
|
+
* // Sin argumentos: ver estado actual
|
|
1017
|
+
* // > /config
|
|
1018
|
+
*
|
|
1019
|
+
* @example
|
|
1020
|
+
* // Objeto JSON completo
|
|
1021
|
+
* // > /config {"theme":"neon","verbosity":"debug"}
|
|
1022
|
+
*
|
|
1023
|
+
* @example
|
|
1024
|
+
* // Atajo key=value (múltiples pares separados por coma)
|
|
1025
|
+
* // > /config theme=neon,verbosity=debug,globalPrefix=MiApp
|
|
1026
|
+
*
|
|
1027
|
+
* @see {@link ICommand} para el contrato que implementa este comando.
|
|
1028
|
+
* @see {@link Logger.setTheme}, {@link Logger.setVerbosity},
|
|
1029
|
+
* {@link Logger.setBannerType}, {@link Logger.setGlobalPrefix}
|
|
1030
|
+
* para los setters subyacentes.
|
|
377
1031
|
*/
|
|
378
1032
|
var ConfigCommand = class {
|
|
379
1033
|
name = "config";
|
|
380
1034
|
description = "Show or update logger configuration";
|
|
381
1035
|
usage = "/config [json|key=value,...]";
|
|
1036
|
+
/**
|
|
1037
|
+
* Ejecuta el comando `/config` contra el logger dado.
|
|
1038
|
+
*
|
|
1039
|
+
* @param args - Argumentos crudos del usuario. Vacío = status; con `{`
|
|
1040
|
+
* inicial = parse JSON; resto = pares `key=value` separados
|
|
1041
|
+
* por coma.
|
|
1042
|
+
* @param logger - Instancia destino cuyos setters se invocan.
|
|
1043
|
+
*/
|
|
382
1044
|
execute(args, logger) {
|
|
383
1045
|
if (!args) {
|
|
384
1046
|
this.showStatus(logger);
|
|
@@ -452,12 +1114,30 @@ var ConfigCommand = class {
|
|
|
452
1114
|
//#endregion
|
|
453
1115
|
//#region src/cli/commands/ThemeCommand.ts
|
|
454
1116
|
/**
|
|
455
|
-
*
|
|
1117
|
+
* Comando `/themes` del CLI runtime del {@link Logger}. Lista los presets
|
|
1118
|
+
* temáticos disponibles en {@link THEME_PRESETS}, renderizando una preview
|
|
1119
|
+
* con los colores reales de cada tema (background, foreground, border).
|
|
1120
|
+
*
|
|
1121
|
+
* Es de solo lectura: no muta el logger. Útil para descubrir qué tema
|
|
1122
|
+
* aplicar antes de correr `/config theme=<name>`.
|
|
1123
|
+
*
|
|
1124
|
+
* @example
|
|
1125
|
+
* // Listar todos los temas con preview coloreada
|
|
1126
|
+
* // > /themes
|
|
1127
|
+
*
|
|
1128
|
+
* @see {@link THEME_PRESETS} para el catálogo completo de temas.
|
|
1129
|
+
* @see {@link ConfigCommand} para aplicar un tema vía `/config theme=...`.
|
|
456
1130
|
*/
|
|
457
1131
|
var ThemesCommand = class {
|
|
458
1132
|
name = "themes";
|
|
459
1133
|
description = "Show available theme presets";
|
|
460
1134
|
usage = "/themes";
|
|
1135
|
+
/**
|
|
1136
|
+
* Ejecuta el comando `/themes` contra el logger dado.
|
|
1137
|
+
*
|
|
1138
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1139
|
+
* @param logger - Instancia usada para abrir/cerrar el `group` de salida.
|
|
1140
|
+
*/
|
|
461
1141
|
execute(_args, logger) {
|
|
462
1142
|
logger.group("🎨 Available Themes");
|
|
463
1143
|
Object.keys(require_styling.THEME_PRESETS).forEach((themeName) => {
|
|
@@ -469,12 +1149,30 @@ var ThemesCommand = class {
|
|
|
469
1149
|
}
|
|
470
1150
|
};
|
|
471
1151
|
/**
|
|
472
|
-
*
|
|
1152
|
+
* Comando `/banners` del CLI runtime del {@link Logger}. Enumera los tipos
|
|
1153
|
+
* de banner disponibles en {@link BANNER_VARIANTS} (`simple`, `ascii`,
|
|
1154
|
+
* `unicode`, ...) con una mini-preview de cada uno para inspección visual.
|
|
1155
|
+
*
|
|
1156
|
+
* Es de solo lectura: no muta el logger. Para cambiar el banner activo
|
|
1157
|
+
* usar {@link BannerCommand}.
|
|
1158
|
+
*
|
|
1159
|
+
* @example
|
|
1160
|
+
* // Listar todas las variantes de banner con preview
|
|
1161
|
+
* // > /banners
|
|
1162
|
+
*
|
|
1163
|
+
* @see {@link BANNER_VARIANTS} para el catálogo completo de variantes.
|
|
1164
|
+
* @see {@link BannerCommand} para aplicar un tipo concreto.
|
|
473
1165
|
*/
|
|
474
1166
|
var BannersCommand = class {
|
|
475
1167
|
name = "banners";
|
|
476
1168
|
description = "Show available banner types";
|
|
477
1169
|
usage = "/banners";
|
|
1170
|
+
/**
|
|
1171
|
+
* Ejecuta el comando `/banners` contra el logger dado.
|
|
1172
|
+
*
|
|
1173
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1174
|
+
* @param logger - Instancia usada para abrir/cerrar el `group` de salida.
|
|
1175
|
+
*/
|
|
478
1176
|
execute(_args, logger) {
|
|
479
1177
|
logger.group("🖼️ Available Banner Types");
|
|
480
1178
|
Object.keys(require_styling.BANNER_VARIANTS).forEach((bannerName) => {
|
|
@@ -490,12 +1188,35 @@ var BannersCommand = class {
|
|
|
490
1188
|
}
|
|
491
1189
|
};
|
|
492
1190
|
/**
|
|
493
|
-
*
|
|
1191
|
+
* Comando `/banner [type]` del CLI runtime del {@link Logger}.
|
|
1192
|
+
*
|
|
1193
|
+
* - Sin argumentos: re-renderiza el banner actualmente activo.
|
|
1194
|
+
* - Con un tipo válido: lo aplica vía {@link Logger.setBannerType} y lo
|
|
1195
|
+
* muestra inmediatamente.
|
|
1196
|
+
* - Con un tipo inválido: loguea un `error` listando las opciones válidas.
|
|
1197
|
+
*
|
|
1198
|
+
* @example
|
|
1199
|
+
* // Mostrar el banner actual
|
|
1200
|
+
* // > /banner
|
|
1201
|
+
*
|
|
1202
|
+
* @example
|
|
1203
|
+
* // Cambiar a un tipo concreto
|
|
1204
|
+
* // > /banner ascii
|
|
1205
|
+
*
|
|
1206
|
+
* @see {@link BANNER_VARIANTS} para los tipos aceptados.
|
|
1207
|
+
* @see {@link Logger.setBannerType} y {@link Logger.showBanner} para los
|
|
1208
|
+
* métodos subyacentes.
|
|
494
1209
|
*/
|
|
495
1210
|
var BannerCommand = class {
|
|
496
1211
|
name = "banner";
|
|
497
1212
|
description = "Change or show current banner type";
|
|
498
1213
|
usage = "/banner [type]";
|
|
1214
|
+
/**
|
|
1215
|
+
* Ejecuta el comando `/banner` contra el logger dado.
|
|
1216
|
+
*
|
|
1217
|
+
* @param args - Tipo de banner solicitado. Vacío = mostrar banner actual.
|
|
1218
|
+
* @param logger - Instancia destino cuyo banner se actualiza/muestra.
|
|
1219
|
+
*/
|
|
499
1220
|
execute(args, logger) {
|
|
500
1221
|
if (!args) {
|
|
501
1222
|
logger.showBanner();
|
|
@@ -510,12 +1231,27 @@ var BannerCommand = class {
|
|
|
510
1231
|
//#endregion
|
|
511
1232
|
//#region src/cli/commands/ExportCommand.ts
|
|
512
1233
|
/**
|
|
513
|
-
*
|
|
1234
|
+
* Comando `/status` del CLI runtime del {@link Logger}. Vuelca la
|
|
1235
|
+
* configuración vigente y algunas estadísticas (theme, verbosity, flags
|
|
1236
|
+
* de features, handler count, bufferSize) en una tabla agrupada dentro
|
|
1237
|
+
* de la consola. Es de solo lectura: no muta el logger.
|
|
1238
|
+
*
|
|
1239
|
+
* @example
|
|
1240
|
+
* // Inspeccionar el estado actual del logger
|
|
1241
|
+
* // > /status
|
|
1242
|
+
*
|
|
1243
|
+
* @see {@link Logger.getConfig} fuente de los datos mostrados.
|
|
514
1244
|
*/
|
|
515
1245
|
var StatusCommand = class {
|
|
516
1246
|
name = "status";
|
|
517
1247
|
description = "Show current logger status and configuration";
|
|
518
1248
|
usage = "/status";
|
|
1249
|
+
/**
|
|
1250
|
+
* Ejecuta el comando `/status` contra el logger dado.
|
|
1251
|
+
*
|
|
1252
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1253
|
+
* @param logger - Instancia de la que se lee la configuración.
|
|
1254
|
+
*/
|
|
519
1255
|
execute(_args, logger) {
|
|
520
1256
|
const config = logger.getConfig();
|
|
521
1257
|
const statusData = {
|
|
@@ -535,23 +1271,54 @@ var StatusCommand = class {
|
|
|
535
1271
|
}
|
|
536
1272
|
};
|
|
537
1273
|
/**
|
|
538
|
-
*
|
|
1274
|
+
* Comando `/reset` del CLI runtime del {@link Logger}. Restaura la
|
|
1275
|
+
* configuración a sus defaults de fábrica vía {@link Logger.resetConfig}.
|
|
1276
|
+
* No resetea handlers ni transports registrados — solo config.
|
|
1277
|
+
*
|
|
1278
|
+
* @example
|
|
1279
|
+
* // Volver a la configuración por defecto
|
|
1280
|
+
* // > /reset
|
|
1281
|
+
*
|
|
1282
|
+
* @see {@link Logger.resetConfig} para el método subyacente.
|
|
539
1283
|
*/
|
|
540
1284
|
var ResetCommand = class {
|
|
541
1285
|
name = "reset";
|
|
542
1286
|
description = "Reset logger configuration to defaults";
|
|
543
1287
|
usage = "/reset";
|
|
1288
|
+
/**
|
|
1289
|
+
* Ejecuta el comando `/reset` contra el logger dado.
|
|
1290
|
+
*
|
|
1291
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1292
|
+
* @param logger - Instancia cuya configuración se resetea.
|
|
1293
|
+
*/
|
|
544
1294
|
execute(_args, logger) {
|
|
545
1295
|
logger.resetConfig();
|
|
546
1296
|
}
|
|
547
1297
|
};
|
|
548
1298
|
/**
|
|
549
|
-
*
|
|
1299
|
+
* Comando `/demo` del CLI runtime del {@link Logger}. Ejecuta una
|
|
1300
|
+
* demostración integral de las capacidades del logger: todos los niveles
|
|
1301
|
+
* de log (debug → critical), tablas, timers (`time`/`timeEnd`), SVG inline
|
|
1302
|
+
* y mensajes animados. Útil para validar que el styling funciona en un
|
|
1303
|
+
* entorno nuevo o tras un cambio de tema.
|
|
1304
|
+
*
|
|
1305
|
+
* @example
|
|
1306
|
+
* // Lanzar la demo completa
|
|
1307
|
+
* // > /demo
|
|
1308
|
+
*
|
|
1309
|
+
* @see {@link Logger} para cada feature individual (`table`, `time`,
|
|
1310
|
+
* `logWithSVG`, `logAnimated`, ...).
|
|
550
1311
|
*/
|
|
551
1312
|
var DemoCommand = class {
|
|
552
1313
|
name = "demo";
|
|
553
1314
|
description = "Show comprehensive feature demonstration";
|
|
554
1315
|
usage = "/demo";
|
|
1316
|
+
/**
|
|
1317
|
+
* Ejecuta el comando `/demo` contra el logger dado.
|
|
1318
|
+
*
|
|
1319
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1320
|
+
* @param logger - Instancia sobre la que se ejecutan los ejemplos.
|
|
1321
|
+
*/
|
|
555
1322
|
execute(_args, logger) {
|
|
556
1323
|
logger.group("🎪 Advanced Logger Demo");
|
|
557
1324
|
logger.debug("Debug message with detailed information");
|
|
@@ -597,12 +1364,38 @@ var DemoCommand = class {
|
|
|
597
1364
|
//#endregion
|
|
598
1365
|
//#region src/cli/help.ts
|
|
599
1366
|
/**
|
|
600
|
-
*
|
|
1367
|
+
* Comando `/help`: renderiza en consola el panel de ayuda del CLI con todos
|
|
1368
|
+
* los comandos disponibles, opciones de configuración, filtros de export y
|
|
1369
|
+
* ejemplos. El panel usa un gradient claro con {@link StyleBuilder} y los
|
|
1370
|
+
* quick tips se agrupan vía `logger.group`.
|
|
1371
|
+
*
|
|
1372
|
+
* Registrado por defecto por {@link createDefaultCLI}.
|
|
1373
|
+
*
|
|
1374
|
+
* @example
|
|
1375
|
+
* ```ts
|
|
1376
|
+
* const cli = createDefaultCLI();
|
|
1377
|
+
* await cli.processCommand('/help', logger);
|
|
1378
|
+
* // Imprime el panel ASCII con gradient + grupo "Quick Tips".
|
|
1379
|
+
* ```
|
|
1380
|
+
*
|
|
1381
|
+
* @see {@link ICommand}
|
|
1382
|
+
* @see {@link createDefaultCLI}
|
|
601
1383
|
*/
|
|
602
1384
|
var HelpCommand = class {
|
|
603
1385
|
name = "help";
|
|
604
1386
|
description = "Show CLI help and available commands";
|
|
605
1387
|
usage = "/help [command]";
|
|
1388
|
+
/**
|
|
1389
|
+
* Renderiza el panel de ayuda completo. Actualmente ignora `_args`: el
|
|
1390
|
+
* `usage` declara `/help [command]` (sub-comando opcional) pero la
|
|
1391
|
+
* implementación siempre muestra el panel global.
|
|
1392
|
+
*
|
|
1393
|
+
* @param {string} _args - Argumentos opcionales (reservado para ayuda por
|
|
1394
|
+
* sub-comando; sin uso actual).
|
|
1395
|
+
* @param {Logger} logger - Logger activo; se usa solo para `group`/`info`
|
|
1396
|
+
* de los quick tips.
|
|
1397
|
+
* @returns {void}
|
|
1398
|
+
*/
|
|
606
1399
|
execute(_args, logger) {
|
|
607
1400
|
const helpStyle = new require_styling.StyleBuilder().bg("linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%)").color("#495057").padding("15px 20px").rounded("8px").border("1px solid #dee2e6").font("Monaco, Consolas, monospace").size("13px").build();
|
|
608
1401
|
console.log(`%c
|
|
@@ -702,7 +1495,30 @@ var HelpCommand = class {
|
|
|
702
1495
|
//#endregion
|
|
703
1496
|
//#region src/cli/index.ts
|
|
704
1497
|
/**
|
|
705
|
-
*
|
|
1498
|
+
* Crea un {@link CommandProcessor} con los 8 comandos estándar ya registrados:
|
|
1499
|
+
* `help`, `config`, `themes`, `banners`, `banner`, `status`, `reset` y
|
|
1500
|
+
* `demo`. Es el factory canónico — los consumidores normalmente no construyen
|
|
1501
|
+
* un `CommandProcessor` vacío a mano, ya que este no trae comandos cargados.
|
|
1502
|
+
*
|
|
1503
|
+
* @returns {CommandProcessor} Processor listo para usar, sin modo interactivo activo.
|
|
1504
|
+
*
|
|
1505
|
+
* @example
|
|
1506
|
+
* ```ts
|
|
1507
|
+
* const cli = createDefaultCLI();
|
|
1508
|
+
* await cli.processCommand('/help', logger);
|
|
1509
|
+
* await cli.processCommand('/config theme=neon', logger);
|
|
1510
|
+
* ```
|
|
1511
|
+
*
|
|
1512
|
+
* @example
|
|
1513
|
+
* ```ts
|
|
1514
|
+
* // Modo interactivo en el navegador: expone `window.cli`
|
|
1515
|
+
* const cli = createDefaultCLI();
|
|
1516
|
+
* cli.enterInteractiveMode(logger);
|
|
1517
|
+
* // desde devtools: cli('themes') → procesa '/themes'
|
|
1518
|
+
* ```
|
|
1519
|
+
*
|
|
1520
|
+
* @see {@link CommandProcessor}
|
|
1521
|
+
* @see {@link HelpCommand}
|
|
706
1522
|
*/
|
|
707
1523
|
function createDefaultCLI() {
|
|
708
1524
|
const processor = new CommandProcessor();
|
|
@@ -719,7 +1535,9 @@ function createDefaultCLI() {
|
|
|
719
1535
|
//#endregion
|
|
720
1536
|
//#region src/transports/TransportBridge.ts
|
|
721
1537
|
/**
|
|
722
|
-
*
|
|
1538
|
+
* Crea una instancia de {@link TransportBridge}.
|
|
1539
|
+
*
|
|
1540
|
+
* @internal
|
|
723
1541
|
*/
|
|
724
1542
|
function createTransportBridge() {
|
|
725
1543
|
let transportManager;
|
|
@@ -747,9 +1565,170 @@ function createTransportBridge() {
|
|
|
747
1565
|
};
|
|
748
1566
|
}
|
|
749
1567
|
//#endregion
|
|
1568
|
+
//#region src/transports/SpanRuntime.ts
|
|
1569
|
+
/** ALS singleton del módulo — compartido por todas las instancias de Logger.
|
|
1570
|
+
*
|
|
1571
|
+
* Resolución por capas (global → `process.getBuiltinModule` → `require`,
|
|
1572
|
+
* undefined en browser) delegada al helper compartido
|
|
1573
|
+
* {@link resolveAsyncLocalStorage} — ver su doc para el detalle de capas.
|
|
1574
|
+
* `context/LogContext.ts` usa el mismo helper para su ALS de MDC. */
|
|
1575
|
+
const activeSpanStore = require_LogContext.resolveAsyncLocalStorage();
|
|
1576
|
+
/**
|
|
1577
|
+
* Span activo en el call stack corriente (dentro de `span(fn)`), si lo hay.
|
|
1578
|
+
* Lo consumen la correlación log→span (`TransportRecord.traceId/spanId`) y la
|
|
1579
|
+
* resolución de `parentSpanId` en spans hijos.
|
|
1580
|
+
*/
|
|
1581
|
+
function getActiveSpan() {
|
|
1582
|
+
return activeSpanStore?.getStore();
|
|
1583
|
+
}
|
|
1584
|
+
/**
|
|
1585
|
+
* Ejecuta `fn` con `record` como span activo. Sin ALS disponible (browser),
|
|
1586
|
+
* ejecuta `fn` directamente — sin correlación pero funcional.
|
|
1587
|
+
*/
|
|
1588
|
+
function runWithActiveSpan(record, fn) {
|
|
1589
|
+
return activeSpanStore ? activeSpanStore.run(record, fn) : fn();
|
|
1590
|
+
}
|
|
1591
|
+
/** Nanosegundos Unix actuales como string decimal (formato OTLP). */
|
|
1592
|
+
function nowUnixNano() {
|
|
1593
|
+
return String(BigInt(Date.now()) * 1000000n);
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Hex aleatorio de `bytes` bytes. Usa `crypto.getRandomValues`; sin
|
|
1597
|
+
* `crypto` (runtimes exóticos) degrada a `Math.random` — suficiente para ids
|
|
1598
|
+
* de correlación, no para secrets.
|
|
1599
|
+
*/
|
|
1600
|
+
function randomHex(bytes) {
|
|
1601
|
+
const cryptoObj = globalThis.crypto;
|
|
1602
|
+
if (cryptoObj?.getRandomValues) {
|
|
1603
|
+
const buf = new Uint8Array(bytes);
|
|
1604
|
+
cryptoObj.getRandomValues(buf);
|
|
1605
|
+
let out = "";
|
|
1606
|
+
for (const b of buf) out += b.toString(16).padStart(2, "0");
|
|
1607
|
+
return out;
|
|
1608
|
+
}
|
|
1609
|
+
let out = "";
|
|
1610
|
+
for (let i = 0; i < bytes * 2; i++) out += Math.floor(Math.random() * 16).toString(16);
|
|
1611
|
+
return out;
|
|
1612
|
+
}
|
|
1613
|
+
/** Trace id W3C: 16 bytes → 32 chars hex. */
|
|
1614
|
+
function generateTraceId() {
|
|
1615
|
+
return randomHex(16);
|
|
1616
|
+
}
|
|
1617
|
+
/** Span id W3C: 8 bytes → 16 chars hex. */
|
|
1618
|
+
function generateSpanId() {
|
|
1619
|
+
return randomHex(8);
|
|
1620
|
+
}
|
|
1621
|
+
/**
|
|
1622
|
+
* Registry de spans abiertos (leak-safety). Cubre tanto los de `startSpan()`
|
|
1623
|
+
* (externally-ended, el caso del handoff) como los de `span(fn)` en curso:
|
|
1624
|
+
* si un flush llega mid-flight, es mejor exportar el span incompleto que
|
|
1625
|
+
* tirarlo. El doble-`end()` es no-op, así que el cierre natural posterior no
|
|
1626
|
+
* duplica el export.
|
|
1627
|
+
*/
|
|
1628
|
+
const openSpans = /* @__PURE__ */ new Map();
|
|
1629
|
+
/**
|
|
1630
|
+
* Crea el record de span y su {@link Span} handle. El handle registra el
|
|
1631
|
+
* span en el registry de abiertos; `onEnd` se invoca una única vez, con el
|
|
1632
|
+
* record final (duración real o `incomplete: true`), para su export al
|
|
1633
|
+
* pipeline de transports.
|
|
1634
|
+
*
|
|
1635
|
+
* `end()` solo fija `endTimeUnixNano` si no se fijó antes — así los
|
|
1636
|
+
* point-spans (`event()`) pueden fijar `end = start` exacto.
|
|
1637
|
+
*
|
|
1638
|
+
* @param name - Nombre de la operación.
|
|
1639
|
+
* @param attributes - Attributes iniciales (copia propia del record).
|
|
1640
|
+
* @param scope - Scope del logger emisor.
|
|
1641
|
+
* @param onEnd - Callback de export; recibe el record cerrado.
|
|
1642
|
+
* @returns El record (para el ALS store) y el handle del span.
|
|
1643
|
+
*/
|
|
1644
|
+
function createSpan(name, attributes, scope, onEnd) {
|
|
1645
|
+
const parent = getActiveSpan();
|
|
1646
|
+
const record = {
|
|
1647
|
+
kind: "span",
|
|
1648
|
+
traceId: parent?.traceId ?? generateTraceId(),
|
|
1649
|
+
spanId: generateSpanId(),
|
|
1650
|
+
parentSpanId: parent?.spanId,
|
|
1651
|
+
name,
|
|
1652
|
+
spanKind: 1,
|
|
1653
|
+
startTimeUnixNano: nowUnixNano(),
|
|
1654
|
+
endTimeUnixNano: "0",
|
|
1655
|
+
attributes: { ...attributes ?? {} },
|
|
1656
|
+
scope
|
|
1657
|
+
};
|
|
1658
|
+
let ended = false;
|
|
1659
|
+
const finish = () => {
|
|
1660
|
+
if (ended) return;
|
|
1661
|
+
ended = true;
|
|
1662
|
+
openSpans.delete(record);
|
|
1663
|
+
onEnd(record);
|
|
1664
|
+
};
|
|
1665
|
+
openSpans.set(record, {
|
|
1666
|
+
record,
|
|
1667
|
+
end: finish,
|
|
1668
|
+
forceEnd: () => {
|
|
1669
|
+
if (ended) return;
|
|
1670
|
+
record.incomplete = true;
|
|
1671
|
+
if (record.endTimeUnixNano === "0") record.endTimeUnixNano = nowUnixNano();
|
|
1672
|
+
finish();
|
|
1673
|
+
}
|
|
1674
|
+
});
|
|
1675
|
+
const handle = {
|
|
1676
|
+
traceId: record.traceId,
|
|
1677
|
+
spanId: record.spanId,
|
|
1678
|
+
set(key, value) {
|
|
1679
|
+
record.attributes[key] = value;
|
|
1680
|
+
return handle;
|
|
1681
|
+
},
|
|
1682
|
+
end(attributes) {
|
|
1683
|
+
if (attributes) Object.assign(record.attributes, attributes);
|
|
1684
|
+
if (ended) return;
|
|
1685
|
+
if (record.endTimeUnixNano === "0") record.endTimeUnixNano = nowUnixNano();
|
|
1686
|
+
finish();
|
|
1687
|
+
},
|
|
1688
|
+
fail(err) {
|
|
1689
|
+
if (ended) return;
|
|
1690
|
+
record.status = {
|
|
1691
|
+
code: 2,
|
|
1692
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1693
|
+
};
|
|
1694
|
+
this.end();
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
return {
|
|
1698
|
+
record,
|
|
1699
|
+
span: handle
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Emite un point-span (`event()`): start = end exactamente, sin registro en
|
|
1704
|
+
* abiertos tras el cierre — no hay leak posible. El `parentSpanId` se resuelve
|
|
1705
|
+
* contra el span activo si existe, pero NO fija contexto ALS.
|
|
1706
|
+
*/
|
|
1707
|
+
function emitEventSpan(name, attributes, scope, onEnd) {
|
|
1708
|
+
const { record, span } = createSpan(name, attributes, scope, onEnd);
|
|
1709
|
+
record.endTimeUnixNano = record.startTimeUnixNano;
|
|
1710
|
+
span.end();
|
|
1711
|
+
}
|
|
1712
|
+
/**
|
|
1713
|
+
* Fuerza el cierre de todos los spans abiertos (`incomplete: true`) y los
|
|
1714
|
+
* exporta vía el `onEnd` de cada uno. Lo invocan `flushTransports()` /
|
|
1715
|
+
* `closeTransports()` / `cleanup()` ANTES del flush real — un span abierto
|
|
1716
|
+
* nunca se tira en shutdown.
|
|
1717
|
+
*
|
|
1718
|
+
* @returns Los records forzados a cerrar (para diagnóstico/tests).
|
|
1719
|
+
*/
|
|
1720
|
+
function forceCloseOpenSpans() {
|
|
1721
|
+
const snapshot = [...openSpans.values()];
|
|
1722
|
+
for (const entry of snapshot) entry.forceEnd();
|
|
1723
|
+
return snapshot.map((entry) => entry.record);
|
|
1724
|
+
}
|
|
1725
|
+
//#endregion
|
|
750
1726
|
//#region src/playground/TerminalBridge.ts
|
|
751
1727
|
/**
|
|
752
|
-
*
|
|
1728
|
+
* Crea un {@link TerminalBridge} usando un getter para evitar referencias
|
|
1729
|
+
* circulares en la construcción.
|
|
1730
|
+
*
|
|
1731
|
+
* @internal
|
|
753
1732
|
*/
|
|
754
1733
|
function createTerminalBridge(options) {
|
|
755
1734
|
let _showPrimitives = true;
|
|
@@ -874,37 +1853,38 @@ var Logger = class Logger {
|
|
|
874
1853
|
hookBridge;
|
|
875
1854
|
logContext;
|
|
876
1855
|
transportBridge;
|
|
877
|
-
/**
|
|
1856
|
+
/** Fijado por `success()` para que `log()` salte su propio dispatch. */
|
|
878
1857
|
_successTagDispatched = false;
|
|
879
1858
|
styleManager;
|
|
880
|
-
/**
|
|
1859
|
+
/** Controla si las CLI primitives (step, box, header, ...) deben renderizarse. */
|
|
881
1860
|
_showPrimitives = true;
|
|
882
1861
|
terminalBridge;
|
|
883
1862
|
/**
|
|
884
|
-
*
|
|
885
|
-
*
|
|
1863
|
+
* Referencia activa al smart-preset (fijada por `preset()`). Tipada como
|
|
1864
|
+
* `unknown` para mantener limpia la surface pública; la consume
|
|
1865
|
+
* `createStyledOutput`.
|
|
886
1866
|
*/
|
|
887
1867
|
_activePreset;
|
|
888
1868
|
/**
|
|
889
|
-
*
|
|
890
|
-
*
|
|
1869
|
+
* Nombre del smart-preset activo. Se guarda aparte para que la detección
|
|
1870
|
+
* de cambio de tema pueda re-renderizar sin re-ejecutar el body del preset.
|
|
891
1871
|
*/
|
|
892
1872
|
_activePresetName;
|
|
893
1873
|
/**
|
|
894
|
-
*
|
|
895
|
-
* `createStyledOutput
|
|
1874
|
+
* Overrides aplicados por el último `customize()`. Se conservan para que
|
|
1875
|
+
* `createStyledOutput` los lea después.
|
|
896
1876
|
*/
|
|
897
1877
|
_customization;
|
|
898
1878
|
/**
|
|
899
|
-
*
|
|
900
|
-
*
|
|
1879
|
+
* Bindings propios de este logger (provenientes de llamadas a `child()`).
|
|
1880
|
+
* Source of truth única de la contribución de este logger a la cadena de contexto.
|
|
901
1881
|
* @private
|
|
902
1882
|
*/
|
|
903
1883
|
_bindings = {};
|
|
904
1884
|
/**
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
*
|
|
1885
|
+
* Referencia al record de contexto mergueado del parent en el momento en
|
|
1886
|
+
* que se creó este logger. Junto con `_bindings`, forma la cadena de
|
|
1887
|
+
* contexto. `undefined` para el logger raíz.
|
|
908
1888
|
* @private
|
|
909
1889
|
*/
|
|
910
1890
|
_parentContextRecord;
|
|
@@ -1072,65 +2052,66 @@ var Logger = class Logger {
|
|
|
1072
2052
|
this.success(`Banner type changed to: ${bannerType}`);
|
|
1073
2053
|
}
|
|
1074
2054
|
/**
|
|
1075
|
-
*
|
|
1076
|
-
*
|
|
2055
|
+
* Ejecuta `fn` dentro de un scope AsyncLocalStorage donde `bindings` se
|
|
2056
|
+
* merguean al contexto para todas las llamadas de log dentro de `fn`.
|
|
1077
2057
|
*
|
|
1078
|
-
*
|
|
1079
|
-
*
|
|
1080
|
-
*
|
|
2058
|
+
* Sin `fn` (el shape legacy de setter): no-op por backwards compatibility.
|
|
2059
|
+
* Preferir `child()` para bindings persistentes o `withContextAsync()`
|
|
2060
|
+
* para callbacks async.
|
|
1081
2061
|
*
|
|
1082
|
-
* @param bindings -
|
|
1083
|
-
* @param fn -
|
|
1084
|
-
* @returns
|
|
2062
|
+
* @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
|
|
2063
|
+
* @param fn - Función sincrónica opcional a ejecutar con los bindings en scope
|
|
2064
|
+
* @returns El valor de retorno de `fn`, o `undefined` si no se pasa `fn`
|
|
1085
2065
|
*
|
|
1086
2066
|
* @example
|
|
1087
|
-
* //
|
|
2067
|
+
* // Callback sincrónico scoped
|
|
1088
2068
|
* logger.withContext({ requestId: 'r-42' }, () => {
|
|
1089
|
-
* doWork(); // logs
|
|
2069
|
+
* doWork(); // los logs de aquí ven requestId en attributes
|
|
1090
2070
|
* });
|
|
1091
2071
|
*
|
|
1092
2072
|
* @example
|
|
1093
|
-
* //
|
|
2073
|
+
* // Binding persistente: usar child()
|
|
1094
2074
|
* const reqLog = logger.child({ requestId: 'r-42' });
|
|
1095
|
-
* reqLog.info('handling request'); // attributes
|
|
2075
|
+
* reqLog.info('handling request'); // attributes incluye requestId
|
|
1096
2076
|
*
|
|
1097
|
-
* @see {@link child}
|
|
1098
|
-
* @see {@link withContextAsync}
|
|
2077
|
+
* @see {@link child} para una copia inmutable con el contexto mergueado
|
|
2078
|
+
* @see {@link withContextAsync} para la variante con callback async
|
|
1099
2079
|
*/
|
|
1100
2080
|
withContext(bindings, fn) {
|
|
1101
2081
|
return this.logContext.withContext(bindings, fn);
|
|
1102
2082
|
}
|
|
1103
2083
|
/**
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
2084
|
+
* Variante async de `withContext`. Ejecuta `fn` dentro de un scope
|
|
2085
|
+
* AsyncLocalStorage para que los bindings estén disponibles a todas las
|
|
2086
|
+
* llamadas de log async dentro de `fn`.
|
|
1106
2087
|
*
|
|
1107
|
-
* @param bindings -
|
|
1108
|
-
* @param fn -
|
|
1109
|
-
* @returns
|
|
2088
|
+
* @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
|
|
2089
|
+
* @param fn - Función async a ejecutar con los bindings en scope
|
|
2090
|
+
* @returns El valor de retorno de `fn`
|
|
1110
2091
|
*
|
|
1111
2092
|
* @example
|
|
1112
2093
|
* await logger.withContextAsync({ requestId: 'r-42' }, async () => {
|
|
1113
|
-
* await fetchData(); // logs
|
|
2094
|
+
* await fetchData(); // los logs de aquí ven requestId en attributes
|
|
1114
2095
|
* });
|
|
1115
2096
|
*
|
|
1116
|
-
* @see {@link child}
|
|
1117
|
-
* @see {@link withContext}
|
|
2097
|
+
* @see {@link child} para un child logger persistente
|
|
2098
|
+
* @see {@link withContext} para la variante con callback sincrónico
|
|
1118
2099
|
*/
|
|
1119
2100
|
withContextAsync(bindings, fn) {
|
|
1120
2101
|
return this.logContext.withContextAsync(bindings, fn);
|
|
1121
2102
|
}
|
|
1122
2103
|
/**
|
|
1123
|
-
*
|
|
1124
|
-
*
|
|
1125
|
-
*
|
|
2104
|
+
* Devuelve una copia inmutable de este logger con el contexto extra bound.
|
|
2105
|
+
* Las llamadas futuras sobre el child emiten con el contexto mergueado,
|
|
2106
|
+
* sin mutar al parent — el patrón canónico de MDC.
|
|
1126
2107
|
*
|
|
1127
|
-
* @param extra -
|
|
1128
|
-
* @returns
|
|
2108
|
+
* @param extra - Pares key-value a adjuntar (requestId, userId, ...)
|
|
2109
|
+
* @returns Un nuevo Logger con el contexto mergueado
|
|
1129
2110
|
*
|
|
1130
2111
|
* @example
|
|
1131
2112
|
* const reqLog = logger.child({ requestId: req.id });
|
|
1132
|
-
* reqLog.info('start'); //
|
|
1133
|
-
* logger.info('unrelated'); //
|
|
2113
|
+
* reqLog.info('start'); // emite attributes: { requestId }
|
|
2114
|
+
* logger.info('unrelated'); // NO afectado — el contexto del parent queda intacto
|
|
1134
2115
|
*
|
|
1135
2116
|
*/
|
|
1136
2117
|
child(extra) {
|
|
@@ -1140,21 +2121,21 @@ var Logger = class Logger {
|
|
|
1140
2121
|
return childLogger;
|
|
1141
2122
|
}
|
|
1142
2123
|
/**
|
|
1143
|
-
*
|
|
1144
|
-
* records
|
|
1145
|
-
* {@link child}
|
|
2124
|
+
* Descarta todas las keys del contexto bound. Tras esta llamada, los
|
|
2125
|
+
* records emitidos dejan de llevar `attributes` hasta que
|
|
2126
|
+
* {@link withContext} o {@link child} restablezcan uno.
|
|
1146
2127
|
*
|
|
1147
|
-
* @returns
|
|
2128
|
+
* @returns La misma instancia del logger, ahora sin contexto
|
|
1148
2129
|
*/
|
|
1149
2130
|
clearContext() {
|
|
1150
2131
|
this.logContext.clearContext();
|
|
1151
2132
|
return this;
|
|
1152
2133
|
}
|
|
1153
2134
|
/**
|
|
1154
|
-
* Snapshot
|
|
1155
|
-
*
|
|
2135
|
+
* Snapshot del contexto bound. El objeto devuelto es una shallow copy:
|
|
2136
|
+
* mutarlo NO afecta lo que emiten las llamadas de log posteriores.
|
|
1156
2137
|
*
|
|
1157
|
-
* @returns
|
|
2138
|
+
* @returns Un snapshot read-only del contexto actual
|
|
1158
2139
|
*/
|
|
1159
2140
|
getContext() {
|
|
1160
2141
|
let merged = this._parentContextRecord ?? {};
|
|
@@ -1165,12 +2146,12 @@ var Logger = class Logger {
|
|
|
1165
2146
|
return merged;
|
|
1166
2147
|
}
|
|
1167
2148
|
/**
|
|
1168
|
-
*
|
|
1169
|
-
*
|
|
1170
|
-
* record
|
|
2149
|
+
* Actualiza el resource OTel por defecto (service.name, version, env).
|
|
2150
|
+
* Se persiste en el campo `resource` de cada record emitido, salvo que
|
|
2151
|
+
* el propio record lo override.
|
|
1171
2152
|
*
|
|
1172
|
-
* @param resource -
|
|
1173
|
-
* @returns
|
|
2153
|
+
* @param resource - Resource OTel parcial a merguear con el actual
|
|
2154
|
+
* @returns La misma instancia del logger, para chaining
|
|
1174
2155
|
*
|
|
1175
2156
|
* @example
|
|
1176
2157
|
* logger.setResource({ 'service.name': 'api', 'service.version': '1.2.3' });
|
|
@@ -1199,20 +2180,15 @@ var Logger = class Logger {
|
|
|
1199
2180
|
this.success("Logger configuration reset to defaults");
|
|
1200
2181
|
}
|
|
1201
2182
|
/**
|
|
1202
|
-
* Método de limpieza para eliminar listeners y liberar recursos
|
|
1203
|
-
*
|
|
1204
|
-
*
|
|
1205
|
-
*
|
|
1206
|
-
*
|
|
1207
|
-
*
|
|
1208
|
-
*/
|
|
1209
|
-
/**
|
|
1210
|
-
* Tears down every resource held by this Logger. Safe to call multiple
|
|
1211
|
-
* times. Fixed in 5.1.0 to fully drain transports + clear timers +
|
|
1212
|
-
* drop the legacy handler list + reset group depth + clear context.
|
|
2183
|
+
* Método de limpieza para eliminar listeners y liberar recursos.
|
|
2184
|
+
*
|
|
2185
|
+
* Vacía los transports (drain), limpia timers, suelta la lista de
|
|
2186
|
+
* handlers legacy, resetea el group depth y limpia el context.
|
|
2187
|
+
* Seguro de invocar múltiples veces.
|
|
1213
2188
|
*
|
|
1214
2189
|
* @example
|
|
1215
|
-
*
|
|
2190
|
+
* // Antes de cerrar la aplicación
|
|
2191
|
+
* await logger.cleanup();
|
|
1216
2192
|
*
|
|
1217
2193
|
*/
|
|
1218
2194
|
async cleanup() {
|
|
@@ -1222,6 +2198,7 @@ var Logger = class Logger {
|
|
|
1222
2198
|
} catch {}
|
|
1223
2199
|
this.themeChangeListener = null;
|
|
1224
2200
|
}
|
|
2201
|
+
forceCloseOpenSpans();
|
|
1225
2202
|
await this.transportBridge.closeTransports();
|
|
1226
2203
|
this.handlers.length = 0;
|
|
1227
2204
|
this.timers.clear();
|
|
@@ -1241,7 +2218,7 @@ var Logger = class Logger {
|
|
|
1241
2218
|
* logger.preset('glassmorphism'); // Efectos de blur modernos
|
|
1242
2219
|
* logger.preset('minimal'); // Minimalista y elegante
|
|
1243
2220
|
* logger.preset('debug'); // Modo desarrollo detallado
|
|
1244
|
-
* logger.preset('production'); //
|
|
2221
|
+
* logger.preset('production'); // Enfocado en producción
|
|
1245
2222
|
*
|
|
1246
2223
|
*/
|
|
1247
2224
|
preset(name) {
|
|
@@ -1387,12 +2364,63 @@ var Logger = class Logger {
|
|
|
1387
2364
|
this.badgeList = [];
|
|
1388
2365
|
return this;
|
|
1389
2366
|
}
|
|
2367
|
+
/**
|
|
2368
|
+
* Crea un logger scoped para un componente o módulo del dominio.
|
|
2369
|
+
*
|
|
2370
|
+
* El `ComponentLogger` resultante prepends un badge `[name]` a cada
|
|
2371
|
+
* mensaje y comparte configuración, transports y hooks con el logger
|
|
2372
|
+
* padre. Útil para trazar el origen de los logs en apps con muchos
|
|
2373
|
+
* módulos (Auth, DB, Cache, ...).
|
|
2374
|
+
*
|
|
2375
|
+
* @param {string} name - Nombre del componente que aparecerá como badge
|
|
2376
|
+
* @returns {ComponentLogger} Logger scoped para el componente
|
|
2377
|
+
*
|
|
2378
|
+
* @example
|
|
2379
|
+
* const auth = logger.component('Auth');
|
|
2380
|
+
* auth.info('Validando token'); // [Auth] Validando token
|
|
2381
|
+
* auth.success('Token válido');
|
|
2382
|
+
*
|
|
2383
|
+
* @see {@link api} para loggers de endpoints REST/GraphQL
|
|
2384
|
+
* @see {@link scope} para un scope genérico sin badge de componente
|
|
2385
|
+
*/
|
|
1390
2386
|
component(name) {
|
|
1391
2387
|
return new ComponentLogger(this, name);
|
|
1392
2388
|
}
|
|
2389
|
+
/**
|
|
2390
|
+
* Crea un logger scoped para un endpoint o surface de API.
|
|
2391
|
+
*
|
|
2392
|
+
* Como `component()` pero con styling orientado a APIs (badge `[API]`
|
|
2393
|
+
* por defecto más el nombre del sub-scope). Útil para distinguir
|
|
2394
|
+
* tráfico REST vs GraphQL vs WebSocket en los logs.
|
|
2395
|
+
*
|
|
2396
|
+
* @param {string} name - Nombre de la API o surface (p.ej. `'REST'`, `'GraphQL'`)
|
|
2397
|
+
* @returns {APILogger} Logger scoped para la API
|
|
2398
|
+
*
|
|
2399
|
+
* @example
|
|
2400
|
+
* const rest = logger.api('REST');
|
|
2401
|
+
* rest.info('GET /users/42'); // [API] [REST] GET /users/42
|
|
2402
|
+
*
|
|
2403
|
+
* @see {@link component} para loggers de componentes de dominio
|
|
2404
|
+
*/
|
|
1393
2405
|
api(name) {
|
|
1394
2406
|
return new APILogger(this, name);
|
|
1395
2407
|
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Crea un logger scoped genérico con un prefijo.
|
|
2410
|
+
*
|
|
2411
|
+
* Variante minimal de `component()` / `api()`: solo aplica un prefijo
|
|
2412
|
+
* de scope sin badges ni styling especial. Útil para sub-módulos que
|
|
2413
|
+
* no encajan en las categorías de `component`/`api`.
|
|
2414
|
+
*
|
|
2415
|
+
* @param {string} name - Texto del prefijo de scope
|
|
2416
|
+
* @returns {ScopedLogger} Logger con el scope aplicado
|
|
2417
|
+
*
|
|
2418
|
+
* @example
|
|
2419
|
+
* const db = logger.scope('db');
|
|
2420
|
+
* db.info('Pool conectado'); // [db] Pool conectado
|
|
2421
|
+
*
|
|
2422
|
+
* @see {@link component} y {@link api} para variantes con badges
|
|
2423
|
+
*/
|
|
1396
2424
|
scope(name) {
|
|
1397
2425
|
return new ScopedLogger(this, name);
|
|
1398
2426
|
}
|
|
@@ -1593,21 +2621,27 @@ var Logger = class Logger {
|
|
|
1593
2621
|
return this.transportBridge.removeTransport(id);
|
|
1594
2622
|
}
|
|
1595
2623
|
/**
|
|
1596
|
-
* Fuerza el flush de todos los transports
|
|
2624
|
+
* Fuerza el flush de todos los transports. Antes de flushear, cierra los
|
|
2625
|
+
* spans aún abiertos (`incomplete: true`) y los encola para export — un
|
|
2626
|
+
* span abierto nunca se tira en un flush.
|
|
1597
2627
|
*
|
|
1598
2628
|
* @returns Promise que resuelve cuando todos los buffers están vaciados
|
|
1599
2629
|
*
|
|
1600
2630
|
*/
|
|
1601
2631
|
async flushTransports() {
|
|
2632
|
+
forceCloseOpenSpans();
|
|
1602
2633
|
await this.transportBridge.flushTransports();
|
|
1603
2634
|
}
|
|
1604
2635
|
/**
|
|
1605
|
-
* Cierra todos los transports
|
|
2636
|
+
* Cierra todos los transports. Como en {@link flushTransports}, primero
|
|
2637
|
+
* fuerza el cierre de los spans abiertos para que viajen en el flush
|
|
2638
|
+
* final del close.
|
|
1606
2639
|
*
|
|
1607
2640
|
* @returns Promise que resuelve cuando todos están cerrados
|
|
1608
2641
|
*
|
|
1609
2642
|
*/
|
|
1610
2643
|
async closeTransports() {
|
|
2644
|
+
forceCloseOpenSpans();
|
|
1611
2645
|
await this.transportBridge.closeTransports();
|
|
1612
2646
|
}
|
|
1613
2647
|
/**
|
|
@@ -1629,33 +2663,29 @@ var Logger = class Logger {
|
|
|
1629
2663
|
return require_core.LOG_LEVELS[level] >= require_core.LOG_LEVELS[this.config.verbosity];
|
|
1630
2664
|
}
|
|
1631
2665
|
/**
|
|
1632
|
-
*
|
|
1633
|
-
* (
|
|
1634
|
-
* `log()
|
|
1635
|
-
* `time()` — so all emissions hit the same transport pipeline.
|
|
2666
|
+
* Tag pendiente de inyectar en el siguiente `TransportRecord` emitido
|
|
2667
|
+
* por `log()`. Lo fijan `success()` y `logWithBindingsAndTag()` antes
|
|
2668
|
+
* de delegar; `log()` lo consume y lo resetea a `undefined`.
|
|
1636
2669
|
*
|
|
1637
|
-
* @
|
|
1638
|
-
* @param message - Final, post-hook message text
|
|
1639
|
-
* @param prefix - Effective prefix (global + scope)
|
|
1640
|
-
* @param stackInfo - Optional caller location
|
|
1641
|
-
* @param extra - Optional fields to merge into the record (e.g. `{ tag: 'success' }`)
|
|
2670
|
+
* @internal
|
|
1642
2671
|
*/
|
|
1643
2672
|
_dispatchTag;
|
|
1644
2673
|
/**
|
|
1645
|
-
*
|
|
2674
|
+
* Computa el contexto completamente mergueado para este logger.
|
|
1646
2675
|
*
|
|
1647
|
-
*
|
|
1648
|
-
*
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
2676
|
+
* La cadena de contexto se construye en el momento de crear el child:
|
|
2677
|
+
* cada child almacena el contexto fully-merged de su parent (en ese
|
|
2678
|
+
* instante) como `_parentContextRecord`. Esto implica que
|
|
2679
|
+
* `_parentContextRecord` ya contiene los bindings de todos los ancestros
|
|
2680
|
+
* en el orden de precedencia correcto (root primero, child más cercano al final).
|
|
1651
2681
|
*
|
|
1652
|
-
*
|
|
1653
|
-
* 1. _parentContextRecord —
|
|
1654
|
-
* 2. _bindings —
|
|
1655
|
-
* 3. ALS store — withContext
|
|
2682
|
+
* Orden de merge (gana el último):
|
|
2683
|
+
* 1. _parentContextRecord — snapshot del contexto mergueado del parent en la creación
|
|
2684
|
+
* 2. _bindings — bindings propios de este logger (llamadas a `child()`)
|
|
2685
|
+
* 3. ALS store — scope de `withContext`/`withContextAsync` (prioridad máxima)
|
|
1656
2686
|
*
|
|
1657
2687
|
* @internal
|
|
1658
|
-
* @returns
|
|
2688
|
+
* @returns El record de contexto mergueado
|
|
1659
2689
|
*/
|
|
1660
2690
|
_getMergedContext() {
|
|
1661
2691
|
let merged = this._parentContextRecord ?? {};
|
|
@@ -1670,7 +2700,7 @@ var Logger = class Logger {
|
|
|
1670
2700
|
};
|
|
1671
2701
|
return merged;
|
|
1672
2702
|
}
|
|
1673
|
-
/** @internal
|
|
2703
|
+
/** @internal Expone el contexto base mergueado (sin ALS) a la closure de la child factory de LogContext. */
|
|
1674
2704
|
_captureMergedContext() {
|
|
1675
2705
|
let merged = this._parentContextRecord ?? {};
|
|
1676
2706
|
if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
|
|
@@ -1679,6 +2709,21 @@ var Logger = class Logger {
|
|
|
1679
2709
|
};
|
|
1680
2710
|
return merged;
|
|
1681
2711
|
}
|
|
2712
|
+
/**
|
|
2713
|
+
* Construye y despacha un `TransportRecord` al {@link TransportManager}
|
|
2714
|
+
* (no-op si no hay transports registrados). Lo comparten todos los
|
|
2715
|
+
* caminos de log — `log()`, `success()` y los métodos visuales como
|
|
2716
|
+
* `table()` / `group()` / `time()` — para que toda emisión atraviese
|
|
2717
|
+
* el mismo pipeline de transports.
|
|
2718
|
+
*
|
|
2719
|
+
* @protected
|
|
2720
|
+
* @param {LogLevel} level - Nivel canónico (trace/debug/info/warn/error/critical)
|
|
2721
|
+
* @param {string} message - Mensaje final, post-hook
|
|
2722
|
+
* @param {string | undefined} prefix - Prefijo efectivo (global + scope)
|
|
2723
|
+
* @param {StackInfo | null} stackInfo - Ubicación del caller, opcional
|
|
2724
|
+
* @param {Partial<TransportRecord>} [extra] - Campos extra a mergear en el record
|
|
2725
|
+
* (p.ej. `{ tag: 'success' }` o `attributes` adicionales)
|
|
2726
|
+
*/
|
|
1682
2727
|
dispatchToTransports(level, message, prefix, stackInfo, extra) {
|
|
1683
2728
|
const record = {
|
|
1684
2729
|
level,
|
|
@@ -1698,6 +2743,11 @@ var Logger = class Logger {
|
|
|
1698
2743
|
resource: this.logContext._getResource() ? { ...this.logContext._getResource() } : void 0,
|
|
1699
2744
|
...extra
|
|
1700
2745
|
};
|
|
2746
|
+
const activeSpan = getActiveSpan();
|
|
2747
|
+
if (activeSpan && !record.traceId) {
|
|
2748
|
+
record.traceId = activeSpan.traceId;
|
|
2749
|
+
record.spanId = activeSpan.spanId;
|
|
2750
|
+
}
|
|
1701
2751
|
this.transportBridge.writeRecord(record);
|
|
1702
2752
|
}
|
|
1703
2753
|
/**
|
|
@@ -1710,37 +2760,23 @@ var Logger = class Logger {
|
|
|
1710
2760
|
return parts.length > 0 ? parts.join(":") : void 0;
|
|
1711
2761
|
}
|
|
1712
2762
|
/**
|
|
1713
|
-
* Método central de logging.
|
|
1714
|
-
*
|
|
1715
|
-
*
|
|
1716
|
-
*
|
|
1717
|
-
* Fire-and-forget callers (e.g. `logger.info(...)` without `await`)
|
|
1718
|
-
* still work — the resulting `Promise<void>` is dropped on the floor.
|
|
1719
|
-
* Awaiting is recommended when `beforeLog` hooks mutate `message`
|
|
1720
|
-
* (e.g. PII redaction, correlation IDs).
|
|
1721
|
-
*
|
|
1722
|
-
* @protected
|
|
1723
|
-
* @param level - Nivel del log
|
|
1724
|
-
* @param args - Argumentos a loggear
|
|
1725
|
-
* @returns Promise that resolves once the record has been dispatched
|
|
2763
|
+
* Método central de logging. Espera el hook pipeline `beforeLog`
|
|
2764
|
+
* antes de despachar a consola y transports, para que redacciones
|
|
2765
|
+
* o enriquecimientos (PII, correlation IDs) se reflejen en el
|
|
2766
|
+
* mensaje emitido.
|
|
1726
2767
|
*
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
*
|
|
1730
|
-
* synchronously (so redactions / enrichments are reflected in the
|
|
1731
|
-
* emitted message before console + transport dispatch).
|
|
2768
|
+
* Los callers fire-and-forget (p.ej. `logger.info(...)` sin `await`)
|
|
2769
|
+
* siguen funcionando: el `Promise<void>` resultante se descarta.
|
|
2770
|
+
* Se recomienda `await` cuando los hooks `beforeLog` mutan `message`.
|
|
1732
2771
|
*
|
|
1733
|
-
*
|
|
1734
|
-
*
|
|
1735
|
-
*
|
|
1736
|
-
* (e.g. PII redaction, correlation IDs).
|
|
2772
|
+
* El tag opcional (`TransportRecord.tag`) NO se pasa como argumento:
|
|
2773
|
+
* se establece vía `_dispatchTag` (ver `success()` y
|
|
2774
|
+
* {@link logWithBindingsAndTag}) antes de invocar este método.
|
|
1737
2775
|
*
|
|
1738
2776
|
* @protected
|
|
1739
|
-
* @param level - Nivel del log
|
|
1740
|
-
* @param args - Argumentos a loggear
|
|
1741
|
-
* @
|
|
1742
|
-
* `TransportRecord.tag` (e.g. `'success'` for success records).
|
|
1743
|
-
* @returns Promise that resolves once the record has been dispatched
|
|
2777
|
+
* @param {LogLevel} level - Nivel del log
|
|
2778
|
+
* @param {unknown[]} args - Argumentos a loggear (mensaje + datos)
|
|
2779
|
+
* @returns {Promise<void>} Promesa que resuelve al completar el dispatch
|
|
1744
2780
|
*
|
|
1745
2781
|
*/
|
|
1746
2782
|
async log(level, ...args) {
|
|
@@ -1790,6 +2826,22 @@ var Logger = class Logger {
|
|
|
1790
2826
|
else this.dispatchToTransports(level, message, prefix, stackInfo);
|
|
1791
2827
|
this.hookBridge.getHookManager().emit("afterLog", processed).catch(() => {});
|
|
1792
2828
|
}
|
|
2829
|
+
/**
|
|
2830
|
+
* Emite un log aplicando bindings (badges, scope) al prefijo del
|
|
2831
|
+
* mensaje antes de delegar en {@link Logger.log}.
|
|
2832
|
+
*
|
|
2833
|
+
* No es API pública de consumo: existe para que `ScopedLogger`
|
|
2834
|
+
* (`component()` / `api()` / `scope()`) pueda reutilizar el pipeline
|
|
2835
|
+
* central de `log()` sin duplicar la lógica de styling/badges.
|
|
2836
|
+
*
|
|
2837
|
+
* @internal
|
|
2838
|
+
* @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
|
|
2839
|
+
* @param {LogLevel} level - Nivel de log
|
|
2840
|
+
* @param {unknown[]} args - Argumentos a loggear
|
|
2841
|
+
* @returns {Promise<void>} Promesa del dispatch
|
|
2842
|
+
*
|
|
2843
|
+
* @see {@link logWithBindingsAndTag} para la variante con `tag`
|
|
2844
|
+
*/
|
|
1793
2845
|
logWithBindings(bindings, level, ...args) {
|
|
1794
2846
|
if (!this.shouldLog(level)) return Promise.resolve();
|
|
1795
2847
|
let prefix = "";
|
|
@@ -1800,19 +2852,45 @@ var Logger = class Logger {
|
|
|
1800
2852
|
return this.log(level, ...args);
|
|
1801
2853
|
}
|
|
1802
2854
|
/**
|
|
1803
|
-
*
|
|
1804
|
-
* `log()`
|
|
1805
|
-
*
|
|
2855
|
+
* Como {@link logWithBindings} pero fija `_dispatchTag` antes de
|
|
2856
|
+
* delegar, para que `log()` despache el `TransportRecord` con el
|
|
2857
|
+
* tag indicado. Lo usa `ScopedLogger.success()` para propagar
|
|
2858
|
+
* `tag: 'success'` a través del pipeline normal de `log()`.
|
|
2859
|
+
*
|
|
2860
|
+
* @internal
|
|
2861
|
+
* @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
|
|
2862
|
+
* @param {LogLevel} level - Nivel de log
|
|
2863
|
+
* @param {LogTag} tag - Tag a inyectar en el `TransportRecord`
|
|
2864
|
+
* @param {unknown[]} args - Argumentos a loggear
|
|
2865
|
+
* @returns {Promise<void>} Promesa del dispatch
|
|
1806
2866
|
*/
|
|
1807
2867
|
logWithBindingsAndTag(bindings, level, tag, ...args) {
|
|
1808
2868
|
this._dispatchTag = tag;
|
|
1809
2869
|
return this.logWithBindings(bindings, level, ...args);
|
|
1810
2870
|
}
|
|
2871
|
+
/**
|
|
2872
|
+
* Registra mensajes de debug (nivel más verboso junto a `trace`).
|
|
2873
|
+
* Pensado para diagnóstico de desarrollo: valores intermedios, flags
|
|
2874
|
+
* de control flow, estado interno. Devuelve `Promise<void>`.
|
|
2875
|
+
*
|
|
2876
|
+
* Filtrado por defecto cuando `verbosity > 'debug'` (ver `setVerbosity`).
|
|
2877
|
+
*
|
|
2878
|
+
* @param {unknown[]} args - Mensaje + datos a inspeccionar
|
|
2879
|
+
* @returns {Promise<void>} Promesa del dispatch
|
|
2880
|
+
*
|
|
2881
|
+
* @example
|
|
2882
|
+
* logger.debug('Estado interno:', { conn, queueSize });
|
|
2883
|
+
* logger.debug('Entrando en branch X');
|
|
2884
|
+
*
|
|
2885
|
+
* @see {@link trace} para diagnósticos aún más granulares
|
|
2886
|
+
* @see {@link setVerbosity} para controlar el nivel mínimo visible
|
|
2887
|
+
*/
|
|
1811
2888
|
debug(...args) {
|
|
1812
2889
|
return this.log("debug", ...args);
|
|
1813
2890
|
}
|
|
1814
2891
|
/**
|
|
1815
|
-
* Registra mensajes informativos.
|
|
2892
|
+
* Registra mensajes informativos. El `await` retorna cuando el hook
|
|
2893
|
+
* `beforeLog` y el dispatch a transports han terminado.
|
|
1816
2894
|
*
|
|
1817
2895
|
* @param args - Mensajes y datos informativos
|
|
1818
2896
|
*
|
|
@@ -1825,7 +2903,7 @@ var Logger = class Logger {
|
|
|
1825
2903
|
return this.log("info", ...args);
|
|
1826
2904
|
}
|
|
1827
2905
|
/**
|
|
1828
|
-
* Registra mensajes de advertencia.
|
|
2906
|
+
* Registra mensajes de advertencia.
|
|
1829
2907
|
*
|
|
1830
2908
|
* @param args - Mensajes de advertencia
|
|
1831
2909
|
*
|
|
@@ -1834,7 +2912,7 @@ var Logger = class Logger {
|
|
|
1834
2912
|
return this.log("warn", ...args);
|
|
1835
2913
|
}
|
|
1836
2914
|
/**
|
|
1837
|
-
* Registra mensajes de error.
|
|
2915
|
+
* Registra mensajes de error.
|
|
1838
2916
|
*
|
|
1839
2917
|
* @param args - Mensaje de error y stack traces
|
|
1840
2918
|
*
|
|
@@ -1914,7 +2992,7 @@ var Logger = class Logger {
|
|
|
1914
2992
|
this.log("trace", ...args);
|
|
1915
2993
|
}
|
|
1916
2994
|
/**
|
|
1917
|
-
* Registra errores críticos (prioridad más alta).
|
|
2995
|
+
* Registra errores críticos (prioridad más alta).
|
|
1918
2996
|
*
|
|
1919
2997
|
* @param args - Errores críticos del sistema
|
|
1920
2998
|
*
|
|
@@ -1926,6 +3004,104 @@ var Logger = class Logger {
|
|
|
1926
3004
|
return this.log("critical", ...args);
|
|
1927
3005
|
}
|
|
1928
3006
|
/**
|
|
3007
|
+
* Emite un **point-span**: un span con `start = end` para completion
|
|
3008
|
+
* signals y eventos puntuales (una operación instantánea, un hito).
|
|
3009
|
+
* No registra contexto activo ni puede leakear — se exporta de inmediato.
|
|
3010
|
+
*
|
|
3011
|
+
* El nombre `event` (y no `trace`) es deliberado: `trace` es un log level
|
|
3012
|
+
* (el -1) y está reservado.
|
|
3013
|
+
*
|
|
3014
|
+
* @param {string} name - Nombre del evento (`job.completed`, `cache.flushed`, ...).
|
|
3015
|
+
* @param {SpanAttributes} [attributes] - Attributes del span.
|
|
3016
|
+
*
|
|
3017
|
+
* @example
|
|
3018
|
+
* logger.event('build.finished', { status: 'ok', durationMs: 4200 });
|
|
3019
|
+
*
|
|
3020
|
+
* @see {@link span} para intervalos con work-block
|
|
3021
|
+
* @see {@link startSpan} para intervalos externally-ended
|
|
3022
|
+
*/
|
|
3023
|
+
event(name, attributes) {
|
|
3024
|
+
emitEventSpan(name, attributes, this._spanScopeName(), (record) => {
|
|
3025
|
+
this.transportBridge.writeRecord(record);
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
span(name, fnOrAttributes, maybeFn) {
|
|
3029
|
+
const { attributes, fn } = resolveSpanArgs(fnOrAttributes, maybeFn);
|
|
3030
|
+
return this._runSpan(name, attributes, this._spanScopeName(), fn);
|
|
3031
|
+
}
|
|
3032
|
+
/**
|
|
3033
|
+
* Inicia un span de intervalo **externally-ended**: devuelve el handle y
|
|
3034
|
+
* NO fija contexto ALS (el cierre ocurre fuera del bloque léxico — p.ej.
|
|
3035
|
+
* un `cli.spawn` que se cierra desde un poll o callback externo).
|
|
3036
|
+
*
|
|
3037
|
+
* Si el span no se cierra antes de `flushTransports()` / shutdown, el
|
|
3038
|
+
* flush lo fuerza a cerrar con `incomplete: true` y lo exporta — nunca
|
|
3039
|
+
* se tira.
|
|
3040
|
+
*
|
|
3041
|
+
* @param {string} name - Nombre de la operación.
|
|
3042
|
+
* @param {SpanAttributes} [attributes] - Attributes iniciales.
|
|
3043
|
+
* @returns {Span} Handle con `set`/`end`/`fail` y los ids del span.
|
|
3044
|
+
*
|
|
3045
|
+
* @example
|
|
3046
|
+
* const s = logger.startSpan('spawn.build', { cmd: 'make' });
|
|
3047
|
+
* proc.on('exit', code => {
|
|
3048
|
+
* if (code === 0) s.end({ exitCode: code });
|
|
3049
|
+
* else s.fail(new Error(`exit ${code}`));
|
|
3050
|
+
* });
|
|
3051
|
+
*
|
|
3052
|
+
* @see {@link span} para el caso con work-block
|
|
3053
|
+
*/
|
|
3054
|
+
startSpan(name, attributes) {
|
|
3055
|
+
return this._startSpan(name, attributes, this._spanScopeName());
|
|
3056
|
+
}
|
|
3057
|
+
/**
|
|
3058
|
+
* Scope por defecto de los spans emitidos por este logger (el
|
|
3059
|
+
* `globalPrefix`, o `'root'`).
|
|
3060
|
+
* @internal
|
|
3061
|
+
*/
|
|
3062
|
+
_spanScopeName() {
|
|
3063
|
+
return this.config.globalPrefix || "root";
|
|
3064
|
+
}
|
|
3065
|
+
/**
|
|
3066
|
+
* Emite un point-span con scope explícito. Lo consume
|
|
3067
|
+
* {@link ScopedLogger.event}, que pasa su scope compuesto.
|
|
3068
|
+
* @internal
|
|
3069
|
+
*/
|
|
3070
|
+
_emitSpanEvent(name, attributes, scope) {
|
|
3071
|
+
emitEventSpan(name, attributes, scope, (record) => {
|
|
3072
|
+
this.transportBridge.writeRecord(record);
|
|
3073
|
+
});
|
|
3074
|
+
}
|
|
3075
|
+
/**
|
|
3076
|
+
* Crea un span externally-ended con scope explícito. Lo consume
|
|
3077
|
+
* {@link ScopedLogger.startSpan}.
|
|
3078
|
+
* @internal
|
|
3079
|
+
*/
|
|
3080
|
+
_startSpan(name, attributes, scope) {
|
|
3081
|
+
const { span } = createSpan(name, attributes, scope, (record) => {
|
|
3082
|
+
this.transportBridge.writeRecord(record);
|
|
3083
|
+
});
|
|
3084
|
+
return span;
|
|
3085
|
+
}
|
|
3086
|
+
/**
|
|
3087
|
+
* Corre `fn` dentro de un span activo en el ALS con scope explícito.
|
|
3088
|
+
* Lo consume {@link ScopedLogger.span}.
|
|
3089
|
+
* @internal
|
|
3090
|
+
*/
|
|
3091
|
+
async _runSpan(name, attributes, scope, fn) {
|
|
3092
|
+
const { record, span } = createSpan(name, attributes, scope, (r) => {
|
|
3093
|
+
this.transportBridge.writeRecord(r);
|
|
3094
|
+
});
|
|
3095
|
+
try {
|
|
3096
|
+
const result = await runWithActiveSpan(record, () => fn(span));
|
|
3097
|
+
span.end();
|
|
3098
|
+
return result;
|
|
3099
|
+
} catch (error) {
|
|
3100
|
+
span.fail(error);
|
|
3101
|
+
throw error;
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
/**
|
|
1929
3105
|
* Muestra datos en formato de tabla. Pasa por la pipeline completa
|
|
1930
3106
|
* (outputMode-respecting writeOutput + transports + hooks).
|
|
1931
3107
|
*
|
|
@@ -2034,7 +3210,7 @@ var Logger = class Logger {
|
|
|
2034
3210
|
* Finaliza un temporizador y muestra el tiempo transcurrido
|
|
2035
3211
|
*
|
|
2036
3212
|
* @param {string} label - Etiqueta del temporizador a finalizar
|
|
2037
|
-
* @returns {number}
|
|
3213
|
+
* @returns {number} Milisegundos transcurridos, o `-1` si no se encuentra el timer
|
|
2038
3214
|
*
|
|
2039
3215
|
* @example
|
|
2040
3216
|
* logger.time('consulta-db');
|
|
@@ -2156,11 +3332,11 @@ var Logger = class Logger {
|
|
|
2156
3332
|
} });
|
|
2157
3333
|
}
|
|
2158
3334
|
/**
|
|
2159
|
-
*
|
|
3335
|
+
* Muestra un indicador de progreso de pasos en la terminal
|
|
2160
3336
|
*
|
|
2161
|
-
* @param {number} current -
|
|
2162
|
-
* @param {number} total -
|
|
2163
|
-
* @param {string} message -
|
|
3337
|
+
* @param {number} current - Número de paso actual
|
|
3338
|
+
* @param {number} total - Número total de pasos
|
|
3339
|
+
* @param {string} message - Descripción del paso
|
|
2164
3340
|
*
|
|
2165
3341
|
* @example
|
|
2166
3342
|
* logger.step(1, 5, 'Analyzing repository...');
|
|
@@ -2171,10 +3347,10 @@ var Logger = class Logger {
|
|
|
2171
3347
|
this.terminalBridge.step(current, total, message);
|
|
2172
3348
|
}
|
|
2173
3349
|
/**
|
|
2174
|
-
*
|
|
3350
|
+
* Muestra un header con estilo y subtítulo opcional
|
|
2175
3351
|
*
|
|
2176
|
-
* @param {string} title -
|
|
2177
|
-
* @param {string} subtitle -
|
|
3352
|
+
* @param {string} title - Texto del título principal
|
|
3353
|
+
* @param {string} subtitle - Subtítulo opcional (se renderiza atenuado)
|
|
2178
3354
|
*
|
|
2179
3355
|
* @example
|
|
2180
3356
|
* logger.header('Commit Wizard', 'v2.0.0');
|
|
@@ -2184,7 +3360,7 @@ var Logger = class Logger {
|
|
|
2184
3360
|
this.terminalBridge.header(title, subtitle);
|
|
2185
3361
|
}
|
|
2186
3362
|
/**
|
|
2187
|
-
*
|
|
3363
|
+
* Muestra una línea divisoria horizontal
|
|
2188
3364
|
*
|
|
2189
3365
|
* @example
|
|
2190
3366
|
* logger.divider();
|
|
@@ -2194,7 +3370,7 @@ var Logger = class Logger {
|
|
|
2194
3370
|
this.terminalBridge.divider();
|
|
2195
3371
|
}
|
|
2196
3372
|
/**
|
|
2197
|
-
*
|
|
3373
|
+
* Emite una línea en blanco
|
|
2198
3374
|
*
|
|
2199
3375
|
* @example
|
|
2200
3376
|
* logger.blank();
|
|
@@ -2204,10 +3380,10 @@ var Logger = class Logger {
|
|
|
2204
3380
|
this.terminalBridge.blank();
|
|
2205
3381
|
}
|
|
2206
3382
|
/**
|
|
2207
|
-
*
|
|
3383
|
+
* Renderiza contenido dentro de un box con borde
|
|
2208
3384
|
*
|
|
2209
|
-
* @param {string} content -
|
|
2210
|
-
* @param {IBoxOptions} options -
|
|
3385
|
+
* @param {string} content - String de contenido (puede contener newlines)
|
|
3386
|
+
* @param {IBoxOptions} options - Opciones de renderizado del box
|
|
2211
3387
|
*
|
|
2212
3388
|
* @example
|
|
2213
3389
|
* logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
|
|
@@ -2217,11 +3393,11 @@ var Logger = class Logger {
|
|
|
2217
3393
|
this.terminalBridge.box(content, options);
|
|
2218
3394
|
}
|
|
2219
3395
|
/**
|
|
2220
|
-
*
|
|
2221
|
-
*
|
|
3396
|
+
* Renderiza un array de objetos como una tabla ASCII formateada.
|
|
3397
|
+
* Distinto del método `table()` existente, que usa `console.table`.
|
|
2222
3398
|
*
|
|
2223
|
-
* @param {Record<string, unknown>[]} rows - Array
|
|
2224
|
-
* @param {ITableOptions} options -
|
|
3399
|
+
* @param {Record<string, unknown>[]} rows - Array de objetos fila
|
|
3400
|
+
* @param {ITableOptions} options - Opciones de renderizado de la tabla
|
|
2225
3401
|
*
|
|
2226
3402
|
* @example
|
|
2227
3403
|
* logger.cliTable([
|
|
@@ -2234,11 +3410,11 @@ var Logger = class Logger {
|
|
|
2234
3410
|
this.terminalBridge.cliTable(rows, options);
|
|
2235
3411
|
}
|
|
2236
3412
|
/**
|
|
2237
|
-
*
|
|
2238
|
-
*
|
|
3413
|
+
* Crea un handle de spinner para mostrar progreso durante operaciones async.
|
|
3414
|
+
* Devuelve un `NoopSpinner` en entornos non-TTY.
|
|
2239
3415
|
*
|
|
2240
|
-
* @param {string} message -
|
|
2241
|
-
* @returns {ISpinnerHandle}
|
|
3416
|
+
* @param {string} message - Texto inicial del spinner
|
|
3417
|
+
* @returns {ISpinnerHandle} Controller del spinner
|
|
2242
3418
|
*
|
|
2243
3419
|
* @example
|
|
2244
3420
|
* const s = logger.spinner('Analyzing repository...');
|
|
@@ -2251,13 +3427,14 @@ var Logger = class Logger {
|
|
|
2251
3427
|
return this.terminalBridge.spinner(message);
|
|
2252
3428
|
}
|
|
2253
3429
|
/**
|
|
2254
|
-
*
|
|
3430
|
+
* Fija el nivel de verbosidad del CLI, controlando a la vez la verbosidad
|
|
3431
|
+
* de logs y la visibilidad de las primitives
|
|
2255
3432
|
*
|
|
2256
|
-
* @param {CLILogLevel} level -
|
|
3433
|
+
* @param {CLILogLevel} level - Nivel de log del CLI
|
|
2257
3434
|
*
|
|
2258
3435
|
* @example
|
|
2259
|
-
* logger.setCLILevel('quiet'); //
|
|
2260
|
-
* logger.setCLILevel('verbose'); // Debug logs +
|
|
3436
|
+
* logger.setCLILevel('quiet'); // Solo errors, sin CLI primitives
|
|
3437
|
+
* logger.setCLILevel('verbose'); // Debug logs + todas las CLI primitives
|
|
2261
3438
|
*
|
|
2262
3439
|
*/
|
|
2263
3440
|
setCLILevel(level) {
|
|
@@ -2267,21 +3444,21 @@ var Logger = class Logger {
|
|
|
2267
3444
|
this.config.cliLevel = level;
|
|
2268
3445
|
}
|
|
2269
3446
|
/**
|
|
2270
|
-
*
|
|
2271
|
-
* @returns {CLILogLevel}
|
|
3447
|
+
* Devuelve el nivel de log del CLI actual
|
|
3448
|
+
* @returns {CLILogLevel} Nivel de log del CLI actual
|
|
2272
3449
|
*/
|
|
2273
3450
|
get cliLevel() {
|
|
2274
3451
|
return this.config.cliLevel ?? "normal";
|
|
2275
3452
|
}
|
|
2276
3453
|
/**
|
|
2277
|
-
*
|
|
2278
|
-
*
|
|
3454
|
+
* Escribe output formateado al destino configurado.
|
|
3455
|
+
* Respeta la configuración `outputMode` para output a consola, silencioso o custom.
|
|
2279
3456
|
*
|
|
2280
3457
|
* @private
|
|
2281
|
-
* @param {string} message -
|
|
2282
|
-
* @param {LogLevel} level -
|
|
2283
|
-
* @param {string[]} styles - CSS
|
|
2284
|
-
* @param {unknown[]} additionalArgs -
|
|
3458
|
+
* @param {string} message - Mensaje de log formateado
|
|
3459
|
+
* @param {LogLevel} level - Nivel de log
|
|
3460
|
+
* @param {string[]} styles - Estilos CSS para la consola del navegador
|
|
3461
|
+
* @param {unknown[]} additionalArgs - Argumentos adicionales a loggear
|
|
2285
3462
|
*/
|
|
2286
3463
|
writeOutput(message, level, styles, additionalArgs) {
|
|
2287
3464
|
const mode = this.config.outputMode ?? "console";
|
|
@@ -2321,21 +3498,20 @@ var Logger = class Logger {
|
|
|
2321
3498
|
}
|
|
2322
3499
|
};
|
|
2323
3500
|
/**
|
|
2324
|
-
|
|
2325
|
-
*
|
|
2326
|
-
* not on module import. Fixes BUG-N11 (eager side-effect at import time).
|
|
3501
|
+
* Instancia singleton lazy — se inicializa en la primera llamada a
|
|
3502
|
+
* {@link getDefaultLogger}, no al importar el módulo.
|
|
2327
3503
|
*
|
|
2328
3504
|
* @private
|
|
2329
3505
|
*/
|
|
2330
3506
|
let _defaultLogger = null;
|
|
2331
3507
|
/**
|
|
2332
|
-
*
|
|
3508
|
+
* Crea el singleton del Logger por defecto de forma lazy.
|
|
2333
3509
|
*
|
|
2334
|
-
*
|
|
2335
|
-
*
|
|
2336
|
-
*
|
|
3510
|
+
* El singleton se construye solo en la primera llamada, de modo que
|
|
3511
|
+
* importar el módulo nunca ejecuta `new Logger(...)` ni
|
|
3512
|
+
* `displayInitBanner()`. Así los imports del módulo quedan side-effect free.
|
|
2337
3513
|
*
|
|
2338
|
-
* @returns
|
|
3514
|
+
* @returns La instancia compartida de Logger
|
|
2339
3515
|
*/
|
|
2340
3516
|
function getDefaultLogger() {
|
|
2341
3517
|
if (!_defaultLogger) {
|
|
@@ -2358,12 +3534,12 @@ new Proxy({}, { get(_target, prop, receiver) {
|
|
|
2358
3534
|
return typeof value === "function" ? value.bind(instance) : value;
|
|
2359
3535
|
} });
|
|
2360
3536
|
/**
|
|
2361
|
-
*
|
|
2362
|
-
* `ILogAttributes
|
|
2363
|
-
*
|
|
3537
|
+
* Estrecha un contexto free-form `Record<string, unknown>` a un bag tipado
|
|
3538
|
+
* `ILogAttributes`. Los shapes desconocidos caen a strings JSON-encoded,
|
|
3539
|
+
* lo que mantiene conforme al transport OTLP (cada valor cae en un slot tipado).
|
|
2364
3540
|
*
|
|
2365
|
-
* @param input -
|
|
2366
|
-
* @returns
|
|
3541
|
+
* @param input - Contexto suministrado por el usuario (típicamente `Logger.context`).
|
|
3542
|
+
* @returns Un nuevo bag de attributes que satisface `ILogAttributes`.
|
|
2367
3543
|
*/
|
|
2368
3544
|
function toLogAttributes(input) {
|
|
2369
3545
|
const out = {};
|
|
@@ -2390,6 +3566,23 @@ function toAttributeValue(value) {
|
|
|
2390
3566
|
return;
|
|
2391
3567
|
}
|
|
2392
3568
|
}
|
|
3569
|
+
/**
|
|
3570
|
+
* Resuelve los argumentos del overload `span(name, fn?)` /
|
|
3571
|
+
* `span(name, attributes, fn)` a `{ attributes, fn }`.
|
|
3572
|
+
*
|
|
3573
|
+
* @internal Compartido con `ScopedLogger.span`; no es API pública.
|
|
3574
|
+
*/
|
|
3575
|
+
function resolveSpanArgs(fnOrAttributes, maybeFn) {
|
|
3576
|
+
if (typeof fnOrAttributes === "function") return {
|
|
3577
|
+
attributes: void 0,
|
|
3578
|
+
fn: fnOrAttributes
|
|
3579
|
+
};
|
|
3580
|
+
if (typeof maybeFn === "function") return {
|
|
3581
|
+
attributes: fnOrAttributes,
|
|
3582
|
+
fn: maybeFn
|
|
3583
|
+
};
|
|
3584
|
+
throw new TypeError("span(name, …): se requiere una función fn");
|
|
3585
|
+
}
|
|
2393
3586
|
//#endregion
|
|
2394
3587
|
//#region src/index.ts
|
|
2395
3588
|
/**
|
|
@@ -2422,6 +3615,11 @@ const group = (label, collapsed) => getLogger().group(label, collapsed);
|
|
|
2422
3615
|
const groupEnd = () => getLogger().groupEnd();
|
|
2423
3616
|
const time = (label) => getLogger().time(label);
|
|
2424
3617
|
const timeEnd = (label) => getLogger().timeEnd(label);
|
|
3618
|
+
const event = (name, attributes) => getLogger().event(name, attributes);
|
|
3619
|
+
const startSpan = (name, attributes) => getLogger().startSpan(name, attributes);
|
|
3620
|
+
function span(name, fnOrAttributes, maybeFn) {
|
|
3621
|
+
return getLogger().span(name, fnOrAttributes, maybeFn);
|
|
3622
|
+
}
|
|
2425
3623
|
const setGlobalPrefix = (prefix) => getLogger().setGlobalPrefix(prefix);
|
|
2426
3624
|
const scope = (name) => getLogger().scope(name);
|
|
2427
3625
|
const component = (name) => getLogger().component(name);
|
|
@@ -2480,6 +3678,7 @@ exports.critical = critical;
|
|
|
2480
3678
|
exports.debug = debug;
|
|
2481
3679
|
exports.default = src_default;
|
|
2482
3680
|
exports.error = error;
|
|
3681
|
+
exports.event = event;
|
|
2483
3682
|
exports.flushTransports = flushTransports;
|
|
2484
3683
|
exports.formatLogLevelANSI = require_utils.formatLogLevelANSI;
|
|
2485
3684
|
exports.formatSuccessANSI = require_utils.formatSuccessANSI;
|
|
@@ -2510,6 +3709,8 @@ exports.setGlobalPrefix = setGlobalPrefix;
|
|
|
2510
3709
|
exports.setTheme = setTheme;
|
|
2511
3710
|
exports.setVerbosity = setVerbosity;
|
|
2512
3711
|
exports.showBanner = showBanner;
|
|
3712
|
+
exports.span = span;
|
|
3713
|
+
exports.startSpan = startSpan;
|
|
2513
3714
|
exports.success = success;
|
|
2514
3715
|
exports.supportsANSI = require_environment_detector.supportsANSI;
|
|
2515
3716
|
exports.table = table;
|