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