@mks2508/better-logger 0.14.0-alpha.2 → 0.18.2-alpha.2
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 +50 -244
- package/dist/Logger.d.ts +662 -202
- package/dist/Logger.d.ts.map +1 -1
- package/dist/ScopedLogger.d.ts +434 -175
- 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-BaMXleWj.cjs +105 -0
- package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
- package/dist/chunks/LogContext-DjlITOzZ.js +100 -0
- package/dist/chunks/LogContext-DjlITOzZ.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-DQ6UNRB-.cjs +118 -0
- 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-Blfi2klP.js +31 -0
- package/dist/chunks/core-Blfi2klP.js.map +1 -0
- package/dist/chunks/core-CqS_UBzJ.cjs +36 -0
- package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
- package/dist/chunks/environment-detector-7NvnYUfr.js +110 -0
- package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
- package/dist/chunks/environment-detector-D-tHkKWA.cjs +163 -0
- 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-BHyYEXsM.cjs +1029 -0
- package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
- package/dist/chunks/spinner-BtkwpzYv.js +982 -0
- 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-yK6CL0Ml.cjs +1278 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
- package/dist/chunks/utils-W_cxqriN.cjs +705 -0
- package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
- package/dist/chunks/utils-tKfBAWUM.js +586 -0
- 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 +54 -26
- 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 +30 -4
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli-module.d.ts +13 -0
- package/dist/cli-module.d.ts.map +1 -0
- package/dist/cli.cjs +11 -0
- package/dist/cli.js +3 -0
- package/dist/constants.d.ts +16 -47
- package/dist/constants.d.ts.map +1 -1
- package/dist/context/LogContext.d.ts +245 -0
- package/dist/context/LogContext.d.ts.map +1 -0
- package/dist/context/index.d.ts +6 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context-module.d.ts +6 -0
- package/dist/context-module.d.ts.map +1 -0
- package/dist/context.cjs +3 -0
- package/dist/context.js +2 -0
- package/dist/core.cjs +304 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +56 -34
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +281 -314
- package/dist/core.js.map +1 -1
- package/dist/hooks/HookBridge.d.ts +32 -0
- package/dist/hooks/HookBridge.d.ts.map +1 -0
- package/dist/hooks/HookManager.d.ts +319 -0
- package/dist/hooks/HookManager.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks-module.d.ts +7 -0
- package/dist/hooks-module.d.ts.map +1 -0
- package/dist/hooks.cjs +5 -0
- package/dist/hooks.js +2 -0
- package/dist/index.cjs +3402 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +42 -130
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3327 -158
- package/dist/index.js.map +1 -1
- package/dist/node-module.d.ts +10 -0
- package/dist/node-module.d.ts.map +1 -0
- package/dist/node.cjs +13 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.js +12 -0
- package/dist/node.js.map +1 -0
- package/dist/playground/TerminalBridge.d.ts +53 -0
- package/dist/playground/TerminalBridge.d.ts.map +1 -0
- package/dist/playground/box.d.ts +45 -0
- package/dist/playground/box.d.ts.map +1 -0
- package/dist/playground/cli-table.d.ts +50 -0
- package/dist/playground/cli-table.d.ts.map +1 -0
- package/dist/playground/divider.d.ts +29 -0
- package/dist/playground/divider.d.ts.map +1 -0
- package/dist/playground/header.d.ts +28 -0
- package/dist/playground/header.d.ts.map +1 -0
- package/dist/playground/index.d.ts +11 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/server-fallback.d.ts +114 -0
- package/dist/playground/server-fallback.d.ts.map +1 -0
- package/dist/playground/spinner.d.ts +197 -0
- package/dist/playground/spinner.d.ts.map +1 -0
- package/dist/playground/step.d.ts +33 -0
- package/dist/playground/step.d.ts.map +1 -0
- package/dist/playground-module.d.ts +11 -0
- package/dist/playground-module.d.ts.map +1 -0
- package/dist/playground.cjs +9 -0
- package/dist/playground.js +2 -0
- package/dist/serializers/SerializerBridge.d.ts +28 -0
- package/dist/serializers/SerializerBridge.d.ts.map +1 -0
- package/dist/serializers/SerializerRegistry.d.ts +252 -0
- package/dist/serializers/SerializerRegistry.d.ts.map +1 -0
- package/dist/serializers/index.d.ts +7 -0
- package/dist/serializers/index.d.ts.map +1 -0
- package/dist/serializers-module.d.ts +7 -0
- package/dist/serializers-module.d.ts.map +1 -0
- package/dist/serializers.cjs +5 -0
- package/dist/serializers.js +2 -0
- package/dist/styles/StyleManager.d.ts +190 -0
- package/dist/styles/StyleManager.d.ts.map +1 -0
- package/dist/styles/index.d.ts +7 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/styles-module.d.ts +7 -0
- package/dist/styles-module.d.ts.map +1 -0
- package/dist/styles.cjs +7 -0
- package/dist/styles.js +3 -0
- 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 +85 -5
- package/dist/styling/banners.d.ts.map +1 -1
- package/dist/styling/index.d.ts +8 -3
- package/dist/styling/index.d.ts.map +1 -1
- package/dist/styling/themes.d.ts +41 -2
- package/dist/styling/themes.d.ts.map +1 -1
- package/dist/terminal/color-converter.d.ts +73 -0
- package/dist/terminal/color-converter.d.ts.map +1 -0
- package/dist/terminal/formatter.d.ts +23 -0
- package/dist/terminal/formatter.d.ts.map +1 -0
- package/dist/transports/ConsoleTransport.d.ts +104 -0
- package/dist/transports/ConsoleTransport.d.ts.map +1 -0
- package/dist/transports/FileTransport.d.ts +137 -0
- package/dist/transports/FileTransport.d.ts.map +1 -0
- package/dist/transports/HttpTransport.d.ts +180 -0
- package/dist/transports/HttpTransport.d.ts.map +1 -0
- package/dist/transports/OtlpTransport.d.ts +165 -0
- package/dist/transports/OtlpTransport.d.ts.map +1 -0
- package/dist/transports/TransportBridge.d.ts +43 -0
- package/dist/transports/TransportBridge.d.ts.map +1 -0
- package/dist/transports/TransportManager.d.ts +251 -0
- package/dist/transports/TransportManager.d.ts.map +1 -0
- package/dist/transports/index.d.ts +6 -0
- package/dist/transports/index.d.ts.map +1 -0
- package/dist/transports-module.d.ts +10 -0
- package/dist/transports-module.d.ts.map +1 -0
- package/dist/transports.cjs +7 -0
- package/dist/transports.js +2 -0
- package/dist/types/core.d.ts +295 -17
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/handlers.d.ts +0 -67
- package/dist/types/handlers.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +138 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/serializers.d.ts +97 -0
- package/dist/types/serializers.d.ts.map +1 -0
- package/dist/types/transports.d.ts +132 -0
- package/dist/types/transports.d.ts.map +1 -0
- package/dist/utils/ansi-colors.d.ts +115 -0
- package/dist/utils/ansi-colors.d.ts.map +1 -0
- package/dist/utils/environment-detector.d.ts +53 -0
- package/dist/utils/environment-detector.d.ts.map +1 -0
- package/dist/utils/formatting.d.ts +9 -8
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/output.d.ts +14 -17
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/stackTrace.d.ts +2 -2
- package/dist/utils/stackTrace.d.ts.map +1 -1
- package/dist/utils/timestamps.d.ts +0 -12
- package/dist/utils/timestamps.d.ts.map +1 -1
- package/package.json +95 -21
- package/.claude/settings.local.json +0 -39
- package/.github/workflows/ci-quality.yml +0 -357
- package/.github/workflows/docs-demo.yml +0 -119
- package/.github/workflows/releases-core.yml +0 -512
- package/.github/workflows/releases-full.yml +0 -582
- package/.github/workflows-backup/ci.yml +0 -221
- package/.github/workflows-backup/nightly.yml +0 -196
- package/.github/workflows-backup/release-optimized.yml +0 -373
- package/.github/workflows-backup/release.yml +0 -269
- package/.release-notes-0.2.0.md +0 -129
- package/.yamllint +0 -28
- package/CHANGELOG.json +0 -865
- package/CLAUDE.md +0 -204
- package/bun.lock +0 -323
- package/demo.html +0 -847
- package/dist/.tsbuildinfo +0 -1
- package/dist/Logger.js +0 -1124
- package/dist/ScopedLogger.js +0 -426
- package/dist/chunks/Logger-Crw1woqR.js +0 -3464
- package/dist/chunks/Logger-Crw1woqR.js.map +0 -1
- package/dist/chunks/Logger-D_p3xnbq.js +0 -2
- package/dist/chunks/Logger-D_p3xnbq.js.map +0 -1
- package/dist/chunks/RemoteLogHandler-CjWpWZGl.js +0 -33
- package/dist/chunks/RemoteLogHandler-CjWpWZGl.js.map +0 -1
- package/dist/chunks/RemoteLogHandler-ymkQ97xl.js +0 -2
- package/dist/chunks/RemoteLogHandler-ymkQ97xl.js.map +0 -1
- package/dist/chunks/environment-Bxbnw4pd.js +0 -544
- package/dist/chunks/environment-Bxbnw4pd.js.map +0 -1
- package/dist/chunks/environment-Dm66zOML.js +0 -4
- package/dist/chunks/environment-Dm66zOML.js.map +0 -1
- package/dist/chunks/formatting-C0riPC5_.js +0 -95
- package/dist/chunks/formatting-C0riPC5_.js.map +0 -1
- package/dist/chunks/formatting-DNCAV66-.js +0 -2
- package/dist/chunks/formatting-DNCAV66-.js.map +0 -1
- package/dist/cli/CommandProcessor.js +0 -184
- package/dist/cli/commands/ConfigCommand.js +0 -88
- package/dist/cli/commands/ExportCommand.js +0 -243
- package/dist/cli/commands/HistoryCommand.d.ts +0 -50
- package/dist/cli/commands/HistoryCommand.d.ts.map +0 -1
- package/dist/cli/commands/HistoryCommand.js +0 -96
- package/dist/cli/commands/StatusCommand.d.ts +0 -33
- package/dist/cli/commands/StatusCommand.d.ts.map +0 -1
- package/dist/cli/commands/StatusCommand.js +0 -93
- package/dist/cli/commands/ThemeCommand.js +0 -79
- package/dist/cli/help.js +0 -118
- package/dist/cli/index.js +0 -46
- package/dist/constants.js +0 -159
- package/dist/example.d.ts +0 -18
- package/dist/example.d.ts.map +0 -1
- package/dist/example.js +0 -154
- package/dist/exports-module.d.ts +0 -203
- package/dist/exports-module.d.ts.map +0 -1
- package/dist/exports-module.js +0 -260
- package/dist/exports.cjs +0 -2
- package/dist/exports.cjs.map +0 -1
- package/dist/exports.js +0 -238
- package/dist/exports.js.map +0 -1
- package/dist/handlers/AnalyticsLogHandler.d.ts +0 -11
- package/dist/handlers/AnalyticsLogHandler.d.ts.map +0 -1
- package/dist/handlers/AnalyticsLogHandler.js +0 -19
- package/dist/handlers/ExportLogHandler.d.ts +0 -103
- package/dist/handlers/ExportLogHandler.d.ts.map +0 -1
- package/dist/handlers/ExportLogHandler.js +0 -516
- package/dist/handlers/FileLogHandler.d.ts +0 -36
- package/dist/handlers/FileLogHandler.d.ts.map +0 -1
- package/dist/handlers/FileLogHandler.js +0 -156
- package/dist/handlers/RemoteLogHandler.d.ts +0 -14
- package/dist/handlers/RemoteLogHandler.d.ts.map +0 -1
- package/dist/handlers/RemoteLogHandler.js +0 -37
- package/dist/handlers/index.d.ts +0 -8
- package/dist/handlers/index.d.ts.map +0 -1
- package/dist/handlers/index.js +0 -7
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -139
- package/dist/styling/LogStyleBuilder.d.ts +0 -149
- package/dist/styling/LogStyleBuilder.d.ts.map +0 -1
- package/dist/styling/LogStyleBuilder.js +0 -289
- package/dist/styling/SemanticStyles.d.ts +0 -181
- package/dist/styling/SemanticStyles.d.ts.map +0 -1
- package/dist/styling/SemanticStyles.js +0 -339
- package/dist/styling/SmartPresets.js +0 -276
- package/dist/styling/StyleBuilder.js +0 -280
- package/dist/styling/banners.js +0 -155
- package/dist/styling/index.js +0 -9
- package/dist/styling/themes.js +0 -231
- package/dist/styling-module.d.ts +0 -185
- package/dist/styling-module.d.ts.map +0 -1
- package/dist/styling-module.js +0 -199
- package/dist/styling.cjs +0 -2
- package/dist/styling.cjs.map +0 -1
- package/dist/styling.js +0 -146
- package/dist/styling.js.map +0 -1
- package/dist/types/Logger.d.ts +0 -700
- package/dist/types/Logger.d.ts.map +0 -1
- package/dist/types/ScopedLogger.d.ts +0 -310
- package/dist/types/ScopedLogger.d.ts.map +0 -1
- package/dist/types/cli/CommandProcessor.d.ts +0 -100
- package/dist/types/cli/CommandProcessor.d.ts.map +0 -1
- package/dist/types/cli/commands/ConfigCommand.d.ts +0 -14
- package/dist/types/cli/commands/ConfigCommand.d.ts.map +0 -1
- package/dist/types/cli/commands/ExportCommand.d.ts +0 -48
- package/dist/types/cli/commands/ExportCommand.d.ts.map +0 -1
- package/dist/types/cli/commands/HistoryCommand.d.ts +0 -47
- package/dist/types/cli/commands/HistoryCommand.d.ts.map +0 -1
- package/dist/types/cli/commands/StatusCommand.d.ts +0 -30
- package/dist/types/cli/commands/StatusCommand.d.ts.map +0 -1
- package/dist/types/cli/commands/ThemeCommand.d.ts +0 -30
- package/dist/types/cli/commands/ThemeCommand.d.ts.map +0 -1
- package/dist/types/cli/help.d.ts +0 -12
- package/dist/types/cli/help.d.ts.map +0 -1
- package/dist/types/cli/index.d.ts +0 -15
- package/dist/types/cli/index.d.ts.map +0 -1
- package/dist/types/constants.d.ts +0 -119
- package/dist/types/constants.d.ts.map +0 -1
- package/dist/types/core.js +0 -28
- package/dist/types/example.d.ts +0 -18
- package/dist/types/example.d.ts.map +0 -1
- package/dist/types/exports-module.d.ts +0 -196
- package/dist/types/exports-module.d.ts.map +0 -1
- package/dist/types/handlers/AnalyticsLogHandler.d.ts +0 -8
- package/dist/types/handlers/AnalyticsLogHandler.d.ts.map +0 -1
- package/dist/types/handlers/ExportLogHandler.d.ts +0 -100
- package/dist/types/handlers/ExportLogHandler.d.ts.map +0 -1
- package/dist/types/handlers/FileLogHandler.d.ts +0 -33
- package/dist/types/handlers/FileLogHandler.d.ts.map +0 -1
- package/dist/types/handlers/RemoteLogHandler.d.ts +0 -11
- package/dist/types/handlers/RemoteLogHandler.d.ts.map +0 -1
- package/dist/types/handlers/index.d.ts +0 -8
- package/dist/types/handlers/index.d.ts.map +0 -1
- package/dist/types/handlers.js +0 -4
- package/dist/types/index.js +0 -4
- package/dist/types/main.d.ts +0 -2
- package/dist/types/main.d.ts.map +0 -1
- package/dist/types/styling/LogStyleBuilder.d.ts +0 -146
- package/dist/types/styling/LogStyleBuilder.d.ts.map +0 -1
- package/dist/types/styling/SemanticStyles.d.ts +0 -178
- package/dist/types/styling/SemanticStyles.d.ts.map +0 -1
- package/dist/types/styling/SmartPresets.d.ts +0 -22
- package/dist/types/styling/SmartPresets.d.ts.map +0 -1
- package/dist/types/styling/StyleBuilder.d.ts +0 -140
- package/dist/types/styling/StyleBuilder.d.ts.map +0 -1
- package/dist/types/styling/banners.d.ts +0 -42
- package/dist/types/styling/banners.d.ts.map +0 -1
- package/dist/types/styling/index.d.ts +0 -10
- package/dist/types/styling/index.d.ts.map +0 -1
- package/dist/types/styling/themes.d.ts +0 -7
- package/dist/types/styling/themes.d.ts.map +0 -1
- package/dist/types/styling-module.d.ts +0 -178
- package/dist/types/styling-module.d.ts.map +0 -1
- package/dist/types/types/core.d.ts +0 -221
- package/dist/types/types/core.d.ts.map +0 -1
- package/dist/types/types/handlers.d.ts +0 -85
- package/dist/types/types/handlers.d.ts.map +0 -1
- package/dist/types/types/index.d.ts +0 -7
- package/dist/types/types/index.d.ts.map +0 -1
- package/dist/types/utils/environment.d.ts +0 -47
- package/dist/types/utils/environment.d.ts.map +0 -1
- package/dist/types/utils/formatting.d.ts +0 -37
- package/dist/types/utils/formatting.d.ts.map +0 -1
- package/dist/types/utils/index.d.ts +0 -7
- package/dist/types/utils/index.d.ts.map +0 -1
- package/dist/types/utils/opentui-detection.d.ts +0 -34
- package/dist/types/utils/opentui-detection.d.ts.map +0 -1
- package/dist/types/utils/output.d.ts +0 -41
- package/dist/types/utils/output.d.ts.map +0 -1
- package/dist/types/utils/stackTrace.d.ts +0 -6
- package/dist/types/utils/stackTrace.d.ts.map +0 -1
- package/dist/types/utils/timestamps.d.ts +0 -20
- package/dist/types/utils/timestamps.d.ts.map +0 -1
- package/dist/utils/environment.d.ts +0 -47
- package/dist/utils/environment.d.ts.map +0 -1
- package/dist/utils/environment.js +0 -85
- package/dist/utils/formatting.js +0 -117
- package/dist/utils/index.js +0 -6
- package/dist/utils/opentui-detection.d.ts +0 -34
- package/dist/utils/opentui-detection.d.ts.map +0 -1
- package/dist/utils/opentui-detection.js +0 -116
- package/dist/utils/output.js +0 -150
- package/dist/utils/stackTrace.js +0 -81
- package/dist/utils/timestamps.js +0 -71
- package/dist/vite.svg +0 -1
- package/docs/API.md +0 -691
- package/docs/CORE.md +0 -264
- package/docs/DEVELOPMENT.md +0 -731
- package/docs/EXPORTS.md +0 -467
- package/docs/PACKAGES.md +0 -244
- package/docs/STYLING.md +0 -405
- package/docs/_config.yml +0 -36
- package/docs/index.md +0 -179
- package/examples/README.md +0 -208
- package/examples/basic-logging.js +0 -75
- package/examples/data-export.js +0 -234
- package/examples/package.json +0 -16
- package/examples/performance-timing.js +0 -170
- package/examples/simplified-api.js +0 -124
- package/examples/styling-themes.js +0 -207
- package/index.html +0 -358
- package/packages/core/package.json +0 -57
- package/packages/exports/package.json +0 -41
- package/packages/nodejs-opentui/README.md +0 -232
- package/packages/nodejs-opentui/package.json +0 -72
- package/packages/nodejs-opentui/src/LogRenderer.ts +0 -171
- package/packages/nodejs-opentui/src/OpenTUILogHandler.ts +0 -178
- package/packages/nodejs-opentui/src/components/LogBadge.tsx +0 -131
- package/packages/nodejs-opentui/src/index.ts +0 -133
- package/packages/nodejs-opentui/src/types.ts +0 -158
- package/packages/nodejs-opentui/tsconfig.json +0 -20
- package/packages/styling/package.json +0 -41
- package/project-utils/README.md +0 -172
- package/project-utils/auto-release-gemini.ts +0 -1193
- package/project-utils/auto-release-ui.ts +0 -1329
- package/project-utils/commit-generator.ts +0 -1385
- package/project-utils/commit-ui.ts +0 -264
- package/project-utils/git-utils.ts +0 -199
- package/project-utils/github-release-manager.ts +0 -466
- package/project-utils/project-config.ts +0 -260
- package/project-utils/prompt-templates.js +0 -345
- package/project-utils/prompt-templates.ts +0 -422
- package/project-utils/version-manager.ts +0 -1078
- package/public/vite.svg +0 -1
- package/src/Logger.ts +0 -1276
- package/src/ScopedLogger.ts +0 -454
- package/src/cli/CommandProcessor.ts +0 -248
- package/src/cli/commands/ConfigCommand.ts +0 -93
- package/src/cli/commands/ExportCommand.ts +0 -276
- package/src/cli/commands/HistoryCommand.ts +0 -117
- package/src/cli/commands/StatusCommand.ts +0 -112
- package/src/cli/commands/ThemeCommand.ts +0 -88
- package/src/cli/help.ts +0 -127
- package/src/cli/index.ts +0 -71
- package/src/constants.ts +0 -171
- package/src/core.ts +0 -393
- package/src/example.ts +0 -210
- package/src/exports-module.ts +0 -311
- package/src/handlers/AnalyticsLogHandler.ts +0 -22
- package/src/handlers/ExportLogHandler.ts +0 -609
- package/src/handlers/FileLogHandler.ts +0 -169
- package/src/handlers/RemoteLogHandler.ts +0 -42
- package/src/handlers/index.ts +0 -8
- package/src/index.ts +0 -209
- package/src/main.ts +0 -196
- package/src/style.css +0 -96
- package/src/styling/LogStyleBuilder.ts +0 -355
- package/src/styling/SemanticStyles.ts +0 -380
- package/src/styling/SmartPresets.ts +0 -288
- package/src/styling/StyleBuilder.ts +0 -319
- package/src/styling/banners.ts +0 -168
- package/src/styling/index.ts +0 -27
- package/src/styling/themes.ts +0 -235
- package/src/styling-module.ts +0 -244
- package/src/types/core.ts +0 -236
- package/src/types/handlers.ts +0 -95
- package/src/types/index.ts +0 -35
- package/src/typescript.svg +0 -1
- package/src/utils/environment.ts +0 -94
- package/src/utils/formatting.ts +0 -142
- package/src/utils/index.ts +0 -21
- package/src/utils/opentui-detection.ts +0 -138
- package/src/utils/output.ts +0 -185
- package/src/utils/stackTrace.ts +0 -95
- package/src/utils/timestamps.ts +0 -80
- package/src/vite-env.d.ts +0 -1
- package/test-core-browser.html +0 -237
- package/test-core-node.js +0 -63
- package/tests/test-conflict-resolution.ts +0 -391
- package/tests/validate-workflows.sh +0 -131
- package/tests/yaml-autofix.sh +0 -146
- package/tsconfig.json +0 -50
- package/vite.config.ts +0 -223
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,3402 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
const require_core = require("./chunks/core-CqS_UBzJ.cjs");
|
|
6
|
+
const require_transports = require("./chunks/transports-yK6CL0Ml.cjs");
|
|
7
|
+
const require_utils = require("./chunks/utils-W_cxqriN.cjs");
|
|
8
|
+
const require_styling = require("./chunks/styling-Cel2wPRy.cjs");
|
|
9
|
+
const require_environment_detector = require("./chunks/environment-detector-D-tHkKWA.cjs");
|
|
10
|
+
const require_spinner = require("./chunks/spinner-BHyYEXsM.cjs");
|
|
11
|
+
const require_LogContext = require("./chunks/LogContext-BaMXleWj.cjs");
|
|
12
|
+
const require_HookBridge = require("./chunks/HookBridge-C-AvXmPD.cjs");
|
|
13
|
+
const require_SerializerBridge = require("./chunks/SerializerBridge-C4a9Z37F.cjs");
|
|
14
|
+
const require_server_fallback = require("./chunks/server-fallback-CaCPjWby.cjs");
|
|
15
|
+
const require_StyleManager = require("./chunks/StyleManager-DQ6UNRB-.cjs");
|
|
16
|
+
//#region src/ScopedLogger.ts
|
|
17
|
+
/**
|
|
18
|
+
* Logger prefijado por un scope nominal. Mantiene su propio stack de badges
|
|
19
|
+
* y contextos y delega el envío de mensajes al {@link Logger} padre a través
|
|
20
|
+
* de bindings (`{ scope, badges }`).
|
|
21
|
+
*
|
|
22
|
+
* Es la base de la jerarquía temática: {@link APILogger} y
|
|
23
|
+
* {@link ComponentLogger} extienden de ella, y {@link ContextLogger} la
|
|
24
|
+
* consume para apilar/subdesapilar sub-prefijos en el scope.
|
|
25
|
+
*
|
|
26
|
+
* No se construye directamente: se obtiene con `logger.scope('name')`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // El factory method del Logger raíz devuelve un ScopedLogger
|
|
30
|
+
* import logger from '@mks2508/better-logger';
|
|
31
|
+
*
|
|
32
|
+
* const http = logger.scope('HTTP');
|
|
33
|
+
* http.badge('OUTBOUND').info('Request enviada');
|
|
34
|
+
* // salida: [HTTP] [OUTBOUND] Request enviada
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Anidar contextos dentro de un scope (el prefijo se compone con ':')
|
|
38
|
+
* const retry = http.context('retry');
|
|
39
|
+
* retry.run(() => http.warn('Reintentando petición'));
|
|
40
|
+
* // salida: [HTTP:retry] Reintentando petición
|
|
41
|
+
*
|
|
42
|
+
* @see {@link Logger.scope}
|
|
43
|
+
* @see {@link APILogger}
|
|
44
|
+
* @see {@link ComponentLogger}
|
|
45
|
+
* @see {@link ContextLogger}
|
|
46
|
+
*/
|
|
47
|
+
var ScopedLogger = class {
|
|
48
|
+
parent;
|
|
49
|
+
scopeName;
|
|
50
|
+
badgeList = [];
|
|
51
|
+
contextStack = [];
|
|
52
|
+
_timers;
|
|
53
|
+
/**
|
|
54
|
+
* Construye un ScopedLogger vinculado a un {@link Logger} padre.
|
|
55
|
+
*
|
|
56
|
+
* Los clientes no deben llamar a este constructor directamente: usen
|
|
57
|
+
* `logger.scope(name)`, que configura correctamente la instancia.
|
|
58
|
+
*
|
|
59
|
+
* @param {Logger} parent - Logger raíz al que se delegan los mensajes.
|
|
60
|
+
* @param {string} scopeName - Etiqueta del scope; se renderiza como
|
|
61
|
+
* prefijo `[scopeName]` en cada línea.
|
|
62
|
+
*/
|
|
63
|
+
constructor(parent, scopeName) {
|
|
64
|
+
this.parent = parent;
|
|
65
|
+
this.scopeName = scopeName;
|
|
66
|
+
}
|
|
67
|
+
get timers() {
|
|
68
|
+
if (!this._timers) this._timers = /* @__PURE__ */ new Map();
|
|
69
|
+
return this._timers;
|
|
70
|
+
}
|
|
71
|
+
getBindings() {
|
|
72
|
+
return {
|
|
73
|
+
scope: this.getScopePrefix(),
|
|
74
|
+
badges: this.badgeList.length > 0 ? [...this.badgeList] : void 0
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
getScopePrefix() {
|
|
78
|
+
if (this.contextStack.length === 0) return this.scopeName;
|
|
79
|
+
return [this.scopeName, ...this.contextStack].join(":");
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Reemplaza la lista actual de badges por la pasada y la aplica a todos
|
|
83
|
+
* los mensajes posteriores de este scope.
|
|
84
|
+
*
|
|
85
|
+
* @param {string[]} badges - Etiquetas a mostrar como badges adyacentes
|
|
86
|
+
* al prefijo (p. ej. `['OUTBOUND', 'CACHED']`).
|
|
87
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* logger.scope('HTTP').badges(['OUTBOUND', 'CACHED']).info('Cache hit');
|
|
91
|
+
* // salida: [HTTP] [OUTBOUND] [CACHED] Cache hit
|
|
92
|
+
*
|
|
93
|
+
* @see {@link badge} para añadir sin reemplazar los existentes.
|
|
94
|
+
* @see {@link clearBadges} para vaciar la lista.
|
|
95
|
+
*/
|
|
96
|
+
badges(badges) {
|
|
97
|
+
this.badgeList = [...badges];
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Añade un badge al scope de forma idempotente (no lo duplica si ya existe).
|
|
102
|
+
*
|
|
103
|
+
* @param {string} badge - Etiqueta a añadir a la lista de badges.
|
|
104
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* logger.scope('API')
|
|
108
|
+
* .badge('OUTBOUND')
|
|
109
|
+
* .badge('RETRY')
|
|
110
|
+
* .warn('Reintentando');
|
|
111
|
+
* // salida: [API] [OUTBOUND] [RETRY] Reintentando
|
|
112
|
+
*/
|
|
113
|
+
badge(badge) {
|
|
114
|
+
if (!this.badgeList.includes(badge)) this.badgeList.push(badge);
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Vacía la lista de badges del scope.
|
|
119
|
+
*
|
|
120
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* const http = logger.scope('HTTP');
|
|
124
|
+
* http.badge('OUTBOUND').info('uno');
|
|
125
|
+
* http.clearBadges().info('dos');
|
|
126
|
+
* // [HTTP] [OUTBOUND] uno / [HTTP] dos
|
|
127
|
+
*/
|
|
128
|
+
clearBadges() {
|
|
129
|
+
this.badgeList = [];
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Aplica un theme preset al logger padre. El preset afecta a toda la
|
|
134
|
+
* instancia raíz (no solo a este scope) porque el style es compartido.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} presetName - Nombre del preset registrado en el StyleManager.
|
|
137
|
+
* @returns {this} La misma instancia, para encadenar llamadas.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* logger.scope('UI').style('cyberpunk').info('neon');
|
|
141
|
+
* @see {@link Logger.setTheme}
|
|
142
|
+
*/
|
|
143
|
+
style(presetName) {
|
|
144
|
+
this.parent.setTheme(presetName);
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Crea un {@link ContextLogger} vinculado a este scope. Los contextos se
|
|
149
|
+
* apilan en el prefijo separados por `:`, permitiendo agrupar bloques de
|
|
150
|
+
* logs relacionados (reintentos, sub-etapas, etc.) sin `console.group`.
|
|
151
|
+
*
|
|
152
|
+
* @param {string} contextName - Nombre del contexto a apilar.
|
|
153
|
+
* @returns {ContextLogger} Handler con `run`, `runAsync`, `start`/`end`.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* const retry = logger.scope('HTTP').context('retry');
|
|
157
|
+
* retry.run(() => logger.warn('Reintentando'));
|
|
158
|
+
* // salida: [HTTP:retry] Reintentando
|
|
159
|
+
* @see {@link ContextLogger}
|
|
160
|
+
*/
|
|
161
|
+
context(contextName) {
|
|
162
|
+
return new ContextLogger(this, contextName);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Inicia un timer etiquetado bajo el namespace `<scopeName>:<label>`.
|
|
166
|
+
* El label es local a este scope, así que dos scopes pueden reutilizar el
|
|
167
|
+
* mismo nombre sin colisión.
|
|
168
|
+
*
|
|
169
|
+
* @param {string} label - Identificador del timer.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* const http = logger.scope('HTTP');
|
|
173
|
+
* http.time('request');
|
|
174
|
+
* // ... trabajo ...
|
|
175
|
+
* http.timeEnd('request'); // imprime "Timer: request - 12.34ms"
|
|
176
|
+
* @see {@link timeEnd}
|
|
177
|
+
*/
|
|
178
|
+
time(label) {
|
|
179
|
+
this.timers.set(label, {
|
|
180
|
+
label: `${this.scopeName}:${label}`,
|
|
181
|
+
startTime: performance.now()
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Detiene un timer previamente iniciado con {@link time} y registra la
|
|
186
|
+
* duración con nivel `success`. Si el label no existe, emite un `warn`
|
|
187
|
+
* y devuelve `undefined`.
|
|
188
|
+
*
|
|
189
|
+
* @param {string} label - Mismo label pasado a {@link time}.
|
|
190
|
+
* @returns {number | undefined} Milisegundos transcurridos, o `undefined`
|
|
191
|
+
* si el timer no estaba registrado.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* const http = logger.scope('HTTP');
|
|
195
|
+
* http.time('fetch');
|
|
196
|
+
* await fetch(url);
|
|
197
|
+
* const ms = http.timeEnd('fetch');
|
|
198
|
+
* if (ms && ms > 1000) http.warn('Latencia alta');
|
|
199
|
+
*/
|
|
200
|
+
timeEnd(label) {
|
|
201
|
+
const timer = this.timers.get(label);
|
|
202
|
+
if (!timer) {
|
|
203
|
+
this.warn(`Timer '${label}' not found`);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const elapsed = performance.now() - timer.startTime;
|
|
207
|
+
this.timers.delete(label);
|
|
208
|
+
this.success(`Timer: ${label} - ${elapsed.toFixed(2)}ms`);
|
|
209
|
+
return elapsed;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Emite un mensaje a nivel `debug` con los bindings actuales del scope.
|
|
213
|
+
*
|
|
214
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales (objetos,
|
|
215
|
+
* errores, etc.) serializados igual que en el logger raíz.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* logger.scope('DB').debug('query', { sql, params });
|
|
219
|
+
*/
|
|
220
|
+
debug(...args) {
|
|
221
|
+
this.parent.logWithBindings(this.getBindings(), "debug", ...args);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Emite un mensaje a nivel `info` con los bindings actuales del scope.
|
|
225
|
+
*
|
|
226
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* logger.scope('AUTH').info('Login exitoso', { userId });
|
|
230
|
+
*/
|
|
231
|
+
info(...args) {
|
|
232
|
+
this.parent.logWithBindings(this.getBindings(), "info", ...args);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Emite un mensaje a nivel `warn` con los bindings actuales del scope.
|
|
236
|
+
*
|
|
237
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* logger.scope('CACHE').warn('Cache miss', { key });
|
|
241
|
+
*/
|
|
242
|
+
warn(...args) {
|
|
243
|
+
this.parent.logWithBindings(this.getBindings(), "warn", ...args);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Emite un mensaje a nivel `error` con los bindings actuales del scope.
|
|
247
|
+
*
|
|
248
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales (típicamente
|
|
249
|
+
* un `Error` o contexto del fallo).
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* logger.scope('DB').error('Conexión rechazada', err);
|
|
253
|
+
*/
|
|
254
|
+
error(...args) {
|
|
255
|
+
this.parent.logWithBindings(this.getBindings(), "error", ...args);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Emite un mensaje con badge visual `SUCCESS` a nivel `info`. Úselo para
|
|
259
|
+
* hitos positivos dentro del scope (conexión establecida, sync completo,
|
|
260
|
+
* commit aplicado).
|
|
261
|
+
*
|
|
262
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* logger.scope('SYNC').success('Sincronización completa', { count: 42 });
|
|
266
|
+
*/
|
|
267
|
+
success(...args) {
|
|
268
|
+
const bindings = this.getBindings();
|
|
269
|
+
this.parent.logWithBindingsAndTag(bindings, "info", "success", ...args);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Emite un mensaje a nivel `critical` con los bindings actuales del scope.
|
|
273
|
+
* Reservado para fallos que detienen el flujo de la aplicación.
|
|
274
|
+
*
|
|
275
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* logger.scope('PAY').critical('Pasarela inaccesible', err);
|
|
279
|
+
*/
|
|
280
|
+
critical(...args) {
|
|
281
|
+
this.parent.logWithBindings(this.getBindings(), "critical", ...args);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Emite un mensaje a nivel `trace` (verbosidad máxima) con los bindings
|
|
285
|
+
* actuales del scope. Solo aparece si la verbosity global lo permite.
|
|
286
|
+
*
|
|
287
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* logger.scope('NET').trace('packet', { bytes });
|
|
291
|
+
*/
|
|
292
|
+
trace(...args) {
|
|
293
|
+
this.parent.logWithBindings(this.getBindings(), "trace", ...args);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Delegación a {@link Logger.step}: dibuja una barra de progreso discreta
|
|
297
|
+
* `current/total` para este scope.
|
|
298
|
+
*
|
|
299
|
+
* @param {number} current - Paso actual (1-indexed).
|
|
300
|
+
* @param {number} total - Total de pasos.
|
|
301
|
+
* @param {string} message - Texto mostrado junto al contador.
|
|
302
|
+
* @see {@link Logger.step}
|
|
303
|
+
*/
|
|
304
|
+
step(current, total, message) {
|
|
305
|
+
this.parent.step(current, total, message);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Delegación a {@link Logger.header}: imprime un título con separadores visuales.
|
|
309
|
+
*
|
|
310
|
+
* @param {string} title - Texto del título.
|
|
311
|
+
* @param {string} [subtitle] - Subtítulo opcional bajo el título.
|
|
312
|
+
* @see {@link Logger.header}
|
|
313
|
+
*/
|
|
314
|
+
header(title, subtitle) {
|
|
315
|
+
this.parent.header(title, subtitle);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Delegación a {@link Logger.divider}: imprime una línea separadora horizontal.
|
|
319
|
+
* @see {@link Logger.divider}
|
|
320
|
+
*/
|
|
321
|
+
divider() {
|
|
322
|
+
this.parent.divider();
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Delegación a {@link Logger.blank}: inserta una línea en blanco.
|
|
326
|
+
* @see {@link Logger.blank}
|
|
327
|
+
*/
|
|
328
|
+
blank() {
|
|
329
|
+
this.parent.blank();
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Delegación a {@link Logger.box}: dibuja un recuadro ANSI alrededor de `content`.
|
|
333
|
+
*
|
|
334
|
+
* @param {string} content - Texto a enmarcar.
|
|
335
|
+
* @param {IBoxOptions} [options] - Opciones de estilo del box.
|
|
336
|
+
* @see {@link Logger.box}
|
|
337
|
+
*/
|
|
338
|
+
box(content, options) {
|
|
339
|
+
this.parent.box(content, options);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Delegación a {@link Logger.cliTable}: renderiza `rows` como tabla ASCII.
|
|
343
|
+
*
|
|
344
|
+
* @param {Record<string, unknown>[]} rows - Filas a mostrar.
|
|
345
|
+
* @param {ITableOptions} [options] - Opciones de columnas y estilo.
|
|
346
|
+
* @see {@link Logger.cliTable}
|
|
347
|
+
*/
|
|
348
|
+
cliTable(rows, options) {
|
|
349
|
+
this.parent.cliTable(rows, options);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Delegación a {@link Logger.spinner}: arranca un spinner con `message`.
|
|
353
|
+
*
|
|
354
|
+
* @param {string} message - Texto a mostrar al lado del spinner.
|
|
355
|
+
* @returns {ISpinnerHandle} Handle para detener/actualizar el spinner.
|
|
356
|
+
* @see {@link Logger.spinner}
|
|
357
|
+
*/
|
|
358
|
+
spinner(message) {
|
|
359
|
+
return this.parent.spinner(message);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Delegación a {@link Logger.setCLILevel}: ajusta el nivel mínimo de las
|
|
363
|
+
* primitivas CLI visibles.
|
|
364
|
+
*
|
|
365
|
+
* @param {CLILogLevel} level - Nivel CLI (`silent` … `verbose`).
|
|
366
|
+
* @see {@link Logger.setCLILevel}
|
|
367
|
+
*/
|
|
368
|
+
setCLILevel(level) {
|
|
369
|
+
this.parent.setCLILevel(level);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Apila un contexto en el prefijo del scope. Invocado por
|
|
373
|
+
* {@link ContextLogger}; los clientes no deben llamarlo directamente.
|
|
374
|
+
*
|
|
375
|
+
* @param {string} context - Nombre del contexto a apilar.
|
|
376
|
+
* @internal
|
|
377
|
+
*/
|
|
378
|
+
_pushContext(context) {
|
|
379
|
+
this.contextStack.push(context);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Desapila el último contexto del prefijo del scope. Invocado por
|
|
383
|
+
* {@link ContextLogger}; los clientes no deben llamarlo directamente.
|
|
384
|
+
*
|
|
385
|
+
* @internal
|
|
386
|
+
*/
|
|
387
|
+
_popContext() {
|
|
388
|
+
this.contextStack.pop();
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
/**
|
|
392
|
+
* Logger especializado para llamadas a APIs y servicios externos.
|
|
393
|
+
*
|
|
394
|
+
* Extiende {@link ScopedLogger} pre-seteando el badge `API` y exponiendo
|
|
395
|
+
* atajos para eventos típicos de integración: llamadas lentas ({@link slow}),
|
|
396
|
+
* rate limiting ({@link rateLimit}), fallos de autenticación ({@link auth}) y
|
|
397
|
+
* APIs deprecadas ({@link deprecated}).
|
|
398
|
+
*
|
|
399
|
+
* Se obtiene con `logger.api(name)` y no se construye directamente.
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* import logger from '@mks2508/better-logger';
|
|
403
|
+
*
|
|
404
|
+
* const stripe = logger.api('Stripe');
|
|
405
|
+
* stripe.info('Consultando customer', { id });
|
|
406
|
+
* // salida: [API:Stripe] [API] Consultando customer
|
|
407
|
+
*
|
|
408
|
+
* stripe.slow('customer.retrieve', 1250);
|
|
409
|
+
* // salida: [API:Stripe] [API] [SLOW] customer.retrieve (1250ms)
|
|
410
|
+
*
|
|
411
|
+
* @see {@link Logger.api}
|
|
412
|
+
* @see {@link ScopedLogger}
|
|
413
|
+
*/
|
|
414
|
+
var APILogger = class extends ScopedLogger {
|
|
415
|
+
/**
|
|
416
|
+
* Construye un APILogger con scope `API:<apiName>` y badge `API` ya aplicado.
|
|
417
|
+
*
|
|
418
|
+
* Los clientes deben usar `logger.api(name)`.
|
|
419
|
+
*
|
|
420
|
+
* @param {Logger} parent - Logger raíz al que se delegan los mensajes.
|
|
421
|
+
* @param {string} apiName - Nombre del servicio/API (se prefija con `API:`).
|
|
422
|
+
*/
|
|
423
|
+
constructor(parent, apiName) {
|
|
424
|
+
super(parent, `API:${apiName}`);
|
|
425
|
+
this.badge("API");
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Registra una llamada lenta con badge `SLOW` a nivel `warn`.
|
|
429
|
+
*
|
|
430
|
+
* @param {string} message - Descripción de la operación lenta.
|
|
431
|
+
* @param {number} [duration] - Duración medida en ms; si se pasa, se
|
|
432
|
+
* anexa al mensaje como `(Nms)`.
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* const t0 = performance.now();
|
|
436
|
+
* await stripe.customers.retrieve(id);
|
|
437
|
+
* logger.api('Stripe').slow('retrieve', performance.now() - t0);
|
|
438
|
+
*/
|
|
439
|
+
slow(message, duration) {
|
|
440
|
+
this.badge("SLOW");
|
|
441
|
+
const msg = duration ? `${message} (${duration}ms)` : message;
|
|
442
|
+
this.warn(msg);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Registra un evento de rate limiting (HTTP 429) con badge `RATE_LIMIT`.
|
|
446
|
+
*
|
|
447
|
+
* @param {string} message - Detalle del límite golpeado.
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* logger.api('GitHub').rateLimit('Secondary rate limit on /search');
|
|
451
|
+
*/
|
|
452
|
+
rateLimit(message) {
|
|
453
|
+
this.badge("RATE_LIMIT");
|
|
454
|
+
this.warn(message);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Registra un fallo de autenticación (401/403) con badge `AUTH` a nivel
|
|
458
|
+
* `error`.
|
|
459
|
+
*
|
|
460
|
+
* @param {string} message - Detalle del fallo de credenciales/token.
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* logger.api('OAuth').auth('Token expirado');
|
|
464
|
+
*/
|
|
465
|
+
auth(message) {
|
|
466
|
+
this.badge("AUTH");
|
|
467
|
+
this.error(message);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Marca una API como deprecada con badge `DEPRECATED` a nivel `warn`.
|
|
471
|
+
*
|
|
472
|
+
* @param {string} message - Mensaje guiando a la migración (endpoint
|
|
473
|
+
* alternativo, versión retirada, etc.).
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* logger.api('Legacy').deprecated('Usar v3; v2 se retira en Q4');
|
|
477
|
+
*/
|
|
478
|
+
deprecated(message) {
|
|
479
|
+
this.badge("DEPRECATED");
|
|
480
|
+
this.warn(message);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
/**
|
|
484
|
+
* Logger para componentes UI, módulos o cualquier unidad con ciclo de vida.
|
|
485
|
+
*
|
|
486
|
+
* Extiende {@link ScopedLogger} pre-seteando el badge `COMPONENT` y exponiendo
|
|
487
|
+
* atajos para eventos típicos: {@link lifecycle}, {@link stateChange} y
|
|
488
|
+
* {@link propsChange}.
|
|
489
|
+
*
|
|
490
|
+
* Se obtiene con `logger.component(name)` y no se construye directamente.
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* import logger from '@mks2508/better-logger';
|
|
494
|
+
*
|
|
495
|
+
* const cart = logger.component('Cart');
|
|
496
|
+
* cart.lifecycle('mount');
|
|
497
|
+
* // salida: [Cart] [COMPONENT] [LIFECYCLE] mount
|
|
498
|
+
*
|
|
499
|
+
* cart.stateChange('empty', 'has-items', { count: 3 });
|
|
500
|
+
* // salida: [Cart] [COMPONENT] [STATE] empty → has-items { count: 3 }
|
|
501
|
+
*
|
|
502
|
+
* @see {@link Logger.component}
|
|
503
|
+
* @see {@link ScopedLogger}
|
|
504
|
+
*/
|
|
505
|
+
var ComponentLogger = class extends ScopedLogger {
|
|
506
|
+
/**
|
|
507
|
+
* Construye un ComponentLogger con badge `COMPONENT` ya aplicado.
|
|
508
|
+
*
|
|
509
|
+
* Los clientes deben usar `logger.component(name)`.
|
|
510
|
+
*
|
|
511
|
+
* @param {Logger} parent - Logger raíz al que se delegan los mensajes.
|
|
512
|
+
* @param {string} componentName - Nombre del componente (scope label).
|
|
513
|
+
*/
|
|
514
|
+
constructor(parent, componentName) {
|
|
515
|
+
super(parent, componentName);
|
|
516
|
+
this.badge("COMPONENT");
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Registra un evento de ciclo de vida con badge `LIFECYCLE` a nivel `info`.
|
|
520
|
+
*
|
|
521
|
+
* @param {string} event - Nombre del evento (`mount`, `unmount`,
|
|
522
|
+
* `update`, ...).
|
|
523
|
+
* @param {string} [message] - Detalle opcional; si se omite, solo se
|
|
524
|
+
* registra el nombre del evento.
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* logger.component('Cart').lifecycle('mount', 'Modal abierto');
|
|
528
|
+
*/
|
|
529
|
+
lifecycle(event, message) {
|
|
530
|
+
this.badge("LIFECYCLE");
|
|
531
|
+
const msg = message ? `${event}: ${message}` : event;
|
|
532
|
+
this.info(msg);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Registra una transición de estado con badge `STATE` a nivel `info`.
|
|
536
|
+
*
|
|
537
|
+
* @param {string} from - Estado previo.
|
|
538
|
+
* @param {string} to - Estado nuevo.
|
|
539
|
+
* @param {unknown} [data] - Payload opcional asociado a la transición.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* const fsm = logger.component('FSM');
|
|
543
|
+
* fsm.stateChange('idle', 'loading');
|
|
544
|
+
* fsm.stateChange('loading', 'success', { items: 3 });
|
|
545
|
+
*/
|
|
546
|
+
stateChange(from, to, data) {
|
|
547
|
+
this.badge("STATE");
|
|
548
|
+
const msg = `${from} → ${to}`;
|
|
549
|
+
if (data) this.info(msg, data);
|
|
550
|
+
else this.info(msg);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Registra cambios de props/debug del componente con badge `PROPS` a nivel
|
|
554
|
+
* `debug`.
|
|
555
|
+
*
|
|
556
|
+
* @param {Record<string, unknown>} changes - Mapa prop → valor (típicamente
|
|
557
|
+
* el diff de props entre renders).
|
|
558
|
+
*
|
|
559
|
+
* @example
|
|
560
|
+
* logger.component('Cart').propsChange({ itemCount: 5, currency: 'EUR' });
|
|
561
|
+
*/
|
|
562
|
+
propsChange(changes) {
|
|
563
|
+
this.badge("PROPS");
|
|
564
|
+
this.debug("Props changed:", changes);
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
/**
|
|
568
|
+
* Handler de contexto apilable sobre un {@link ScopedLogger}.
|
|
569
|
+
*
|
|
570
|
+
* Permite agrupar bloques de logs bajo un sub-prefijo separado por `:`,
|
|
571
|
+
* manteniendo la correlación visual sin necesidad de `console.group`. El
|
|
572
|
+
* prefijo compuesto se forma como `<scopeName>:<contextName>`.
|
|
573
|
+
*
|
|
574
|
+
* Se crea con `scopedLogger.context(name)`. El patrón idiomático es
|
|
575
|
+
* {@link run}/{@link runAsync} (auto push/pop con try/finally); {@link start}
|
|
576
|
+
* y {@link end} permiten control manual cuando el bloque no cierra
|
|
577
|
+
* léxicamente (event handlers distribuidos, promesas de larga duración).
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* import logger from '@mks2508/better-logger';
|
|
581
|
+
*
|
|
582
|
+
* const http = logger.scope('HTTP');
|
|
583
|
+
*
|
|
584
|
+
* // Bloque síncrono auto-cerrado
|
|
585
|
+
* http.context('retry').run(() => {
|
|
586
|
+
* http.warn('Reintentando petición');
|
|
587
|
+
* });
|
|
588
|
+
* // salida: [HTTP:retry] Reintentando petición
|
|
589
|
+
*
|
|
590
|
+
* // Bloque async auto-cerrado
|
|
591
|
+
* await http.context('refresh').runAsync(async () => {
|
|
592
|
+
* await refreshToken();
|
|
593
|
+
* http.info('Token refrescado');
|
|
594
|
+
* });
|
|
595
|
+
*
|
|
596
|
+
* @see {@link ScopedLogger.context}
|
|
597
|
+
*/
|
|
598
|
+
var ContextLogger = class {
|
|
599
|
+
parentLogger;
|
|
600
|
+
contextName;
|
|
601
|
+
/**
|
|
602
|
+
* @param {ScopedLogger} parentLogger - Scope sobre el que se apila el contexto.
|
|
603
|
+
* @param {string} contextName - Sub-prefijo a apilar en el scope padre.
|
|
604
|
+
*/
|
|
605
|
+
constructor(parentLogger, contextName) {
|
|
606
|
+
this.parentLogger = parentLogger;
|
|
607
|
+
this.contextName = contextName;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Ejecuta `fn` síncrona dentro del contexto, garantizando el pop del
|
|
611
|
+
* prefijo incluso si `fn` lanza. El contexto solo está activo durante la
|
|
612
|
+
* ejecución de `fn`.
|
|
613
|
+
*
|
|
614
|
+
* @typeParam T - Tipo de retorno de `fn`.
|
|
615
|
+
* @param {() => T} fn - Función a ejecutar bajo el contexto.
|
|
616
|
+
* @returns {T} Lo que devuelva `fn`.
|
|
617
|
+
* @throws {unknown} Relanza cualquier excepción de `fn` tras desapilar.
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* logger.scope('HTTP').context('warmup').run(() => {
|
|
621
|
+
* logger.info('Pre-cargando caché');
|
|
622
|
+
* });
|
|
623
|
+
*/
|
|
624
|
+
run(fn) {
|
|
625
|
+
this.parentLogger._pushContext(this.contextName);
|
|
626
|
+
try {
|
|
627
|
+
return fn();
|
|
628
|
+
} finally {
|
|
629
|
+
this.parentLogger._popContext();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Variante async de {@link run}: mantiene el contexto activo mientras se
|
|
634
|
+
* awaiting la promesa de `fn`, incluyendo awaits internos.
|
|
635
|
+
*
|
|
636
|
+
* @typeParam T - Tipo resuelto por la promesa de `fn`.
|
|
637
|
+
* @param {() => Promise<T>} fn - Función async a ejecutar bajo el contexto.
|
|
638
|
+
* @returns {Promise<T>} Promesa que resuelve al valor de `fn`.
|
|
639
|
+
* @throws {unknown} Relanza cualquier rechazo de `fn` tras desapilar.
|
|
640
|
+
*
|
|
641
|
+
* @example
|
|
642
|
+
* await logger.scope('HTTP').context('fetch').runAsync(async () => {
|
|
643
|
+
* const r = await fetch(url);
|
|
644
|
+
* logger.info('Recibido', { status: r.status });
|
|
645
|
+
* });
|
|
646
|
+
*/
|
|
647
|
+
async runAsync(fn) {
|
|
648
|
+
this.parentLogger._pushContext(this.contextName);
|
|
649
|
+
try {
|
|
650
|
+
return await fn();
|
|
651
|
+
} finally {
|
|
652
|
+
this.parentLogger._popContext();
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Apila el contexto manualmente. Útil cuando el bloque que lo consume no
|
|
657
|
+
* cierra léxicamente (event handlers, timeouts, streams). Debe emparejarse
|
|
658
|
+
* con un {@link end} posterior; olvidarlo deja el prefijo contaminado para
|
|
659
|
+
* los logs siguientes del scope.
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* const ctx = logger.scope('WS').context('subscribe');
|
|
663
|
+
* socket.onopen = () => { ctx.start(); ctx.info('connected'); };
|
|
664
|
+
* socket.onclose = () => { ctx.info('disconnected'); ctx.end(); };
|
|
665
|
+
* @see {@link end}
|
|
666
|
+
*/
|
|
667
|
+
start() {
|
|
668
|
+
this.parentLogger._pushContext(this.contextName);
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Desapila el último contexto abierto con {@link start}.
|
|
672
|
+
*
|
|
673
|
+
* @see {@link start}
|
|
674
|
+
*/
|
|
675
|
+
end() {
|
|
676
|
+
this.parentLogger._popContext();
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Atajo a `scopedLogger.debug(...)`. El contexto se aplica al prefijo del
|
|
680
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
681
|
+
*
|
|
682
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
683
|
+
*/
|
|
684
|
+
debug(...args) {
|
|
685
|
+
this.parentLogger.debug(...args);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Atajo a `scopedLogger.info(...)`. El contexto se aplica al prefijo del
|
|
689
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
690
|
+
*
|
|
691
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
692
|
+
*/
|
|
693
|
+
info(...args) {
|
|
694
|
+
this.parentLogger.info(...args);
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Atajo a `scopedLogger.warn(...)`. El contexto se aplica al prefijo del
|
|
698
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
699
|
+
*
|
|
700
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
701
|
+
*/
|
|
702
|
+
warn(...args) {
|
|
703
|
+
this.parentLogger.warn(...args);
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Atajo a `scopedLogger.error(...)`. El contexto se aplica al prefijo del
|
|
707
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
708
|
+
*
|
|
709
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
710
|
+
*/
|
|
711
|
+
error(...args) {
|
|
712
|
+
this.parentLogger.error(...args);
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Atajo a `scopedLogger.success(...)`. El contexto se aplica al prefijo del
|
|
716
|
+
* scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
717
|
+
*
|
|
718
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
719
|
+
*/
|
|
720
|
+
success(...args) {
|
|
721
|
+
this.parentLogger.success(...args);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Atajo a `scopedLogger.critical(...)`. El contexto se aplica al prefijo
|
|
725
|
+
* del scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
|
|
726
|
+
*
|
|
727
|
+
* @param {...unknown[]} args - Mensaje y argumentos adicionales.
|
|
728
|
+
*/
|
|
729
|
+
critical(...args) {
|
|
730
|
+
this.parentLogger.critical(...args);
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
//#endregion
|
|
734
|
+
//#region src/cli/CommandProcessor.ts
|
|
735
|
+
/**
|
|
736
|
+
* Procesador central del CLI del logger. Resuelve nombres de comando (con
|
|
737
|
+
* aliases), despacha ejecución, mantiene historial acotado (max 100 entradas)
|
|
738
|
+
* y soporta un sistema de plugins para extensión de terceros.
|
|
739
|
+
*
|
|
740
|
+
* No es un binario standalone: se invoca desde la consola del navegador vía
|
|
741
|
+
* `window.cli("<command>")` (modo interactivo habilitado por
|
|
742
|
+
* {@link enterInteractiveMode}) o desde código vía `logger.cli()`. El
|
|
743
|
+
* constructor no registra ningún comando por defecto — usar
|
|
744
|
+
* {@link createDefaultCLI} para obtener una instancia con los 8 comandos
|
|
745
|
+
* estándar ya cargados.
|
|
746
|
+
*
|
|
747
|
+
* @example
|
|
748
|
+
* ```ts
|
|
749
|
+
* const cli = createDefaultCLI();
|
|
750
|
+
* await cli.processCommand('/themes', logger);
|
|
751
|
+
* await cli.processCommand('/config theme=neon', logger);
|
|
752
|
+
* ```
|
|
753
|
+
*
|
|
754
|
+
* @example
|
|
755
|
+
* ```ts
|
|
756
|
+
* // Modo interactivo: expone `window.cli` en el navegador
|
|
757
|
+
* cli.enterInteractiveMode(logger);
|
|
758
|
+
* // Desde la devtools: cli('help') → procesa '/help'
|
|
759
|
+
* ```
|
|
760
|
+
*
|
|
761
|
+
* @see {@link createDefaultCLI}
|
|
762
|
+
* @see {@link ICommand}
|
|
763
|
+
* @see {@link ICLIPlugin}
|
|
764
|
+
*/
|
|
765
|
+
var CommandProcessor = class {
|
|
766
|
+
commands = /* @__PURE__ */ new Map();
|
|
767
|
+
aliases = /* @__PURE__ */ new Map();
|
|
768
|
+
plugins = /* @__PURE__ */ new Map();
|
|
769
|
+
history = [];
|
|
770
|
+
maxHistorySize = 100;
|
|
771
|
+
isInteractiveMode = false;
|
|
772
|
+
/**
|
|
773
|
+
* Registra un comando. Si el comando declara `aliases`, también se indexan
|
|
774
|
+
* para resolución. Un comando con el mismo `name` sobreescribe al previo.
|
|
775
|
+
*
|
|
776
|
+
* @param {ICommand} command - Comando a registrar.
|
|
777
|
+
* @see {@link ICommand}
|
|
778
|
+
*/
|
|
779
|
+
registerCommand(command) {
|
|
780
|
+
this.commands.set(command.name, command);
|
|
781
|
+
if (command.aliases) for (const alias of command.aliases) this.aliases.set(alias, command.name);
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Registra un plugin: indexa todos sus commands y, si el plugin define
|
|
785
|
+
* `initialize`, lo invoca con el processor y el logger. Los comandos del
|
|
786
|
+
* plugin se registran vía {@link registerCommand} y sus aliases quedan
|
|
787
|
+
* resolvibles igual que los directos.
|
|
788
|
+
*
|
|
789
|
+
* @param {ICLIPlugin} plugin - Plugin a registrar.
|
|
790
|
+
* @param {Logger} [logger] - Logger activo; requerido solo si el plugin define `initialize`.
|
|
791
|
+
* @throws {Error} Si ya existe un plugin registrado con el mismo `name`.
|
|
792
|
+
* @see {@link unregisterPlugin}
|
|
793
|
+
*/
|
|
794
|
+
registerPlugin(plugin, logger) {
|
|
795
|
+
if (this.plugins.has(plugin.name)) throw new Error(`Plugin ${plugin.name} is already registered`);
|
|
796
|
+
this.plugins.set(plugin.name, plugin);
|
|
797
|
+
for (const command of plugin.commands) this.registerCommand(command);
|
|
798
|
+
if (plugin.initialize && logger) plugin.initialize(this, logger);
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Desregistra un plugin por nombre: elimina todos sus commands (y los
|
|
802
|
+
* aliases que aportasen), invoca su hook `cleanup` si existe y lo quita
|
|
803
|
+
* del registry. No-op si el nombre no existe.
|
|
804
|
+
*
|
|
805
|
+
* @param {string} pluginName - Nombre del plugin a desregistrar.
|
|
806
|
+
* @see {@link registerPlugin}
|
|
807
|
+
*/
|
|
808
|
+
unregisterPlugin(pluginName) {
|
|
809
|
+
const plugin = this.plugins.get(pluginName);
|
|
810
|
+
if (!plugin) return;
|
|
811
|
+
for (const command of plugin.commands) {
|
|
812
|
+
this.commands.delete(command.name);
|
|
813
|
+
if (command.aliases) for (const alias of command.aliases) this.aliases.delete(alias);
|
|
814
|
+
}
|
|
815
|
+
if (plugin.cleanup) plugin.cleanup();
|
|
816
|
+
this.plugins.delete(pluginName);
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Lista todos los commands registrados (directamente o vía plugins).
|
|
820
|
+
* No incluye aliases.
|
|
821
|
+
*
|
|
822
|
+
* @returns {ICommand[]} Snapshot array de los commands registrados.
|
|
823
|
+
*/
|
|
824
|
+
getCommands() {
|
|
825
|
+
return Array.from(this.commands.values());
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Resuelve un comando por nombre canónico o alias. Devuelve `undefined`
|
|
829
|
+
* si no existe ninguno que matchee.
|
|
830
|
+
*
|
|
831
|
+
* @param {string} name - Nombre canónico o alias del comando.
|
|
832
|
+
* @returns {ICommand | undefined} El comando resuelto, o `undefined`.
|
|
833
|
+
*/
|
|
834
|
+
getCommand(name) {
|
|
835
|
+
let command = this.commands.get(name);
|
|
836
|
+
if (command) return command;
|
|
837
|
+
const aliasTarget = this.aliases.get(name);
|
|
838
|
+
if (aliasTarget) return this.commands.get(aliasTarget);
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Devuelve una copia del historial de comandos ejecutados (más recientes
|
|
842
|
+
* primero). Acotado a 100 entradas por {@link maxHistorySize}; las más
|
|
843
|
+
* viejas se descartan al insertar nuevas.
|
|
844
|
+
*
|
|
845
|
+
* @returns {HistoryEntry[]} Snapshot del historial; mutar el array devuelto
|
|
846
|
+
* no afecta al estado interno del processor.
|
|
847
|
+
*/
|
|
848
|
+
getHistory() {
|
|
849
|
+
return [...this.history];
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Vacía el historial de comandos en memoria.
|
|
853
|
+
*/
|
|
854
|
+
clearHistory() {
|
|
855
|
+
this.history = [];
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Lista los plugins actualmente registrados.
|
|
859
|
+
*
|
|
860
|
+
* @returns {ICLIPlugin[]} Snapshot array de plugins activos.
|
|
861
|
+
*/
|
|
862
|
+
getPlugins() {
|
|
863
|
+
return Array.from(this.plugins.values());
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Activa el modo interactivo. Marca el flag interno y, si se ejecuta en
|
|
867
|
+
* navegador, expone `window.cli(command)` para invocar comandos desde la
|
|
868
|
+
* devtools sin prefijo `/` (se añade automáticamente al input).
|
|
869
|
+
*
|
|
870
|
+
* @param {Logger} logger - Logger activo (emite el mensaje de bienvenida
|
|
871
|
+
* con hint sobre `cli(...)` en browser).
|
|
872
|
+
* @see {@link exitInteractiveMode}
|
|
873
|
+
*/
|
|
874
|
+
enterInteractiveMode(logger) {
|
|
875
|
+
this.isInteractiveMode = true;
|
|
876
|
+
logger.info("🔧 Interactive CLI mode activated. Type /exit to quit, /help for commands.");
|
|
877
|
+
if (typeof window !== "undefined") this.setupBrowserInteractiveMode(logger);
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Desactiva el flag de modo interactivo. Nota: no elimina el `window.cli`
|
|
881
|
+
* que {@link enterInteractiveMode} haya expuesto en el navegador — el
|
|
882
|
+
* handler global sigue vivo hasta reload.
|
|
883
|
+
*
|
|
884
|
+
* @see {@link enterInteractiveMode}
|
|
885
|
+
*/
|
|
886
|
+
exitInteractiveMode() {
|
|
887
|
+
this.isInteractiveMode = false;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Instala `window.cli(command)` como wrapper delgado alrededor de
|
|
891
|
+
* {@link processCommand}, prefijando `/` automáticamente. Solo se invoca
|
|
892
|
+
* desde {@link enterInteractiveMode} cuando `window` está disponible.
|
|
893
|
+
*
|
|
894
|
+
* @internal
|
|
895
|
+
* @param logger - Logger activo, reenviado a cada invocación.
|
|
896
|
+
*/
|
|
897
|
+
setupBrowserInteractiveMode(logger) {
|
|
898
|
+
window.cli = (commandString) => {
|
|
899
|
+
return this.processCommand(`/${commandString}`, logger);
|
|
900
|
+
};
|
|
901
|
+
logger.info("💡 Use cli(\"command\") to execute CLI commands in browser console.");
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Parsea y ejecuta un comando. El formato esperado es `/name args...`:
|
|
905
|
+
* split por espacios, primer token = nombre del comando, resto = args
|
|
906
|
+
* (re-joined con espacios). Si el comando no existe, loguea el error y
|
|
907
|
+
* sugiere similares vía {@link getSuggestions} ("Did you mean: ...?").
|
|
908
|
+
*
|
|
909
|
+
* Toda invocación (válida o no) se registra en el historial con flag de
|
|
910
|
+
* éxito/fallo según si `execute` resolvió o throweó.
|
|
911
|
+
*
|
|
912
|
+
* @param {string} commandString - Comando completo, debe empezar con `/`.
|
|
913
|
+
* @param {Logger} logger - Logger activo para output y errores.
|
|
914
|
+
* @returns {Promise<void>} Resuelve cuando el comando termina (sync o async).
|
|
915
|
+
* Nunca rechaza: los errores de `execute` se capturan y se loguean.
|
|
916
|
+
* @see {@link ICommand.execute}
|
|
917
|
+
* @see {@link getSuggestions}
|
|
918
|
+
*/
|
|
919
|
+
async processCommand(commandString, logger) {
|
|
920
|
+
if (!commandString.startsWith("/")) {
|
|
921
|
+
logger.error("Invalid command. Commands must start with /");
|
|
922
|
+
this.addToHistory(commandString, false);
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
const parts = commandString.slice(1).split(" ");
|
|
926
|
+
const commandName = parts[0] || "";
|
|
927
|
+
const args = parts.slice(1).join(" ");
|
|
928
|
+
const command = this.getCommand(commandName);
|
|
929
|
+
if (!command) {
|
|
930
|
+
logger.error(`Unknown command: ${commandName}. Type /help for available commands.`);
|
|
931
|
+
const suggestions = this.getSuggestions(commandName);
|
|
932
|
+
if (suggestions.length > 0) logger.info(`📋 Did you mean: ${suggestions.slice(0, 3).join(", ")}?`);
|
|
933
|
+
this.addToHistory(commandString, false);
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
try {
|
|
937
|
+
await command.execute(args || "", logger);
|
|
938
|
+
this.addToHistory(commandString, true);
|
|
939
|
+
} catch (error) {
|
|
940
|
+
logger.error(`Command '${commandName}' failed:`, error);
|
|
941
|
+
this.addToHistory(commandString, false);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Inserta una entrada al frente del historial y trunca a
|
|
946
|
+
* {@link maxHistorySize} (100) si hace falta.
|
|
947
|
+
*
|
|
948
|
+
* @internal
|
|
949
|
+
* @param command - String crudo del comando ejecutado.
|
|
950
|
+
* @param success - Si la ejecución tuvo éxito.
|
|
951
|
+
*/
|
|
952
|
+
addToHistory(command, success) {
|
|
953
|
+
this.history.unshift({
|
|
954
|
+
command,
|
|
955
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
956
|
+
success
|
|
957
|
+
});
|
|
958
|
+
if (this.history.length > this.maxHistorySize) this.history = this.history.slice(0, this.maxHistorySize);
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Devuelve nombres de comando que empiezan con el prefijo dado. Alimente
|
|
962
|
+
* el hint "Did you mean" de {@link processCommand} cuando un comando no
|
|
963
|
+
* se encuentra. Match por `startsWith` (no fuzzy).
|
|
964
|
+
*
|
|
965
|
+
* @param {string} partial - Prefijo parcial tipeado por el usuario.
|
|
966
|
+
* @returns {string[]} Nombres canónicos que matchean; aliases excluidos.
|
|
967
|
+
*/
|
|
968
|
+
getSuggestions(partial) {
|
|
969
|
+
return Array.from(this.commands.keys()).filter((name) => name.startsWith(partial));
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
//#endregion
|
|
973
|
+
//#region src/cli/commands/ConfigCommand.ts
|
|
974
|
+
/**
|
|
975
|
+
* Comando `/config` del CLI runtime del {@link Logger}. Inspecciona o muta
|
|
976
|
+
* la configuración del logger en vivo desde la DevTools console.
|
|
977
|
+
*
|
|
978
|
+
* Acepta tres modos de invocación:
|
|
979
|
+
* - Sin argumentos: vuelca el estado actual como tabla agrupada.
|
|
980
|
+
* - JSON completo (empieza con `{`): aplica un objeto de configuración parcial.
|
|
981
|
+
* - Pares `key=value` separados por coma: atajo para mutaciones puntuales.
|
|
982
|
+
*
|
|
983
|
+
* Solo se aplican las keys de la whitelist interna (`theme`, `verbosity`,
|
|
984
|
+
* `enableColors`, `enableTimestamps`, `enableStackTrace`, `globalPrefix`,
|
|
985
|
+
* `bannerType`); cualquier otra key se rechaza con un `warn` y se ignora.
|
|
986
|
+
*
|
|
987
|
+
* @example
|
|
988
|
+
* // Sin argumentos: ver estado actual
|
|
989
|
+
* // > /config
|
|
990
|
+
*
|
|
991
|
+
* @example
|
|
992
|
+
* // Objeto JSON completo
|
|
993
|
+
* // > /config {"theme":"neon","verbosity":"debug"}
|
|
994
|
+
*
|
|
995
|
+
* @example
|
|
996
|
+
* // Atajo key=value (múltiples pares separados por coma)
|
|
997
|
+
* // > /config theme=neon,verbosity=debug,globalPrefix=MiApp
|
|
998
|
+
*
|
|
999
|
+
* @see {@link ICommand} para el contrato que implementa este comando.
|
|
1000
|
+
* @see {@link Logger.setTheme}, {@link Logger.setVerbosity},
|
|
1001
|
+
* {@link Logger.setBannerType}, {@link Logger.setGlobalPrefix}
|
|
1002
|
+
* para los setters subyacentes.
|
|
1003
|
+
*/
|
|
1004
|
+
var ConfigCommand = class {
|
|
1005
|
+
name = "config";
|
|
1006
|
+
description = "Show or update logger configuration";
|
|
1007
|
+
usage = "/config [json|key=value,...]";
|
|
1008
|
+
/**
|
|
1009
|
+
* Ejecuta el comando `/config` contra el logger dado.
|
|
1010
|
+
*
|
|
1011
|
+
* @param args - Argumentos crudos del usuario. Vacío = status; con `{`
|
|
1012
|
+
* inicial = parse JSON; resto = pares `key=value` separados
|
|
1013
|
+
* por coma.
|
|
1014
|
+
* @param logger - Instancia destino cuyos setters se invocan.
|
|
1015
|
+
*/
|
|
1016
|
+
execute(args, logger) {
|
|
1017
|
+
if (!args) {
|
|
1018
|
+
this.showStatus(logger);
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
try {
|
|
1022
|
+
if (args.startsWith("{")) {
|
|
1023
|
+
const config = JSON.parse(args);
|
|
1024
|
+
this.applyConfig(config, logger);
|
|
1025
|
+
} else {
|
|
1026
|
+
const pairs = args.split(",").map((pair) => pair.trim().split("="));
|
|
1027
|
+
const config = {};
|
|
1028
|
+
pairs.forEach(([key, value]) => {
|
|
1029
|
+
if (key && value) config[key.trim()] = value.trim().replace(/["']/g, "");
|
|
1030
|
+
});
|
|
1031
|
+
this.applyConfig(config, logger);
|
|
1032
|
+
}
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
logger.error("Invalid config format. Use JSON or key=value pairs:", error);
|
|
1035
|
+
logger.info("Examples: /config {\"theme\":\"dark\"} or /config theme=neon,verbosity=debug");
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
showStatus(logger) {
|
|
1039
|
+
const statusData = {
|
|
1040
|
+
theme: logger.getConfig().theme || "default",
|
|
1041
|
+
verbosity: logger.getConfig().verbosity,
|
|
1042
|
+
colors: logger.getConfig().enableColors,
|
|
1043
|
+
timestamps: logger.getConfig().enableTimestamps,
|
|
1044
|
+
stackTrace: logger.getConfig().enableStackTrace,
|
|
1045
|
+
globalPrefix: logger.getConfig().globalPrefix || "none",
|
|
1046
|
+
bannerType: logger.getConfig().bannerType || "simple",
|
|
1047
|
+
handlers: logger.getHandlers().length
|
|
1048
|
+
};
|
|
1049
|
+
logger.group("⚙️ Logger Configuration");
|
|
1050
|
+
logger.table(statusData);
|
|
1051
|
+
logger.groupEnd();
|
|
1052
|
+
}
|
|
1053
|
+
applyConfig(config, logger) {
|
|
1054
|
+
const validKeys = [
|
|
1055
|
+
"theme",
|
|
1056
|
+
"verbosity",
|
|
1057
|
+
"enableColors",
|
|
1058
|
+
"enableTimestamps",
|
|
1059
|
+
"enableStackTrace",
|
|
1060
|
+
"globalPrefix",
|
|
1061
|
+
"bannerType"
|
|
1062
|
+
];
|
|
1063
|
+
const applied = [];
|
|
1064
|
+
Object.entries(config).forEach(([key, value]) => {
|
|
1065
|
+
if (validKeys.includes(key)) if (key === "theme" && typeof value === "string") {
|
|
1066
|
+
logger.setTheme(value);
|
|
1067
|
+
applied.push(`${key}=${value}`);
|
|
1068
|
+
} else if (key === "bannerType" && typeof value === "string") {
|
|
1069
|
+
logger.setBannerType(value);
|
|
1070
|
+
applied.push(`${key}=${value}`);
|
|
1071
|
+
} else if (key === "verbosity") {
|
|
1072
|
+
logger.setVerbosity(value);
|
|
1073
|
+
applied.push(`${key}=${value}`);
|
|
1074
|
+
} else if (key === "globalPrefix") {
|
|
1075
|
+
logger.setGlobalPrefix(value);
|
|
1076
|
+
applied.push(`${key}=${value}`);
|
|
1077
|
+
} else {
|
|
1078
|
+
logger.updateConfig({ [key]: value });
|
|
1079
|
+
applied.push(`${key}=${value}`);
|
|
1080
|
+
}
|
|
1081
|
+
else logger.warn(`Invalid config key: ${key}`);
|
|
1082
|
+
});
|
|
1083
|
+
if (applied.length > 0) logger.success(`Configuration updated: ${applied.join(", ")}`);
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
//#endregion
|
|
1087
|
+
//#region src/cli/commands/ThemeCommand.ts
|
|
1088
|
+
/**
|
|
1089
|
+
* Comando `/themes` del CLI runtime del {@link Logger}. Lista los presets
|
|
1090
|
+
* temáticos disponibles en {@link THEME_PRESETS}, renderizando una preview
|
|
1091
|
+
* con los colores reales de cada tema (background, foreground, border).
|
|
1092
|
+
*
|
|
1093
|
+
* Es de solo lectura: no muta el logger. Útil para descubrir qué tema
|
|
1094
|
+
* aplicar antes de correr `/config theme=<name>`.
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* // Listar todos los temas con preview coloreada
|
|
1098
|
+
* // > /themes
|
|
1099
|
+
*
|
|
1100
|
+
* @see {@link THEME_PRESETS} para el catálogo completo de temas.
|
|
1101
|
+
* @see {@link ConfigCommand} para aplicar un tema vía `/config theme=...`.
|
|
1102
|
+
*/
|
|
1103
|
+
var ThemesCommand = class {
|
|
1104
|
+
name = "themes";
|
|
1105
|
+
description = "Show available theme presets";
|
|
1106
|
+
usage = "/themes";
|
|
1107
|
+
/**
|
|
1108
|
+
* Ejecuta el comando `/themes` contra el logger dado.
|
|
1109
|
+
*
|
|
1110
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1111
|
+
* @param logger - Instancia usada para abrir/cerrar el `group` de salida.
|
|
1112
|
+
*/
|
|
1113
|
+
execute(_args, logger) {
|
|
1114
|
+
logger.group("🎨 Available Themes");
|
|
1115
|
+
Object.keys(require_styling.THEME_PRESETS).forEach((themeName) => {
|
|
1116
|
+
const preview = require_styling.THEME_PRESETS[themeName];
|
|
1117
|
+
const previewStyle = new require_styling.StyleBuilder().bg(preview.info.background).color(preview.info.color).padding("4px 8px").rounded("4px").border(preview.info.border).build();
|
|
1118
|
+
console.log(`%c${themeName}`, previewStyle, `- ${themeName} theme preview`);
|
|
1119
|
+
});
|
|
1120
|
+
logger.groupEnd();
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
/**
|
|
1124
|
+
* Comando `/banners` del CLI runtime del {@link Logger}. Enumera los tipos
|
|
1125
|
+
* de banner disponibles en {@link BANNER_VARIANTS} (`simple`, `ascii`,
|
|
1126
|
+
* `unicode`, ...) con una mini-preview de cada uno para inspección visual.
|
|
1127
|
+
*
|
|
1128
|
+
* Es de solo lectura: no muta el logger. Para cambiar el banner activo
|
|
1129
|
+
* usar {@link BannerCommand}.
|
|
1130
|
+
*
|
|
1131
|
+
* @example
|
|
1132
|
+
* // Listar todas las variantes de banner con preview
|
|
1133
|
+
* // > /banners
|
|
1134
|
+
*
|
|
1135
|
+
* @see {@link BANNER_VARIANTS} para el catálogo completo de variantes.
|
|
1136
|
+
* @see {@link BannerCommand} para aplicar un tipo concreto.
|
|
1137
|
+
*/
|
|
1138
|
+
var BannersCommand = class {
|
|
1139
|
+
name = "banners";
|
|
1140
|
+
description = "Show available banner types";
|
|
1141
|
+
usage = "/banners";
|
|
1142
|
+
/**
|
|
1143
|
+
* Ejecuta el comando `/banners` contra el logger dado.
|
|
1144
|
+
*
|
|
1145
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1146
|
+
* @param logger - Instancia usada para abrir/cerrar el `group` de salida.
|
|
1147
|
+
*/
|
|
1148
|
+
execute(_args, logger) {
|
|
1149
|
+
logger.group("🖼️ Available Banner Types");
|
|
1150
|
+
Object.keys(require_styling.BANNER_VARIANTS).forEach((bannerName) => {
|
|
1151
|
+
const banner = require_styling.BANNER_VARIANTS[bannerName];
|
|
1152
|
+
console.log(`%c${bannerName}`, "font-weight: bold; color: #667eea;");
|
|
1153
|
+
console.log(`%cPreview:`, "color: #666; font-size: 12px;");
|
|
1154
|
+
if (bannerName === "simple") console.log(`%c${banner.text}`, banner.style);
|
|
1155
|
+
else if (bannerName === "ascii") console.log(`%c${banner.text.split("\n").slice(1, 4).join("\n")}...`, "font-family: monospace; color: #667eea; font-size: 10px;");
|
|
1156
|
+
else if (bannerName === "unicode") console.log(`%c${banner.text}`, banner.style);
|
|
1157
|
+
else console.log(`%c${bannerName} banner`, "color: #666; font-style: italic;");
|
|
1158
|
+
});
|
|
1159
|
+
logger.groupEnd();
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
/**
|
|
1163
|
+
* Comando `/banner [type]` del CLI runtime del {@link Logger}.
|
|
1164
|
+
*
|
|
1165
|
+
* - Sin argumentos: re-renderiza el banner actualmente activo.
|
|
1166
|
+
* - Con un tipo válido: lo aplica vía {@link Logger.setBannerType} y lo
|
|
1167
|
+
* muestra inmediatamente.
|
|
1168
|
+
* - Con un tipo inválido: loguea un `error` listando las opciones válidas.
|
|
1169
|
+
*
|
|
1170
|
+
* @example
|
|
1171
|
+
* // Mostrar el banner actual
|
|
1172
|
+
* // > /banner
|
|
1173
|
+
*
|
|
1174
|
+
* @example
|
|
1175
|
+
* // Cambiar a un tipo concreto
|
|
1176
|
+
* // > /banner ascii
|
|
1177
|
+
*
|
|
1178
|
+
* @see {@link BANNER_VARIANTS} para los tipos aceptados.
|
|
1179
|
+
* @see {@link Logger.setBannerType} y {@link Logger.showBanner} para los
|
|
1180
|
+
* métodos subyacentes.
|
|
1181
|
+
*/
|
|
1182
|
+
var BannerCommand = class {
|
|
1183
|
+
name = "banner";
|
|
1184
|
+
description = "Change or show current banner type";
|
|
1185
|
+
usage = "/banner [type]";
|
|
1186
|
+
/**
|
|
1187
|
+
* Ejecuta el comando `/banner` contra el logger dado.
|
|
1188
|
+
*
|
|
1189
|
+
* @param args - Tipo de banner solicitado. Vacío = mostrar banner actual.
|
|
1190
|
+
* @param logger - Instancia destino cuyo banner se actualiza/muestra.
|
|
1191
|
+
*/
|
|
1192
|
+
execute(args, logger) {
|
|
1193
|
+
if (!args) {
|
|
1194
|
+
logger.showBanner();
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
if (args in require_styling.BANNER_VARIANTS) {
|
|
1198
|
+
logger.setBannerType(args);
|
|
1199
|
+
logger.showBanner();
|
|
1200
|
+
} else logger.error(`Invalid banner type: ${args}. Available: ${Object.keys(require_styling.BANNER_VARIANTS).join(", ")}`);
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
//#endregion
|
|
1204
|
+
//#region src/cli/commands/ExportCommand.ts
|
|
1205
|
+
/**
|
|
1206
|
+
* Comando `/status` del CLI runtime del {@link Logger}. Vuelca la
|
|
1207
|
+
* configuración vigente y algunas estadísticas (theme, verbosity, flags
|
|
1208
|
+
* de features, handler count, bufferSize) en una tabla agrupada dentro
|
|
1209
|
+
* de la consola. Es de solo lectura: no muta el logger.
|
|
1210
|
+
*
|
|
1211
|
+
* @example
|
|
1212
|
+
* // Inspeccionar el estado actual del logger
|
|
1213
|
+
* // > /status
|
|
1214
|
+
*
|
|
1215
|
+
* @see {@link Logger.getConfig} fuente de los datos mostrados.
|
|
1216
|
+
*/
|
|
1217
|
+
var StatusCommand = class {
|
|
1218
|
+
name = "status";
|
|
1219
|
+
description = "Show current logger status and configuration";
|
|
1220
|
+
usage = "/status";
|
|
1221
|
+
/**
|
|
1222
|
+
* Ejecuta el comando `/status` contra el logger dado.
|
|
1223
|
+
*
|
|
1224
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1225
|
+
* @param logger - Instancia de la que se lee la configuración.
|
|
1226
|
+
*/
|
|
1227
|
+
execute(_args, logger) {
|
|
1228
|
+
const config = logger.getConfig();
|
|
1229
|
+
const statusData = {
|
|
1230
|
+
theme: config.theme ? config.theme : "default",
|
|
1231
|
+
verbosity: config.verbosity,
|
|
1232
|
+
colors: config.enableColors,
|
|
1233
|
+
timestamps: config.enableTimestamps,
|
|
1234
|
+
stackTrace: config.enableStackTrace,
|
|
1235
|
+
globalPrefix: config.globalPrefix ? config.globalPrefix : "none",
|
|
1236
|
+
bannerType: config.bannerType ? config.bannerType : "simple",
|
|
1237
|
+
handlers: logger.getHandlers().length,
|
|
1238
|
+
bufferSize: config.bufferSize ? config.bufferSize : 1e3
|
|
1239
|
+
};
|
|
1240
|
+
logger.group("⚙️ Logger Configuration");
|
|
1241
|
+
logger.table(statusData);
|
|
1242
|
+
logger.groupEnd();
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
/**
|
|
1246
|
+
* Comando `/reset` del CLI runtime del {@link Logger}. Restaura la
|
|
1247
|
+
* configuración a sus defaults de fábrica vía {@link Logger.resetConfig}.
|
|
1248
|
+
* No resetea handlers ni transports registrados — solo config.
|
|
1249
|
+
*
|
|
1250
|
+
* @example
|
|
1251
|
+
* // Volver a la configuración por defecto
|
|
1252
|
+
* // > /reset
|
|
1253
|
+
*
|
|
1254
|
+
* @see {@link Logger.resetConfig} para el método subyacente.
|
|
1255
|
+
*/
|
|
1256
|
+
var ResetCommand = class {
|
|
1257
|
+
name = "reset";
|
|
1258
|
+
description = "Reset logger configuration to defaults";
|
|
1259
|
+
usage = "/reset";
|
|
1260
|
+
/**
|
|
1261
|
+
* Ejecuta el comando `/reset` contra el logger dado.
|
|
1262
|
+
*
|
|
1263
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1264
|
+
* @param logger - Instancia cuya configuración se resetea.
|
|
1265
|
+
*/
|
|
1266
|
+
execute(_args, logger) {
|
|
1267
|
+
logger.resetConfig();
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
/**
|
|
1271
|
+
* Comando `/demo` del CLI runtime del {@link Logger}. Ejecuta una
|
|
1272
|
+
* demostración integral de las capacidades del logger: todos los niveles
|
|
1273
|
+
* de log (debug → critical), tablas, timers (`time`/`timeEnd`), SVG inline
|
|
1274
|
+
* y mensajes animados. Útil para validar que el styling funciona en un
|
|
1275
|
+
* entorno nuevo o tras un cambio de tema.
|
|
1276
|
+
*
|
|
1277
|
+
* @example
|
|
1278
|
+
* // Lanzar la demo completa
|
|
1279
|
+
* // > /demo
|
|
1280
|
+
*
|
|
1281
|
+
* @see {@link Logger} para cada feature individual (`table`, `time`,
|
|
1282
|
+
* `logWithSVG`, `logAnimated`, ...).
|
|
1283
|
+
*/
|
|
1284
|
+
var DemoCommand = class {
|
|
1285
|
+
name = "demo";
|
|
1286
|
+
description = "Show comprehensive feature demonstration";
|
|
1287
|
+
usage = "/demo";
|
|
1288
|
+
/**
|
|
1289
|
+
* Ejecuta el comando `/demo` contra el logger dado.
|
|
1290
|
+
*
|
|
1291
|
+
* @param _args - Ignorado (comando sin parámetros).
|
|
1292
|
+
* @param logger - Instancia sobre la que se ejecutan los ejemplos.
|
|
1293
|
+
*/
|
|
1294
|
+
execute(_args, logger) {
|
|
1295
|
+
logger.group("🎪 Advanced Logger Demo");
|
|
1296
|
+
logger.debug("Debug message with detailed information");
|
|
1297
|
+
logger.info("Informational message about system state");
|
|
1298
|
+
logger.warn("Warning about deprecated feature");
|
|
1299
|
+
logger.error("Error processing user request");
|
|
1300
|
+
logger.success("Operation completed successfully");
|
|
1301
|
+
logger.critical("Critical system failure detected");
|
|
1302
|
+
logger.group("📊 Advanced Features Demo");
|
|
1303
|
+
logger.table([
|
|
1304
|
+
{
|
|
1305
|
+
feature: "Styled Console",
|
|
1306
|
+
status: "✅ Active",
|
|
1307
|
+
performance: "Excellent"
|
|
1308
|
+
},
|
|
1309
|
+
{
|
|
1310
|
+
feature: "Theme System",
|
|
1311
|
+
status: "✅ Active",
|
|
1312
|
+
performance: "Great"
|
|
1313
|
+
},
|
|
1314
|
+
{
|
|
1315
|
+
feature: "CLI Interface",
|
|
1316
|
+
status: "✅ Active",
|
|
1317
|
+
performance: "Good"
|
|
1318
|
+
},
|
|
1319
|
+
{
|
|
1320
|
+
feature: "Export System",
|
|
1321
|
+
status: "✅ Active",
|
|
1322
|
+
performance: "Excellent"
|
|
1323
|
+
}
|
|
1324
|
+
]);
|
|
1325
|
+
logger.time("demo-operation");
|
|
1326
|
+
setTimeout(() => {
|
|
1327
|
+
logger.timeEnd("demo-operation");
|
|
1328
|
+
}, 100);
|
|
1329
|
+
logger.logWithSVG("SVG Demo");
|
|
1330
|
+
logger.logAnimated("🌟 Animated Logger Demo 🌟", 2);
|
|
1331
|
+
logger.groupEnd();
|
|
1332
|
+
logger.groupEnd();
|
|
1333
|
+
logger.info("Demo completed! Check the console for styled output.");
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
//#endregion
|
|
1337
|
+
//#region src/cli/help.ts
|
|
1338
|
+
/**
|
|
1339
|
+
* Comando `/help`: renderiza en consola el panel de ayuda del CLI con todos
|
|
1340
|
+
* los comandos disponibles, opciones de configuración, filtros de export y
|
|
1341
|
+
* ejemplos. El panel usa un gradient claro con {@link StyleBuilder} y los
|
|
1342
|
+
* quick tips se agrupan vía `logger.group`.
|
|
1343
|
+
*
|
|
1344
|
+
* Registrado por defecto por {@link createDefaultCLI}.
|
|
1345
|
+
*
|
|
1346
|
+
* @example
|
|
1347
|
+
* ```ts
|
|
1348
|
+
* const cli = createDefaultCLI();
|
|
1349
|
+
* await cli.processCommand('/help', logger);
|
|
1350
|
+
* // Imprime el panel ASCII con gradient + grupo "Quick Tips".
|
|
1351
|
+
* ```
|
|
1352
|
+
*
|
|
1353
|
+
* @see {@link ICommand}
|
|
1354
|
+
* @see {@link createDefaultCLI}
|
|
1355
|
+
*/
|
|
1356
|
+
var HelpCommand = class {
|
|
1357
|
+
name = "help";
|
|
1358
|
+
description = "Show CLI help and available commands";
|
|
1359
|
+
usage = "/help [command]";
|
|
1360
|
+
/**
|
|
1361
|
+
* Renderiza el panel de ayuda completo. Actualmente ignora `_args`: el
|
|
1362
|
+
* `usage` declara `/help [command]` (sub-comando opcional) pero la
|
|
1363
|
+
* implementación siempre muestra el panel global.
|
|
1364
|
+
*
|
|
1365
|
+
* @param {string} _args - Argumentos opcionales (reservado para ayuda por
|
|
1366
|
+
* sub-comando; sin uso actual).
|
|
1367
|
+
* @param {Logger} logger - Logger activo; se usa solo para `group`/`info`
|
|
1368
|
+
* de los quick tips.
|
|
1369
|
+
* @returns {void}
|
|
1370
|
+
*/
|
|
1371
|
+
execute(_args, logger) {
|
|
1372
|
+
const helpStyle = new require_styling.StyleBuilder().bg("linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%)").color("#495057").padding("15px 20px").rounded("8px").border("1px solid #dee2e6").font("Monaco, Consolas, monospace").size("13px").build();
|
|
1373
|
+
console.log(`%c
|
|
1374
|
+
╭─────────────── ADVANCED LOGGER CLI COMMANDS ─────────────────╮
|
|
1375
|
+
│ │
|
|
1376
|
+
│ CONFIGURATION │
|
|
1377
|
+
│ /config Show current configuration │
|
|
1378
|
+
│ /config {json} Apply JSON configuration │
|
|
1379
|
+
│ /config key=val Apply key-value configuration │
|
|
1380
|
+
│ /themes Show available themes │
|
|
1381
|
+
│ /banners Show available banner types │
|
|
1382
|
+
│ /banner [type] Change/show banner type │
|
|
1383
|
+
│ /status Show logger status & buffer stats │
|
|
1384
|
+
│ /demo Show feature demonstration │
|
|
1385
|
+
│ /reset Reset to default configuration │
|
|
1386
|
+
│ │
|
|
1387
|
+
│ EXPORT & CLIPBOARD │
|
|
1388
|
+
│ /export <format> Export logs (json|csv|md|plain|html) │
|
|
1389
|
+
│ /copy <format> Copy logs to clipboard │
|
|
1390
|
+
│ /buffer-size N Set log buffer size │
|
|
1391
|
+
│ /buffer-info Show buffer statistics │
|
|
1392
|
+
│ /clear-buffer Clear stored logs │
|
|
1393
|
+
│ │
|
|
1394
|
+
│ EXPORT FILTERS (for export/copy commands) │
|
|
1395
|
+
│ --level error,warn Filter by log levels │
|
|
1396
|
+
│ --since 2h Logs from last 2 hours │
|
|
1397
|
+
│ --until 1h Logs until 1 hour ago │
|
|
1398
|
+
│ --prefix API,DB Filter by prefixes │
|
|
1399
|
+
│ --exclude-prefix INT Exclude prefixes │
|
|
1400
|
+
│ --last 50 Last 50 logs only │
|
|
1401
|
+
│ --first 25 First 25 logs only │
|
|
1402
|
+
│ --search "error" Search in log messages │
|
|
1403
|
+
│ --with-stack Only logs with stack traces │
|
|
1404
|
+
│ --errors-only Only error + critical logs │
|
|
1405
|
+
│ --group-by level Group by level/prefix/hour │
|
|
1406
|
+
│ │
|
|
1407
|
+
│ EXPORT OPTIONS │
|
|
1408
|
+
│ --minimal Minimal output format │
|
|
1409
|
+
│ --compact Remove extra whitespace │
|
|
1410
|
+
│ --styled Include styling (HTML format) │
|
|
1411
|
+
│ │
|
|
1412
|
+
├──────────────────── CONFIGURATION OPTIONS ─────────────────┤
|
|
1413
|
+
│ │
|
|
1414
|
+
│ theme: default | dark | light | neon | minimal | cyberpunk│
|
|
1415
|
+
│ bannerType: simple | ascii | unicode | svg | animated │
|
|
1416
|
+
│ verbosity: debug | info | warn | error | critical | silent│
|
|
1417
|
+
│ enableColors: true | false │
|
|
1418
|
+
│ enableTimestamps: true | false │
|
|
1419
|
+
│ enableStackTrace: true | false │
|
|
1420
|
+
│ globalPrefix: "string" │
|
|
1421
|
+
│ bufferSize: number (50-10000) │
|
|
1422
|
+
│ │
|
|
1423
|
+
├──────────────────────── EXAMPLES ──────────────────────────┤
|
|
1424
|
+
│ │
|
|
1425
|
+
│ Basic Configuration: │
|
|
1426
|
+
│ /config {"theme":"dark","verbosity":"debug"} │
|
|
1427
|
+
│ /config theme=neon,bufferSize=2000 │
|
|
1428
|
+
│ /banner animated Change to animated banner │
|
|
1429
|
+
│ │
|
|
1430
|
+
│ Export Examples: │
|
|
1431
|
+
│ /export json --level=error,warn --last=25 │
|
|
1432
|
+
│ /export csv --since=2h --prefix=API │
|
|
1433
|
+
│ /export markdown --group-by=level --errors-only │
|
|
1434
|
+
│ /export html --styled --since=1h │
|
|
1435
|
+
│ │
|
|
1436
|
+
│ Clipboard Examples: │
|
|
1437
|
+
│ /copy plain --minimal --last=10 │
|
|
1438
|
+
│ /copy json --search="authentication" --compact │
|
|
1439
|
+
│ /copy csv --since=30m --exclude-prefix=DEBUG │
|
|
1440
|
+
│ │
|
|
1441
|
+
│ Buffer Management: │
|
|
1442
|
+
│ /buffer-size 5000 Increase buffer to 5000 logs │
|
|
1443
|
+
│ /buffer-info Show detailed buffer statistics │
|
|
1444
|
+
│ /clear-buffer Clear all stored logs │
|
|
1445
|
+
│ │
|
|
1446
|
+
│ Time Formats: │
|
|
1447
|
+
│ --since=2h 2 hours ago │
|
|
1448
|
+
│ --since=30m 30 minutes ago │
|
|
1449
|
+
│ --since=1d 1 day ago │
|
|
1450
|
+
│ --since="2024-01-01T10:00:00Z" Specific ISO date │
|
|
1451
|
+
│ │
|
|
1452
|
+
╰─────────────────────────────────────────────────────────────╯`, helpStyle);
|
|
1453
|
+
logger.group("💡 Quick Tips");
|
|
1454
|
+
[
|
|
1455
|
+
"Use /demo to see all logger features in action",
|
|
1456
|
+
"Logs are automatically stored in a circular buffer for export",
|
|
1457
|
+
"Export formats: JSON (structured), CSV (Excel), Markdown (readable), Plain (simple), HTML (styled)",
|
|
1458
|
+
"Time filters support relative (2h, 30m) and absolute (ISO) formats",
|
|
1459
|
+
"Combine multiple filters: /export json --level=error --since=1h --search=\"auth\"",
|
|
1460
|
+
"Use /copy for quick clipboard access instead of /export"
|
|
1461
|
+
].forEach((tip) => {
|
|
1462
|
+
logger.info(`• ${tip}`);
|
|
1463
|
+
});
|
|
1464
|
+
logger.groupEnd();
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
//#endregion
|
|
1468
|
+
//#region src/cli/index.ts
|
|
1469
|
+
/**
|
|
1470
|
+
* Crea un {@link CommandProcessor} con los 8 comandos estándar ya registrados:
|
|
1471
|
+
* `help`, `config`, `themes`, `banners`, `banner`, `status`, `reset` y
|
|
1472
|
+
* `demo`. Es el factory canónico — los consumidores normalmente no construyen
|
|
1473
|
+
* un `CommandProcessor` vacío a mano, ya que este no trae comandos cargados.
|
|
1474
|
+
*
|
|
1475
|
+
* @returns {CommandProcessor} Processor listo para usar, sin modo interactivo activo.
|
|
1476
|
+
*
|
|
1477
|
+
* @example
|
|
1478
|
+
* ```ts
|
|
1479
|
+
* const cli = createDefaultCLI();
|
|
1480
|
+
* await cli.processCommand('/help', logger);
|
|
1481
|
+
* await cli.processCommand('/config theme=neon', logger);
|
|
1482
|
+
* ```
|
|
1483
|
+
*
|
|
1484
|
+
* @example
|
|
1485
|
+
* ```ts
|
|
1486
|
+
* // Modo interactivo en el navegador: expone `window.cli`
|
|
1487
|
+
* const cli = createDefaultCLI();
|
|
1488
|
+
* cli.enterInteractiveMode(logger);
|
|
1489
|
+
* // desde devtools: cli('themes') → procesa '/themes'
|
|
1490
|
+
* ```
|
|
1491
|
+
*
|
|
1492
|
+
* @see {@link CommandProcessor}
|
|
1493
|
+
* @see {@link HelpCommand}
|
|
1494
|
+
*/
|
|
1495
|
+
function createDefaultCLI() {
|
|
1496
|
+
const processor = new CommandProcessor();
|
|
1497
|
+
processor.registerCommand(new HelpCommand());
|
|
1498
|
+
processor.registerCommand(new ConfigCommand());
|
|
1499
|
+
processor.registerCommand(new ThemesCommand());
|
|
1500
|
+
processor.registerCommand(new BannersCommand());
|
|
1501
|
+
processor.registerCommand(new BannerCommand());
|
|
1502
|
+
processor.registerCommand(new StatusCommand());
|
|
1503
|
+
processor.registerCommand(new ResetCommand());
|
|
1504
|
+
processor.registerCommand(new DemoCommand());
|
|
1505
|
+
return processor;
|
|
1506
|
+
}
|
|
1507
|
+
//#endregion
|
|
1508
|
+
//#region src/transports/TransportBridge.ts
|
|
1509
|
+
/**
|
|
1510
|
+
* Crea una instancia de {@link TransportBridge}.
|
|
1511
|
+
*
|
|
1512
|
+
* @internal
|
|
1513
|
+
*/
|
|
1514
|
+
function createTransportBridge() {
|
|
1515
|
+
let transportManager;
|
|
1516
|
+
return {
|
|
1517
|
+
addTransport(target) {
|
|
1518
|
+
if (!transportManager) transportManager = new require_transports.TransportManager();
|
|
1519
|
+
return transportManager.add(target);
|
|
1520
|
+
},
|
|
1521
|
+
removeTransport(id) {
|
|
1522
|
+
return transportManager?.remove(id) ?? false;
|
|
1523
|
+
},
|
|
1524
|
+
async flushTransports() {
|
|
1525
|
+
await transportManager?.flush();
|
|
1526
|
+
},
|
|
1527
|
+
async closeTransports() {
|
|
1528
|
+
await transportManager?.close();
|
|
1529
|
+
},
|
|
1530
|
+
getTransportManager() {
|
|
1531
|
+
return transportManager;
|
|
1532
|
+
},
|
|
1533
|
+
writeRecord(record) {
|
|
1534
|
+
if (!transportManager) return;
|
|
1535
|
+
transportManager.write(record).catch(() => {});
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
//#endregion
|
|
1540
|
+
//#region src/playground/TerminalBridge.ts
|
|
1541
|
+
/**
|
|
1542
|
+
* Crea un {@link TerminalBridge} usando un getter para evitar referencias
|
|
1543
|
+
* circulares en la construcción.
|
|
1544
|
+
*
|
|
1545
|
+
* @internal
|
|
1546
|
+
*/
|
|
1547
|
+
function createTerminalBridge(options) {
|
|
1548
|
+
let _showPrimitives = true;
|
|
1549
|
+
let _serverFallback;
|
|
1550
|
+
return {
|
|
1551
|
+
step(current, total, message) {
|
|
1552
|
+
if (!_showPrimitives) return;
|
|
1553
|
+
if (!require_environment_detector.isRunningInTerminal()) {
|
|
1554
|
+
this.getServerFallback().step(current, total, message);
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const output = require_spinner.renderStep(current, total, message, require_environment_detector.getColorCapability());
|
|
1558
|
+
process.stderr.write(output + "\n");
|
|
1559
|
+
},
|
|
1560
|
+
header(title, subtitle) {
|
|
1561
|
+
if (!_showPrimitives) return;
|
|
1562
|
+
if (!require_environment_detector.isRunningInTerminal()) {
|
|
1563
|
+
this.getServerFallback().header(title, subtitle);
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
const output = require_spinner.renderHeader(title, subtitle);
|
|
1567
|
+
process.stderr.write(output + "\n");
|
|
1568
|
+
},
|
|
1569
|
+
divider() {
|
|
1570
|
+
if (!_showPrimitives) return;
|
|
1571
|
+
if (!require_environment_detector.isRunningInTerminal()) {
|
|
1572
|
+
this.getServerFallback().divider();
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
const output = require_spinner.renderDivider();
|
|
1576
|
+
process.stderr.write(output + "\n");
|
|
1577
|
+
},
|
|
1578
|
+
blank() {
|
|
1579
|
+
if (!_showPrimitives) return;
|
|
1580
|
+
if (!require_environment_detector.isRunningInTerminal()) {
|
|
1581
|
+
this.getServerFallback().blank();
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
process.stderr.write("\n");
|
|
1585
|
+
},
|
|
1586
|
+
box(content, opts) {
|
|
1587
|
+
if (!_showPrimitives) return;
|
|
1588
|
+
if (!require_environment_detector.isRunningInTerminal()) {
|
|
1589
|
+
this.getServerFallback().box(content, opts);
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
const output = require_spinner.renderBox(content, opts, require_environment_detector.getColorCapability());
|
|
1593
|
+
process.stderr.write(output + "\n");
|
|
1594
|
+
},
|
|
1595
|
+
cliTable(rows, opts) {
|
|
1596
|
+
if (!_showPrimitives) return;
|
|
1597
|
+
if (!require_environment_detector.isRunningInTerminal()) {
|
|
1598
|
+
this.getServerFallback().cliTable(rows, opts);
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
const output = require_spinner.renderTable(rows, opts, require_environment_detector.getColorCapability());
|
|
1602
|
+
process.stderr.write(output + "\n");
|
|
1603
|
+
},
|
|
1604
|
+
spinner(message) {
|
|
1605
|
+
const logger = options.getLogger();
|
|
1606
|
+
if (!require_environment_detector.isRunningInTerminal() || options.config.outputMode === "silent") return new require_spinner.NoopSpinner(message, logger);
|
|
1607
|
+
return new require_spinner.SpinnerManager(message, options.config, logger);
|
|
1608
|
+
},
|
|
1609
|
+
getShowPrimitives() {
|
|
1610
|
+
return _showPrimitives;
|
|
1611
|
+
},
|
|
1612
|
+
setShowPrimitives(show) {
|
|
1613
|
+
_showPrimitives = show;
|
|
1614
|
+
},
|
|
1615
|
+
getServerFallback() {
|
|
1616
|
+
if (!_serverFallback) _serverFallback = new require_server_fallback.ServerFallback(options.getLogger());
|
|
1617
|
+
return _serverFallback;
|
|
1618
|
+
},
|
|
1619
|
+
isInTerminal() {
|
|
1620
|
+
return require_environment_detector.isRunningInTerminal();
|
|
1621
|
+
}
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
//#endregion
|
|
1625
|
+
//#region src/Logger.ts
|
|
1626
|
+
require_styling.THEME_PRESETS.default;
|
|
1627
|
+
/**
|
|
1628
|
+
* Clase principal Logger con capacidades avanzadas de logging
|
|
1629
|
+
*
|
|
1630
|
+
* @class Logger
|
|
1631
|
+
* @description Sistema completo de logging con temas, badges, contextos y exportación.
|
|
1632
|
+
* Detecta automáticamente el tema claro/oscuro del navegador.
|
|
1633
|
+
*
|
|
1634
|
+
* @example
|
|
1635
|
+
* // Uso básico sin configuración
|
|
1636
|
+
* import logger from '@mks2508/better-logger';
|
|
1637
|
+
* logger.info('Aplicación iniciada');
|
|
1638
|
+
* logger.success('Conexión establecida');
|
|
1639
|
+
*
|
|
1640
|
+
* @example
|
|
1641
|
+
* // Aplicar un preset temático
|
|
1642
|
+
* logger.preset('cyberpunk');
|
|
1643
|
+
* logger.warn('Advertencia con estilo neón');
|
|
1644
|
+
*
|
|
1645
|
+
* @example
|
|
1646
|
+
* // Logger con scope para componentes
|
|
1647
|
+
* const auth = logger.component('Autenticación');
|
|
1648
|
+
* auth.info('Usuario intentando login');
|
|
1649
|
+
* auth.success('Login exitoso');
|
|
1650
|
+
*
|
|
1651
|
+
*/
|
|
1652
|
+
var Logger = class Logger {
|
|
1653
|
+
config;
|
|
1654
|
+
scopedPrefix;
|
|
1655
|
+
handlers = [];
|
|
1656
|
+
timers = /* @__PURE__ */ new Map();
|
|
1657
|
+
groupDepth = 0;
|
|
1658
|
+
cliProcessor;
|
|
1659
|
+
themeChangeListener;
|
|
1660
|
+
badgeList = [];
|
|
1661
|
+
displaySettings = {
|
|
1662
|
+
showTimestamp: true,
|
|
1663
|
+
showLocation: true,
|
|
1664
|
+
showBadges: true
|
|
1665
|
+
};
|
|
1666
|
+
serializerBridge;
|
|
1667
|
+
hookBridge;
|
|
1668
|
+
logContext;
|
|
1669
|
+
transportBridge;
|
|
1670
|
+
/** Fijado por `success()` para que `log()` salte su propio dispatch. */
|
|
1671
|
+
_successTagDispatched = false;
|
|
1672
|
+
styleManager;
|
|
1673
|
+
/** Controla si las CLI primitives (step, box, header, ...) deben renderizarse. */
|
|
1674
|
+
_showPrimitives = true;
|
|
1675
|
+
terminalBridge;
|
|
1676
|
+
/**
|
|
1677
|
+
* Referencia activa al smart-preset (fijada por `preset()`). Tipada como
|
|
1678
|
+
* `unknown` para mantener limpia la surface pública; la consume
|
|
1679
|
+
* `createStyledOutput`.
|
|
1680
|
+
*/
|
|
1681
|
+
_activePreset;
|
|
1682
|
+
/**
|
|
1683
|
+
* Nombre del smart-preset activo. Se guarda aparte para que la detección
|
|
1684
|
+
* de cambio de tema pueda re-renderizar sin re-ejecutar el body del preset.
|
|
1685
|
+
*/
|
|
1686
|
+
_activePresetName;
|
|
1687
|
+
/**
|
|
1688
|
+
* Overrides aplicados por el último `customize()`. Se conservan para que
|
|
1689
|
+
* `createStyledOutput` los lea después.
|
|
1690
|
+
*/
|
|
1691
|
+
_customization;
|
|
1692
|
+
/**
|
|
1693
|
+
* Bindings propios de este logger (provenientes de llamadas a `child()`).
|
|
1694
|
+
* Source of truth única de la contribución de este logger a la cadena de contexto.
|
|
1695
|
+
* @private
|
|
1696
|
+
*/
|
|
1697
|
+
_bindings = {};
|
|
1698
|
+
/**
|
|
1699
|
+
* Referencia al record de contexto mergueado del parent en el momento en
|
|
1700
|
+
* que se creó este logger. Junto con `_bindings`, forma la cadena de
|
|
1701
|
+
* contexto. `undefined` para el logger raíz.
|
|
1702
|
+
* @private
|
|
1703
|
+
*/
|
|
1704
|
+
_parentContextRecord;
|
|
1705
|
+
/**
|
|
1706
|
+
* Crea una nueva instancia del Logger
|
|
1707
|
+
*
|
|
1708
|
+
* @param {Partial<LoggerConfig>} config - Configuración opcional del logger
|
|
1709
|
+
*
|
|
1710
|
+
* @example
|
|
1711
|
+
* // Logger con configuración personalizada
|
|
1712
|
+
* const logger = new Logger({
|
|
1713
|
+
* theme: 'neon',
|
|
1714
|
+
* globalPrefix: 'MiApp',
|
|
1715
|
+
* verbosity: 'debug',
|
|
1716
|
+
* bufferSize: 1000
|
|
1717
|
+
* });
|
|
1718
|
+
*/
|
|
1719
|
+
constructor(config = {}) {
|
|
1720
|
+
this.config = {
|
|
1721
|
+
...require_utils.DEFAULT_CONFIG,
|
|
1722
|
+
...config
|
|
1723
|
+
};
|
|
1724
|
+
this.serializerBridge = require_SerializerBridge.createSerializerBridge();
|
|
1725
|
+
this.hookBridge = require_HookBridge.createHookBridge();
|
|
1726
|
+
this.logContext = require_LogContext.createLogContext({
|
|
1727
|
+
initialResource: this.config.resource,
|
|
1728
|
+
childLoggerFactory: (childConfig) => {
|
|
1729
|
+
return new Logger({
|
|
1730
|
+
...this.config,
|
|
1731
|
+
...childConfig
|
|
1732
|
+
});
|
|
1733
|
+
},
|
|
1734
|
+
getParentContextRecord: () => this._captureMergedContext()
|
|
1735
|
+
});
|
|
1736
|
+
this.transportBridge = createTransportBridge();
|
|
1737
|
+
this.styleManager = require_StyleManager.createStyleManager();
|
|
1738
|
+
this.terminalBridge = createTerminalBridge({
|
|
1739
|
+
config: this.config,
|
|
1740
|
+
getLogger: () => this
|
|
1741
|
+
});
|
|
1742
|
+
this.cliProcessor = createDefaultCLI();
|
|
1743
|
+
if (this.config.autoDetectTheme) this.setupAutoThemeDetection();
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Configura la detección automática de tema con listener de cambios
|
|
1747
|
+
* @private
|
|
1748
|
+
* @description Detecta automáticamente si el navegador está en modo claro u oscuro
|
|
1749
|
+
*/
|
|
1750
|
+
setupAutoThemeDetection() {
|
|
1751
|
+
if (this.themeChangeListener) {
|
|
1752
|
+
this.themeChangeListener();
|
|
1753
|
+
this.themeChangeListener = null;
|
|
1754
|
+
}
|
|
1755
|
+
this.themeChangeListener = require_utils.setupThemeChangeListener((theme) => {
|
|
1756
|
+
this.debug(`DevTools theme changed to: ${theme}`);
|
|
1757
|
+
});
|
|
1758
|
+
}
|
|
1759
|
+
/**
|
|
1760
|
+
* Obtiene la configuración actual del logger
|
|
1761
|
+
*
|
|
1762
|
+
* @returns {LoggerConfig} Configuración completa actual
|
|
1763
|
+
*
|
|
1764
|
+
* @example
|
|
1765
|
+
* const config = logger.getConfig();
|
|
1766
|
+
* console.log('Verbosidad actual:', config.verbosity);
|
|
1767
|
+
* console.log('Tema actual:', config.theme);
|
|
1768
|
+
*
|
|
1769
|
+
*/
|
|
1770
|
+
getConfig() {
|
|
1771
|
+
return { ...this.config };
|
|
1772
|
+
}
|
|
1773
|
+
/**
|
|
1774
|
+
* Actualiza la configuración del logger
|
|
1775
|
+
*
|
|
1776
|
+
* @param {Partial<LoggerConfig>} updates - Propiedades a actualizar
|
|
1777
|
+
*
|
|
1778
|
+
* @example
|
|
1779
|
+
* logger.updateConfig({
|
|
1780
|
+
* verbosity: 'debug',
|
|
1781
|
+
* enableTimestamps: false,
|
|
1782
|
+
* theme: 'cyberpunk'
|
|
1783
|
+
* });
|
|
1784
|
+
*
|
|
1785
|
+
*/
|
|
1786
|
+
updateConfig(updates) {
|
|
1787
|
+
const previousAutoDetect = this.config.autoDetectTheme;
|
|
1788
|
+
this.config = {
|
|
1789
|
+
...this.config,
|
|
1790
|
+
...updates
|
|
1791
|
+
};
|
|
1792
|
+
if (updates.autoDetectTheme !== void 0 && updates.autoDetectTheme !== previousAutoDetect) {
|
|
1793
|
+
if (updates.autoDetectTheme) this.setupAutoThemeDetection();
|
|
1794
|
+
else if (this.themeChangeListener) {
|
|
1795
|
+
this.themeChangeListener();
|
|
1796
|
+
this.themeChangeListener = null;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Establece el prefijo global para todos los mensajes de log
|
|
1802
|
+
*
|
|
1803
|
+
* @param {string} prefix - Prefijo a usar
|
|
1804
|
+
*
|
|
1805
|
+
* @example
|
|
1806
|
+
* logger.setGlobalPrefix('MiApp');
|
|
1807
|
+
* logger.info('Iniciado'); // [MiApp] Iniciado
|
|
1808
|
+
*
|
|
1809
|
+
*/
|
|
1810
|
+
setGlobalPrefix(prefix) {
|
|
1811
|
+
this.config.globalPrefix = prefix;
|
|
1812
|
+
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Establece el nivel de verbosidad para filtrar la salida de logs
|
|
1815
|
+
*
|
|
1816
|
+
* @param {Verbosity} level - Nivel mínimo a mostrar ('debug' | 'info' | 'warn' | 'error' | 'critical' | 'silent')
|
|
1817
|
+
*
|
|
1818
|
+
* @example
|
|
1819
|
+
* logger.setVerbosity('warn'); // Solo muestra warn, error y critical
|
|
1820
|
+
* logger.setVerbosity('debug'); // Muestra todos los niveles
|
|
1821
|
+
* logger.setVerbosity('silent'); // No muestra nada
|
|
1822
|
+
*
|
|
1823
|
+
*/
|
|
1824
|
+
setVerbosity(level) {
|
|
1825
|
+
this.config.verbosity = level;
|
|
1826
|
+
}
|
|
1827
|
+
/**
|
|
1828
|
+
* Establece el tema del logger
|
|
1829
|
+
*
|
|
1830
|
+
* @param {ThemeVariant} theme - Tema a aplicar ('default' | 'dark' | 'light' | 'neon' | 'minimal' | 'cyberpunk')
|
|
1831
|
+
*
|
|
1832
|
+
* @example
|
|
1833
|
+
* logger.setTheme('neon'); // Tema con colores neón
|
|
1834
|
+
* logger.setTheme('minimal'); // Tema minimalista
|
|
1835
|
+
* logger.setTheme('cyberpunk'); // Tema cyberpunk con efectos
|
|
1836
|
+
*
|
|
1837
|
+
*/
|
|
1838
|
+
setTheme(theme) {
|
|
1839
|
+
if (require_styling.hasPreset(theme)) {
|
|
1840
|
+
this.preset(theme);
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
if (this.styleManager.setTheme(theme)) {
|
|
1844
|
+
this.config.theme = theme;
|
|
1845
|
+
const bannersRecord = require_styling.THEME_BANNERS;
|
|
1846
|
+
if (theme in bannersRecord) {
|
|
1847
|
+
const themeBanner = bannersRecord[theme];
|
|
1848
|
+
if (themeBanner) this.writeOutput(`%c${themeBanner.simple}`, "info", [themeBanner.style], []);
|
|
1849
|
+
}
|
|
1850
|
+
this.success(`Theme changed to: ${theme}`);
|
|
1851
|
+
} else this.error(`Invalid theme: ${theme}. Available:`, [...require_styling.getAvailablePresets(), ...Object.keys(require_styling.THEME_PRESETS)]);
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Establece el tipo de banner para mostrar en la inicialización
|
|
1855
|
+
*
|
|
1856
|
+
* @param {BannerType} bannerType - Tipo de banner ('simple' | 'ascii' | 'unicode' | 'svg' | 'animated')
|
|
1857
|
+
*
|
|
1858
|
+
* @example
|
|
1859
|
+
* logger.setBannerType('ascii'); // Banner con arte ASCII
|
|
1860
|
+
* logger.setBannerType('unicode'); // Banner con caracteres Unicode
|
|
1861
|
+
* logger.setBannerType('animated'); // Banner con animación
|
|
1862
|
+
*
|
|
1863
|
+
*/
|
|
1864
|
+
setBannerType(bannerType) {
|
|
1865
|
+
this.config.bannerType = bannerType;
|
|
1866
|
+
this.success(`Banner type changed to: ${bannerType}`);
|
|
1867
|
+
}
|
|
1868
|
+
/**
|
|
1869
|
+
* Ejecuta `fn` dentro de un scope AsyncLocalStorage donde `bindings` se
|
|
1870
|
+
* merguean al contexto para todas las llamadas de log dentro de `fn`.
|
|
1871
|
+
*
|
|
1872
|
+
* Sin `fn` (el shape legacy de setter): no-op por backwards compatibility.
|
|
1873
|
+
* Preferir `child()` para bindings persistentes o `withContextAsync()`
|
|
1874
|
+
* para callbacks async.
|
|
1875
|
+
*
|
|
1876
|
+
* @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
|
|
1877
|
+
* @param fn - Función sincrónica opcional a ejecutar con los bindings en scope
|
|
1878
|
+
* @returns El valor de retorno de `fn`, o `undefined` si no se pasa `fn`
|
|
1879
|
+
*
|
|
1880
|
+
* @example
|
|
1881
|
+
* // Callback sincrónico scoped
|
|
1882
|
+
* logger.withContext({ requestId: 'r-42' }, () => {
|
|
1883
|
+
* doWork(); // los logs de aquí ven requestId en attributes
|
|
1884
|
+
* });
|
|
1885
|
+
*
|
|
1886
|
+
* @example
|
|
1887
|
+
* // Binding persistente: usar child()
|
|
1888
|
+
* const reqLog = logger.child({ requestId: 'r-42' });
|
|
1889
|
+
* reqLog.info('handling request'); // attributes incluye requestId
|
|
1890
|
+
*
|
|
1891
|
+
* @see {@link child} para una copia inmutable con el contexto mergueado
|
|
1892
|
+
* @see {@link withContextAsync} para la variante con callback async
|
|
1893
|
+
*/
|
|
1894
|
+
withContext(bindings, fn) {
|
|
1895
|
+
return this.logContext.withContext(bindings, fn);
|
|
1896
|
+
}
|
|
1897
|
+
/**
|
|
1898
|
+
* Variante async de `withContext`. Ejecuta `fn` dentro de un scope
|
|
1899
|
+
* AsyncLocalStorage para que los bindings estén disponibles a todas las
|
|
1900
|
+
* llamadas de log async dentro de `fn`.
|
|
1901
|
+
*
|
|
1902
|
+
* @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
|
|
1903
|
+
* @param fn - Función async a ejecutar con los bindings en scope
|
|
1904
|
+
* @returns El valor de retorno de `fn`
|
|
1905
|
+
*
|
|
1906
|
+
* @example
|
|
1907
|
+
* await logger.withContextAsync({ requestId: 'r-42' }, async () => {
|
|
1908
|
+
* await fetchData(); // los logs de aquí ven requestId en attributes
|
|
1909
|
+
* });
|
|
1910
|
+
*
|
|
1911
|
+
* @see {@link child} para un child logger persistente
|
|
1912
|
+
* @see {@link withContext} para la variante con callback sincrónico
|
|
1913
|
+
*/
|
|
1914
|
+
withContextAsync(bindings, fn) {
|
|
1915
|
+
return this.logContext.withContextAsync(bindings, fn);
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* Devuelve una copia inmutable de este logger con el contexto extra bound.
|
|
1919
|
+
* Las llamadas futuras sobre el child emiten con el contexto mergueado,
|
|
1920
|
+
* sin mutar al parent — el patrón canónico de MDC.
|
|
1921
|
+
*
|
|
1922
|
+
* @param extra - Pares key-value a adjuntar (requestId, userId, ...)
|
|
1923
|
+
* @returns Un nuevo Logger con el contexto mergueado
|
|
1924
|
+
*
|
|
1925
|
+
* @example
|
|
1926
|
+
* const reqLog = logger.child({ requestId: req.id });
|
|
1927
|
+
* reqLog.info('start'); // emite attributes: { requestId }
|
|
1928
|
+
* logger.info('unrelated'); // NO afectado — el contexto del parent queda intacto
|
|
1929
|
+
*
|
|
1930
|
+
*/
|
|
1931
|
+
child(extra) {
|
|
1932
|
+
const childLogger = this.logContext.child(extra);
|
|
1933
|
+
childLogger._parentContextRecord = childLogger["__parentSnapshot"] ?? {};
|
|
1934
|
+
childLogger._bindings = extra;
|
|
1935
|
+
return childLogger;
|
|
1936
|
+
}
|
|
1937
|
+
/**
|
|
1938
|
+
* Descarta todas las keys del contexto bound. Tras esta llamada, los
|
|
1939
|
+
* records emitidos dejan de llevar `attributes` hasta que
|
|
1940
|
+
* {@link withContext} o {@link child} restablezcan uno.
|
|
1941
|
+
*
|
|
1942
|
+
* @returns La misma instancia del logger, ahora sin contexto
|
|
1943
|
+
*/
|
|
1944
|
+
clearContext() {
|
|
1945
|
+
this.logContext.clearContext();
|
|
1946
|
+
return this;
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* Snapshot del contexto bound. El objeto devuelto es una shallow copy:
|
|
1950
|
+
* mutarlo NO afecta lo que emiten las llamadas de log posteriores.
|
|
1951
|
+
*
|
|
1952
|
+
* @returns Un snapshot read-only del contexto actual
|
|
1953
|
+
*/
|
|
1954
|
+
getContext() {
|
|
1955
|
+
let merged = this._parentContextRecord ?? {};
|
|
1956
|
+
if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
|
|
1957
|
+
...merged,
|
|
1958
|
+
...this._bindings
|
|
1959
|
+
};
|
|
1960
|
+
return merged;
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* Actualiza el resource OTel por defecto (service.name, version, env).
|
|
1964
|
+
* Se persiste en el campo `resource` de cada record emitido, salvo que
|
|
1965
|
+
* el propio record lo override.
|
|
1966
|
+
*
|
|
1967
|
+
* @param resource - Resource OTel parcial a merguear con el actual
|
|
1968
|
+
* @returns La misma instancia del logger, para chaining
|
|
1969
|
+
*
|
|
1970
|
+
* @example
|
|
1971
|
+
* logger.setResource({ 'service.name': 'api', 'service.version': '1.2.3' });
|
|
1972
|
+
*
|
|
1973
|
+
*/
|
|
1974
|
+
setResource(resource) {
|
|
1975
|
+
this.logContext.setResource(resource);
|
|
1976
|
+
return this;
|
|
1977
|
+
}
|
|
1978
|
+
/**
|
|
1979
|
+
* Reinicia el logger a la configuración por defecto
|
|
1980
|
+
*
|
|
1981
|
+
* @example
|
|
1982
|
+
* logger.resetConfig();
|
|
1983
|
+
* // Todo vuelve a la configuración inicial
|
|
1984
|
+
*
|
|
1985
|
+
*/
|
|
1986
|
+
resetConfig() {
|
|
1987
|
+
if (this.themeChangeListener) {
|
|
1988
|
+
this.themeChangeListener();
|
|
1989
|
+
this.themeChangeListener = null;
|
|
1990
|
+
}
|
|
1991
|
+
this.config = { ...require_utils.DEFAULT_CONFIG };
|
|
1992
|
+
this.styleManager.resetStyles();
|
|
1993
|
+
if (this.config.autoDetectTheme) this.setupAutoThemeDetection();
|
|
1994
|
+
this.success("Logger configuration reset to defaults");
|
|
1995
|
+
}
|
|
1996
|
+
/**
|
|
1997
|
+
* Método de limpieza para eliminar listeners y liberar recursos.
|
|
1998
|
+
*
|
|
1999
|
+
* Vacía los transports (drain), limpia timers, suelta la lista de
|
|
2000
|
+
* handlers legacy, resetea el group depth y limpia el context.
|
|
2001
|
+
* Seguro de invocar múltiples veces.
|
|
2002
|
+
*
|
|
2003
|
+
* @example
|
|
2004
|
+
* // Antes de cerrar la aplicación
|
|
2005
|
+
* await logger.cleanup();
|
|
2006
|
+
*
|
|
2007
|
+
*/
|
|
2008
|
+
async cleanup() {
|
|
2009
|
+
if (this.themeChangeListener) {
|
|
2010
|
+
try {
|
|
2011
|
+
this.themeChangeListener();
|
|
2012
|
+
} catch {}
|
|
2013
|
+
this.themeChangeListener = null;
|
|
2014
|
+
}
|
|
2015
|
+
await this.transportBridge.closeTransports();
|
|
2016
|
+
this.handlers.length = 0;
|
|
2017
|
+
this.timers.clear();
|
|
2018
|
+
this.badgeList = [];
|
|
2019
|
+
this.logContext.clearContext();
|
|
2020
|
+
this.groupDepth = 0;
|
|
2021
|
+
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Aplica un preset inteligente - funciona perfectamente sin configuración
|
|
2024
|
+
*
|
|
2025
|
+
* @param {string} name - Nombre del preset a aplicar
|
|
2026
|
+
*
|
|
2027
|
+
* @example
|
|
2028
|
+
* // Presets disponibles
|
|
2029
|
+
* logger.preset('default'); // Limpio y adaptativo
|
|
2030
|
+
* logger.preset('cyberpunk'); // Colores neón, efectos brillantes
|
|
2031
|
+
* logger.preset('glassmorphism'); // Efectos de blur modernos
|
|
2032
|
+
* logger.preset('minimal'); // Minimalista y elegante
|
|
2033
|
+
* logger.preset('debug'); // Modo desarrollo detallado
|
|
2034
|
+
* logger.preset('production'); // Enfocado en producción
|
|
2035
|
+
*
|
|
2036
|
+
*/
|
|
2037
|
+
preset(name) {
|
|
2038
|
+
if (!require_styling.hasPreset(name)) {
|
|
2039
|
+
this.error(`Unknown preset: ${name}. Available presets:`, require_styling.getAvailablePresets());
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
2042
|
+
const presetConfig = require_styling.getSmartPreset(name);
|
|
2043
|
+
if (presetConfig) {
|
|
2044
|
+
this.displaySettings.showTimestamp = presetConfig.timestamp?.show ?? true;
|
|
2045
|
+
this.displaySettings.showLocation = presetConfig.location?.show ?? true;
|
|
2046
|
+
this._activePreset = presetConfig;
|
|
2047
|
+
this._activePresetName = name;
|
|
2048
|
+
if (require_environment_detector.getEnvironment() === "browser") this.success(`Applied preset: ${name}`);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* Lista todos los presets disponibles
|
|
2053
|
+
*
|
|
2054
|
+
* @returns {string[]} Array con nombres de presets disponibles
|
|
2055
|
+
*
|
|
2056
|
+
* @example
|
|
2057
|
+
* const disponibles = logger.presets();
|
|
2058
|
+
* console.log(disponibles); // ['default', 'cyberpunk', 'glassmorphism', ...]
|
|
2059
|
+
*
|
|
2060
|
+
*/
|
|
2061
|
+
presets() {
|
|
2062
|
+
return require_styling.getAvailablePresets();
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* Oculta el timestamp en los logs
|
|
2066
|
+
*
|
|
2067
|
+
* @example
|
|
2068
|
+
* logger.hideTimestamp();
|
|
2069
|
+
* logger.info('Sin marca de tiempo'); // Sin timestamp visible
|
|
2070
|
+
*
|
|
2071
|
+
*/
|
|
2072
|
+
hideTimestamp() {
|
|
2073
|
+
this.displaySettings.showTimestamp = false;
|
|
2074
|
+
return this;
|
|
2075
|
+
}
|
|
2076
|
+
/**
|
|
2077
|
+
* Muestra el timestamp en los logs
|
|
2078
|
+
*
|
|
2079
|
+
* @example
|
|
2080
|
+
* logger.showTimestamp();
|
|
2081
|
+
* logger.info('Con marca de tiempo'); // [2024-01-15 10:30:45] Con marca de tiempo
|
|
2082
|
+
*
|
|
2083
|
+
*/
|
|
2084
|
+
showTimestamp() {
|
|
2085
|
+
this.displaySettings.showTimestamp = true;
|
|
2086
|
+
return this;
|
|
2087
|
+
}
|
|
2088
|
+
/**
|
|
2089
|
+
* Oculta la información de ubicación (archivo:línea) en los logs
|
|
2090
|
+
*
|
|
2091
|
+
* @example
|
|
2092
|
+
* logger.hideLocation();
|
|
2093
|
+
* logger.debug('Sin ubicación'); // Sin mostrar archivo:línea
|
|
2094
|
+
*
|
|
2095
|
+
*/
|
|
2096
|
+
hideLocation() {
|
|
2097
|
+
this.displaySettings.showLocation = false;
|
|
2098
|
+
return this;
|
|
2099
|
+
}
|
|
2100
|
+
/**
|
|
2101
|
+
* Muestra la información de ubicación (archivo:línea) en los logs
|
|
2102
|
+
*
|
|
2103
|
+
* @example
|
|
2104
|
+
* logger.showLocation();
|
|
2105
|
+
* logger.debug('Con ubicación'); // app.js:42 Con ubicación
|
|
2106
|
+
*
|
|
2107
|
+
*/
|
|
2108
|
+
showLocation() {
|
|
2109
|
+
this.displaySettings.showLocation = true;
|
|
2110
|
+
return this;
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* Oculta los badges en los logs
|
|
2114
|
+
*
|
|
2115
|
+
* @example
|
|
2116
|
+
* logger.hideBadges();
|
|
2117
|
+
* const api = logger.api('REST');
|
|
2118
|
+
* api.info('Sin badges'); // Sin mostrar [API] [REST]
|
|
2119
|
+
*
|
|
2120
|
+
*/
|
|
2121
|
+
hideBadges() {
|
|
2122
|
+
this.displaySettings.showBadges = false;
|
|
2123
|
+
return this;
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Muestra los badges en los logs
|
|
2127
|
+
*
|
|
2128
|
+
* @example
|
|
2129
|
+
* logger.showBadges();
|
|
2130
|
+
* const api = logger.api('GraphQL');
|
|
2131
|
+
* api.info('Con badges'); // [API] [GraphQL] Con badges
|
|
2132
|
+
*
|
|
2133
|
+
*/
|
|
2134
|
+
showBadges() {
|
|
2135
|
+
this.displaySettings.showBadges = true;
|
|
2136
|
+
return this;
|
|
2137
|
+
}
|
|
2138
|
+
/**
|
|
2139
|
+
* Establece múltiples badges para los logs
|
|
2140
|
+
*
|
|
2141
|
+
* @param {string[]} badges - Array de badges a mostrar
|
|
2142
|
+
* @returns {this} Logger instance para encadenamiento
|
|
2143
|
+
*
|
|
2144
|
+
* @example
|
|
2145
|
+
* logger.badges(['v3', 'stable']).info('Release publicado');
|
|
2146
|
+
* logger.badges(['API', 'v2']).warn('Endpoint deprecado');
|
|
2147
|
+
*
|
|
2148
|
+
*/
|
|
2149
|
+
badges(badges) {
|
|
2150
|
+
this.badgeList = [...badges];
|
|
2151
|
+
return this;
|
|
2152
|
+
}
|
|
2153
|
+
/**
|
|
2154
|
+
* Añade un badge individual a la lista
|
|
2155
|
+
*
|
|
2156
|
+
* @param {string} badge - Badge a añadir
|
|
2157
|
+
* @returns {this} Logger instance para encadenamiento
|
|
2158
|
+
*
|
|
2159
|
+
* @example
|
|
2160
|
+
* logger.badge('DEBUG').badge('AUTH').info('Token validado');
|
|
2161
|
+
*
|
|
2162
|
+
*/
|
|
2163
|
+
badge(badge) {
|
|
2164
|
+
if (!this.badgeList.includes(badge)) this.badgeList.push(badge);
|
|
2165
|
+
return this;
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Limpia todos los badges activos
|
|
2169
|
+
*
|
|
2170
|
+
* @returns {this} Logger instance para encadenamiento
|
|
2171
|
+
*
|
|
2172
|
+
* @example
|
|
2173
|
+
* logger.clearBadges().info('Sin badges');
|
|
2174
|
+
*
|
|
2175
|
+
*/
|
|
2176
|
+
clearBadges() {
|
|
2177
|
+
this.badgeList = [];
|
|
2178
|
+
return this;
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Crea un logger scoped para un componente o módulo del dominio.
|
|
2182
|
+
*
|
|
2183
|
+
* El `ComponentLogger` resultante prepends un badge `[name]` a cada
|
|
2184
|
+
* mensaje y comparte configuración, transports y hooks con el logger
|
|
2185
|
+
* padre. Útil para trazar el origen de los logs en apps con muchos
|
|
2186
|
+
* módulos (Auth, DB, Cache, ...).
|
|
2187
|
+
*
|
|
2188
|
+
* @param {string} name - Nombre del componente que aparecerá como badge
|
|
2189
|
+
* @returns {ComponentLogger} Logger scoped para el componente
|
|
2190
|
+
*
|
|
2191
|
+
* @example
|
|
2192
|
+
* const auth = logger.component('Auth');
|
|
2193
|
+
* auth.info('Validando token'); // [Auth] Validando token
|
|
2194
|
+
* auth.success('Token válido');
|
|
2195
|
+
*
|
|
2196
|
+
* @see {@link api} para loggers de endpoints REST/GraphQL
|
|
2197
|
+
* @see {@link scope} para un scope genérico sin badge de componente
|
|
2198
|
+
*/
|
|
2199
|
+
component(name) {
|
|
2200
|
+
return new ComponentLogger(this, name);
|
|
2201
|
+
}
|
|
2202
|
+
/**
|
|
2203
|
+
* Crea un logger scoped para un endpoint o surface de API.
|
|
2204
|
+
*
|
|
2205
|
+
* Como `component()` pero con styling orientado a APIs (badge `[API]`
|
|
2206
|
+
* por defecto más el nombre del sub-scope). Útil para distinguir
|
|
2207
|
+
* tráfico REST vs GraphQL vs WebSocket en los logs.
|
|
2208
|
+
*
|
|
2209
|
+
* @param {string} name - Nombre de la API o surface (p.ej. `'REST'`, `'GraphQL'`)
|
|
2210
|
+
* @returns {APILogger} Logger scoped para la API
|
|
2211
|
+
*
|
|
2212
|
+
* @example
|
|
2213
|
+
* const rest = logger.api('REST');
|
|
2214
|
+
* rest.info('GET /users/42'); // [API] [REST] GET /users/42
|
|
2215
|
+
*
|
|
2216
|
+
* @see {@link component} para loggers de componentes de dominio
|
|
2217
|
+
*/
|
|
2218
|
+
api(name) {
|
|
2219
|
+
return new APILogger(this, name);
|
|
2220
|
+
}
|
|
2221
|
+
/**
|
|
2222
|
+
* Crea un logger scoped genérico con un prefijo.
|
|
2223
|
+
*
|
|
2224
|
+
* Variante minimal de `component()` / `api()`: solo aplica un prefijo
|
|
2225
|
+
* de scope sin badges ni styling especial. Útil para sub-módulos que
|
|
2226
|
+
* no encajan en las categorías de `component`/`api`.
|
|
2227
|
+
*
|
|
2228
|
+
* @param {string} name - Texto del prefijo de scope
|
|
2229
|
+
* @returns {ScopedLogger} Logger con el scope aplicado
|
|
2230
|
+
*
|
|
2231
|
+
* @example
|
|
2232
|
+
* const db = logger.scope('db');
|
|
2233
|
+
* db.info('Pool conectado'); // [db] Pool conectado
|
|
2234
|
+
*
|
|
2235
|
+
* @see {@link component} y {@link api} para variantes con badges
|
|
2236
|
+
*/
|
|
2237
|
+
scope(name) {
|
|
2238
|
+
return new ScopedLogger(this, name);
|
|
2239
|
+
}
|
|
2240
|
+
/**
|
|
2241
|
+
* Personalización simple con configuración mínima
|
|
2242
|
+
*
|
|
2243
|
+
* @param {Object} overrides - Opciones de personalización
|
|
2244
|
+
* @param {Object} overrides.message - Configuración del mensaje
|
|
2245
|
+
* @param {Object} overrides.timestamp - Configuración del timestamp
|
|
2246
|
+
* @param {Object} overrides.location - Configuración de ubicación
|
|
2247
|
+
* @param {Object} overrides.level - Configuración del nivel
|
|
2248
|
+
* @param {Object} overrides.prefix - Configuración del prefijo
|
|
2249
|
+
* @param {string} overrides.spacing - Espaciado: 'compact' | 'normal' | 'spacious'
|
|
2250
|
+
*
|
|
2251
|
+
* @example
|
|
2252
|
+
* logger.customize({
|
|
2253
|
+
* message: { color: '#00ff00', size: '16px' },
|
|
2254
|
+
* timestamp: { show: false },
|
|
2255
|
+
* spacing: 'compact'
|
|
2256
|
+
* });
|
|
2257
|
+
*
|
|
2258
|
+
*/
|
|
2259
|
+
customize(overrides) {
|
|
2260
|
+
if (overrides.timestamp?.show !== void 0) this.displaySettings.showTimestamp = overrides.timestamp.show;
|
|
2261
|
+
if (overrides.location?.show !== void 0) this.displaySettings.showLocation = overrides.location.show;
|
|
2262
|
+
if (overrides.prefix?.show !== void 0) {}
|
|
2263
|
+
this._customization = overrides;
|
|
2264
|
+
this.success("Customization applied");
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Añade un handler personalizado para extender funcionalidad
|
|
2268
|
+
*
|
|
2269
|
+
* @param {ILogHandler} handler - Handler que implementa ILogHandler
|
|
2270
|
+
*
|
|
2271
|
+
* @example
|
|
2272
|
+
* // Handler personalizado para enviar logs a servidor
|
|
2273
|
+
* logger.addHandler({
|
|
2274
|
+
* handle(level, message, args, metadata) {
|
|
2275
|
+
* fetch('/logs', { method: 'POST', body: JSON.stringify({ level, message }) });
|
|
2276
|
+
* }
|
|
2277
|
+
* });
|
|
2278
|
+
*
|
|
2279
|
+
* @example
|
|
2280
|
+
* // Para escribir a archivo, usa `addTransport` con un `FileTransport`
|
|
2281
|
+
* logger.addTransport({ target: new FileTransport({ destination: 'app.log' }) });
|
|
2282
|
+
*
|
|
2283
|
+
*/
|
|
2284
|
+
addHandler(handler) {
|
|
2285
|
+
this.handlers.push(handler);
|
|
2286
|
+
}
|
|
2287
|
+
/**
|
|
2288
|
+
* Obtiene todos los handlers registrados
|
|
2289
|
+
*
|
|
2290
|
+
* @returns {ILogHandler[]} Array de handlers activos
|
|
2291
|
+
*/
|
|
2292
|
+
getHandlers() {
|
|
2293
|
+
return [...this.handlers];
|
|
2294
|
+
}
|
|
2295
|
+
/**
|
|
2296
|
+
* Añade un serializador personalizado para un tipo específico
|
|
2297
|
+
*
|
|
2298
|
+
* @param type - Constructor del tipo a serializar
|
|
2299
|
+
* @param serializer - Función de serialización
|
|
2300
|
+
* @param priority - Prioridad (mayor = primero)
|
|
2301
|
+
*
|
|
2302
|
+
* @example
|
|
2303
|
+
* logger.addSerializer(Error, (err) => ({
|
|
2304
|
+
* name: err.name,
|
|
2305
|
+
* message: err.message,
|
|
2306
|
+
* stack: err.stack?.split('\n').slice(0, 5)
|
|
2307
|
+
* }));
|
|
2308
|
+
*
|
|
2309
|
+
*/
|
|
2310
|
+
addSerializer(type, serializer, priority) {
|
|
2311
|
+
this.serializerBridge.addSerializer(type, serializer, priority);
|
|
2312
|
+
}
|
|
2313
|
+
/**
|
|
2314
|
+
* Elimina un serializador registrado
|
|
2315
|
+
*
|
|
2316
|
+
* @param type - Constructor del tipo a remover
|
|
2317
|
+
* @returns true si se eliminó
|
|
2318
|
+
*
|
|
2319
|
+
*/
|
|
2320
|
+
removeSerializer(type) {
|
|
2321
|
+
return this.serializerBridge.removeSerializer(type);
|
|
2322
|
+
}
|
|
2323
|
+
/**
|
|
2324
|
+
* Obtiene el registry de serializadores
|
|
2325
|
+
*
|
|
2326
|
+
* @returns SerializerRegistry
|
|
2327
|
+
*/
|
|
2328
|
+
getSerializerRegistry() {
|
|
2329
|
+
return this.serializerBridge.getSerializerRegistry();
|
|
2330
|
+
}
|
|
2331
|
+
/**
|
|
2332
|
+
* Registra un hook para un evento
|
|
2333
|
+
*
|
|
2334
|
+
* @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
|
|
2335
|
+
* @param callback - Función a ejecutar
|
|
2336
|
+
* @param priority - Prioridad (mayor = primero)
|
|
2337
|
+
* @returns Función para desregistrar
|
|
2338
|
+
*
|
|
2339
|
+
* @example
|
|
2340
|
+
* const unsubscribe = logger.on('beforeLog', (entry) => {
|
|
2341
|
+
* entry.correlationId = getCorrelationId();
|
|
2342
|
+
* return entry;
|
|
2343
|
+
* });
|
|
2344
|
+
*
|
|
2345
|
+
*/
|
|
2346
|
+
on(event, callback, priority) {
|
|
2347
|
+
return this.hookBridge.on(event, callback, priority);
|
|
2348
|
+
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Registra un hook que se ejecuta solo una vez
|
|
2351
|
+
*
|
|
2352
|
+
* @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
|
|
2353
|
+
* @param callback - Función a ejecutar
|
|
2354
|
+
* @param priority - Prioridad (mayor = primero)
|
|
2355
|
+
* @returns Función para desregistrar
|
|
2356
|
+
*
|
|
2357
|
+
*/
|
|
2358
|
+
once(event, callback, priority) {
|
|
2359
|
+
return this.hookBridge.once(event, callback, priority);
|
|
2360
|
+
}
|
|
2361
|
+
/**
|
|
2362
|
+
* Elimina un hook registrado
|
|
2363
|
+
*
|
|
2364
|
+
* @param event - Evento del hook
|
|
2365
|
+
* @param callback - Callback a remover
|
|
2366
|
+
* @returns true si se eliminó
|
|
2367
|
+
*
|
|
2368
|
+
*/
|
|
2369
|
+
off(event, callback) {
|
|
2370
|
+
return this.hookBridge.off(event, callback);
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* Añade un middleware al pipeline
|
|
2374
|
+
*
|
|
2375
|
+
* @param middleware - Función middleware
|
|
2376
|
+
* @param priority - Prioridad (mayor = primero)
|
|
2377
|
+
* @returns Función para desregistrar
|
|
2378
|
+
*
|
|
2379
|
+
* @example
|
|
2380
|
+
* logger.use((entry, next) => {
|
|
2381
|
+
* entry.requestId = asyncLocalStorage.getStore()?.requestId;
|
|
2382
|
+
* next();
|
|
2383
|
+
* });
|
|
2384
|
+
*
|
|
2385
|
+
*/
|
|
2386
|
+
use(middleware, priority) {
|
|
2387
|
+
return this.hookBridge.use(middleware, priority);
|
|
2388
|
+
}
|
|
2389
|
+
/**
|
|
2390
|
+
* Obtiene el HookManager
|
|
2391
|
+
*
|
|
2392
|
+
* @returns HookManager
|
|
2393
|
+
*/
|
|
2394
|
+
getHookManager() {
|
|
2395
|
+
return this.hookBridge.getHookManager();
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Añade un transport para envío de logs
|
|
2399
|
+
*
|
|
2400
|
+
* @param target - Configuración del transport
|
|
2401
|
+
* @returns ID único del transport
|
|
2402
|
+
*
|
|
2403
|
+
* @example
|
|
2404
|
+
* // File transport
|
|
2405
|
+
* logger.addTransport({
|
|
2406
|
+
* target: 'file',
|
|
2407
|
+
* options: { destination: '/var/log/app.log' }
|
|
2408
|
+
* });
|
|
2409
|
+
*
|
|
2410
|
+
* @example
|
|
2411
|
+
* // HTTP transport con batching
|
|
2412
|
+
* logger.addTransport({
|
|
2413
|
+
* target: 'http',
|
|
2414
|
+
* options: {
|
|
2415
|
+
* url: 'https://logs.example.com',
|
|
2416
|
+
* batchSize: 100,
|
|
2417
|
+
* flushInterval: 5000
|
|
2418
|
+
* },
|
|
2419
|
+
* level: 'warn'
|
|
2420
|
+
* });
|
|
2421
|
+
*
|
|
2422
|
+
*/
|
|
2423
|
+
addTransport(target) {
|
|
2424
|
+
return this.transportBridge.addTransport(target);
|
|
2425
|
+
}
|
|
2426
|
+
/**
|
|
2427
|
+
* Elimina un transport
|
|
2428
|
+
*
|
|
2429
|
+
* @param id - ID del transport a remover
|
|
2430
|
+
* @returns true si se eliminó
|
|
2431
|
+
*
|
|
2432
|
+
*/
|
|
2433
|
+
removeTransport(id) {
|
|
2434
|
+
return this.transportBridge.removeTransport(id);
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Fuerza el flush de todos los transports
|
|
2438
|
+
*
|
|
2439
|
+
* @returns Promise que resuelve cuando todos los buffers están vaciados
|
|
2440
|
+
*
|
|
2441
|
+
*/
|
|
2442
|
+
async flushTransports() {
|
|
2443
|
+
await this.transportBridge.flushTransports();
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Cierra todos los transports
|
|
2447
|
+
*
|
|
2448
|
+
* @returns Promise que resuelve cuando todos están cerrados
|
|
2449
|
+
*
|
|
2450
|
+
*/
|
|
2451
|
+
async closeTransports() {
|
|
2452
|
+
await this.transportBridge.closeTransports();
|
|
2453
|
+
}
|
|
2454
|
+
/**
|
|
2455
|
+
* Obtiene el TransportManager
|
|
2456
|
+
*
|
|
2457
|
+
* @returns TransportManager o undefined si no hay transports
|
|
2458
|
+
*/
|
|
2459
|
+
getTransportManager() {
|
|
2460
|
+
return this.transportBridge.getTransportManager();
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Verifica si un nivel de log debe mostrarse según la verbosidad actual.
|
|
2464
|
+
* @private
|
|
2465
|
+
* @param {LogLevel} level - Nivel de log a verificar
|
|
2466
|
+
* @returns {boolean} True si debe mostrarse, false si no
|
|
2467
|
+
*/
|
|
2468
|
+
shouldLog(level) {
|
|
2469
|
+
if (this.config.verbosity === "silent") return false;
|
|
2470
|
+
return require_core.LOG_LEVELS[level] >= require_core.LOG_LEVELS[this.config.verbosity];
|
|
2471
|
+
}
|
|
2472
|
+
/**
|
|
2473
|
+
* Tag pendiente de inyectar en el siguiente `TransportRecord` emitido
|
|
2474
|
+
* por `log()`. Lo fijan `success()` y `logWithBindingsAndTag()` antes
|
|
2475
|
+
* de delegar; `log()` lo consume y lo resetea a `undefined`.
|
|
2476
|
+
*
|
|
2477
|
+
* @internal
|
|
2478
|
+
*/
|
|
2479
|
+
_dispatchTag;
|
|
2480
|
+
/**
|
|
2481
|
+
* Computa el contexto completamente mergueado para este logger.
|
|
2482
|
+
*
|
|
2483
|
+
* La cadena de contexto se construye en el momento de crear el child:
|
|
2484
|
+
* cada child almacena el contexto fully-merged de su parent (en ese
|
|
2485
|
+
* instante) como `_parentContextRecord`. Esto implica que
|
|
2486
|
+
* `_parentContextRecord` ya contiene los bindings de todos los ancestros
|
|
2487
|
+
* en el orden de precedencia correcto (root primero, child más cercano al final).
|
|
2488
|
+
*
|
|
2489
|
+
* Orden de merge (gana el último):
|
|
2490
|
+
* 1. _parentContextRecord — snapshot del contexto mergueado del parent en la creación
|
|
2491
|
+
* 2. _bindings — bindings propios de este logger (llamadas a `child()`)
|
|
2492
|
+
* 3. ALS store — scope de `withContext`/`withContextAsync` (prioridad máxima)
|
|
2493
|
+
*
|
|
2494
|
+
* @internal
|
|
2495
|
+
* @returns El record de contexto mergueado
|
|
2496
|
+
*/
|
|
2497
|
+
_getMergedContext() {
|
|
2498
|
+
let merged = this._parentContextRecord ?? {};
|
|
2499
|
+
if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
|
|
2500
|
+
...merged,
|
|
2501
|
+
...this._bindings
|
|
2502
|
+
};
|
|
2503
|
+
const alsContext = this.logContext._getAlsStore?.() ?? {};
|
|
2504
|
+
if (alsContext && Object.keys(alsContext).length > 0) merged = {
|
|
2505
|
+
...merged,
|
|
2506
|
+
...alsContext
|
|
2507
|
+
};
|
|
2508
|
+
return merged;
|
|
2509
|
+
}
|
|
2510
|
+
/** @internal Expone el contexto base mergueado (sin ALS) a la closure de la child factory de LogContext. */
|
|
2511
|
+
_captureMergedContext() {
|
|
2512
|
+
let merged = this._parentContextRecord ?? {};
|
|
2513
|
+
if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
|
|
2514
|
+
...merged,
|
|
2515
|
+
...this._bindings
|
|
2516
|
+
};
|
|
2517
|
+
return merged;
|
|
2518
|
+
}
|
|
2519
|
+
/**
|
|
2520
|
+
* Construye y despacha un `TransportRecord` al {@link TransportManager}
|
|
2521
|
+
* (no-op si no hay transports registrados). Lo comparten todos los
|
|
2522
|
+
* caminos de log — `log()`, `success()` y los métodos visuales como
|
|
2523
|
+
* `table()` / `group()` / `time()` — para que toda emisión atraviese
|
|
2524
|
+
* el mismo pipeline de transports.
|
|
2525
|
+
*
|
|
2526
|
+
* @protected
|
|
2527
|
+
* @param {LogLevel} level - Nivel canónico (trace/debug/info/warn/error/critical)
|
|
2528
|
+
* @param {string} message - Mensaje final, post-hook
|
|
2529
|
+
* @param {string | undefined} prefix - Prefijo efectivo (global + scope)
|
|
2530
|
+
* @param {StackInfo | null} stackInfo - Ubicación del caller, opcional
|
|
2531
|
+
* @param {Partial<TransportRecord>} [extra] - Campos extra a mergear en el record
|
|
2532
|
+
* (p.ej. `{ tag: 'success' }` o `attributes` adicionales)
|
|
2533
|
+
*/
|
|
2534
|
+
dispatchToTransports(level, message, prefix, stackInfo, extra) {
|
|
2535
|
+
const record = {
|
|
2536
|
+
level,
|
|
2537
|
+
levelValue: require_core.LOG_LEVELS[level],
|
|
2538
|
+
severityNumber: require_transports.LOG_LEVEL_TO_SEVERITY_NUMBER[level],
|
|
2539
|
+
severityText: require_transports.LOG_LEVEL_TO_SEVERITY_TEXT[level],
|
|
2540
|
+
time: Date.now(),
|
|
2541
|
+
msg: message,
|
|
2542
|
+
prefix,
|
|
2543
|
+
location: stackInfo ? {
|
|
2544
|
+
file: stackInfo.file,
|
|
2545
|
+
line: stackInfo.line,
|
|
2546
|
+
column: stackInfo.column,
|
|
2547
|
+
function: stackInfo.function
|
|
2548
|
+
} : void 0,
|
|
2549
|
+
attributes: Object.keys(this.logContext._getContextRecord()).length > 0 ? toLogAttributes(this.logContext._getContextRecord()) : void 0,
|
|
2550
|
+
resource: this.logContext._getResource() ? { ...this.logContext._getResource() } : void 0,
|
|
2551
|
+
...extra
|
|
2552
|
+
};
|
|
2553
|
+
this.transportBridge.writeRecord(record);
|
|
2554
|
+
}
|
|
2555
|
+
/**
|
|
2556
|
+
* Obtiene el prefijo efectivo (global + scope)
|
|
2557
|
+
* @private
|
|
2558
|
+
* @returns {string | undefined} Prefijo combinado o undefined
|
|
2559
|
+
*/
|
|
2560
|
+
getEffectivePrefix() {
|
|
2561
|
+
const parts = [this.config.globalPrefix, this.scopedPrefix].filter(Boolean);
|
|
2562
|
+
return parts.length > 0 ? parts.join(":") : void 0;
|
|
2563
|
+
}
|
|
2564
|
+
/**
|
|
2565
|
+
* Método central de logging. Espera el hook pipeline `beforeLog`
|
|
2566
|
+
* antes de despachar a consola y transports, para que redacciones
|
|
2567
|
+
* o enriquecimientos (PII, correlation IDs) se reflejen en el
|
|
2568
|
+
* mensaje emitido.
|
|
2569
|
+
*
|
|
2570
|
+
* Los callers fire-and-forget (p.ej. `logger.info(...)` sin `await`)
|
|
2571
|
+
* siguen funcionando: el `Promise<void>` resultante se descarta.
|
|
2572
|
+
* Se recomienda `await` cuando los hooks `beforeLog` mutan `message`.
|
|
2573
|
+
*
|
|
2574
|
+
* El tag opcional (`TransportRecord.tag`) NO se pasa como argumento:
|
|
2575
|
+
* se establece vía `_dispatchTag` (ver `success()` y
|
|
2576
|
+
* {@link logWithBindingsAndTag}) antes de invocar este método.
|
|
2577
|
+
*
|
|
2578
|
+
* @protected
|
|
2579
|
+
* @param {LogLevel} level - Nivel del log
|
|
2580
|
+
* @param {unknown[]} args - Argumentos a loggear (mensaje + datos)
|
|
2581
|
+
* @returns {Promise<void>} Promesa que resuelve al completar el dispatch
|
|
2582
|
+
*
|
|
2583
|
+
*/
|
|
2584
|
+
async log(level, ...args) {
|
|
2585
|
+
if (!this.shouldLog(level)) return;
|
|
2586
|
+
const dispatchTag = this._dispatchTag;
|
|
2587
|
+
this._dispatchTag = void 0;
|
|
2588
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2589
|
+
const prefix = this.getEffectivePrefix();
|
|
2590
|
+
const timestamp = require_utils.formatTimestamp();
|
|
2591
|
+
const serializedArgs = args.map((arg) => this.serializerBridge.getSerializerRegistry().serialize(arg));
|
|
2592
|
+
let message = serializedArgs.length > 0 ? String(serializedArgs[0]) : "";
|
|
2593
|
+
if (this.badgeList.length > 0 && this.displaySettings.showBadges) message = this.badgeList.map((b) => `[${b}]`).join("") + " " + message;
|
|
2594
|
+
const additionalArgs = serializedArgs.slice(1);
|
|
2595
|
+
const hookEntry = {
|
|
2596
|
+
level,
|
|
2597
|
+
message,
|
|
2598
|
+
args: serializedArgs,
|
|
2599
|
+
timestamp,
|
|
2600
|
+
prefix,
|
|
2601
|
+
stackInfo: stackInfo ?? void 0
|
|
2602
|
+
};
|
|
2603
|
+
let processed;
|
|
2604
|
+
try {
|
|
2605
|
+
processed = await this.hookBridge.getHookManager().emit("beforeLog", hookEntry);
|
|
2606
|
+
} catch (error) {
|
|
2607
|
+
console.error("HookManager beforeLog failed:", error);
|
|
2608
|
+
processed = hookEntry;
|
|
2609
|
+
}
|
|
2610
|
+
message = processed.message;
|
|
2611
|
+
const [format, ...styles] = require_utils.createStyledOutput(level, this.styleManager.getStyles(), prefix, message, this.displaySettings.showLocation ? stackInfo : null, this.config.autoDetectTheme, this._activePreset, this._activePresetName);
|
|
2612
|
+
const finalFormat = " ".repeat(this.groupDepth) + format;
|
|
2613
|
+
this.writeOutput(finalFormat, level, styles, additionalArgs);
|
|
2614
|
+
const metadata = {
|
|
2615
|
+
timestamp,
|
|
2616
|
+
level,
|
|
2617
|
+
prefix,
|
|
2618
|
+
stackInfo: stackInfo ?? void 0
|
|
2619
|
+
};
|
|
2620
|
+
this.handlers.forEach((handler) => {
|
|
2621
|
+
try {
|
|
2622
|
+
handler.handle(level, message, serializedArgs, metadata);
|
|
2623
|
+
} catch (error) {
|
|
2624
|
+
console.error("Log handler failed:", error);
|
|
2625
|
+
}
|
|
2626
|
+
});
|
|
2627
|
+
if (dispatchTag !== void 0) this.dispatchToTransports(level, message, prefix, stackInfo, { tag: dispatchTag });
|
|
2628
|
+
else this.dispatchToTransports(level, message, prefix, stackInfo);
|
|
2629
|
+
this.hookBridge.getHookManager().emit("afterLog", processed).catch(() => {});
|
|
2630
|
+
}
|
|
2631
|
+
/**
|
|
2632
|
+
* Emite un log aplicando bindings (badges, scope) al prefijo del
|
|
2633
|
+
* mensaje antes de delegar en {@link Logger.log}.
|
|
2634
|
+
*
|
|
2635
|
+
* No es API pública de consumo: existe para que `ScopedLogger`
|
|
2636
|
+
* (`component()` / `api()` / `scope()`) pueda reutilizar el pipeline
|
|
2637
|
+
* central de `log()` sin duplicar la lógica de styling/badges.
|
|
2638
|
+
*
|
|
2639
|
+
* @internal
|
|
2640
|
+
* @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
|
|
2641
|
+
* @param {LogLevel} level - Nivel de log
|
|
2642
|
+
* @param {unknown[]} args - Argumentos a loggear
|
|
2643
|
+
* @returns {Promise<void>} Promesa del dispatch
|
|
2644
|
+
*
|
|
2645
|
+
* @see {@link logWithBindingsAndTag} para la variante con `tag`
|
|
2646
|
+
*/
|
|
2647
|
+
logWithBindings(bindings, level, ...args) {
|
|
2648
|
+
if (!this.shouldLog(level)) return Promise.resolve();
|
|
2649
|
+
let prefix = "";
|
|
2650
|
+
const colorCapability = require_environment_detector.getColorCapability();
|
|
2651
|
+
if (bindings.badges?.length) prefix += bindings.badges.map((b) => require_spinner.formatBadge(b, "pill", colorCapability, "#00ff88")).join(" ") + " ";
|
|
2652
|
+
if (bindings.scope) prefix += require_spinner.formatBadge(bindings.scope, "pill", colorCapability, "#00ffff") + " ";
|
|
2653
|
+
if (prefix && args.length > 0) args[0] = prefix + String(args[0]);
|
|
2654
|
+
return this.log(level, ...args);
|
|
2655
|
+
}
|
|
2656
|
+
/**
|
|
2657
|
+
* Como {@link logWithBindings} pero fija `_dispatchTag` antes de
|
|
2658
|
+
* delegar, para que `log()` despache el `TransportRecord` con el
|
|
2659
|
+
* tag indicado. Lo usa `ScopedLogger.success()` para propagar
|
|
2660
|
+
* `tag: 'success'` a través del pipeline normal de `log()`.
|
|
2661
|
+
*
|
|
2662
|
+
* @internal
|
|
2663
|
+
* @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
|
|
2664
|
+
* @param {LogLevel} level - Nivel de log
|
|
2665
|
+
* @param {LogTag} tag - Tag a inyectar en el `TransportRecord`
|
|
2666
|
+
* @param {unknown[]} args - Argumentos a loggear
|
|
2667
|
+
* @returns {Promise<void>} Promesa del dispatch
|
|
2668
|
+
*/
|
|
2669
|
+
logWithBindingsAndTag(bindings, level, tag, ...args) {
|
|
2670
|
+
this._dispatchTag = tag;
|
|
2671
|
+
return this.logWithBindings(bindings, level, ...args);
|
|
2672
|
+
}
|
|
2673
|
+
/**
|
|
2674
|
+
* Registra mensajes de debug (nivel más verboso junto a `trace`).
|
|
2675
|
+
* Pensado para diagnóstico de desarrollo: valores intermedios, flags
|
|
2676
|
+
* de control flow, estado interno. Devuelve `Promise<void>`.
|
|
2677
|
+
*
|
|
2678
|
+
* Filtrado por defecto cuando `verbosity > 'debug'` (ver `setVerbosity`).
|
|
2679
|
+
*
|
|
2680
|
+
* @param {unknown[]} args - Mensaje + datos a inspeccionar
|
|
2681
|
+
* @returns {Promise<void>} Promesa del dispatch
|
|
2682
|
+
*
|
|
2683
|
+
* @example
|
|
2684
|
+
* logger.debug('Estado interno:', { conn, queueSize });
|
|
2685
|
+
* logger.debug('Entrando en branch X');
|
|
2686
|
+
*
|
|
2687
|
+
* @see {@link trace} para diagnósticos aún más granulares
|
|
2688
|
+
* @see {@link setVerbosity} para controlar el nivel mínimo visible
|
|
2689
|
+
*/
|
|
2690
|
+
debug(...args) {
|
|
2691
|
+
return this.log("debug", ...args);
|
|
2692
|
+
}
|
|
2693
|
+
/**
|
|
2694
|
+
* Registra mensajes informativos. El `await` retorna cuando el hook
|
|
2695
|
+
* `beforeLog` y el dispatch a transports han terminado.
|
|
2696
|
+
*
|
|
2697
|
+
* @param args - Mensajes y datos informativos
|
|
2698
|
+
*
|
|
2699
|
+
* @example
|
|
2700
|
+
* logger.info('Servidor iniciado en puerto 3000');
|
|
2701
|
+
* await logger.info('Procesando', totalItems, 'elementos'); // espera hooks
|
|
2702
|
+
*
|
|
2703
|
+
*/
|
|
2704
|
+
info(...args) {
|
|
2705
|
+
return this.log("info", ...args);
|
|
2706
|
+
}
|
|
2707
|
+
/**
|
|
2708
|
+
* Registra mensajes de advertencia.
|
|
2709
|
+
*
|
|
2710
|
+
* @param args - Mensajes de advertencia
|
|
2711
|
+
*
|
|
2712
|
+
*/
|
|
2713
|
+
warn(...args) {
|
|
2714
|
+
return this.log("warn", ...args);
|
|
2715
|
+
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Registra mensajes de error.
|
|
2718
|
+
*
|
|
2719
|
+
* @param args - Mensaje de error y stack traces
|
|
2720
|
+
*
|
|
2721
|
+
*/
|
|
2722
|
+
error(...args) {
|
|
2723
|
+
return this.log("error", ...args);
|
|
2724
|
+
}
|
|
2725
|
+
/**
|
|
2726
|
+
* Registra mensajes de éxito. Mapeado internamente a nivel `info` con
|
|
2727
|
+
* styling de success y `record.tag = 'success'` para que los transports
|
|
2728
|
+
* puedan distinguirlo (sin perder info semantics para filtering).
|
|
2729
|
+
*
|
|
2730
|
+
* @param args - Mensaje + datos adicionales
|
|
2731
|
+
*
|
|
2732
|
+
* @example
|
|
2733
|
+
* logger.success('Base de datos conectada');
|
|
2734
|
+
* logger.success('Usuario creado con ID:', userId);
|
|
2735
|
+
* logger.success('✓ Tests pasados: 42/42');
|
|
2736
|
+
*
|
|
2737
|
+
*/
|
|
2738
|
+
async success(...args) {
|
|
2739
|
+
if (!this.shouldLog("info")) return;
|
|
2740
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2741
|
+
const prefix = this.getEffectivePrefix();
|
|
2742
|
+
const timestamp = require_utils.formatTimestamp();
|
|
2743
|
+
const serializedArgs = args.map((arg) => this.serializerBridge.getSerializerRegistry().serialize(arg));
|
|
2744
|
+
let message = serializedArgs.length > 0 ? String(serializedArgs[0]) : "";
|
|
2745
|
+
if (this.badgeList.length > 0 && this.displaySettings.showBadges) message = this.badgeList.map((b) => `[${b}]`).join("") + " " + message;
|
|
2746
|
+
const additionalArgs = serializedArgs.slice(1);
|
|
2747
|
+
const hookEntry = {
|
|
2748
|
+
level: "info",
|
|
2749
|
+
message,
|
|
2750
|
+
args: serializedArgs,
|
|
2751
|
+
timestamp,
|
|
2752
|
+
prefix,
|
|
2753
|
+
stackInfo: stackInfo ?? void 0
|
|
2754
|
+
};
|
|
2755
|
+
try {
|
|
2756
|
+
message = (await this.hookBridge.getHookManager().emit("beforeLog", hookEntry)).message;
|
|
2757
|
+
} catch {}
|
|
2758
|
+
const [format, ...styles] = require_utils.createStyledOutput("info", this.styleManager.getStyles(), prefix, message, this.displaySettings.showLocation ? stackInfo : null, this.config.autoDetectTheme, this._activePreset, this._activePresetName);
|
|
2759
|
+
const successStyle = this.styleManager.getStyles().success;
|
|
2760
|
+
const emoji = successStyle?.emoji ?? "✅";
|
|
2761
|
+
const label = successStyle?.label ?? "SUCCESS";
|
|
2762
|
+
const successFormat = format.replace(/ℹ️ INFO/, `${emoji} ${label}`);
|
|
2763
|
+
const finalFormat = " ".repeat(this.groupDepth) + successFormat;
|
|
2764
|
+
this.writeOutput(finalFormat, "info", styles, additionalArgs);
|
|
2765
|
+
const metadata = {
|
|
2766
|
+
timestamp,
|
|
2767
|
+
level: "info",
|
|
2768
|
+
prefix,
|
|
2769
|
+
stackInfo: stackInfo ?? void 0
|
|
2770
|
+
};
|
|
2771
|
+
this.handlers.forEach((handler) => {
|
|
2772
|
+
try {
|
|
2773
|
+
handler.handle("info", message, args, metadata);
|
|
2774
|
+
} catch (error) {
|
|
2775
|
+
console.error("Log handler failed:", error);
|
|
2776
|
+
}
|
|
2777
|
+
});
|
|
2778
|
+
this._dispatchTag = "success";
|
|
2779
|
+
await this.log("info", ...args);
|
|
2780
|
+
this.hookBridge.getHookManager().emit("afterLog", hookEntry).catch(() => {});
|
|
2781
|
+
}
|
|
2782
|
+
/**
|
|
2783
|
+
* Registra información de trace (nivel más bajo, debajo de debug).
|
|
2784
|
+
* Alineado con OpenTelemetry `TRACE` severity (1-4).
|
|
2785
|
+
*
|
|
2786
|
+
* @param args - Datos muy verbosos (entrada/salida de funciones, valores intermedios)
|
|
2787
|
+
*
|
|
2788
|
+
* @example
|
|
2789
|
+
* logger.trace('Entrando en función processData');
|
|
2790
|
+
* logger.trace('Variables intermedias:', { a, b, c });
|
|
2791
|
+
*
|
|
2792
|
+
*/
|
|
2793
|
+
trace(...args) {
|
|
2794
|
+
this.log("trace", ...args);
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* Registra errores críticos (prioridad más alta).
|
|
2798
|
+
*
|
|
2799
|
+
* @param args - Errores críticos del sistema
|
|
2800
|
+
*
|
|
2801
|
+
* @example
|
|
2802
|
+
* await logger.critical('Sistema caído - reinicio inmediato requerido');
|
|
2803
|
+
*
|
|
2804
|
+
*/
|
|
2805
|
+
critical(...args) {
|
|
2806
|
+
return this.log("critical", ...args);
|
|
2807
|
+
}
|
|
2808
|
+
/**
|
|
2809
|
+
* Muestra datos en formato de tabla. Pasa por la pipeline completa
|
|
2810
|
+
* (outputMode-respecting writeOutput + transports + hooks).
|
|
2811
|
+
*
|
|
2812
|
+
* @param data - Array de objetos o matriz
|
|
2813
|
+
* @param columns - Columnas específicas a mostrar (opcional)
|
|
2814
|
+
*
|
|
2815
|
+
* @example
|
|
2816
|
+
* logger.table([{ id: 1, nombre: 'Juan' }, { id: 2, nombre: 'María' }]);
|
|
2817
|
+
*
|
|
2818
|
+
*/
|
|
2819
|
+
table(data, columns) {
|
|
2820
|
+
if (!this.shouldLog("info")) return;
|
|
2821
|
+
const prefix = this.getEffectivePrefix();
|
|
2822
|
+
const tableStyle = require_styling.StylePresets.accent().build();
|
|
2823
|
+
const format = `%c${`📊 TABLE${prefix ? ` [${prefix}]` : ""}`}`;
|
|
2824
|
+
const styles = [tableStyle];
|
|
2825
|
+
this.writeOutput(format, "info", styles, []);
|
|
2826
|
+
[...columns ? [columns] : []];
|
|
2827
|
+
if (this.config.outputMode !== "silent") if (columns) console.table(data, columns);
|
|
2828
|
+
else console.table(data);
|
|
2829
|
+
const message = `table:${Array.isArray(data) ? `${data.length} rows` : "data"}`;
|
|
2830
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2831
|
+
this.dispatchToTransports("info", message, prefix, stackInfo, { attributes: {
|
|
2832
|
+
...this.logContext._getContextRecord(),
|
|
2833
|
+
"logger.visual": "table",
|
|
2834
|
+
"logger.data": JSON.stringify(data).slice(0, 4096),
|
|
2835
|
+
...columns ? { "logger.columns": columns.join(",") } : {}
|
|
2836
|
+
} });
|
|
2837
|
+
}
|
|
2838
|
+
/**
|
|
2839
|
+
* Inicia un grupo colapsable en la consola. Emite un marker a
|
|
2840
|
+
* transports con `attributes.logger.visual = 'groupStart'` para que
|
|
2841
|
+
* backends puedan reconstruir la jerarquía.
|
|
2842
|
+
*
|
|
2843
|
+
* @param label - Etiqueta del grupo
|
|
2844
|
+
* @param collapsed - Si el grupo inicia colapsado (default: false)
|
|
2845
|
+
*
|
|
2846
|
+
* @example
|
|
2847
|
+
* logger.group('Procesando usuarios');
|
|
2848
|
+
* logger.info('Usuario 1 procesado');
|
|
2849
|
+
* logger.groupEnd();
|
|
2850
|
+
*
|
|
2851
|
+
*/
|
|
2852
|
+
group(label, collapsed = false) {
|
|
2853
|
+
const groupStyle = new require_styling.StyleBuilder().bg("linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%)").color("#1565c0").border("1px solid #90caf9").padding("4px 12px").rounded("6px").bold().build();
|
|
2854
|
+
const format = `%c📁 ${label}`;
|
|
2855
|
+
if (this.config.outputMode !== "silent") if (collapsed) console.groupCollapsed(format, groupStyle);
|
|
2856
|
+
else console.group(format, groupStyle);
|
|
2857
|
+
this.groupDepth++;
|
|
2858
|
+
const prefix = this.getEffectivePrefix();
|
|
2859
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2860
|
+
this.dispatchToTransports("info", `group:start:${label}`, prefix, stackInfo, { attributes: {
|
|
2861
|
+
...this.logContext._getContextRecord(),
|
|
2862
|
+
"logger.visual": "groupStart",
|
|
2863
|
+
"logger.group.label": label,
|
|
2864
|
+
"logger.group.collapsed": collapsed,
|
|
2865
|
+
"logger.group.depth": this.groupDepth
|
|
2866
|
+
} });
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* Finaliza el grupo actual de la consola. Emite un marker a transports
|
|
2870
|
+
* simétrico al `group()` start, para que backends puedan cerrar la
|
|
2871
|
+
* jerarquía correctamente.
|
|
2872
|
+
*
|
|
2873
|
+
* @example
|
|
2874
|
+
* logger.group('Operaciones');
|
|
2875
|
+
* logger.info('Operación 1');
|
|
2876
|
+
* logger.groupEnd();
|
|
2877
|
+
*
|
|
2878
|
+
*/
|
|
2879
|
+
groupEnd() {
|
|
2880
|
+
if (this.groupDepth > 0) {
|
|
2881
|
+
this.groupDepth--;
|
|
2882
|
+
if (this.config.outputMode !== "silent") console.groupEnd();
|
|
2883
|
+
const prefix = this.getEffectivePrefix();
|
|
2884
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2885
|
+
this.dispatchToTransports("info", "group:end", prefix, stackInfo, { attributes: {
|
|
2886
|
+
...this.logContext._getContextRecord(),
|
|
2887
|
+
"logger.visual": "groupEnd",
|
|
2888
|
+
"logger.group.depth": this.groupDepth
|
|
2889
|
+
} });
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
/**
|
|
2893
|
+
* Inicia un temporizador con la etiqueta dada
|
|
2894
|
+
*
|
|
2895
|
+
* @param {string} label - Etiqueta identificadora del temporizador
|
|
2896
|
+
*
|
|
2897
|
+
* @example
|
|
2898
|
+
* logger.time('proceso-datos');
|
|
2899
|
+
* // ... operación costosa ...
|
|
2900
|
+
* logger.timeEnd('proceso-datos'); // ⏱️ Timer ended: proceso-datos - 1523.45ms
|
|
2901
|
+
*
|
|
2902
|
+
*/
|
|
2903
|
+
time(label) {
|
|
2904
|
+
const timer = {
|
|
2905
|
+
label,
|
|
2906
|
+
startTime: (typeof performance !== "undefined" ? performance : Date).now()
|
|
2907
|
+
};
|
|
2908
|
+
this.timers.set(label, timer);
|
|
2909
|
+
const timerStyle = require_styling.StylePresets.warning().build();
|
|
2910
|
+
const format = `%c⏱️ Timer started: ${label}`;
|
|
2911
|
+
this.writeOutput(format, "debug", [timerStyle], []);
|
|
2912
|
+
}
|
|
2913
|
+
/**
|
|
2914
|
+
* Finaliza un temporizador y muestra el tiempo transcurrido
|
|
2915
|
+
*
|
|
2916
|
+
* @param {string} label - Etiqueta del temporizador a finalizar
|
|
2917
|
+
* @returns {number} Milisegundos transcurridos, o `-1` si no se encuentra el timer
|
|
2918
|
+
*
|
|
2919
|
+
* @example
|
|
2920
|
+
* logger.time('consulta-db');
|
|
2921
|
+
* await consultarBaseDatos();
|
|
2922
|
+
* const elapsed = logger.timeEnd('consulta-db'); // ⏱️ Timer ended: consulta-db - 234.56ms
|
|
2923
|
+
*
|
|
2924
|
+
*/
|
|
2925
|
+
timeEnd(label) {
|
|
2926
|
+
const timer = this.timers.get(label);
|
|
2927
|
+
if (!timer) {
|
|
2928
|
+
this.warn(`Timer '${label}' does not exist`);
|
|
2929
|
+
return -1;
|
|
2930
|
+
}
|
|
2931
|
+
const elapsed = (typeof performance !== "undefined" ? performance : Date).now() - timer.startTime;
|
|
2932
|
+
this.timers.delete(label);
|
|
2933
|
+
const timerStyle = require_styling.StylePresets.success().build();
|
|
2934
|
+
const format = `%c⏱️ Timer ended: ${label} - ${elapsed.toFixed(2)}ms`;
|
|
2935
|
+
this.writeOutput(format, "info", [timerStyle], []);
|
|
2936
|
+
const prefix = this.getEffectivePrefix();
|
|
2937
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2938
|
+
this.dispatchToTransports("info", `timer:${label}`, prefix, stackInfo, {
|
|
2939
|
+
tag: "success",
|
|
2940
|
+
attributes: {
|
|
2941
|
+
...this.logContext._getContextRecord(),
|
|
2942
|
+
"logger.visual": "timer",
|
|
2943
|
+
"logger.timer.label": label,
|
|
2944
|
+
"logger.timer.elapsedMs": elapsed
|
|
2945
|
+
}
|
|
2946
|
+
});
|
|
2947
|
+
return elapsed;
|
|
2948
|
+
}
|
|
2949
|
+
/**
|
|
2950
|
+
* Muestra un banner con el tipo especificado o configurado
|
|
2951
|
+
*
|
|
2952
|
+
* @param {BannerType} bannerType - Tipo de banner (opcional)
|
|
2953
|
+
*
|
|
2954
|
+
* @example
|
|
2955
|
+
* logger.showBanner('ascii'); // Banner ASCII art
|
|
2956
|
+
* logger.showBanner('unicode'); // Banner con caracteres Unicode
|
|
2957
|
+
* logger.showBanner('svg'); // Banner con gráfico SVG
|
|
2958
|
+
* logger.showBanner(); // Usa el tipo configurado
|
|
2959
|
+
*
|
|
2960
|
+
*/
|
|
2961
|
+
showBanner(bannerType) {
|
|
2962
|
+
require_styling.displayInitBanner(bannerType ? bannerType : this.config.bannerType);
|
|
2963
|
+
}
|
|
2964
|
+
/**
|
|
2965
|
+
* Registra mensaje con imagen SVG de fondo
|
|
2966
|
+
*
|
|
2967
|
+
* @param {string} message - Mensaje a mostrar
|
|
2968
|
+
* @param {string} svgContent - Contenido SVG personalizado (opcional)
|
|
2969
|
+
* @param {StyleOptions} options - Opciones de estilo (ancho, alto, padding)
|
|
2970
|
+
*
|
|
2971
|
+
* @example
|
|
2972
|
+
* // SVG automático con gradiente
|
|
2973
|
+
* logger.logWithSVG('🎆 Bienvenido a Better Logger');
|
|
2974
|
+
*
|
|
2975
|
+
* @example
|
|
2976
|
+
* // SVG personalizado
|
|
2977
|
+
* const customSVG = '<svg>...</svg>';
|
|
2978
|
+
* logger.logWithSVG('Logo', customSVG, { width: 400, height: 100 });
|
|
2979
|
+
*
|
|
2980
|
+
*/
|
|
2981
|
+
logWithSVG(message, svgContent, options = {}) {
|
|
2982
|
+
if (!this.shouldLog("info")) return;
|
|
2983
|
+
const { width = 300, height = 60, padding = "30px 150px" } = options;
|
|
2984
|
+
let svgDataUri = "";
|
|
2985
|
+
if (svgContent) svgDataUri = `data:image/svg+xml,${encodeURIComponent(svgContent)}`;
|
|
2986
|
+
else {
|
|
2987
|
+
const defaultSVG = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${width} ${height}'><defs><linearGradient id='grad' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:%23667eea'/><stop offset='100%' style='stop-color:%23764ba2'/></linearGradient></defs><rect width='100%' height='100%' fill='url(%23grad)' rx='4'/><text x='${width / 2}' y='${height / 2 + 5}' text-anchor='middle' fill='white' font-family='monospace' font-size='14' font-weight='bold'>${message}</text></svg>`;
|
|
2988
|
+
svgDataUri = `data:image/svg+xml,${encodeURIComponent(defaultSVG)}`;
|
|
2989
|
+
}
|
|
2990
|
+
const svgStyle = new require_styling.StyleBuilder().bg(`url("${svgDataUri}") no-repeat center center`).padding(padding).color("transparent").rounded("4px").build();
|
|
2991
|
+
this.writeOutput(`%c${message}`, "info", [svgStyle], []);
|
|
2992
|
+
const prefix = this.getEffectivePrefix();
|
|
2993
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
2994
|
+
this.dispatchToTransports("info", `svg:${message}`, prefix, stackInfo, { attributes: {
|
|
2995
|
+
...this.logContext._getContextRecord(),
|
|
2996
|
+
"logger.visual": "svg",
|
|
2997
|
+
"logger.svg.width": width,
|
|
2998
|
+
"logger.svg.height": height
|
|
2999
|
+
} });
|
|
3000
|
+
}
|
|
3001
|
+
/**
|
|
3002
|
+
* Registra mensaje con gradiente animado de fondo
|
|
3003
|
+
*
|
|
3004
|
+
* @param {string} message - Mensaje a animar
|
|
3005
|
+
* @param {number} duration - Duración de la animación en segundos (default: 3)
|
|
3006
|
+
*
|
|
3007
|
+
* @example
|
|
3008
|
+
* logger.logAnimated('🌈 Animación en progreso');
|
|
3009
|
+
* logger.logAnimated('Cargando...', 5); // Animación de 5 segundos
|
|
3010
|
+
*
|
|
3011
|
+
*/
|
|
3012
|
+
logAnimated(message, duration = 3) {
|
|
3013
|
+
if (!this.shouldLog("info")) return;
|
|
3014
|
+
if (typeof document !== "undefined") {
|
|
3015
|
+
if (!document.getElementById("logger-animations")) {
|
|
3016
|
+
const style = document.createElement("style");
|
|
3017
|
+
style.id = "logger-animations";
|
|
3018
|
+
style.textContent = `
|
|
3019
|
+
@keyframes loggerGradient {
|
|
3020
|
+
0% { background-position: 0% 50%; }
|
|
3021
|
+
50% { background-position: 100% 50%; }
|
|
3022
|
+
100% { background-position: 0% 50%; }
|
|
3023
|
+
}
|
|
3024
|
+
`;
|
|
3025
|
+
document.head.appendChild(style);
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
const animatedStyle = new require_styling.StyleBuilder().bg("linear-gradient(-45deg, #667eea, #764ba2, #667eea, #764ba2)").css("background-size", "400% 400%").color("#ffffff").padding("12px 20px").rounded("8px").bold().font("Monaco, Consolas, monospace").animation(`loggerGradient ${duration}s ease infinite`).display("inline-block").build();
|
|
3029
|
+
this.writeOutput(`%c${message}`, "info", [animatedStyle], []);
|
|
3030
|
+
const prefix = this.getEffectivePrefix();
|
|
3031
|
+
const stackInfo = this.config.enableStackTrace ? require_utils.parseStackTrace() : null;
|
|
3032
|
+
this.dispatchToTransports("info", `animated:${message}`, prefix, stackInfo, { attributes: {
|
|
3033
|
+
...this.logContext._getContextRecord(),
|
|
3034
|
+
"logger.visual": "animated",
|
|
3035
|
+
"logger.animation.durationSec": duration
|
|
3036
|
+
} });
|
|
3037
|
+
}
|
|
3038
|
+
/**
|
|
3039
|
+
* Muestra un indicador de progreso de pasos en la terminal
|
|
3040
|
+
*
|
|
3041
|
+
* @param {number} current - Número de paso actual
|
|
3042
|
+
* @param {number} total - Número total de pasos
|
|
3043
|
+
* @param {string} message - Descripción del paso
|
|
3044
|
+
*
|
|
3045
|
+
* @example
|
|
3046
|
+
* logger.step(1, 5, 'Analyzing repository...');
|
|
3047
|
+
* logger.step(2, 5, 'Generating commit message...');
|
|
3048
|
+
*
|
|
3049
|
+
*/
|
|
3050
|
+
step(current, total, message) {
|
|
3051
|
+
this.terminalBridge.step(current, total, message);
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* Muestra un header con estilo y subtítulo opcional
|
|
3055
|
+
*
|
|
3056
|
+
* @param {string} title - Texto del título principal
|
|
3057
|
+
* @param {string} subtitle - Subtítulo opcional (se renderiza atenuado)
|
|
3058
|
+
*
|
|
3059
|
+
* @example
|
|
3060
|
+
* logger.header('Commit Wizard', 'v2.0.0');
|
|
3061
|
+
*
|
|
3062
|
+
*/
|
|
3063
|
+
header(title, subtitle) {
|
|
3064
|
+
this.terminalBridge.header(title, subtitle);
|
|
3065
|
+
}
|
|
3066
|
+
/**
|
|
3067
|
+
* Muestra una línea divisoria horizontal
|
|
3068
|
+
*
|
|
3069
|
+
* @example
|
|
3070
|
+
* logger.divider();
|
|
3071
|
+
*
|
|
3072
|
+
*/
|
|
3073
|
+
divider() {
|
|
3074
|
+
this.terminalBridge.divider();
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Emite una línea en blanco
|
|
3078
|
+
*
|
|
3079
|
+
* @example
|
|
3080
|
+
* logger.blank();
|
|
3081
|
+
*
|
|
3082
|
+
*/
|
|
3083
|
+
blank() {
|
|
3084
|
+
this.terminalBridge.blank();
|
|
3085
|
+
}
|
|
3086
|
+
/**
|
|
3087
|
+
* Renderiza contenido dentro de un box con borde
|
|
3088
|
+
*
|
|
3089
|
+
* @param {string} content - String de contenido (puede contener newlines)
|
|
3090
|
+
* @param {IBoxOptions} options - Opciones de renderizado del box
|
|
3091
|
+
*
|
|
3092
|
+
* @example
|
|
3093
|
+
* logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
|
|
3094
|
+
*
|
|
3095
|
+
*/
|
|
3096
|
+
box(content, options) {
|
|
3097
|
+
this.terminalBridge.box(content, options);
|
|
3098
|
+
}
|
|
3099
|
+
/**
|
|
3100
|
+
* Renderiza un array de objetos como una tabla ASCII formateada.
|
|
3101
|
+
* Distinto del método `table()` existente, que usa `console.table`.
|
|
3102
|
+
*
|
|
3103
|
+
* @param {Record<string, unknown>[]} rows - Array de objetos fila
|
|
3104
|
+
* @param {ITableOptions} options - Opciones de renderizado de la tabla
|
|
3105
|
+
*
|
|
3106
|
+
* @example
|
|
3107
|
+
* logger.cliTable([
|
|
3108
|
+
* { provider: 'Groq', status: 'Available', model: 'llama-3.3-70b' },
|
|
3109
|
+
* { provider: 'Gemini', status: 'Configured', model: 'gemini-2.5-flash' },
|
|
3110
|
+
* ]);
|
|
3111
|
+
*
|
|
3112
|
+
*/
|
|
3113
|
+
cliTable(rows, options) {
|
|
3114
|
+
this.terminalBridge.cliTable(rows, options);
|
|
3115
|
+
}
|
|
3116
|
+
/**
|
|
3117
|
+
* Crea un handle de spinner para mostrar progreso durante operaciones async.
|
|
3118
|
+
* Devuelve un `NoopSpinner` en entornos non-TTY.
|
|
3119
|
+
*
|
|
3120
|
+
* @param {string} message - Texto inicial del spinner
|
|
3121
|
+
* @returns {ISpinnerHandle} Controller del spinner
|
|
3122
|
+
*
|
|
3123
|
+
* @example
|
|
3124
|
+
* const s = logger.spinner('Analyzing repository...');
|
|
3125
|
+
* s.start();
|
|
3126
|
+
* await analyzeRepo();
|
|
3127
|
+
* s.succeed('Analysis complete (1.2s)');
|
|
3128
|
+
*
|
|
3129
|
+
*/
|
|
3130
|
+
spinner(message) {
|
|
3131
|
+
return this.terminalBridge.spinner(message);
|
|
3132
|
+
}
|
|
3133
|
+
/**
|
|
3134
|
+
* Fija el nivel de verbosidad del CLI, controlando a la vez la verbosidad
|
|
3135
|
+
* de logs y la visibilidad de las primitives
|
|
3136
|
+
*
|
|
3137
|
+
* @param {CLILogLevel} level - Nivel de log del CLI
|
|
3138
|
+
*
|
|
3139
|
+
* @example
|
|
3140
|
+
* logger.setCLILevel('quiet'); // Solo errors, sin CLI primitives
|
|
3141
|
+
* logger.setCLILevel('verbose'); // Debug logs + todas las CLI primitives
|
|
3142
|
+
*
|
|
3143
|
+
*/
|
|
3144
|
+
setCLILevel(level) {
|
|
3145
|
+
const mapping = require_utils.CLI_LEVEL_MAP[level];
|
|
3146
|
+
this.setVerbosity(mapping.verbosity);
|
|
3147
|
+
this.terminalBridge.setShowPrimitives(mapping.showPrimitives);
|
|
3148
|
+
this.config.cliLevel = level;
|
|
3149
|
+
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Devuelve el nivel de log del CLI actual
|
|
3152
|
+
* @returns {CLILogLevel} Nivel de log del CLI actual
|
|
3153
|
+
*/
|
|
3154
|
+
get cliLevel() {
|
|
3155
|
+
return this.config.cliLevel ?? "normal";
|
|
3156
|
+
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Escribe output formateado al destino configurado.
|
|
3159
|
+
* Respeta la configuración `outputMode` para output a consola, silencioso o custom.
|
|
3160
|
+
*
|
|
3161
|
+
* @private
|
|
3162
|
+
* @param {string} message - Mensaje de log formateado
|
|
3163
|
+
* @param {LogLevel} level - Nivel de log
|
|
3164
|
+
* @param {string[]} styles - Estilos CSS para la consola del navegador
|
|
3165
|
+
* @param {unknown[]} additionalArgs - Argumentos adicionales a loggear
|
|
3166
|
+
*/
|
|
3167
|
+
writeOutput(message, level, styles, additionalArgs) {
|
|
3168
|
+
const mode = this.config.outputMode ?? "console";
|
|
3169
|
+
if (mode === "silent") return;
|
|
3170
|
+
if (mode === "custom" && this.config.outputWriter) {
|
|
3171
|
+
const fullMessage = additionalArgs.length > 0 ? `${message} ${additionalArgs.map((a) => String(a)).join(" ")}` : message;
|
|
3172
|
+
this.config.outputWriter.write(fullMessage, level, styles);
|
|
3173
|
+
return;
|
|
3174
|
+
}
|
|
3175
|
+
if (additionalArgs.length > 0) console.log(message, ...styles, ...additionalArgs);
|
|
3176
|
+
else console.log(message, ...styles);
|
|
3177
|
+
}
|
|
3178
|
+
/**
|
|
3179
|
+
* Procesador de comandos CLI para configuración y exportación del logger
|
|
3180
|
+
*
|
|
3181
|
+
* @param {string} command - Comando CLI a ejecutar
|
|
3182
|
+
* @returns {Promise<void>}
|
|
3183
|
+
*
|
|
3184
|
+
* @example
|
|
3185
|
+
* // Comandos disponibles
|
|
3186
|
+
* await logger.cli('export json'); // Exporta logs en JSON
|
|
3187
|
+
* await logger.cli('export csv'); // Exporta logs en CSV
|
|
3188
|
+
* await logger.cli('theme list'); // Lista temas disponibles
|
|
3189
|
+
* await logger.cli('theme set neon'); // Cambia al tema neon
|
|
3190
|
+
* await logger.cli('config show'); // Muestra configuración actual
|
|
3191
|
+
* await logger.cli('history clear'); // Limpia historial de logs
|
|
3192
|
+
* await logger.cli('status'); // Muestra estado del logger
|
|
3193
|
+
* await logger.cli('help'); // Muestra ayuda de comandos
|
|
3194
|
+
*
|
|
3195
|
+
*/
|
|
3196
|
+
async cli(command) {
|
|
3197
|
+
if (!this.cliProcessor) {
|
|
3198
|
+
this.error("CLI processor not initialized");
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
await this.cliProcessor.processCommand(command, this);
|
|
3202
|
+
}
|
|
3203
|
+
};
|
|
3204
|
+
/**
|
|
3205
|
+
* Instancia singleton lazy — se inicializa en la primera llamada a
|
|
3206
|
+
* {@link getDefaultLogger}, no al importar el módulo.
|
|
3207
|
+
*
|
|
3208
|
+
* @private
|
|
3209
|
+
*/
|
|
3210
|
+
let _defaultLogger = null;
|
|
3211
|
+
/**
|
|
3212
|
+
* Crea el singleton del Logger por defecto de forma lazy.
|
|
3213
|
+
*
|
|
3214
|
+
* El singleton se construye solo en la primera llamada, de modo que
|
|
3215
|
+
* importar el módulo nunca ejecuta `new Logger(...)` ni
|
|
3216
|
+
* `displayInitBanner()`. Así los imports del módulo quedan side-effect free.
|
|
3217
|
+
*
|
|
3218
|
+
* @returns La instancia compartida de Logger
|
|
3219
|
+
*/
|
|
3220
|
+
function getDefaultLogger() {
|
|
3221
|
+
if (!_defaultLogger) {
|
|
3222
|
+
_defaultLogger = new Logger({
|
|
3223
|
+
verbosity: "info",
|
|
3224
|
+
enableColors: true,
|
|
3225
|
+
enableTimestamps: true,
|
|
3226
|
+
enableStackTrace: true,
|
|
3227
|
+
cliLevel: "normal"
|
|
3228
|
+
});
|
|
3229
|
+
try {
|
|
3230
|
+
if (typeof window !== "undefined" || typeof document !== "undefined") require_styling.displayInitBanner();
|
|
3231
|
+
} catch {}
|
|
3232
|
+
}
|
|
3233
|
+
return _defaultLogger;
|
|
3234
|
+
}
|
|
3235
|
+
new Proxy({}, { get(_target, prop, receiver) {
|
|
3236
|
+
const instance = getDefaultLogger();
|
|
3237
|
+
const value = Reflect.get(instance, prop, receiver);
|
|
3238
|
+
return typeof value === "function" ? value.bind(instance) : value;
|
|
3239
|
+
} });
|
|
3240
|
+
/**
|
|
3241
|
+
* Estrecha un contexto free-form `Record<string, unknown>` a un bag tipado
|
|
3242
|
+
* `ILogAttributes`. Los shapes desconocidos caen a strings JSON-encoded,
|
|
3243
|
+
* lo que mantiene conforme al transport OTLP (cada valor cae en un slot tipado).
|
|
3244
|
+
*
|
|
3245
|
+
* @param input - Contexto suministrado por el usuario (típicamente `Logger.context`).
|
|
3246
|
+
* @returns Un nuevo bag de attributes que satisface `ILogAttributes`.
|
|
3247
|
+
*/
|
|
3248
|
+
function toLogAttributes(input) {
|
|
3249
|
+
const out = {};
|
|
3250
|
+
for (const [key, value] of Object.entries(input)) {
|
|
3251
|
+
const mapped = toAttributeValue(value);
|
|
3252
|
+
if (mapped !== void 0) out[key] = mapped;
|
|
3253
|
+
}
|
|
3254
|
+
return out;
|
|
3255
|
+
}
|
|
3256
|
+
function toAttributeValue(value) {
|
|
3257
|
+
if (value === null || value === void 0) return void 0;
|
|
3258
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
3259
|
+
if (Array.isArray(value)) {
|
|
3260
|
+
const values = [];
|
|
3261
|
+
for (const item of value) {
|
|
3262
|
+
const mapped = toAttributeValue(item);
|
|
3263
|
+
if (mapped !== void 0) values.push(mapped);
|
|
3264
|
+
}
|
|
3265
|
+
return values;
|
|
3266
|
+
}
|
|
3267
|
+
try {
|
|
3268
|
+
return JSON.stringify(value);
|
|
3269
|
+
} catch {
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
//#endregion
|
|
3274
|
+
//#region src/index.ts
|
|
3275
|
+
/**
|
|
3276
|
+
* @fileoverview Better Logger — default entry point.
|
|
3277
|
+
*
|
|
3278
|
+
* Re-exports `Logger`, the scoped loggers, subpath-style bridges, and
|
|
3279
|
+
* cross-runtime styling/utility helpers. Side-effect free at import.
|
|
3280
|
+
*/
|
|
3281
|
+
let _logger = null;
|
|
3282
|
+
function getLogger() {
|
|
3283
|
+
if (!_logger) _logger = new Logger();
|
|
3284
|
+
return _logger;
|
|
3285
|
+
}
|
|
3286
|
+
/**
|
|
3287
|
+
* Default Logger singleton (lazy). Use this for the common case.
|
|
3288
|
+
*/
|
|
3289
|
+
var src_default = getLogger();
|
|
3290
|
+
/**
|
|
3291
|
+
* Top-level log methods bound to the default singleton.
|
|
3292
|
+
*/
|
|
3293
|
+
const debug = (...args) => getLogger().debug(...args);
|
|
3294
|
+
const info = (...args) => getLogger().info(...args);
|
|
3295
|
+
const warn = (...args) => getLogger().warn(...args);
|
|
3296
|
+
const error = (...args) => getLogger().error(...args);
|
|
3297
|
+
const success = (...args) => getLogger().success(...args);
|
|
3298
|
+
const critical = (...args) => getLogger().critical(...args);
|
|
3299
|
+
const trace = (...args) => getLogger().trace(...args);
|
|
3300
|
+
const table = (data, columns) => getLogger().table(data, columns);
|
|
3301
|
+
const group = (label, collapsed) => getLogger().group(label, collapsed);
|
|
3302
|
+
const groupEnd = () => getLogger().groupEnd();
|
|
3303
|
+
const time = (label) => getLogger().time(label);
|
|
3304
|
+
const timeEnd = (label) => getLogger().timeEnd(label);
|
|
3305
|
+
const setGlobalPrefix = (prefix) => getLogger().setGlobalPrefix(prefix);
|
|
3306
|
+
const scope = (name) => getLogger().scope(name);
|
|
3307
|
+
const component = (name) => getLogger().component(name);
|
|
3308
|
+
const api = (name) => getLogger().api(name);
|
|
3309
|
+
const badges = (badgeList) => getLogger().badges(badgeList);
|
|
3310
|
+
const badge = (badgeName) => getLogger().badge(badgeName);
|
|
3311
|
+
const clearBadges = () => getLogger().clearBadges();
|
|
3312
|
+
const setVerbosity = (level) => getLogger().setVerbosity(level);
|
|
3313
|
+
const addHandler = (handler) => getLogger().addHandler(handler);
|
|
3314
|
+
const setTheme = (theme) => getLogger().setTheme(theme);
|
|
3315
|
+
const setBannerType = (bannerType) => getLogger().setBannerType(bannerType);
|
|
3316
|
+
const showBanner = (bannerType) => getLogger().showBanner(bannerType);
|
|
3317
|
+
const logWithSVG = (message, svgContent, options) => getLogger().logWithSVG(message, svgContent, options);
|
|
3318
|
+
const logAnimated = (message, duration) => getLogger().logAnimated(message, duration);
|
|
3319
|
+
const cli = (command) => getLogger().cli(command);
|
|
3320
|
+
const addSerializer = (type, serializer, priority) => getLogger().addSerializer(type, serializer, priority);
|
|
3321
|
+
const removeSerializer = (type) => getLogger().removeSerializer(type);
|
|
3322
|
+
const on = (event, callback, priority) => getLogger().on(event, callback, priority);
|
|
3323
|
+
const once = (event, callback, priority) => getLogger().once(event, callback, priority);
|
|
3324
|
+
const off = (event, callback) => getLogger().off(event, callback);
|
|
3325
|
+
const use = (middleware, priority) => getLogger().use(middleware, priority);
|
|
3326
|
+
const addTransport = (target) => getLogger().addTransport(target);
|
|
3327
|
+
const removeTransport = (id) => getLogger().removeTransport(id);
|
|
3328
|
+
const flushTransports = () => getLogger().flushTransports();
|
|
3329
|
+
const closeTransports = () => getLogger().closeTransports();
|
|
3330
|
+
//#endregion
|
|
3331
|
+
exports.APILogger = APILogger;
|
|
3332
|
+
exports.BANNER_VARIANTS = require_styling.BANNER_VARIANTS;
|
|
3333
|
+
exports.ComponentLogger = ComponentLogger;
|
|
3334
|
+
exports.ContextLogger = ContextLogger;
|
|
3335
|
+
exports.DEFAULT_CONFIG = require_utils.DEFAULT_CONFIG;
|
|
3336
|
+
exports.Logger = Logger;
|
|
3337
|
+
exports.ScopedLogger = ScopedLogger;
|
|
3338
|
+
exports.StyleBuilder = require_styling.StyleBuilder;
|
|
3339
|
+
exports.StylePresets = require_styling.StylePresets;
|
|
3340
|
+
exports.THEME_BANNERS = require_styling.THEME_BANNERS;
|
|
3341
|
+
exports.THEME_PRESETS = require_styling.THEME_PRESETS;
|
|
3342
|
+
exports.addHandler = addHandler;
|
|
3343
|
+
exports.addSerializer = addSerializer;
|
|
3344
|
+
exports.addTransport = addTransport;
|
|
3345
|
+
exports.ansiBackground = require_utils.ansiBackground;
|
|
3346
|
+
exports.ansiBold = require_utils.ansiBold;
|
|
3347
|
+
exports.ansiColor = require_utils.ansiColor;
|
|
3348
|
+
exports.ansiDim = require_utils.ansiDim;
|
|
3349
|
+
exports.ansiStyle = require_utils.ansiStyle;
|
|
3350
|
+
exports.ansiUnderline = require_utils.ansiUnderline;
|
|
3351
|
+
exports.api = api;
|
|
3352
|
+
exports.badge = badge;
|
|
3353
|
+
exports.badges = badges;
|
|
3354
|
+
exports.clearBadges = clearBadges;
|
|
3355
|
+
exports.cli = cli;
|
|
3356
|
+
exports.closeTransports = closeTransports;
|
|
3357
|
+
exports.component = component;
|
|
3358
|
+
exports.createLogEntry = require_utils.createLogEntry;
|
|
3359
|
+
exports.critical = critical;
|
|
3360
|
+
exports.debug = debug;
|
|
3361
|
+
exports.default = src_default;
|
|
3362
|
+
exports.error = error;
|
|
3363
|
+
exports.flushTransports = flushTransports;
|
|
3364
|
+
exports.formatLogLevelANSI = require_utils.formatLogLevelANSI;
|
|
3365
|
+
exports.formatSuccessANSI = require_utils.formatSuccessANSI;
|
|
3366
|
+
exports.formatTablePlain = require_utils.formatTablePlain;
|
|
3367
|
+
exports.formatTimestamp = require_utils.formatTimestamp;
|
|
3368
|
+
exports.getColorCapability = require_environment_detector.getColorCapability;
|
|
3369
|
+
exports.getConsoleMethod = require_utils.getConsoleMethod;
|
|
3370
|
+
exports.getEnvironment = require_environment_detector.getEnvironment;
|
|
3371
|
+
exports.getEnvironmentInfo = require_environment_detector.getEnvironmentInfo;
|
|
3372
|
+
exports.getTerminalHeight = require_environment_detector.getTerminalHeight;
|
|
3373
|
+
exports.getTerminalWidth = require_environment_detector.getTerminalWidth;
|
|
3374
|
+
exports.group = group;
|
|
3375
|
+
exports.groupEnd = groupEnd;
|
|
3376
|
+
exports.info = info;
|
|
3377
|
+
exports.isRunningInTerminal = require_environment_detector.isRunningInTerminal;
|
|
3378
|
+
exports.logAnimated = logAnimated;
|
|
3379
|
+
exports.logWithSVG = logWithSVG;
|
|
3380
|
+
exports.off = off;
|
|
3381
|
+
exports.on = on;
|
|
3382
|
+
exports.once = once;
|
|
3383
|
+
exports.parseStackTrace = require_utils.parseStackTrace;
|
|
3384
|
+
exports.removeSerializer = removeSerializer;
|
|
3385
|
+
exports.removeTransport = removeTransport;
|
|
3386
|
+
exports.safeSerialize = require_utils.safeSerialize;
|
|
3387
|
+
exports.scope = scope;
|
|
3388
|
+
exports.setBannerType = setBannerType;
|
|
3389
|
+
exports.setGlobalPrefix = setGlobalPrefix;
|
|
3390
|
+
exports.setTheme = setTheme;
|
|
3391
|
+
exports.setVerbosity = setVerbosity;
|
|
3392
|
+
exports.showBanner = showBanner;
|
|
3393
|
+
exports.success = success;
|
|
3394
|
+
exports.supportsANSI = require_environment_detector.supportsANSI;
|
|
3395
|
+
exports.table = table;
|
|
3396
|
+
exports.time = time;
|
|
3397
|
+
exports.timeEnd = timeEnd;
|
|
3398
|
+
exports.trace = trace;
|
|
3399
|
+
exports.use = use;
|
|
3400
|
+
exports.warn = warn;
|
|
3401
|
+
|
|
3402
|
+
//# sourceMappingURL=index.cjs.map
|