logixia 2.0.4 → 2.0.6
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 +172 -2614
- package/dist/{async-context-B05ArHgM.mjs → async-context-2mbUKhcl.mjs} +4 -6
- package/dist/async-context-2mbUKhcl.mjs.map +1 -0
- package/dist/{async-context-DTQgi8f7.js → async-context-DUFMDYAr.js} +4 -6
- package/dist/async-context-DUFMDYAr.js.map +1 -0
- package/dist/{azure-monitor.transport-CwbOLZHB.js → azure-monitor.transport-Bu4S2I2q.js} +5 -5
- package/dist/azure-monitor.transport-Bu4S2I2q.js.map +1 -0
- package/dist/{azure-monitor.transport-DV03Z5P4.d.ts → azure-monitor.transport-Bvf7Xegt.d.ts} +2 -2
- package/dist/{azure-monitor.transport-DV03Z5P4.d.ts.map → azure-monitor.transport-Bvf7Xegt.d.ts.map} +1 -1
- package/dist/{azure-monitor.transport-BPbgjATu.mjs → azure-monitor.transport-C1RWAumT.mjs} +5 -5
- package/dist/azure-monitor.transport-C1RWAumT.mjs.map +1 -0
- package/dist/{azure-monitor.transport-C7kYyZUW.d.mts → azure-monitor.transport-CbSHOnNX.d.mts} +2 -2
- package/dist/{azure-monitor.transport-C7kYyZUW.d.mts.map → azure-monitor.transport-CbSHOnNX.d.mts.map} +1 -1
- package/dist/azure.d.mts +1 -1
- package/dist/azure.d.ts +1 -1
- package/dist/azure.js +1 -1
- package/dist/azure.mjs +1 -1
- package/dist/{batch-buffer-0fgLmIPn.mjs → batch-buffer-BvXLDPlV.mjs} +3 -3
- package/dist/{batch-buffer-0fgLmIPn.mjs.map → batch-buffer-BvXLDPlV.mjs.map} +1 -1
- package/dist/{batch-buffer-DT4gdXmf.js → batch-buffer-C7Am4Mw-.js} +3 -3
- package/dist/{batch-buffer-DT4gdXmf.js.map → batch-buffer-C7Am4Mw-.js.map} +1 -1
- package/dist/browser.d.mts +5 -5
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.d.ts +5 -5
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +47 -12
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +47 -12
- package/dist/browser.mjs.map +1 -1
- package/dist/{builder-D70z6kjj.mjs → builder-DhNhvOkt.mjs} +106 -153
- package/dist/builder-DhNhvOkt.mjs.map +1 -0
- package/dist/{builder-M7NoaugM.js → builder-yFvJrz7o.js} +109 -179
- package/dist/builder-yFvJrz7o.js.map +1 -0
- package/dist/cli/index.js +157 -66
- package/dist/cloudwatch.d.mts +1 -1
- package/dist/cloudwatch.d.ts +1 -1
- package/dist/cloudwatch.js +1 -1
- package/dist/cloudwatch.mjs +1 -1
- package/dist/{cloudwatch.transport-Bf7L4I59.d.ts → cloudwatch.transport-CQyT6U91.d.ts} +2 -2
- package/dist/{cloudwatch.transport-Bf7L4I59.d.ts.map → cloudwatch.transport-CQyT6U91.d.ts.map} +1 -1
- package/dist/{cloudwatch.transport-B2wKQFF7.js → cloudwatch.transport-Ch1Uae-0.js} +6 -6
- package/dist/cloudwatch.transport-Ch1Uae-0.js.map +1 -0
- package/dist/{cloudwatch.transport-Rj4yTpRn.d.mts → cloudwatch.transport-CjVrI6S4.d.mts} +2 -2
- package/dist/{cloudwatch.transport-Rj4yTpRn.d.mts.map → cloudwatch.transport-CjVrI6S4.d.mts.map} +1 -1
- package/dist/{cloudwatch.transport-BTvYfLs9.mjs → cloudwatch.transport-DZqF2xZO.mjs} +6 -6
- package/dist/cloudwatch.transport-DZqF2xZO.mjs.map +1 -0
- package/dist/correlation.d.mts +4 -55
- package/dist/correlation.d.mts.map +1 -1
- package/dist/correlation.d.ts +4 -55
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +13 -13
- package/dist/correlation.js.map +1 -1
- package/dist/correlation.mjs +13 -13
- package/dist/correlation.mjs.map +1 -1
- package/dist/{entry-fields-RLd1jCoR.js → entry-fields-BSLkzw18.js} +8 -3
- package/dist/entry-fields-BSLkzw18.js.map +1 -0
- package/dist/{entry-fields-CGuvT2R0.mjs → entry-fields-J1OBi24o.mjs} +8 -3
- package/dist/entry-fields-J1OBi24o.mjs.map +1 -0
- package/dist/gcp.d.mts +1 -1
- package/dist/gcp.d.ts +1 -1
- package/dist/gcp.js +1 -1
- package/dist/gcp.mjs +1 -1
- package/dist/{gcp.transport-CFQfdAOK.d.ts → gcp.transport-BCIvdFV-.d.ts} +4 -4
- package/dist/{gcp.transport-CFQfdAOK.d.ts.map → gcp.transport-BCIvdFV-.d.ts.map} +1 -1
- package/dist/{gcp.transport-C5D72b1g.d.mts → gcp.transport-D9SdLPwP.d.mts} +4 -4
- package/dist/{gcp.transport-C5D72b1g.d.mts.map → gcp.transport-D9SdLPwP.d.mts.map} +1 -1
- package/dist/{gcp.transport-CGKopAhQ.mjs → gcp.transport-DVCmnA3b.mjs} +20 -16
- package/dist/gcp.transport-DVCmnA3b.mjs.map +1 -0
- package/dist/{gcp.transport-KZe9hCAR.js → gcp.transport-Dy2Lf8FI.js} +20 -16
- package/dist/gcp.transport-Dy2Lf8FI.js.map +1 -0
- package/dist/http-shapes-BnBkJcid.d.mts +32 -0
- package/dist/http-shapes-BnBkJcid.d.mts.map +1 -0
- package/dist/http-shapes-BnBkJcid.d.ts +32 -0
- package/dist/http-shapes-BnBkJcid.d.ts.map +1 -0
- package/dist/{index-xqaJtAZn.d.mts → index-BSTtFcQ6.d.mts} +142 -8
- package/dist/index-BSTtFcQ6.d.mts.map +1 -0
- package/dist/{index-DwozbmB4.d.ts → index-CFDGkI8n.d.ts} +142 -8
- package/dist/index-CFDGkI8n.d.ts.map +1 -0
- package/dist/index.d.mts +21 -65
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +21 -65
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -21
- package/dist/index.mjs.map +1 -1
- package/dist/{internal-log-uCSd1PMc.mjs → internal-log-Bg4V1cPg.mjs} +30 -2
- package/dist/internal-log-Bg4V1cPg.mjs.map +1 -0
- package/dist/{internal-log-b0Vp4qrB.js → internal-log-By4Govmu.js} +41 -1
- package/dist/internal-log-By4Govmu.js.map +1 -0
- package/dist/{logitron-logger-D2B75Oc7.d.ts → logitron-logger-D22Yb61K.d.mts} +13 -100
- package/dist/logitron-logger-D22Yb61K.d.mts.map +1 -0
- package/dist/{logitron-logger-oEd6wNhf.d.mts → logitron-logger-D_MYYrQt.d.ts} +13 -100
- package/dist/logitron-logger-D_MYYrQt.d.ts.map +1 -0
- package/dist/middleware.d.mts +4 -17
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +4 -17
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +9 -39
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +7 -37
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +14 -7
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +14 -7
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +15 -10
- package/dist/nest.js.map +1 -1
- package/dist/nest.mjs +15 -10
- package/dist/nest.mjs.map +1 -1
- package/dist/{transport.manager-eZ_EeC00.mjs → otel-Dt5riXuE.mjs} +173 -24
- package/dist/otel-Dt5riXuE.mjs.map +1 -0
- package/dist/{transport.manager-DkcEOlqV.js → otel-DyeH6DVR.js} +214 -23
- package/dist/otel-DyeH6DVR.js.map +1 -0
- package/dist/own-property-BWkibepN.js +40 -0
- package/dist/own-property-BWkibepN.js.map +1 -0
- package/dist/own-property-CjFw9qwZ.mjs +29 -0
- package/dist/own-property-CjFw9qwZ.mjs.map +1 -0
- package/dist/{request-trace-C_fvIDv4.mjs → request-trace-BgNykH9M.mjs} +1 -5
- package/dist/{request-trace-C_fvIDv4.mjs.map → request-trace-BgNykH9M.mjs.map} +1 -1
- package/dist/{request-trace-wTJdKp6-.js → request-trace-ByujsUZk.js} +1 -5
- package/dist/{request-trace-wTJdKp6-.js.map → request-trace-ByujsUZk.js.map} +1 -1
- package/dist/{safe-stringify-BMRl3EX3.mjs → safe-stringify-B5p5ktFe.mjs} +37 -12
- package/dist/safe-stringify-B5p5ktFe.mjs.map +1 -0
- package/dist/{safe-stringify-DLz1Kz3o.js → safe-stringify-J3sh-7YM.js} +37 -12
- package/dist/safe-stringify-J3sh-7YM.js.map +1 -0
- package/dist/{search-DUfWuzFP.js → search-CRjhHxe9.js} +269 -25
- package/dist/search-CRjhHxe9.js.map +1 -0
- package/dist/{search-CazwyX5Z.d.ts → search-DA3ft3X5.d.mts} +5 -2
- package/dist/search-DA3ft3X5.d.mts.map +1 -0
- package/dist/{search-CWMVYC-R.mjs → search-DAXKE-P9.mjs} +269 -25
- package/dist/search-DAXKE-P9.mjs.map +1 -0
- package/dist/{search-BH33XhuU.d.mts → search-DEl3Pe47.d.ts} +5 -2
- package/dist/search-DEl3Pe47.d.ts.map +1 -0
- package/dist/search.d.mts +1 -1
- package/dist/search.d.ts +1 -1
- package/dist/search.js +1 -1
- package/dist/search.mjs +1 -1
- package/dist/{secret-config-CBZBs0p1.js → secret-config-CmK2wVkr.js} +6 -5
- package/dist/secret-config-CmK2wVkr.js.map +1 -0
- package/dist/{secret-config-BegMLkYl.mjs → secret-config-Dhb6pqTU.mjs} +6 -5
- package/dist/secret-config-Dhb6pqTU.mjs.map +1 -0
- package/dist/{slack.transport-DxHOXlLu.d.mts → slack.transport-BDyENuR0.d.mts} +2 -2
- package/dist/{slack.transport-DxHOXlLu.d.mts.map → slack.transport-BDyENuR0.d.mts.map} +1 -1
- package/dist/{slack.transport-Ce96JBDk.mjs → slack.transport-BTEwsREY.mjs} +66 -15
- package/dist/slack.transport-BTEwsREY.mjs.map +1 -0
- package/dist/{slack.transport-DrirgDNy.d.ts → slack.transport-C6E0l4kw.d.ts} +2 -2
- package/dist/{slack.transport-DrirgDNy.d.ts.map → slack.transport-C6E0l4kw.d.ts.map} +1 -1
- package/dist/{slack.transport-Dlx3xvb7.js → slack.transport-UbYvOdKx.js} +67 -16
- package/dist/slack.transport-UbYvOdKx.js.map +1 -0
- package/dist/testing.d.mts +11 -4
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.d.ts +11 -4
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +38 -3
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +38 -3
- package/dist/testing.mjs.map +1 -1
- package/dist/{transport.types-BJVL1QQl.d.ts → transport.types-CzJq4IrF.d.mts} +14 -3
- package/dist/transport.types-CzJq4IrF.d.mts.map +1 -0
- package/dist/{transport.types-BJVL1QQl.d.mts → transport.types-CzJq4IrF.d.ts} +14 -3
- package/dist/transport.types-CzJq4IrF.d.ts.map +1 -0
- package/dist/transports.d.mts +25 -13
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +25 -13
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +15 -15
- package/dist/transports.mjs +6 -6
- package/dist/worker-entry.js +105 -24
- package/dist/worker.d.mts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.mjs +1 -1
- package/dist/{worker.transport-BuPwBi3d.d.ts → worker.transport-B9mCQSM1.d.ts} +7 -2
- package/dist/worker.transport-B9mCQSM1.d.ts.map +1 -0
- package/dist/{worker.transport-hJay1wxA.d.mts → worker.transport-Bl8lFRck.d.mts} +7 -2
- package/dist/worker.transport-Bl8lFRck.d.mts.map +1 -0
- package/dist/{worker.transport-DLVA4y2e.mjs → worker.transport-BmmOKb1-.mjs} +13 -10
- package/dist/worker.transport-BmmOKb1-.mjs.map +1 -0
- package/dist/{worker.transport-C6GNl_r2.js → worker.transport-DxxbqQCG.js} +13 -10
- package/dist/worker.transport-DxxbqQCG.js.map +1 -0
- package/package.json +33 -65
- package/dist/async-context-B05ArHgM.mjs.map +0 -1
- package/dist/async-context-DTQgi8f7.js.map +0 -1
- package/dist/azure-monitor.transport-BPbgjATu.mjs.map +0 -1
- package/dist/azure-monitor.transport-CwbOLZHB.js.map +0 -1
- package/dist/builder-D70z6kjj.mjs.map +0 -1
- package/dist/builder-M7NoaugM.js.map +0 -1
- package/dist/cloudwatch.transport-B2wKQFF7.js.map +0 -1
- package/dist/cloudwatch.transport-BTvYfLs9.mjs.map +0 -1
- package/dist/entry-fields-CGuvT2R0.mjs.map +0 -1
- package/dist/entry-fields-RLd1jCoR.js.map +0 -1
- package/dist/gcp.transport-CGKopAhQ.mjs.map +0 -1
- package/dist/gcp.transport-KZe9hCAR.js.map +0 -1
- package/dist/index-DwozbmB4.d.ts.map +0 -1
- package/dist/index-xqaJtAZn.d.mts.map +0 -1
- package/dist/internal-log-b0Vp4qrB.js.map +0 -1
- package/dist/internal-log-uCSd1PMc.mjs.map +0 -1
- package/dist/logitron-logger-D2B75Oc7.d.ts.map +0 -1
- package/dist/logitron-logger-oEd6wNhf.d.mts.map +0 -1
- package/dist/safe-stringify-BMRl3EX3.mjs.map +0 -1
- package/dist/safe-stringify-DLz1Kz3o.js.map +0 -1
- package/dist/search-BH33XhuU.d.mts.map +0 -1
- package/dist/search-CWMVYC-R.mjs.map +0 -1
- package/dist/search-CazwyX5Z.d.ts.map +0 -1
- package/dist/search-DUfWuzFP.js.map +0 -1
- package/dist/secret-config-BegMLkYl.mjs.map +0 -1
- package/dist/secret-config-CBZBs0p1.js.map +0 -1
- package/dist/slack.transport-Ce96JBDk.mjs.map +0 -1
- package/dist/slack.transport-Dlx3xvb7.js.map +0 -1
- package/dist/transport.manager-DkcEOlqV.js.map +0 -1
- package/dist/transport.manager-eZ_EeC00.mjs.map +0 -1
- package/dist/transport.types-BJVL1QQl.d.mts.map +0 -1
- package/dist/transport.types-BJVL1QQl.d.ts.map +0 -1
- package/dist/worker.transport-BuPwBi3d.d.ts.map +0 -1
- package/dist/worker.transport-C6GNl_r2.js.map +0 -1
- package/dist/worker.transport-DLVA4y2e.mjs.map +0 -1
- package/dist/worker.transport-hJay1wxA.d.mts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-CazwyX5Z.d.ts","names":[],"sources":["../src/search/types/search.types.ts","../src/search/search-manager.ts","../src/search/core/log-indexer.interface.ts","../src/search/core/basic-log-indexer.ts","../src/search/core/search-engine.interface.ts","../src/search/core/basic-search-engine.ts","../src/search/engines/correlation-engine.ts","../src/search/engines/nlp-search-engine.ts","../src/search/engines/pattern-recognition-engine.ts"],"mappings":";;;;UASiB;EACf;EACA;EACA;EACA,YAAY;EACZ;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;;;;;UAMA;EACf,OAAO;EACP,MAAM;EACN,WAAW;;;;;UAMI;EACf;EACA;;;;;UAMe;EACf,KAAK;EACL;EACA,aAAa;EACb,UAAU;EACV,UAAU;EACV,cAAc;;;;;UAMC;EACf;EACA;EACA;;;;;UAMe;EACf;EACA;EACA;EACA;;;;;UAMe;EACf,KAAK;EACL,cAAc;EACd;;;;;KAMU;;;;UAWK;EACf;EACA;EACA,MAAM;EACN,UAAU;EACV,UAAU;;;;;UAMK;EACf,WAAW;EACX,KAAK;EACL;EACA;;;;;UAMe;EACf;EACA;EACA;EACA;EACA;EACA,eAAe;;;;;UAMA;EACf,KAAK;EACL;EACA;EACA;;;;;UAMe;EACf;EACA,UAAU;EACV,UAAU;EACV,WAAW;EACX;;;;;UAMe;EACf;EACA;EACA,SAAS;EACT;EACA;EACA;EACA;EACA;EACA;EACA;;;;;KAMU;;;;UAKK;EACf;EACA,MAAM;EACN;EACA;EACA,WAAW;;;;;KAMD;;;;UAMK;EACf;EACA;EACA;EACA;EACA;;;;;UAMe;EACf;EACA;EACA,aAAa;EACb,aAAa;EACb,WAAW;;;;;UAMI;EACf;EACA;EACA,MAAM;EACN;EACA;EACA;;;;;UAMe;EACf;EACA;EACA,QAAQ;EACR,UAAU;EACV;EACA,UAAU;EACV;EACA;;;;;UAMe;EACf,KAAK;EACL;EACA;EACA;EACA;;;;;UAMe;EACf;EACA,QAAQ;EACR,UAAU;EACV,SAAS;EACT,YAAY;EACZ;;;;;KAMU;;;;UAaK;EACf,MAAM;EACN;EACA;EACA;;;;;KAMU;;;;UAMK;EACf;EACA;EACA;EACA;EACA,SAAS;EACT,SAAS;EACT,WAAW;EACX,WAAW;EACX;EACA;;;;;UAMe;EACf;EACA;EACA;EACA;;;;;UCpRe;EACf;EACA;EACA;EACA;EACA;;;;;cAMW;UACH;UACA;UACA;UACA;UACA;EAEI,YAAA,SAAS;;;;EA8Bf,UAAU,MAAM,aAAa;;;;EAa7B,SAAS,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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-DUfWuzFP.js","names":["safeToString"],"sources":["../src/utils/csv.utils.ts","../src/search/core/basic-log-indexer.ts","../src/search/core/basic-search-engine.ts","../src/search/engines/correlation-engine.ts","../src/search/engines/nlp-search-engine.ts","../src/search/engines/pattern-recognition-engine.ts","../src/search/search-manager.ts"],"sourcesContent":["const CSV_FORMULA_PREFIX = /^[=+\\-@\\t\\r]/;\n\n/**\n * Render one CSV field. String values that a spreadsheet would treat as a\n * formula (leading `=`, `+`, `-`, `@`, tab or CR) are prefixed with `'`.\n * Objects are JSON-encoded. Fields containing a comma, quote, CR or LF are quoted;\n * `alwaysQuote` quotes every field. `null` / `undefined` render as empty.\n */\nexport function csvField(value: unknown, alwaysQuote = false): string {\n if (value === undefined || value === null) return alwaysQuote ? '\"\"' : '';\n let str: string;\n if (typeof value === 'string') {\n str = CSV_FORMULA_PREFIX.test(value) ? `'${value}` : value;\n } else if (typeof value === 'object') {\n str = JSON.stringify(value);\n } else {\n str = String(value);\n }\n if (alwaysQuote || /[\",\\r\\n]/.test(str)) return `\"${str.replace(/\"/g, '\"\"')}\"`;\n return str;\n}\n","/**\n * Basic log indexer implementation for indexing and managing log entries\n */\n\nimport type { LogEntry } from '../../types';\nimport type { LogCluster, SearchQuery, SemanticIndex } from '../types';\nimport type { ILogIndexer } from './log-indexer.interface';\n\n/**\n * Basic log indexer implementation\n */\nexport class BasicLogIndexer implements ILogIndexer {\n private index: Map<string, LogEntry> = new Map();\n private fieldIndices: Map<string, Map<string, Set<string>>> = new Map();\n private semanticIndex: SemanticIndex | undefined;\n private lastOptimized?: Date;\n /**\n * Running estimate of the serialized index size in bytes, maintained\n * incrementally. The previous implementation JSON.stringify'd EVERY log on\n * each getIndexStats() call — O(n) per call, which for the default 1M-entry\n * cap means stringifying a million objects and blocking the event loop.\n * We keep a per-log byte estimate so the lookup is O(1).\n */\n private indexSizeBytes = 0;\n private readonly logSizeById = new Map<string, number>();\n\n constructor(\n private options?: {\n maxIndexSize?: number;\n autoOptimize?: boolean;\n optimizeThreshold?: number;\n }\n ) {\n this.options = {\n maxIndexSize: 1000000,\n autoOptimize: true,\n optimizeThreshold: 10000,\n ...options,\n };\n\n // Initialize field indices\n this.initializeFieldIndices();\n }\n\n /**\n * Index a single log entry\n */\n async indexLog(log: LogEntry): Promise<void> {\n const logId = this.generateLogId(log);\n\n // Add to main index\n this.trackInsert(logId, log);\n\n // Update field indices\n this.updateFieldIndices(logId, log);\n\n // Auto-optimize if threshold reached\n if (\n this.options?.autoOptimize &&\n this.index.size % (this.options.optimizeThreshold || 10000) === 0\n ) {\n await this.optimizeIndex();\n }\n\n // Enforce max size\n if (this.index.size > (this.options?.maxIndexSize || 1000000)) {\n await this.removeOldestLogs(Math.floor((this.options?.maxIndexSize || 1000000) * 0.1));\n }\n }\n\n /**\n * Index multiple log entries in batch\n */\n async indexBatch(logs: LogEntry[]): Promise<void> {\n for (const log of logs) {\n const logId = this.generateLogId(log);\n this.trackInsert(logId, log);\n this.updateFieldIndices(logId, log);\n }\n\n // Optimize after batch\n if (this.options?.autoOptimize) {\n await this.optimizeIndex();\n }\n }\n\n /**\n * Build semantic index for intelligent search\n */\n async buildSemanticIndex(logs: LogEntry[]): Promise<SemanticIndex> {\n // Build clusters based on log patterns\n const clusters = await this.clusterLogs(logs);\n\n this.semanticIndex = {\n version: '1.0.0',\n indexedCount: logs.length,\n lastUpdated: new Date(),\n clusters,\n };\n\n return this.semanticIndex;\n }\n\n /**\n * Update search suggestions based on search history\n */\n async updateSearchSuggestions(searchHistory: SearchQuery[]): Promise<void> {\n // Extract common patterns from search history\n const patterns = new Map<string, number>();\n\n for (const query of searchHistory) {\n const normalizedQuery = query.query.toLowerCase().trim();\n patterns.set(normalizedQuery, (patterns.get(normalizedQuery) || 0) + 1);\n }\n\n // In a real implementation, this would persist top patterns to storage\n // Top patterns (sorted by frequency) would be stored here\n }\n\n /**\n * Optimize the index for better performance\n */\n async optimizeIndex(): Promise<void> {\n // Rebuild field indices\n this.fieldIndices.clear();\n this.initializeFieldIndices();\n\n for (const [logId, log] of this.index.entries()) {\n this.updateFieldIndices(logId, log);\n }\n\n this.lastOptimized = new Date();\n }\n\n /**\n * Clear the index\n */\n async clearIndex(): Promise<void> {\n this.index.clear();\n this.fieldIndices.clear();\n this.semanticIndex = undefined;\n this.indexSizeBytes = 0;\n this.logSizeById.clear();\n this.initializeFieldIndices();\n }\n\n /**\n * Get index statistics\n */\n async getIndexStats(): Promise<{\n totalDocuments: number;\n indexSize: number;\n lastOptimized?: Date;\n }> {\n return {\n totalDocuments: this.index.size,\n indexSize: this.calculateIndexSize(),\n ...(this.lastOptimized !== undefined ? { lastOptimized: this.lastOptimized } : {}),\n };\n }\n\n /**\n * Remove logs older than specified time\n */\n async removeOldLogs(olderThan: Date): Promise<number> {\n const cutoffTime = olderThan.getTime();\n let removedCount = 0;\n\n for (const [logId, log] of this.index.entries()) {\n const logTime = new Date(log.timestamp).getTime();\n if (logTime < cutoffTime) {\n this.trackDelete(logId);\n this.removeFromFieldIndices(logId);\n removedCount++;\n }\n }\n\n return removedCount;\n }\n\n /**\n * Search logs by field\n */\n public searchByField(field: string, value: string): LogEntry[] {\n const fieldIndex = this.fieldIndices.get(field);\n if (!fieldIndex) return [];\n\n const logIds = fieldIndex.get(value.toLowerCase());\n if (!logIds) return [];\n\n return Array.from(logIds)\n .map((id) => this.index.get(id))\n .filter((log): log is LogEntry => log !== undefined);\n }\n\n /**\n * Get all indexed logs\n */\n public getAllLogs(): LogEntry[] {\n return Array.from(this.index.values());\n }\n\n // Private helper methods\n\n private initializeFieldIndices(): void {\n const fields = ['level', 'appName', 'traceId', 'context', 'environment'];\n for (const field of fields) {\n this.fieldIndices.set(field, new Map());\n }\n }\n\n private updateFieldIndices(logId: string, log: LogEntry): void {\n // Index level\n this.addToFieldIndex('level', log.level, logId);\n\n // Index appName\n if (log.appName) {\n this.addToFieldIndex('appName', log.appName, logId);\n }\n\n // Index traceId\n if (log.traceId) {\n this.addToFieldIndex('traceId', log.traceId, logId);\n }\n\n // Index context\n if (log.context) {\n this.addToFieldIndex('context', log.context, logId);\n }\n\n // Index environment\n if (log.environment) {\n this.addToFieldIndex('environment', log.environment, logId);\n }\n }\n\n private addToFieldIndex(field: string, value: string, logId: string): void {\n const fieldIndex = this.fieldIndices.get(field);\n if (!fieldIndex) return;\n\n const normalizedValue = value.toLowerCase();\n if (!fieldIndex.has(normalizedValue)) {\n fieldIndex.set(normalizedValue, new Set());\n }\n fieldIndex.get(normalizedValue)!.add(logId);\n }\n\n private removeFromFieldIndices(logId: string): void {\n for (const fieldIndex of this.fieldIndices.values()) {\n for (const logIds of fieldIndex.values()) {\n logIds.delete(logId);\n }\n }\n }\n\n private generateLogId(log: LogEntry): string {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security log ID suffix\n return `${log.timestamp}_${log.level}_${Math.random().toString(36).slice(2, 11)}`;\n }\n\n private calculateIndexSize(): number {\n // O(1): return the incrementally-maintained running total instead of\n // re-stringifying every entry on each call.\n return this.indexSizeBytes;\n }\n\n /** Insert into the main index and update the running size estimate. */\n private trackInsert(logId: string, log: LogEntry): void {\n // If this id somehow already exists, subtract its old size first.\n const existing = this.logSizeById.get(logId);\n if (existing !== undefined) this.indexSizeBytes -= existing;\n\n const size = JSON.stringify(log).length;\n this.index.set(logId, log);\n this.logSizeById.set(logId, size);\n this.indexSizeBytes += size;\n }\n\n /** Delete from the main index and update the running size estimate. */\n private trackDelete(logId: string): void {\n const size = this.logSizeById.get(logId);\n if (size !== undefined) {\n this.indexSizeBytes -= size;\n this.logSizeById.delete(logId);\n }\n this.index.delete(logId);\n }\n\n private async removeOldestLogs(count: number): Promise<void> {\n const logs = Array.from(this.index.entries())\n .sort((a, b) => new Date(a[1].timestamp).getTime() - new Date(b[1].timestamp).getTime())\n .slice(0, count);\n\n for (const [logId] of logs) {\n this.trackDelete(logId);\n this.removeFromFieldIndices(logId);\n }\n }\n\n private async clusterLogs(logs: LogEntry[]): Promise<LogCluster[]> {\n // Simple clustering based on log patterns\n const clusters = new Map<string, LogEntry[]>();\n\n for (const log of logs) {\n // Create a pattern key based on level and service\n const patternKey = `${log.level}_${log.appName}`;\n\n if (!clusters.has(patternKey)) {\n clusters.set(patternKey, []);\n }\n clusters.get(patternKey)!.push(log);\n }\n\n // Convert to LogCluster format\n return Array.from(clusters.entries()).map(([pattern, clusterLogs], index) => ({\n id: `cluster_${index}`,\n centroid: [], // Would be calculated in a real implementation\n logs: clusterLogs,\n pattern,\n frequency: clusterLogs.length,\n labels: [pattern],\n }));\n }\n}\n","/**\n * Basic search engine implementation with full-text search and filtering\n */\n\nimport type { LogEntry } from '../../types';\nimport { safeToString } from '../../utils/coerce.utils';\nimport type {\n CorrelatedLogs,\n LogCorrelationSummary,\n ParsedNLQuery,\n SearchFilters,\n SearchHighlight,\n SearchOptions,\n SearchPreset,\n SearchResult,\n SearchStats,\n SearchSuggestion,\n SimilarLog,\n TimelineEvent,\n TimeRange,\n} from '../types';\nimport type { ILogSearchEngine } from './search-engine.interface';\n\n/**\n * Basic search engine implementation\n */\nexport class BasicSearchEngine implements ILogSearchEngine {\n private logs: LogEntry[] = [];\n private presets: Map<string, SearchPreset> = new Map();\n private searchHistory: string[] = [];\n private suggestionCache: Map<string, SearchSuggestion[]> = new Map();\n\n constructor(private options?: { maxHistorySize?: number; cacheSize?: number; maxLogs?: number }) {\n this.options = {\n maxHistorySize: 1000,\n cacheSize: 100,\n maxLogs: 100_000,\n ...options,\n };\n }\n\n /**\n * Add logs to the search index.\n *\n * Bounded to `maxLogs` (default 100k): the buffer previously grew without\n * limit, leaking memory in any long-running process feeding it logs. When the\n * cap is exceeded the oldest entries are dropped (FIFO). We also append with a\n * loop rather than `push(...logs)` to avoid a RangeError from spreading a very\n * large array onto the call stack.\n */\n public addLogs(logs: LogEntry[]): void {\n for (const log of logs) this.logs.push(log);\n\n const maxLogs = this.options?.maxLogs ?? 100_000;\n if (this.logs.length > maxLogs) {\n this.logs.splice(0, this.logs.length - maxLogs);\n }\n }\n\n /**\n * Clear all logs from the index\n */\n public clearLogs(): void {\n this.logs = [];\n }\n\n /**\n * Get all indexed logs\n */\n public getLogs(): LogEntry[] {\n return this.logs;\n }\n\n /**\n * Perform a full-text search across logs\n */\n async search(\n query: string,\n filters?: SearchFilters,\n options?: SearchOptions\n ): Promise<SearchResult[]> {\n // Apply filters first\n const filteredLogs = this.applyFilters(this.logs, filters);\n\n // Perform text search\n const results = this.performTextSearch(filteredLogs, query, options);\n\n // Add to search history\n this.addToSearchHistory(query);\n\n // Apply sorting\n const sorted = this.applySorting(results, options?.sortBy, options?.sortOrder);\n\n // Apply pagination\n const paginated = this.applyPagination(sorted, options?.offset, options?.limit);\n\n // Add context if requested\n if (options?.includeContext) {\n await this.enrichWithContext(paginated, options.contextSize);\n }\n\n return paginated;\n }\n\n /**\n * Natural language search (basic implementation)\n */\n async naturalLanguageSearch(query: string): Promise<SearchResult[]> {\n const parsed = await this.parseNaturalLanguageQuery(query);\n return this.search(parsed.originalQuery, parsed.filters, {\n semanticSearch: true,\n includeContext: true,\n });\n }\n\n /**\n * Find logs correlated by trace ID\n */\n async correlateByTraceId(traceId: string): Promise<CorrelatedLogs> {\n const correlatedLogs = this.logs.filter((log) => log.traceId === traceId);\n\n // Sort by timestamp\n correlatedLogs.sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n\n // Build timeline\n const timeline: TimelineEvent[] = correlatedLogs.map((log) => {\n let eventType: TimelineEvent['eventType'] = 'info';\n\n if (log.level === 'error') eventType = 'error';\n else if (log.message.toLowerCase().includes('start')) eventType = 'start';\n else if (\n log.message.toLowerCase().includes('end') ||\n log.message.toLowerCase().includes('complete')\n )\n eventType = 'end';\n else if (log.message.toLowerCase().includes('milestone')) eventType = 'milestone';\n\n return {\n timestamp: new Date(log.timestamp),\n log,\n eventType,\n };\n });\n\n // Generate summary\n const summary: LogCorrelationSummary = {\n totalLogs: correlatedLogs.length,\n errorCount: correlatedLogs.filter((l) => l.level === 'error').length,\n warningCount: correlatedLogs.filter((l) => l.level === 'warn').length,\n services: [...new Set(correlatedLogs.map((l) => l.appName))],\n };\n\n // Calculate duration if we have start and end\n if (timeline.length > 0) {\n const start = timeline[0]!.timestamp.getTime();\n const end = timeline[timeline.length - 1]!.timestamp.getTime();\n summary.duration = end - start;\n }\n\n return {\n traceId,\n correlationKey: traceId,\n logs: correlatedLogs,\n timeline,\n summary,\n };\n }\n\n /**\n * Find similar logs based on content similarity\n */\n async findSimilarLogs(logEntry: LogEntry, limit: number = 10): Promise<SimilarLog[]> {\n const similarities: SimilarLog[] = [];\n\n for (const log of this.logs) {\n if (log === logEntry) continue;\n\n const similarity = this.calculateSimilarity(logEntry, log);\n if (similarity > 0.3) {\n // Threshold for similarity\n similarities.push({\n log,\n similarity,\n matchedPatterns: this.findMatchedPatterns(logEntry, log),\n reason: this.generateSimilarityReason(logEntry, log, similarity),\n });\n }\n }\n\n // Sort by similarity and return top results\n return similarities.sort((a, b) => b.similarity - a.similarity).slice(0, limit);\n }\n\n /**\n * Get search suggestions\n */\n async getSuggestions(partialQuery: string, limit: number = 10): Promise<SearchSuggestion[]> {\n const cacheKey = partialQuery.toLowerCase();\n\n // Check cache\n if (this.suggestionCache.has(cacheKey)) {\n return this.suggestionCache.get(cacheKey)!.slice(0, limit);\n }\n\n const suggestions: SearchSuggestion[] = [];\n\n // Field suggestions\n const fields = ['level', 'appName', 'traceId', 'message', 'timestamp'];\n for (const field of fields) {\n if (field.toLowerCase().includes(partialQuery.toLowerCase())) {\n suggestions.push({\n text: field,\n type: 'field',\n category: 'field',\n });\n }\n }\n\n // Value suggestions from logs\n const values = new Set<string>();\n for (const log of this.logs.slice(-1000)) {\n // Recent logs only\n if (log.level?.toLowerCase().includes(partialQuery.toLowerCase())) {\n values.add(log.level);\n }\n if (log.appName?.toLowerCase().includes(partialQuery.toLowerCase())) {\n values.add(log.appName);\n }\n }\n\n for (const value of values) {\n suggestions.push({\n text: value,\n type: 'value',\n category: 'value',\n });\n }\n\n // History suggestions\n for (const historyItem of this.searchHistory.slice(-50)) {\n if (historyItem.toLowerCase().includes(partialQuery.toLowerCase())) {\n suggestions.push({\n text: historyItem,\n type: 'query_history',\n category: 'history',\n });\n }\n }\n\n // Cache suggestions\n this.suggestionCache.set(cacheKey, suggestions);\n\n // Trim cache if too large\n if (this.suggestionCache.size > (this.options?.cacheSize || 100)) {\n const firstKey = this.suggestionCache.keys().next().value as string | undefined;\n if (firstKey !== undefined) this.suggestionCache.delete(firstKey);\n }\n\n return suggestions.slice(0, limit);\n }\n\n /**\n * Get search statistics\n */\n async getStats(): Promise<SearchStats> {\n return {\n totalResults: this.logs.length,\n executionTime: 0,\n indexSize: this.logs.length,\n topTerms: this.getTopTerms(),\n };\n }\n\n /**\n * Parse natural language query\n */\n async parseNaturalLanguageQuery(query: string): Promise<ParsedNLQuery> {\n const filters: SearchFilters = {};\n const lowerQuery = query.toLowerCase();\n\n // Extract levels\n const levels: string[] = [];\n if (lowerQuery.includes('error')) levels.push('error');\n if (lowerQuery.includes('warn')) levels.push('warn');\n if (lowerQuery.includes('info')) levels.push('info');\n if (levels.length > 0) filters.levels = levels;\n\n // Extract time range\n const timeRange = this.extractTimeRange(query);\n if (timeRange) filters.timeRange = timeRange;\n\n // Extract service names (basic pattern matching)\n const serviceMatch = query.match(/from\\s+(?:the\\s+)?(\\w+)\\s+service/i);\n if (serviceMatch?.[1]) {\n filters.services = [serviceMatch[1]];\n }\n\n // Extract user ID\n const userMatch = query.match(/user\\s+(?:id\\s+)?(\\w+)/i);\n if (userMatch?.[1]) {\n filters.userIds = [userMatch[1]];\n }\n\n // Determine intent\n let intent: ParsedNLQuery['intent'] = 'general_search';\n if (lowerQuery.includes('error')) intent = 'find_errors';\n if (lowerQuery.includes('trace') || lowerQuery.includes('request')) intent = 'trace_request';\n if (lowerQuery.includes('user')) intent = 'find_user_activity';\n if (lowerQuery.includes('slow') || lowerQuery.includes('performance'))\n intent = 'performance_analysis';\n\n return {\n originalQuery: query,\n intent,\n entities: [],\n filters,\n confidence: 0.7,\n };\n }\n\n /**\n * Save a search preset\n */\n async savePreset(\n preset: Omit<SearchPreset, 'id' | 'createdAt' | 'updatedAt'>\n ): Promise<SearchPreset> {\n const id = this.generateId();\n const now = new Date();\n\n const fullPreset: SearchPreset = {\n ...preset,\n id,\n createdAt: now,\n updatedAt: now,\n };\n\n this.presets.set(id, fullPreset);\n return fullPreset;\n }\n\n /**\n * Get saved presets\n */\n async getPresets(userId?: string): Promise<SearchPreset[]> {\n const allPresets = Array.from(this.presets.values());\n\n if (userId) {\n return allPresets.filter((p) => p.userId === userId || p.shared);\n }\n\n return allPresets;\n }\n\n /**\n * Delete a preset\n */\n async deletePreset(presetId: string): Promise<void> {\n this.presets.delete(presetId);\n }\n\n // Private helper methods\n\n private applyFilters(logs: LogEntry[], filters?: SearchFilters): LogEntry[] {\n if (!filters) return logs;\n\n return logs.filter((log) => {\n // Level filter\n if (filters.levels && !filters.levels.includes(log.level)) {\n return false;\n }\n\n // Service filter\n if (filters.services && !filters.services.includes(log.appName)) {\n return false;\n }\n\n // Trace ID filter\n if (filters.traceIds && log.traceId && !filters.traceIds.includes(log.traceId)) {\n return false;\n }\n\n // Time range filter\n if (filters.timeRange) {\n const logTime = new Date(log.timestamp).getTime();\n const start =\n typeof filters.timeRange.start === 'number'\n ? filters.timeRange.start\n : filters.timeRange.start.getTime();\n\n if (logTime < start) return false;\n\n if (filters.timeRange.end) {\n const end =\n typeof filters.timeRange.end === 'number'\n ? filters.timeRange.end\n : filters.timeRange.end.getTime();\n if (logTime > end) return false;\n }\n }\n\n // Error filter\n if (filters.hasError !== undefined) {\n const hasError = log.level === 'error' || !!log.error;\n if (filters.hasError !== hasError) return false;\n }\n\n // Context filter\n if (filters.contexts && log.context && !filters.contexts.includes(log.context)) {\n return false;\n }\n\n return true;\n });\n }\n\n private performTextSearch(\n logs: LogEntry[],\n query: string,\n options?: SearchOptions\n ): SearchResult[] {\n if (!query) {\n return logs.map((log) => ({ log, score: 1 }));\n }\n\n const queryTerms = query.toLowerCase().split(/\\s+/);\n const results: SearchResult[] = [];\n\n for (const log of logs) {\n const searchableText = this.getSearchableText(log).toLowerCase();\n let score = 0;\n const highlights: SearchHighlight[] = [];\n const matchedTerms: string[] = [];\n\n for (const term of queryTerms) {\n if (searchableText.includes(term)) {\n score += 1;\n matchedTerms.push(term);\n }\n }\n\n if (score > 0) {\n // Add highlights if requested\n if (options?.highlightMatches) {\n highlights.push({\n field: 'message',\n fragments: this.getHighlightFragments(log.message, matchedTerms),\n matchedTerms,\n });\n }\n\n const result: { log: typeof log; score: number; highlights?: typeof highlights } = {\n log,\n score: score / queryTerms.length, // Normalize score\n };\n if (highlights.length > 0) result.highlights = highlights;\n results.push(result as Parameters<typeof results.push>[0]);\n }\n }\n\n return results;\n }\n\n private getSearchableText(log: LogEntry): string {\n // safeToString is circular-safe — a stored log with a cyclic payload (an\n // Express req/res, a DB handle) would otherwise make JSON.stringify throw and\n // crash the ENTIRE search, since this runs for every candidate log.\n const payloadText = log.payload ? safeToString(log.payload) : '';\n return [log.message, log.level, log.appName, log.context, payloadText]\n .filter(Boolean)\n .join(' ');\n }\n\n private getHighlightFragments(text: string, terms: string[]): string[] {\n const fragments: string[] = [];\n const lowerText = text.toLowerCase();\n\n for (const term of terms) {\n const index = lowerText.indexOf(term);\n if (index !== -1) {\n const start = Math.max(0, index - 30);\n const end = Math.min(text.length, index + term.length + 30);\n fragments.push(text.slice(start, end));\n }\n }\n\n return fragments;\n }\n\n private applySorting(\n results: SearchResult[],\n sortBy?: string,\n sortOrder: 'asc' | 'desc' = 'desc'\n ): SearchResult[] {\n const sorted = [...results];\n\n sorted.sort((a, b) => {\n let comparison: number;\n\n switch (sortBy) {\n case 'timestamp':\n comparison = new Date(a.log.timestamp).getTime() - new Date(b.log.timestamp).getTime();\n break;\n case 'level':\n comparison = a.log.level.localeCompare(b.log.level);\n break;\n case 'score':\n case 'relevance':\n default:\n comparison = a.score - b.score;\n break;\n }\n\n return sortOrder === 'asc' ? comparison : -comparison;\n });\n\n return sorted;\n }\n\n private applyPagination(\n results: SearchResult[],\n offset: number = 0,\n limit: number = 100\n ): SearchResult[] {\n return results.slice(offset, offset + limit);\n }\n\n private async enrichWithContext(results: SearchResult[], contextSize: number = 5): Promise<void> {\n for (const result of results) {\n const logIndex = this.logs.indexOf(result.log);\n if (logIndex !== -1) {\n const start = Math.max(0, logIndex - contextSize);\n const end = Math.min(this.logs.length, logIndex + contextSize + 1);\n result.context = this.logs.slice(start, end).filter((l) => l !== result.log);\n }\n }\n }\n\n private calculateSimilarity(log1: LogEntry, log2: LogEntry): number {\n let score = 0;\n let factors = 0;\n\n // Same level\n if (log1.level === log2.level) {\n score += 0.3;\n }\n factors++;\n\n // Same service\n if (log1.appName === log2.appName) {\n score += 0.2;\n }\n factors++;\n\n // Same trace\n if (log1.traceId && log1.traceId === log2.traceId) {\n score += 0.3;\n }\n factors++;\n\n // Message similarity\n const messageSimilarity = this.calculateTextSimilarity(log1.message, log2.message);\n score += messageSimilarity * 0.2;\n factors++;\n\n return score / factors;\n }\n\n private calculateTextSimilarity(text1: string, text2: string): number {\n const words1 = new Set(text1.toLowerCase().split(/\\s+/));\n const words2 = new Set(text2.toLowerCase().split(/\\s+/));\n\n const intersection = new Set([...words1].filter((x) => words2.has(x)));\n const union = new Set([...words1, ...words2]);\n\n return union.size > 0 ? intersection.size / union.size : 0;\n }\n\n private findMatchedPatterns(log1: LogEntry, log2: LogEntry): string[] {\n const patterns: string[] = [];\n\n if (log1.level === log2.level) patterns.push('same_level');\n if (log1.appName === log2.appName) patterns.push('same_service');\n if (log1.traceId === log2.traceId) patterns.push('same_trace');\n if (log1.context === log2.context) patterns.push('same_context');\n\n return patterns;\n }\n\n private generateSimilarityReason(log1: LogEntry, log2: LogEntry, similarity: number): string {\n const reasons: string[] = [];\n\n if (log1.level === log2.level) reasons.push('same log level');\n if (log1.appName === log2.appName) reasons.push('same service');\n if (log1.traceId === log2.traceId) reasons.push('same trace ID');\n\n return reasons.length > 0\n ? `Similar because: ${reasons.join(', ')}`\n : `${Math.round(similarity * 100)}% content similarity`;\n }\n\n private extractTimeRange(query: string): TimeRange | undefined {\n const lowerQuery = query.toLowerCase();\n\n // Last hour\n if (lowerQuery.includes('last hour') || lowerQuery.includes('past hour')) {\n return {\n start: new Date(Date.now() - 60 * 60 * 1000),\n };\n }\n\n // Last N hours\n const hoursMatch = query.match(/last\\s+(\\d+)\\s+hours?/i);\n if (hoursMatch) {\n return {\n start: new Date(Date.now() - Number.parseInt(hoursMatch[1] ?? '0') * 60 * 60 * 1000),\n };\n }\n\n // Today\n if (lowerQuery.includes('today')) {\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n return {\n start: today,\n };\n }\n\n return undefined;\n }\n\n private addToSearchHistory(query: string): void {\n this.searchHistory.push(query);\n\n // Trim history if too large\n const maxSize = this.options?.maxHistorySize || 1000;\n if (this.searchHistory.length > maxSize) {\n this.searchHistory = this.searchHistory.slice(-maxSize);\n }\n }\n\n private getTopTerms(): string[] {\n const termCounts = new Map<string, number>();\n\n for (const log of this.logs.slice(-1000)) {\n const words = log.message.toLowerCase().split(/\\s+/);\n for (const word of words) {\n if (word.length > 3) {\n // Ignore short words\n termCounts.set(word, (termCounts.get(word) || 0) + 1);\n }\n }\n }\n\n return Array.from(termCounts.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([term]) => term);\n }\n\n private generateId(): string {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security preset ID generation\n return `preset_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n }\n}\n","/**\n * Correlation engine for finding relationships between log entries\n */\n\nimport type { LogEntry } from '../../types';\nimport type {\n CorrelatedLogs,\n LogCorrelationSummary,\n RelatedLog,\n RelationshipType,\n TimelineEvent,\n} from '../types';\n\n/**\n * Correlation engine for log analysis\n */\nexport class CorrelationEngine {\n constructor(\n private options?: {\n maxCorrelationDistance?: number;\n temporalWindowMs?: number;\n minSimilarityScore?: number;\n }\n ) {\n this.options = {\n maxCorrelationDistance: 100,\n temporalWindowMs: 5 * 60 * 1000, // 5 minutes\n minSimilarityScore: 0.3,\n ...options,\n };\n }\n\n /**\n * Find logs related to a given log entry\n */\n async findRelatedLogs(\n log: LogEntry,\n allLogs: LogEntry[],\n limit: number = 50\n ): Promise<RelatedLog[]> {\n const related: RelatedLog[] = [];\n\n for (const otherLog of allLogs) {\n if (otherLog === log) continue;\n\n const relationships = this.findRelationships(log, otherLog);\n\n for (const relationship of relationships) {\n const score = this.calculateRelationshipScore(relationship, log, otherLog);\n\n if (score > (this.options?.minSimilarityScore || 0.3)) {\n related.push({\n log: otherLog,\n relationship,\n score,\n });\n }\n }\n }\n\n // Deduplicate and sort by score\n const uniqueRelated = this.deduplicateRelatedLogs(related);\n return uniqueRelated.sort((a, b) => b.score - a.score).slice(0, limit);\n }\n\n /**\n * Correlate logs by multiple criteria\n */\n async correlateByMultipleCriteria(\n logs: LogEntry[],\n criteria: {\n traceId?: boolean;\n userId?: boolean;\n sessionId?: boolean;\n temporal?: boolean;\n errorCascade?: boolean;\n }\n ): Promise<Map<string, CorrelatedLogs>> {\n const correlations = new Map<string, CorrelatedLogs>();\n\n // Correlate by trace ID\n if (criteria.traceId) {\n const traceCorrelations = this.correlateByTraceId(logs);\n for (const [key, value] of traceCorrelations) {\n correlations.set(`trace_${key}`, value);\n }\n }\n\n // Correlate by user ID\n if (criteria.userId) {\n const userCorrelations = this.correlateByUserId(logs);\n for (const [key, value] of userCorrelations) {\n correlations.set(`user_${key}`, value);\n }\n }\n\n // Correlate by session ID\n if (criteria.sessionId) {\n const sessionCorrelations = this.correlateBySessionId(logs);\n for (const [key, value] of sessionCorrelations) {\n correlations.set(`session_${key}`, value);\n }\n }\n\n // Correlate by temporal proximity\n if (criteria.temporal) {\n const temporalCorrelations = this.correlateByTemporalProximity(logs);\n for (const [key, value] of temporalCorrelations) {\n correlations.set(`temporal_${key}`, value);\n }\n }\n\n // Correlate error cascades\n if (criteria.errorCascade) {\n const errorCorrelations = this.correlateErrorCascades(logs);\n for (const [key, value] of errorCorrelations) {\n correlations.set(`error_${key}`, value);\n }\n }\n\n return correlations;\n }\n\n /**\n * Build a timeline from correlated logs\n */\n buildTimeline(logs: LogEntry[]): TimelineEvent[] {\n const timeline: TimelineEvent[] = [];\n\n // Sort logs by timestamp\n const sortedLogs = [...logs].sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n\n for (let i = 0; i < sortedLogs.length; i++) {\n const log = sortedLogs[i] as LogEntry; // noUncheckedIndexedAccess: guarded by loop condition\n const eventType = this.determineEventType(log, sortedLogs, i);\n\n const event: TimelineEvent = {\n timestamp: new Date(log.timestamp),\n log,\n eventType,\n };\n\n // Calculate duration for start/end events\n if (eventType === 'start' && i < sortedLogs.length - 1) {\n const endEvent = sortedLogs\n .slice(i + 1)\n .find((l) => this.determineEventType(l, sortedLogs, sortedLogs.indexOf(l)) === 'end');\n\n if (endEvent) {\n event.duration =\n new Date(endEvent.timestamp).getTime() - new Date(log.timestamp).getTime();\n }\n }\n\n timeline.push(event);\n }\n\n return timeline;\n }\n\n /**\n * Analyze error cascades\n */\n async analyzeErrorCascade(\n logs: LogEntry[]\n ): Promise<{ rootCause?: LogEntry; cascade: LogEntry[]; impactedServices: string[] }> {\n const errors = logs.filter((log) => log.level === 'error');\n\n if (errors.length === 0) {\n return { cascade: [], impactedServices: [] };\n }\n\n // Find root cause (earliest error)\n const rootCause = errors.reduce((earliest, current) =>\n new Date(current.timestamp) < new Date(earliest.timestamp) ? current : earliest\n );\n\n // Build cascade\n const cascade = this.buildErrorCascade(rootCause, errors);\n\n // Get impacted services\n const impactedServices = [...new Set(cascade.map((log) => log.appName))];\n\n return {\n rootCause,\n cascade,\n impactedServices,\n };\n }\n\n // Private methods\n\n private correlateByTraceId(logs: LogEntry[]): Map<string, CorrelatedLogs> {\n const correlations = new Map<string, LogEntry[]>();\n\n for (const log of logs) {\n if (!log.traceId) continue;\n\n if (!correlations.has(log.traceId)) {\n correlations.set(log.traceId, []);\n }\n correlations.get(log.traceId)!.push(log);\n }\n\n return this.convertToCorrelatedLogs(correlations, 'trace');\n }\n\n private correlateByUserId(logs: LogEntry[]): Map<string, CorrelatedLogs> {\n const correlations = new Map<string, LogEntry[]>();\n\n for (const log of logs) {\n const userId = log.payload?.userId as string | undefined;\n if (!userId) continue;\n\n if (!correlations.has(userId)) {\n correlations.set(userId, []);\n }\n correlations.get(userId)!.push(log);\n }\n\n return this.convertToCorrelatedLogs(correlations, 'user');\n }\n\n private correlateBySessionId(logs: LogEntry[]): Map<string, CorrelatedLogs> {\n const correlations = new Map<string, LogEntry[]>();\n\n for (const log of logs) {\n const sessionId = log.payload?.sessionId as string | undefined;\n if (!sessionId) continue;\n\n if (!correlations.has(sessionId)) {\n correlations.set(sessionId, []);\n }\n correlations.get(sessionId)!.push(log);\n }\n\n return this.convertToCorrelatedLogs(correlations, 'session');\n }\n\n private correlateByTemporalProximity(logs: LogEntry[]): Map<string, CorrelatedLogs> {\n const correlations = new Map<string, LogEntry[]>();\n const sortedLogs = [...logs].sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n\n let currentGroup: LogEntry[] = [];\n let groupStartTime: number | null = null;\n\n for (const log of sortedLogs) {\n const logTime = new Date(log.timestamp).getTime();\n\n if (groupStartTime === null) {\n groupStartTime = logTime;\n currentGroup = [log];\n } else if (logTime - groupStartTime <= (this.options?.temporalWindowMs || 300000)) {\n currentGroup.push(log);\n } else {\n // Save current group\n if (currentGroup.length > 1) {\n const groupKey = `${groupStartTime}`;\n correlations.set(groupKey, currentGroup);\n }\n\n // Start new group\n groupStartTime = logTime;\n currentGroup = [log];\n }\n }\n\n // Save last group\n if (currentGroup.length > 1 && groupStartTime !== null) {\n correlations.set(`${groupStartTime}`, currentGroup);\n }\n\n return this.convertToCorrelatedLogs(correlations, 'temporal');\n }\n\n private correlateErrorCascades(logs: LogEntry[]): Map<string, CorrelatedLogs> {\n const correlations = new Map<string, LogEntry[]>();\n const errors = logs.filter((log) => log.level === 'error');\n\n for (const error of errors) {\n const cascade = this.buildErrorCascade(error, logs);\n\n if (cascade.length > 1) {\n const key = `${error.timestamp}_${error.message.slice(0, 20)}`;\n correlations.set(key, cascade);\n }\n }\n\n return this.convertToCorrelatedLogs(correlations, 'error_cascade');\n }\n\n private buildErrorCascade(rootError: LogEntry, allLogs: LogEntry[]): LogEntry[] {\n const cascade: LogEntry[] = [rootError];\n const rootTime = new Date(rootError.timestamp).getTime();\n const windowMs = this.options?.temporalWindowMs || 300000;\n\n // Find related errors within time window\n for (const log of allLogs) {\n if (log === rootError) continue;\n\n const logTime = new Date(log.timestamp).getTime();\n const timeDiff = logTime - rootTime;\n\n if (\n timeDiff > 0 &&\n timeDiff <= windowMs &&\n (log.level === 'error' || log.level === 'warn') &&\n (log.traceId === rootError.traceId || log.appName === rootError.appName)\n ) {\n cascade.push(log);\n }\n }\n\n return cascade.sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n }\n\n private findRelationships(log1: LogEntry, log2: LogEntry): RelationshipType[] {\n const relationships: RelationshipType[] = [];\n\n // Same trace\n if (log1.traceId && log1.traceId === log2.traceId) {\n relationships.push('same_trace');\n }\n\n // Same user\n const user1 = log1.payload?.userId;\n const user2 = log2.payload?.userId;\n if (user1 && user1 === user2) {\n relationships.push('same_user');\n }\n\n // Same session\n const session1 = log1.payload?.sessionId;\n const session2 = log2.payload?.sessionId;\n if (session1 && session1 === session2) {\n relationships.push('same_session');\n }\n\n // Temporal proximity\n const time1 = new Date(log1.timestamp).getTime();\n const time2 = new Date(log2.timestamp).getTime();\n if (Math.abs(time1 - time2) <= (this.options?.temporalWindowMs || 300000)) {\n relationships.push('temporal_proximity');\n }\n\n // Error cascade\n if (\n (log1.level === 'error' || log2.level === 'error') &&\n time2 > time1 &&\n time2 - time1 <= (this.options?.temporalWindowMs || 300000)\n ) {\n relationships.push('error_cascade');\n }\n\n // Similar pattern\n if (this.haveSimilarPattern(log1, log2)) {\n relationships.push('similar_pattern');\n }\n\n return relationships;\n }\n\n private calculateRelationshipScore(\n relationship: RelationshipType,\n log1: LogEntry,\n log2: LogEntry\n ): number {\n const weights: Record<RelationshipType, number> = {\n same_trace: 0.9,\n same_user: 0.7,\n same_session: 0.8,\n temporal_proximity: 0.4,\n error_cascade: 0.8,\n similar_pattern: 0.5,\n };\n\n let score = weights[relationship] || 0.3;\n\n // Boost score for same service\n if (log1.appName === log2.appName) {\n score += 0.1;\n }\n\n return Math.min(score, 1.0);\n }\n\n private haveSimilarPattern(log1: LogEntry, log2: LogEntry): boolean {\n const normalized1 = this.normalizeMessage(log1.message);\n const normalized2 = this.normalizeMessage(log2.message);\n\n return normalized1 === normalized2;\n }\n\n private normalizeMessage(message: string): string {\n return message\n .replace(/\\d+/g, '<NUM>')\n .replace(/[a-f0-9-]{36}/gi, '<UUID>')\n .toLowerCase()\n .trim();\n }\n\n private determineEventType(\n log: LogEntry,\n _allLogs: LogEntry[],\n _index: number\n ): TimelineEvent['eventType'] {\n const message = log.message.toLowerCase();\n\n if (message.includes('start') || message.includes('begin') || message.includes('initiated')) {\n return 'start';\n }\n\n if (message.includes('end') || message.includes('complete') || message.includes('finished')) {\n return 'end';\n }\n\n if (log.level === 'error') {\n return 'error';\n }\n\n if (message.includes('milestone') || message.includes('checkpoint')) {\n return 'milestone';\n }\n\n return 'info';\n }\n\n private deduplicateRelatedLogs(related: RelatedLog[]): RelatedLog[] {\n const seen = new Set<LogEntry>();\n const unique: RelatedLog[] = [];\n\n for (const item of related) {\n if (!seen.has(item.log)) {\n seen.add(item.log);\n unique.push(item);\n }\n }\n\n return unique;\n }\n\n private convertToCorrelatedLogs(\n correlations: Map<string, LogEntry[]>,\n type: string\n ): Map<string, CorrelatedLogs> {\n const result = new Map<string, CorrelatedLogs>();\n\n for (const [key, logs] of correlations.entries()) {\n if (logs.length < 2) continue; // Skip single log entries\n\n const timeline = this.buildTimeline(logs);\n const summary = this.generateSummary(logs);\n\n result.set(key, {\n correlationKey: key,\n ...(type === 'trace' ? { traceId: key } : {}),\n logs,\n timeline,\n summary,\n });\n }\n\n return result;\n }\n\n private generateSummary(logs: LogEntry[]): LogCorrelationSummary {\n const errorCount = logs.filter((l) => l.level === 'error').length;\n const warningCount = logs.filter((l) => l.level === 'warn').length;\n const services = [...new Set(logs.map((l) => l.appName))];\n\n // Calculate duration\n let duration: number | undefined;\n if (logs.length > 1) {\n const sorted = [...logs].sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n const start = new Date((sorted[0] as LogEntry).timestamp).getTime();\n const end = new Date((sorted[sorted.length - 1] as LogEntry).timestamp).getTime();\n duration = end - start;\n }\n\n return {\n totalLogs: logs.length,\n errorCount,\n warningCount,\n services,\n ...(duration !== undefined ? { duration } : {}),\n };\n }\n}\n","/**\n * Advanced search engine with Natural Language Processing capabilities\n */\n\nimport { BasicSearchEngine } from '../core/basic-search-engine';\nimport type {\n EntityType,\n ParsedNLQuery,\n QueryEntity,\n QueryIntent,\n SearchFilters,\n SearchOptions,\n SearchResult,\n TimeRange,\n} from '../types';\n\n/**\n * NLP-enhanced search engine\n */\nexport class NLPSearchEngine extends BasicSearchEngine {\n private intentPatterns!: Map<QueryIntent, RegExp[]>;\n private entityPatterns!: Map<EntityType, RegExp>;\n\n constructor(options?: Record<string, unknown>) {\n super(options);\n this.initializePatterns();\n }\n\n /**\n * Enhanced natural language query parsing\n */\n override async parseNaturalLanguageQuery(query: string): Promise<ParsedNLQuery> {\n const entities: QueryEntity[] = [];\n const filters: SearchFilters = {};\n\n // Detect intent\n const intent = this.detectIntent(query);\n\n // Extract entities\n const extractedEntities = this.extractEntities(query);\n entities.push(...extractedEntities);\n\n // Build filters from entities\n for (const entity of entities) {\n this.applyEntityToFilter(entity, filters);\n }\n\n // Extract time range\n const timeRange = this.extractAdvancedTimeRange(query);\n if (timeRange) {\n filters.timeRange = timeRange;\n }\n\n // Calculate confidence\n const confidence = this.calculateConfidence(intent, entities, query);\n\n return {\n originalQuery: query,\n intent,\n entities,\n filters,\n ...(timeRange !== undefined ? { timeRange } : {}),\n confidence,\n };\n }\n\n /**\n * Enhanced natural language search\n */\n override async naturalLanguageSearch(query: string): Promise<SearchResult[]> {\n const parsed = await this.parseNaturalLanguageQuery(query);\n\n // Adjust search options based on intent\n const options: SearchOptions = this.getOptionsForIntent(parsed.intent);\n\n // Extract clean search query (remove filter terms)\n const cleanQuery = this.extractCleanQuery(query, parsed.entities);\n\n return this.search(cleanQuery, parsed.filters, options);\n }\n\n // Private methods\n\n private initializePatterns(): void {\n // Initialize intent patterns\n this.intentPatterns = new Map([\n [\n 'find_errors',\n [\n /show.*errors?/i,\n /find.*errors?/i,\n /all.*errors?/i,\n /errors?\\s+(?:in|from|for)/i,\n /what.*went wrong/i,\n /failures?/i,\n ],\n ],\n [\n 'trace_request',\n [\n /trace\\s+(?:request|id)/i,\n /follow\\s+request/i,\n /track\\s+request/i,\n /request\\s+(?:flow|path)/i,\n /trace.*across/i,\n ],\n ],\n [\n 'find_user_activity',\n [\n /user\\s+(?:\\w+|id)/i,\n /activity\\s+(?:for|of)\\s+user/i,\n /what\\s+did\\s+user/i,\n /user\\s+journey/i,\n /user\\s+session/i,\n ],\n ],\n [\n 'performance_analysis',\n [\n /slow\\s+(?:queries?|requests?|operations?)/i,\n /performance\\s+issues?/i,\n /latency/i,\n /response\\s+time/i,\n /took\\s+(?:too\\s+)?long/i,\n ],\n ],\n [\n 'time_range_query',\n [\n /(?:in|during|from)\\s+the\\s+last/i,\n /(?:today|yesterday|this\\s+week)/i,\n /between.*and/i,\n /in\\s+the\\s+past/i,\n ],\n ],\n [\n 'correlation',\n [\n /related\\s+to/i,\n /connected\\s+with/i,\n /caused\\s+by/i,\n /before.*happened/i,\n /after.*occurred/i,\n ],\n ],\n ]);\n\n // Initialize entity patterns\n this.entityPatterns = new Map([\n ['level', /(error|warn|warning|info|debug|trace|verbose)/i],\n ['service', /(?:from|in)\\s+(?:the\\s+)?(\\w+)\\s+(?:service|app|application)/i],\n ['user_id', /user\\s+(?:id\\s+)?['\"]?(\\w+)['\"]?/i],\n ['trace_id', /trace\\s+(?:id\\s+)?['\"]?([\\w-]+)['\"]?/i],\n ['time', /(?:last|past|previous)\\s+(\\d+)\\s+(second|minute|hour|day|week)s?/i],\n // eslint-disable-next-line sonarjs/super-linear-regex -- bounded pattern, DoS risk is acceptable for log search\n ['error_type', /(\\w+Error|\\w+Exception)/i],\n ]);\n }\n\n private detectIntent(query: string): QueryIntent {\n let maxScore = 0;\n let detectedIntent: QueryIntent = 'general_search';\n\n for (const [intent, patterns] of this.intentPatterns.entries()) {\n let score = 0;\n for (const pattern of patterns) {\n if (pattern.test(query)) {\n score++;\n }\n }\n\n if (score > maxScore) {\n maxScore = score;\n detectedIntent = intent;\n }\n }\n\n return detectedIntent;\n }\n\n private extractEntities(query: string): QueryEntity[] {\n const entities: QueryEntity[] = [];\n\n for (const [type, pattern] of this.entityPatterns.entries()) {\n const matches = query.matchAll(new RegExp(pattern, 'gi'));\n\n for (const match of matches) {\n const value = match[1] || match[0];\n entities.push({\n type,\n value: value.trim(),\n confidence: 0.8,\n });\n }\n }\n\n return entities;\n }\n\n private applyEntityToFilter(entity: QueryEntity, filters: SearchFilters): void {\n switch (entity.type) {\n case 'level':\n if (!filters.levels) filters.levels = [];\n filters.levels.push(entity.value.toLowerCase());\n break;\n\n case 'service':\n if (!filters.services) filters.services = [];\n filters.services.push(entity.value);\n break;\n\n case 'user_id':\n if (!filters.userIds) filters.userIds = [];\n filters.userIds.push(entity.value);\n break;\n\n case 'trace_id':\n if (!filters.traceIds) filters.traceIds = [];\n filters.traceIds.push(entity.value);\n break;\n\n case 'error_type':\n // Could be used for more specific filtering\n break;\n }\n }\n\n private extractAdvancedTimeRange(query: string): TimeRange | undefined {\n const lowerQuery = query.toLowerCase();\n\n // Relative time patterns\n const relativePatterns = [\n { pattern: /last\\s+(\\d+)\\s+second/i, unit: 'seconds' as const },\n { pattern: /last\\s+(\\d+)\\s+minute/i, unit: 'minutes' as const },\n { pattern: /last\\s+(\\d+)\\s+hour/i, unit: 'hours' as const },\n { pattern: /last\\s+(\\d+)\\s+day/i, unit: 'days' as const },\n ];\n\n for (const { pattern, unit } of relativePatterns) {\n const match = query.match(pattern);\n if (match) {\n const value = Number.parseInt(match[1] ?? '0');\n const multiplier = {\n seconds: 1000,\n minutes: 60 * 1000,\n hours: 60 * 60 * 1000,\n days: 24 * 60 * 60 * 1000,\n }[unit];\n\n return {\n start: new Date(Date.now() - value * multiplier),\n relative: { value, unit },\n };\n }\n }\n\n // Named time ranges\n if (lowerQuery.includes('today')) {\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n return { start: today };\n }\n\n if (lowerQuery.includes('yesterday')) {\n const yesterday = new Date();\n yesterday.setDate(yesterday.getDate() - 1);\n yesterday.setHours(0, 0, 0, 0);\n const endOfYesterday = new Date(yesterday);\n endOfYesterday.setHours(23, 59, 59, 999);\n return { start: yesterday, end: endOfYesterday };\n }\n\n if (lowerQuery.includes('this week')) {\n const now = new Date();\n const startOfWeek = new Date(now);\n startOfWeek.setDate(now.getDate() - now.getDay());\n startOfWeek.setHours(0, 0, 0, 0);\n return { start: startOfWeek };\n }\n\n return undefined;\n }\n\n private calculateConfidence(intent: QueryIntent, entities: QueryEntity[], query: string): number {\n let confidence = 0.5; // Base confidence\n\n // Boost confidence for specific intents\n if (intent !== 'general_search') {\n confidence += 0.2;\n }\n\n // Boost for number of entities found\n confidence += Math.min(entities.length * 0.1, 0.3);\n\n // Reduce confidence for very short or very long queries\n const wordCount = query.split(/\\s+/).length;\n if (wordCount < 3 || wordCount > 20) {\n confidence -= 0.1;\n }\n\n return Math.max(0, Math.min(1, confidence));\n }\n\n private getOptionsForIntent(intent: QueryIntent): SearchOptions {\n const baseOptions: SearchOptions = {\n limit: 100,\n highlightMatches: true,\n };\n\n switch (intent) {\n case 'find_errors':\n return {\n ...baseOptions,\n includeContext: true,\n contextSize: 3,\n findSimilar: true,\n };\n\n case 'trace_request':\n return {\n ...baseOptions,\n includeContext: true,\n contextSize: 10,\n correlate: true,\n sortBy: 'timestamp',\n sortOrder: 'asc',\n };\n\n case 'find_user_activity':\n return {\n ...baseOptions,\n includeContext: true,\n sortBy: 'timestamp',\n sortOrder: 'asc',\n limit: 200,\n };\n\n case 'performance_analysis':\n return {\n ...baseOptions,\n includeContext: true,\n contextSize: 5,\n sortBy: 'timestamp',\n };\n\n case 'correlation':\n return {\n ...baseOptions,\n includeContext: true,\n contextSize: 5,\n correlate: true,\n findSimilar: true,\n };\n\n default:\n return baseOptions;\n }\n }\n\n private extractCleanQuery(query: string, entities: QueryEntity[]): string {\n let cleanQuery = query;\n\n // Remove entity text from query\n for (const entity of entities) {\n // Remove common patterns\n cleanQuery = cleanQuery.replace(new RegExp(`\\\\b${entity.value}\\\\b`, 'gi'), '');\n }\n\n // Remove common filter words\n const filterWords = [\n 'show',\n 'find',\n 'get',\n 'all',\n 'from',\n 'in',\n 'the',\n 'for',\n 'with',\n 'last',\n 'past',\n 'today',\n 'yesterday',\n 'service',\n 'user',\n 'trace',\n 'error',\n 'errors',\n ];\n\n for (const word of filterWords) {\n cleanQuery = cleanQuery.replace(new RegExp(`\\\\b${word}\\\\b`, 'gi'), '');\n }\n\n // Clean up extra whitespace\n cleanQuery = cleanQuery.replace(/\\s+/g, ' ').trim();\n\n return cleanQuery || query; // Fall back to original if nothing left\n }\n}\n","/**\n * Pattern recognition engine for detecting and analyzing log patterns\n */\n\nimport type { LogEntry } from '../../types';\nimport type { AnomalyDetection, LogPattern } from '../types';\n\nconst STACK_FRAME_TAIL = /:\\d+:\\d+\\)?$/;\n\n/** True when any line is a real stack frame, e.g. ` at fn (/app/file.js:10:5)`. */\nfunction hasStackFrame(message: string): boolean {\n return message.split('\\n').some((line) => {\n const t = line.trim();\n return t.startsWith('at ') && STACK_FRAME_TAIL.test(t);\n });\n}\n\n/**\n * Pattern recognition engine for log analysis\n */\nexport class PatternRecognitionEngine {\n private patterns: Map<string, LogPattern> = new Map();\n private patternFrequencies: Map<string, number> = new Map();\n\n constructor(\n private options?: {\n minFrequency?: number;\n maxPatterns?: number;\n anomalyThreshold?: number;\n }\n ) {\n this.options = {\n minFrequency: 3,\n maxPatterns: 1000,\n anomalyThreshold: 0.3,\n ...options,\n };\n }\n\n /**\n * Analyze logs and detect patterns\n */\n async analyzePatterns(logs: LogEntry[]): Promise<LogPattern[]> {\n // Extract patterns from log messages\n const messagePatterns = this.extractMessagePatterns(logs);\n\n // Extract error patterns\n const errorPatterns = this.extractErrorPatterns(logs);\n\n // Extract timing patterns\n const timingPatterns = this.extractTimingPatterns(logs);\n\n // Combine all patterns\n const allPatterns = [...messagePatterns, ...errorPatterns, ...timingPatterns];\n\n // Filter by frequency\n const frequentPatterns = allPatterns.filter(\n (p) => p.frequency >= (this.options?.minFrequency || 3)\n );\n\n // Sort by frequency\n frequentPatterns.sort((a, b) => b.frequency - a.frequency);\n\n // Limit number of patterns\n const limitedPatterns = frequentPatterns.slice(0, this.options?.maxPatterns || 1000);\n\n // Store patterns\n for (const pattern of limitedPatterns) {\n this.patterns.set(pattern.id, pattern);\n }\n\n return limitedPatterns;\n }\n\n /**\n * Detect anomalies in logs\n */\n async detectAnomalies(logs: LogEntry[]): Promise<AnomalyDetection[]> {\n const anomalies: AnomalyDetection[] = [];\n\n for (const log of logs) {\n const anomalyScore = await this.calculateAnomalyScore(log);\n\n if (anomalyScore > (this.options?.anomalyThreshold || 0.3)) {\n anomalies.push({\n log,\n anomalyScore,\n reason: this.generateAnomalyReason(log, anomalyScore),\n deviations: this.findDeviations(log),\n });\n }\n }\n\n return anomalies.sort((a, b) => b.anomalyScore - a.anomalyScore);\n }\n\n /**\n * Find patterns matching a log entry\n */\n findMatchingPatterns(log: LogEntry): LogPattern[] {\n const matching: LogPattern[] = [];\n\n for (const pattern of this.patterns.values()) {\n if (this.doesLogMatchPattern(log, pattern)) {\n matching.push(pattern);\n }\n }\n\n return matching;\n }\n\n /**\n * Get all detected patterns\n */\n getPatterns(): LogPattern[] {\n return Array.from(this.patterns.values());\n }\n\n /**\n * Get pattern by ID\n */\n getPattern(patternId: string): LogPattern | undefined {\n return this.patterns.get(patternId);\n }\n\n // Private methods\n\n private extractMessagePatterns(logs: LogEntry[]): LogPattern[] {\n const patternMap = new Map<string, { examples: LogEntry[]; count: number }>();\n\n for (const log of logs) {\n // Normalize message by replacing numbers and IDs\n const normalizedMessage = this.normalizeMessage(log.message);\n\n if (!patternMap.has(normalizedMessage)) {\n patternMap.set(normalizedMessage, { examples: [], count: 0 });\n }\n\n const pattern = patternMap.get(normalizedMessage)!;\n if (pattern.examples.length < 3) {\n pattern.examples.push(log);\n }\n pattern.count++;\n }\n\n // Convert to LogPattern array\n return Array.from(patternMap.entries()).map(([pattern, data], index) => ({\n id: `msg_pattern_${index}`,\n pattern,\n examples: data.examples,\n frequency: data.count,\n lastSeen: data.examples[data.examples.length - 1]?.timestamp\n ? new Date((data.examples[data.examples.length - 1] as (typeof data.examples)[0]).timestamp)\n : new Date(),\n category: 'message',\n }));\n }\n\n private extractErrorPatterns(logs: LogEntry[]): LogPattern[] {\n const errorLogs = logs.filter((log) => log.level === 'error' || log.error);\n this.patternFrequencies.clear();\n const patternMap = new Map<string, { examples: LogEntry[]; count: number }>();\n\n for (const log of errorLogs) {\n const errorPattern = this.extractErrorPattern(log);\n\n if (!patternMap.has(errorPattern)) {\n patternMap.set(errorPattern, { examples: [], count: 0 });\n }\n\n const pattern = patternMap.get(errorPattern)!;\n if (pattern.examples.length < 3) {\n pattern.examples.push(log);\n }\n pattern.count++;\n this.patternFrequencies.set(errorPattern, pattern.count);\n }\n\n return Array.from(patternMap.entries()).map(([pattern, data], index) => ({\n id: `error_pattern_${index}`,\n pattern,\n examples: data.examples,\n frequency: data.count,\n lastSeen: data.examples[data.examples.length - 1]?.timestamp\n ? new Date((data.examples[data.examples.length - 1] as (typeof data.examples)[0]).timestamp)\n : new Date(),\n category: 'error',\n severity: 'high',\n }));\n }\n\n private extractTimingPatterns(logs: LogEntry[]): LogPattern[] {\n const patterns: LogPattern[] = [];\n const hourCounts = new Map<number, number>();\n\n // Analyze temporal patterns\n for (const log of logs) {\n const hour = new Date(log.timestamp).getHours();\n hourCounts.set(hour, (hourCounts.get(hour) || 0) + 1);\n }\n\n // Find peak hours\n const peakHour = Array.from(hourCounts.entries()).sort((a, b) => b[1] - a[1])[0];\n\n if (peakHour) {\n patterns.push({\n id: 'timing_peak',\n pattern: `Peak activity at hour ${peakHour[0]}`,\n examples: logs.slice(0, 3),\n frequency: peakHour[1],\n lastSeen: new Date(),\n category: 'timing',\n });\n }\n\n return patterns;\n }\n\n private normalizeMessage(message: string): string {\n return message\n .replace(/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi, '<UUID>') // Replace UUIDs\n .replace(/[a-f0-9]{32}/gi, '<HASH>') // Replace hashes\n .replace(/\\d+/g, '<NUM>') // Replace numbers\n .replace(/\"[^\"]*\"/g, '<STRING>') // Replace quoted strings\n .replace(/\\b\\w+@\\w+\\.\\w+\\b/g, '<EMAIL>') // Replace emails\n .trim();\n }\n\n private extractErrorPattern(log: LogEntry): string {\n if (log.error) {\n return `${log.error.name}: ${this.normalizeMessage(log.error.message || '')}`;\n }\n return this.normalizeMessage(log.message);\n }\n\n private async calculateAnomalyScore(log: LogEntry): Promise<number> {\n let score = 0;\n\n // Check if log matches known patterns\n const matchingPatterns = this.findMatchingPatterns(log);\n if (matchingPatterns.length === 0) {\n score += 0.3; // Unknown pattern\n }\n\n // Check error frequency\n if (log.level === 'error') {\n const errorPattern = this.extractErrorPattern(log);\n const frequency = this.patternFrequencies.get(errorPattern) || 0;\n if (frequency < 2) {\n score += 0.3; // Rare error\n }\n }\n\n // Check time of day\n const hour = new Date(log.timestamp).getHours();\n if (hour < 6 || hour > 22) {\n score += 0.2; // Off-hours activity\n }\n\n return Math.min(score, 1.0);\n }\n\n private generateAnomalyReason(log: LogEntry, score: number): string {\n const reasons: string[] = [];\n\n if (score > 0.7) {\n reasons.push('Highly unusual log entry');\n } else if (score > 0.5) {\n reasons.push('Moderately unusual log entry');\n } else {\n reasons.push('Slightly unusual log entry');\n }\n\n const matchingPatterns = this.findMatchingPatterns(log);\n if (matchingPatterns.length === 0) {\n reasons.push('does not match any known patterns');\n }\n\n if (log.level === 'error') {\n reasons.push('rare error type');\n }\n\n const hour = new Date(log.timestamp).getHours();\n if (hour < 6 || hour > 22) {\n reasons.push('occurred during off-hours');\n }\n\n return reasons.join(', ');\n }\n\n private findDeviations(log: LogEntry): string[] {\n const deviations: string[] = [];\n\n // Check for missing standard fields\n if (!log.traceId) deviations.push('Missing trace ID');\n if (!log.context) deviations.push('Missing context');\n\n // Check for unusual payload\n if (log.payload && Object.keys(log.payload).length > 20) {\n deviations.push('Unusually large payload');\n }\n\n // Check for stack trace in non-error logs\n if (log.level !== 'error' && hasStackFrame(log.message)) {\n deviations.push('Stack trace in non-error log');\n }\n\n return deviations;\n }\n\n private doesLogMatchPattern(log: LogEntry, pattern: LogPattern): boolean {\n const normalizedMessage = this.normalizeMessage(log.message);\n\n if (pattern.regex) {\n return pattern.regex.test(log.message);\n }\n\n return normalizedMessage === pattern.pattern;\n }\n}\n","/**\n * Main search manager that orchestrates all search capabilities\n */\n\nimport type { LogEntry } from '../types';\nimport { csvField } from '../utils/csv.utils';\nimport { BasicLogIndexer } from './core/basic-log-indexer';\nimport { BasicSearchEngine } from './core/basic-search-engine';\nimport { CorrelationEngine } from './engines/correlation-engine';\nimport { NLPSearchEngine } from './engines/nlp-search-engine';\nimport { PatternRecognitionEngine } from './engines/pattern-recognition-engine';\nimport type {\n AnomalyDetection,\n CorrelatedLogs,\n ExportOptions,\n LogPattern,\n ParsedNLQuery,\n RelatedLog,\n SearchFilters,\n SearchOptions,\n SearchPreset,\n SearchResult,\n SearchStats,\n SearchSuggestion,\n SimilarLog,\n} from './types';\n\n/**\n * Configuration for search manager\n */\nexport interface SearchManagerConfig {\n enableNLP?: boolean;\n enablePatternRecognition?: boolean;\n enableCorrelation?: boolean;\n maxIndexSize?: number;\n autoOptimize?: boolean;\n}\n\n/**\n * Main search manager class\n */\nexport class SearchManager {\n private searchEngine: BasicSearchEngine | NLPSearchEngine;\n private indexer: BasicLogIndexer;\n private patternEngine?: PatternRecognitionEngine;\n private correlationEngine?: CorrelationEngine;\n private config: Required<SearchManagerConfig>;\n\n constructor(config?: SearchManagerConfig) {\n this.config = {\n enableNLP: true,\n enablePatternRecognition: true,\n enableCorrelation: true,\n maxIndexSize: 1000000,\n autoOptimize: true,\n ...config,\n };\n\n // Initialize components\n this.searchEngine = this.config.enableNLP ? new NLPSearchEngine() : new BasicSearchEngine();\n\n this.indexer = new BasicLogIndexer({\n maxIndexSize: this.config.maxIndexSize,\n autoOptimize: this.config.autoOptimize,\n });\n\n if (this.config.enablePatternRecognition) {\n this.patternEngine = new PatternRecognitionEngine();\n }\n\n if (this.config.enableCorrelation) {\n this.correlationEngine = new CorrelationEngine();\n }\n }\n\n /**\n * Index new logs\n */\n async indexLogs(logs: LogEntry[]): Promise<void> {\n await this.indexer.indexBatch(logs);\n this.searchEngine.addLogs(logs);\n\n // Analyze patterns if enabled\n if (this.patternEngine && logs.length > 10) {\n await this.patternEngine.analyzePatterns(logs);\n }\n }\n\n /**\n * Add a single log to the index\n */\n async indexLog(log: LogEntry): Promise<void> {\n await this.indexer.indexLog(log);\n this.searchEngine.addLogs([log]);\n }\n\n /**\n * Perform a search\n */\n async search(\n query: string,\n filters?: SearchFilters,\n options?: SearchOptions\n ): Promise<SearchResult[]> {\n return this.searchEngine.search(query, filters, options);\n }\n\n /**\n * Perform a natural language search\n */\n async naturalLanguageSearch(query: string): Promise<SearchResult[]> {\n return this.searchEngine.naturalLanguageSearch(query);\n }\n\n /**\n * Find logs correlated by trace ID\n */\n async correlateByTraceId(traceId: string): Promise<CorrelatedLogs> {\n return this.searchEngine.correlateByTraceId(traceId);\n }\n\n /**\n * Find similar logs\n */\n async findSimilarLogs(logEntry: LogEntry, limit?: number): Promise<SimilarLog[]> {\n return this.searchEngine.findSimilarLogs(logEntry, limit);\n }\n\n /**\n * Find logs related to a given log\n */\n async findRelatedLogs(log: LogEntry, limit?: number): Promise<RelatedLog[]> {\n if (!this.correlationEngine) {\n throw new Error('Correlation engine not enabled');\n }\n\n const allLogs = this.searchEngine.getLogs();\n return this.correlationEngine.findRelatedLogs(log, allLogs, limit);\n }\n\n /**\n * Get search suggestions\n */\n async getSuggestions(partialQuery: string, limit?: number): Promise<SearchSuggestion[]> {\n return this.searchEngine.getSuggestions(partialQuery, limit);\n }\n\n /**\n * Get search statistics\n */\n async getStats(): Promise<SearchStats> {\n return this.searchEngine.getStats();\n }\n\n /**\n * Parse natural language query\n */\n async parseNaturalLanguageQuery(query: string): Promise<ParsedNLQuery> {\n return this.searchEngine.parseNaturalLanguageQuery(query);\n }\n\n /**\n * Save a search preset\n */\n async savePreset(\n preset: Omit<SearchPreset, 'id' | 'createdAt' | 'updatedAt'>\n ): Promise<SearchPreset> {\n return this.searchEngine.savePreset(preset);\n }\n\n /**\n * Get saved presets\n */\n async getPresets(userId?: string): Promise<SearchPreset[]> {\n return this.searchEngine.getPresets(userId);\n }\n\n /**\n * Delete a preset\n */\n async deletePreset(presetId: string): Promise<void> {\n return this.searchEngine.deletePreset(presetId);\n }\n\n /**\n * Detect log patterns\n */\n async detectPatterns(): Promise<LogPattern[]> {\n if (!this.patternEngine) {\n throw new Error('Pattern recognition not enabled');\n }\n\n const allLogs = this.searchEngine.getLogs();\n return this.patternEngine.analyzePatterns(allLogs);\n }\n\n /**\n * Get detected patterns\n */\n getPatterns(): LogPattern[] {\n if (!this.patternEngine) {\n return [];\n }\n\n return this.patternEngine.getPatterns();\n }\n\n /**\n * Detect anomalies in logs\n */\n async detectAnomalies(): Promise<AnomalyDetection[]> {\n if (!this.patternEngine) {\n throw new Error('Pattern recognition not enabled');\n }\n\n const allLogs = this.searchEngine.getLogs();\n return this.patternEngine.detectAnomalies(allLogs);\n }\n\n /**\n * Correlate logs by multiple criteria\n */\n async correlateByMultipleCriteria(criteria: {\n traceId?: boolean;\n userId?: boolean;\n sessionId?: boolean;\n temporal?: boolean;\n errorCascade?: boolean;\n }): Promise<Map<string, CorrelatedLogs>> {\n if (!this.correlationEngine) {\n throw new Error('Correlation engine not enabled');\n }\n\n const allLogs = this.searchEngine.getLogs();\n return this.correlationEngine.correlateByMultipleCriteria(allLogs, criteria);\n }\n\n /**\n * Analyze error cascades\n */\n async analyzeErrorCascade(traceId: string): Promise<{\n rootCause?: LogEntry;\n cascade: LogEntry[];\n impactedServices: string[];\n }> {\n if (!this.correlationEngine) {\n throw new Error('Correlation engine not enabled');\n }\n\n const correlated = await this.correlateByTraceId(traceId);\n return this.correlationEngine.analyzeErrorCascade(correlated.logs);\n }\n\n /**\n * Export search results\n */\n async exportResults(results: SearchResult[], options: ExportOptions): Promise<string> {\n switch (options.format) {\n case 'json':\n return this.exportAsJSON(results, options);\n case 'csv':\n return this.exportAsCSV(results, options);\n case 'text':\n return this.exportAsText(results, options);\n default:\n throw new Error(`Unsupported export format: ${options.format}`);\n }\n }\n\n /**\n * Clear all indexed data\n */\n async clearIndex(): Promise<void> {\n await this.indexer.clearIndex();\n this.searchEngine.clearLogs();\n }\n\n /**\n * Optimize the index\n */\n async optimizeIndex(): Promise<void> {\n await this.indexer.optimizeIndex();\n }\n\n /**\n * Get index statistics\n */\n async getIndexStats(): Promise<{\n totalDocuments: number;\n indexSize: number;\n lastOptimized?: Date;\n }> {\n return this.indexer.getIndexStats();\n }\n\n /**\n * Remove old logs\n */\n async removeOldLogs(olderThan: Date): Promise<number> {\n const removed = await this.indexer.removeOldLogs(olderThan);\n\n // Also remove from search engine\n const allLogs = this.searchEngine.getLogs();\n const filteredLogs = allLogs.filter((log) => new Date(log.timestamp) >= olderThan);\n\n this.searchEngine.clearLogs();\n this.searchEngine.addLogs(filteredLogs);\n\n return removed;\n }\n\n // Private export methods\n\n private exportAsJSON(results: SearchResult[], options: ExportOptions): string {\n const data = options.includeMetadata ? results : results.map((r) => r.log);\n\n if (options.fields) {\n return JSON.stringify(\n data.map((item) => this.filterFields(item, options.fields!)),\n null,\n 2\n );\n }\n\n return JSON.stringify(data, null, 2);\n }\n\n private exportAsCSV(results: SearchResult[], options: ExportOptions): string {\n const logs = results.map((r) => r.log);\n\n if (logs.length === 0) {\n return '';\n }\n\n const fields = options.fields || ['timestamp', 'level', 'appName', 'message'];\n const headers = fields.map((f) => csvField(f)).join(',');\n\n const rows = logs.map((log) => {\n return fields\n .map((field) => {\n const value = (log as unknown as Record<string, unknown>)[field];\n return csvField(value);\n })\n .join(',');\n });\n\n return [headers, ...rows].join('\\n');\n }\n\n private exportAsText(results: SearchResult[], options: ExportOptions): string {\n return results\n .map((result) => {\n const log = result.log;\n let text = `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.appName}: ${log.message}`;\n\n if (options.includeMetadata) {\n text += `\\n Score: ${result.score.toFixed(2)}`;\n if (result.highlights) {\n text += `\\n Matches: ${result.highlights.length}`;\n }\n }\n\n return text;\n })\n .join('\\n\\n');\n }\n\n private filterFields(obj: unknown, fields: string[]): Record<string, unknown> {\n const filtered: Record<string, unknown> = {};\n\n for (const field of fields) {\n if (obj !== null && typeof obj === 'object' && field in obj) {\n filtered[field] = (obj as Record<string, unknown>)[field];\n } else if (field.includes('.')) {\n // Handle nested fields\n const value = this.getNestedValue(obj, field);\n if (value !== undefined) {\n filtered[field] = value;\n }\n }\n }\n\n return filtered;\n }\n\n private getNestedValue(obj: unknown, path: string): unknown {\n return path.split('.').reduce((current: unknown, key) => {\n if (current !== null && typeof current === 'object') {\n return (current as Record<string, unknown>)[key];\n }\n // Not an object — path lookup stops here\n return current;\n }, obj);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"secret-config-BegMLkYl.mjs","names":[],"sources":["../src/transports/secret-config.ts"],"sourcesContent":["/**\n * Keeps credentials out of serialized transport output and error text.\n *\n * `protectSecrets()` replaces each listed field with a non-enumerable accessor backed\n * by a WeakMap, whether or not the field is assigned yet, so later assignments (a\n * connection opened on first write, a refreshed token) stay hidden too. It also\n * installs `toJSON()` and a Node inspect hook returning a redacted view: scalar\n * fields stay for debugging, secret-looking keys become '[REDACTED]', URLs lose\n * userinfo, query and fragment. No Node imports, so browser bundles can use it.\n */\n\nimport {\n DEFAULT_REDACT_QUERY_PARAMS,\n SENSITIVE_KEY_NAMES,\n TRANSPORT_CONFIG_SECRET_NAMES,\n} from '../utils/sensitive-names';\n\nexport const REDACTED = '[REDACTED]';\n\nconst INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');\nconst MAX_DEPTH = 4;\nconst MIN_SECRET_LENGTH = 4;\nconst SCHEME_PREFIX = /^[a-z][a-z0-9+.-]*:\\/\\//i;\n/** `scheme://userinfo@`: userinfo runs to the LAST `@` before the path, so `p@ss` is covered. */\nconst USERINFO = /(\\b[a-z][a-z0-9+.-]*:\\/\\/)[^\\s/?#]*@/gi;\n\nfunction normalizeName(name: string): string {\n return name.toLowerCase().replaceAll('-', '').replaceAll('_', '');\n}\n\nconst SECRET_NAMES = [...SENSITIVE_KEY_NAMES, ...TRANSPORT_CONFIG_SECRET_NAMES].map(normalizeName);\nconst QUERY_NAMES = new Set(DEFAULT_REDACT_QUERY_PARAMS.map(normalizeName));\n\n/** Exact match for short names (`key`, `pfx`), suffix match for longer ones (`azureClientSecret`). */\nfunction isSecretKey(key: string): boolean {\n const name = normalizeName(key);\n return SECRET_NAMES.some((n) => name === n || (n.length >= 5 && name.endsWith(n)));\n}\n\nfunction isUrlKey(key: string): boolean {\n return /url|uri|endpoint|href/i.test(key);\n}\n\nfunction isPlainObject(value: object): boolean {\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value.replaceAll('+', ' '));\n } catch {\n return value;\n }\n}\n\n/** Absolute URL: `scheme://host` only. Relative or unparseable: path kept, query and fragment cut. */\nexport function redactUrl(raw: string | URL): string {\n if (typeof raw !== 'string') return `${raw.protocol}//${raw.host}`;\n if (SCHEME_PREFIX.test(raw)) {\n try {\n const url = new URL(raw);\n return `${url.protocol}//${url.host}`;\n } catch {\n return REDACTED;\n }\n }\n return raw.split(/[?#]/, 1)[0] ?? '';\n}\n\nfunction redactHeaders(headers: unknown): unknown {\n if (!headers || typeof headers !== 'object') return headers;\n return Object.fromEntries(Object.keys(headers).map((name) => [name, REDACTED]));\n}\n\n/** Redacted deep copy of a config-like value. Never throws, never returns a secret. */\nexport function redactConfig(value: unknown, depth = 0, key = ''): unknown {\n if (value === null || value === undefined) return value;\n if (typeof value === 'string') {\n return SCHEME_PREFIX.test(value) || isUrlKey(key) ? redactUrl(value) : value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') return value;\n if (typeof value === 'function') return '[Function]';\n if (typeof value !== 'object') return '[Unserializable]';\n if (typeof URL !== 'undefined' && value instanceof URL) return redactUrl(value);\n if (Array.isArray(value)) {\n return depth >= MAX_DEPTH ? '[Array]' : value.map((v) => redactConfig(v, depth + 1, key));\n }\n if (!isPlainObject(value) || depth >= MAX_DEPTH)\n return `[${value.constructor?.name ?? 'Object'}]`;\n const out: Record<string, unknown> = {};\n for (const [name, inner] of Object.entries(value)) {\n if (isSecretKey(name)) out[name] = inner === undefined ? undefined : REDACTED;\n else if (name.toLowerCase() === 'headers') out[name] = redactHeaders(inner);\n else out[name] = redactConfig(inner, depth + 1, name);\n }\n return out;\n}\n\n// ── Secret protection ───────────────────────────────────────────────────────\n\nconst hiddenKeys = new WeakMap<object, Set<string>>();\nconst hiddenValues = new WeakMap<object, Map<string, unknown>>();\n\nfunction viewOf(target: object): Record<string, unknown> {\n const hidden = hiddenKeys.get(target) ?? new Set<string>();\n const values = hiddenValues.get(target);\n const view: Record<string, unknown> = { class: target.constructor?.name };\n for (const key of new Set([...Object.keys(target), ...hidden])) {\n const inner = hidden.has(key) ? values?.get(key) : (target as Record<string, unknown>)[key];\n if (isSecretKey(key)) view[key] = inner === undefined ? undefined : REDACTED;\n else if (key.toLowerCase() === 'headers') view[key] = redactHeaders(inner);\n else if (\n inner !== null &&\n typeof inner === 'object' &&\n !hidden.has(key) &&\n !(inner instanceof URL)\n ) {\n view[key] = '[Object]';\n } else if (hidden.has(key) && typeof inner === 'string' && !isUrlKey(key)) {\n view[key] = REDACTED;\n } else view[key] = redactConfig(inner, 0, key);\n }\n return view;\n}\n\n/**\n * Hides `keys` on `target` (assigned or not yet) and gives it a redacted `toJSON()` /\n * inspect view. Fields stay readable and writable. Safe to call more than once.\n * Throws when the target cannot carry the protection (frozen or sealed), instead of\n * silently leaving the secret enumerable.\n */\nexport function protectSecrets(target: object, keys: readonly string[]): void {\n if (!Object.isExtensible(target)) {\n throw new TypeError(\n `protectSecrets: ${target.constructor?.name ?? 'object'} is not extensible`\n );\n }\n let hidden = hiddenKeys.get(target);\n let values = hiddenValues.get(target);\n if (!hidden || !values) {\n hidden = new Set();\n values = new Map();\n hiddenKeys.set(target, hidden);\n hiddenValues.set(target, values);\n const view = (): Record<string, unknown> => viewOf(target);\n Object.defineProperty(target, 'toJSON', { value: view, enumerable: false, configurable: true });\n Object.defineProperty(target, INSPECT_CUSTOM, {\n value: view,\n enumerable: false,\n configurable: true,\n });\n }\n const store = values;\n for (const key of keys) {\n if (hidden.has(key)) continue;\n const desc = Object.getOwnPropertyDescriptor(target, key);\n if (desc && !desc.configurable) {\n throw new TypeError(`protectSecrets: \"${key}\" is not configurable`);\n }\n if (desc && 'value' in desc) store.set(key, desc.value);\n hidden.add(key);\n Object.defineProperty(target, key, {\n enumerable: false,\n configurable: true,\n get: () => store.get(key),\n set: (next: unknown) => void store.set(key, next),\n });\n }\n}\n\n// ── Scrubbing error text ────────────────────────────────────────────────────\n\n/** The raw, decoded and percent-encoded spellings of a secret. */\nfunction variantsOf(secret: string): string[] {\n return [secret, safeDecode(secret), encodeURIComponent(secret), encodeURI(secret)];\n}\n\n/** Secret parts of a URL string: the password and the values of sensitive query parameters. */\nexport function urlSecrets(raw: string | URL): string[] {\n const text = typeof raw === 'string' ? raw : raw.href;\n const out: string[] = [];\n const userinfo = new RegExp(USERINFO.source, 'i').exec(text);\n if (userinfo) {\n const info = text.slice(userinfo[1]!.length, userinfo.index + userinfo[0].length - 1);\n const colon = info.indexOf(':');\n if (colon !== -1) out.push(info.slice(colon + 1));\n }\n const queryStart = text.indexOf('?');\n if (queryStart !== -1) {\n const query = text.slice(queryStart + 1).split('#', 1)[0] ?? '';\n for (const pair of query.split('&')) {\n const eq = pair.indexOf('=');\n if (eq > 0 && QUERY_NAMES.has(normalizeName(safeDecode(pair.slice(0, eq))))) {\n out.push(pair.slice(eq + 1));\n }\n }\n }\n return out.flatMap(variantsOf);\n}\n\n/** Every secret string held in a config-like value: secret-keyed values, header values, URL secrets. */\nexport function collectSecrets(value: unknown, depth = 0, key = ''): string[] {\n if (typeof value === 'string') {\n if (isSecretKey(key)) return [value];\n return SCHEME_PREFIX.test(value) || isUrlKey(key) ? urlSecrets(value) : [];\n }\n if (!value || typeof value !== 'object' || depth > MAX_DEPTH) return [];\n if (typeof URL !== 'undefined' && value instanceof URL) return urlSecrets(value);\n if (Array.isArray(value)) return value.flatMap((v) => collectSecrets(v, depth + 1, key));\n if (!isPlainObject(value)) return [];\n const isHeaders = key.toLowerCase() === 'headers';\n return Object.entries(value).flatMap(([name, inner]) => {\n if (isHeaders && typeof inner === 'string') return [inner];\n if (isSecretKey(name) && inner !== null && typeof inner === 'object') {\n return collectSecrets(inner, depth + 1, 'secret');\n }\n return collectSecrets(inner, depth + 1, name);\n });\n}\n\n/** Replaces URL userinfo and every spelling of the given secret values in `text`. */\nexport function scrubSecrets(text: string, secrets: readonly (string | undefined)[]): string {\n let out = text.replace(USERINFO, `$1${REDACTED}@`);\n const all = new Set(\n secrets.flatMap((s) => (s && s.length >= MIN_SECRET_LENGTH ? variantsOf(s) : []))\n );\n for (const secret of [...all].sort((a, b) => b.length - a.length)) {\n if (secret.length >= MIN_SECRET_LENGTH) out = out.split(secret).join(REDACTED);\n }\n return out;\n}\n\n/** Scrubs message, stack and the cause chain of `err` in place; returns it. */\nexport function scrubError<T>(err: T, secrets: readonly (string | undefined)[], depth = 0): T {\n if (!(err instanceof Error) || depth > 3) return err;\n try {\n err.message = scrubSecrets(err.message, secrets);\n if (err.stack) err.stack = scrubSecrets(err.stack, secrets);\n scrubError((err as { cause?: unknown }).cause, secrets, depth + 1);\n } catch {\n /* frozen error: leave as is */\n }\n return err;\n}\n\n/** A `.catch()` handler that scrubs the secrets from the error, then rethrows it. */\nexport function scrubbing(secrets: () => (string | undefined)[]): (err: unknown) => never {\n return (err) => {\n throw scrubError(err, secrets());\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"secret-config-CBZBs0p1.js","names":["SENSITIVE_KEY_NAMES","TRANSPORT_CONFIG_SECRET_NAMES","DEFAULT_REDACT_QUERY_PARAMS"],"sources":["../src/transports/secret-config.ts"],"sourcesContent":["/**\n * Keeps credentials out of serialized transport output and error text.\n *\n * `protectSecrets()` replaces each listed field with a non-enumerable accessor backed\n * by a WeakMap, whether or not the field is assigned yet, so later assignments (a\n * connection opened on first write, a refreshed token) stay hidden too. It also\n * installs `toJSON()` and a Node inspect hook returning a redacted view: scalar\n * fields stay for debugging, secret-looking keys become '[REDACTED]', URLs lose\n * userinfo, query and fragment. No Node imports, so browser bundles can use it.\n */\n\nimport {\n DEFAULT_REDACT_QUERY_PARAMS,\n SENSITIVE_KEY_NAMES,\n TRANSPORT_CONFIG_SECRET_NAMES,\n} from '../utils/sensitive-names';\n\nexport const REDACTED = '[REDACTED]';\n\nconst INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');\nconst MAX_DEPTH = 4;\nconst MIN_SECRET_LENGTH = 4;\nconst SCHEME_PREFIX = /^[a-z][a-z0-9+.-]*:\\/\\//i;\n/** `scheme://userinfo@`: userinfo runs to the LAST `@` before the path, so `p@ss` is covered. */\nconst USERINFO = /(\\b[a-z][a-z0-9+.-]*:\\/\\/)[^\\s/?#]*@/gi;\n\nfunction normalizeName(name: string): string {\n return name.toLowerCase().replaceAll('-', '').replaceAll('_', '');\n}\n\nconst SECRET_NAMES = [...SENSITIVE_KEY_NAMES, ...TRANSPORT_CONFIG_SECRET_NAMES].map(normalizeName);\nconst QUERY_NAMES = new Set(DEFAULT_REDACT_QUERY_PARAMS.map(normalizeName));\n\n/** Exact match for short names (`key`, `pfx`), suffix match for longer ones (`azureClientSecret`). */\nfunction isSecretKey(key: string): boolean {\n const name = normalizeName(key);\n return SECRET_NAMES.some((n) => name === n || (n.length >= 5 && name.endsWith(n)));\n}\n\nfunction isUrlKey(key: string): boolean {\n return /url|uri|endpoint|href/i.test(key);\n}\n\nfunction isPlainObject(value: object): boolean {\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value.replaceAll('+', ' '));\n } catch {\n return value;\n }\n}\n\n/** Absolute URL: `scheme://host` only. Relative or unparseable: path kept, query and fragment cut. */\nexport function redactUrl(raw: string | URL): string {\n if (typeof raw !== 'string') return `${raw.protocol}//${raw.host}`;\n if (SCHEME_PREFIX.test(raw)) {\n try {\n const url = new URL(raw);\n return `${url.protocol}//${url.host}`;\n } catch {\n return REDACTED;\n }\n }\n return raw.split(/[?#]/, 1)[0] ?? '';\n}\n\nfunction redactHeaders(headers: unknown): unknown {\n if (!headers || typeof headers !== 'object') return headers;\n return Object.fromEntries(Object.keys(headers).map((name) => [name, REDACTED]));\n}\n\n/** Redacted deep copy of a config-like value. Never throws, never returns a secret. */\nexport function redactConfig(value: unknown, depth = 0, key = ''): unknown {\n if (value === null || value === undefined) return value;\n if (typeof value === 'string') {\n return SCHEME_PREFIX.test(value) || isUrlKey(key) ? redactUrl(value) : value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') return value;\n if (typeof value === 'function') return '[Function]';\n if (typeof value !== 'object') return '[Unserializable]';\n if (typeof URL !== 'undefined' && value instanceof URL) return redactUrl(value);\n if (Array.isArray(value)) {\n return depth >= MAX_DEPTH ? '[Array]' : value.map((v) => redactConfig(v, depth + 1, key));\n }\n if (!isPlainObject(value) || depth >= MAX_DEPTH)\n return `[${value.constructor?.name ?? 'Object'}]`;\n const out: Record<string, unknown> = {};\n for (const [name, inner] of Object.entries(value)) {\n if (isSecretKey(name)) out[name] = inner === undefined ? undefined : REDACTED;\n else if (name.toLowerCase() === 'headers') out[name] = redactHeaders(inner);\n else out[name] = redactConfig(inner, depth + 1, name);\n }\n return out;\n}\n\n// ── Secret protection ───────────────────────────────────────────────────────\n\nconst hiddenKeys = new WeakMap<object, Set<string>>();\nconst hiddenValues = new WeakMap<object, Map<string, unknown>>();\n\nfunction viewOf(target: object): Record<string, unknown> {\n const hidden = hiddenKeys.get(target) ?? new Set<string>();\n const values = hiddenValues.get(target);\n const view: Record<string, unknown> = { class: target.constructor?.name };\n for (const key of new Set([...Object.keys(target), ...hidden])) {\n const inner = hidden.has(key) ? values?.get(key) : (target as Record<string, unknown>)[key];\n if (isSecretKey(key)) view[key] = inner === undefined ? undefined : REDACTED;\n else if (key.toLowerCase() === 'headers') view[key] = redactHeaders(inner);\n else if (\n inner !== null &&\n typeof inner === 'object' &&\n !hidden.has(key) &&\n !(inner instanceof URL)\n ) {\n view[key] = '[Object]';\n } else if (hidden.has(key) && typeof inner === 'string' && !isUrlKey(key)) {\n view[key] = REDACTED;\n } else view[key] = redactConfig(inner, 0, key);\n }\n return view;\n}\n\n/**\n * Hides `keys` on `target` (assigned or not yet) and gives it a redacted `toJSON()` /\n * inspect view. Fields stay readable and writable. Safe to call more than once.\n * Throws when the target cannot carry the protection (frozen or sealed), instead of\n * silently leaving the secret enumerable.\n */\nexport function protectSecrets(target: object, keys: readonly string[]): void {\n if (!Object.isExtensible(target)) {\n throw new TypeError(\n `protectSecrets: ${target.constructor?.name ?? 'object'} is not extensible`\n );\n }\n let hidden = hiddenKeys.get(target);\n let values = hiddenValues.get(target);\n if (!hidden || !values) {\n hidden = new Set();\n values = new Map();\n hiddenKeys.set(target, hidden);\n hiddenValues.set(target, values);\n const view = (): Record<string, unknown> => viewOf(target);\n Object.defineProperty(target, 'toJSON', { value: view, enumerable: false, configurable: true });\n Object.defineProperty(target, INSPECT_CUSTOM, {\n value: view,\n enumerable: false,\n configurable: true,\n });\n }\n const store = values;\n for (const key of keys) {\n if (hidden.has(key)) continue;\n const desc = Object.getOwnPropertyDescriptor(target, key);\n if (desc && !desc.configurable) {\n throw new TypeError(`protectSecrets: \"${key}\" is not configurable`);\n }\n if (desc && 'value' in desc) store.set(key, desc.value);\n hidden.add(key);\n Object.defineProperty(target, key, {\n enumerable: false,\n configurable: true,\n get: () => store.get(key),\n set: (next: unknown) => void store.set(key, next),\n });\n }\n}\n\n// ── Scrubbing error text ────────────────────────────────────────────────────\n\n/** The raw, decoded and percent-encoded spellings of a secret. */\nfunction variantsOf(secret: string): string[] {\n return [secret, safeDecode(secret), encodeURIComponent(secret), encodeURI(secret)];\n}\n\n/** Secret parts of a URL string: the password and the values of sensitive query parameters. */\nexport function urlSecrets(raw: string | URL): string[] {\n const text = typeof raw === 'string' ? raw : raw.href;\n const out: string[] = [];\n const userinfo = new RegExp(USERINFO.source, 'i').exec(text);\n if (userinfo) {\n const info = text.slice(userinfo[1]!.length, userinfo.index + userinfo[0].length - 1);\n const colon = info.indexOf(':');\n if (colon !== -1) out.push(info.slice(colon + 1));\n }\n const queryStart = text.indexOf('?');\n if (queryStart !== -1) {\n const query = text.slice(queryStart + 1).split('#', 1)[0] ?? '';\n for (const pair of query.split('&')) {\n const eq = pair.indexOf('=');\n if (eq > 0 && QUERY_NAMES.has(normalizeName(safeDecode(pair.slice(0, eq))))) {\n out.push(pair.slice(eq + 1));\n }\n }\n }\n return out.flatMap(variantsOf);\n}\n\n/** Every secret string held in a config-like value: secret-keyed values, header values, URL secrets. */\nexport function collectSecrets(value: unknown, depth = 0, key = ''): string[] {\n if (typeof value === 'string') {\n if (isSecretKey(key)) return [value];\n return SCHEME_PREFIX.test(value) || isUrlKey(key) ? urlSecrets(value) : [];\n }\n if (!value || typeof value !== 'object' || depth > MAX_DEPTH) return [];\n if (typeof URL !== 'undefined' && value instanceof URL) return urlSecrets(value);\n if (Array.isArray(value)) return value.flatMap((v) => collectSecrets(v, depth + 1, key));\n if (!isPlainObject(value)) return [];\n const isHeaders = key.toLowerCase() === 'headers';\n return Object.entries(value).flatMap(([name, inner]) => {\n if (isHeaders && typeof inner === 'string') return [inner];\n if (isSecretKey(name) && inner !== null && typeof inner === 'object') {\n return collectSecrets(inner, depth + 1, 'secret');\n }\n return collectSecrets(inner, depth + 1, name);\n });\n}\n\n/** Replaces URL userinfo and every spelling of the given secret values in `text`. */\nexport function scrubSecrets(text: string, secrets: readonly (string | undefined)[]): string {\n let out = text.replace(USERINFO, `$1${REDACTED}@`);\n const all = new Set(\n secrets.flatMap((s) => (s && s.length >= MIN_SECRET_LENGTH ? variantsOf(s) : []))\n );\n for (const secret of [...all].sort((a, b) => b.length - a.length)) {\n if (secret.length >= MIN_SECRET_LENGTH) out = out.split(secret).join(REDACTED);\n }\n return out;\n}\n\n/** Scrubs message, stack and the cause chain of `err` in place; returns it. */\nexport function scrubError<T>(err: T, secrets: readonly (string | undefined)[], depth = 0): T {\n if (!(err instanceof Error) || depth > 3) return err;\n try {\n err.message = scrubSecrets(err.message, secrets);\n if (err.stack) err.stack = scrubSecrets(err.stack, secrets);\n scrubError((err as { cause?: unknown }).cause, secrets, depth + 1);\n } catch {\n /* frozen error: leave as is */\n }\n return err;\n}\n\n/** A `.catch()` handler that scrubs the secrets from the error, then rethrows it. */\nexport function scrubbing(secrets: () => (string | undefined)[]): (err: unknown) => never {\n return (err) => {\n throw scrubError(err, secrets());\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"slack.transport-Ce96JBDk.mjs","names":[],"sources":["../src/transports/otlp.transport.ts","../src/transports/webhook-queue.ts","../src/transports/discord.transport.ts","../src/transports/slack.transport.ts"],"sourcesContent":["/**\n * OTLP Logs transport — emit logixia logs as OpenTelemetry LogRecords.\n *\n * logixia already READS the active OTel span (the bridge injects traceId/spanId\n * into payloads). This transport closes the loop by EMITTING logs OUT in the\n * OTLP/HTTP JSON format to a collector, making logixia an OTel-Logs-native\n * source — logs land in any OTLP backend (Grafana Loki, OpenObserve, Better\n * Stack, Axiom, Datadog, SigNoz…) already correlated with traces.\n *\n * Dependency-free: builds the OTLP/HTTP JSON payload directly (no\n * @opentelemetry/* packages required — that JS API is still alpha), conforming\n * to the OTel logs data model: SeverityNumber (1–24), resource attributes\n * (service.name/version, deployment.environment), and TraceId/SpanId on each\n * record for correlation.\n *\n * @example\n * ```ts\n * transports: {\n * custom: [ new OtlpLogTransport({\n * url: 'http://localhost:4318/v1/logs',\n * serviceName: 'api',\n * headers: { 'x-api-key': process.env.OTLP_KEY! },\n * }) ],\n * }\n * ```\n */\n\nimport type { IAsyncTransport, TransportLogEntry } from '../types/transport.types';\nimport { internalWarn } from '../utils/internal-log';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n BatchBuffer,\n DEFAULT_MAX_BUFFER_SIZE,\n DEFAULT_REQUEST_TIMEOUT_MS,\n HttpError,\n} from './batch-buffer';\nimport { collectSecrets, protectSecrets, scrubError } from './secret-config';\n\nexport interface OtlpLogTransportConfig {\n /** OTLP/HTTP logs endpoint, e.g. `http://localhost:4318/v1/logs`. */\n url: string;\n /** Extra HTTP headers (auth, tenant, etc.). */\n headers?: Record<string, string>;\n /** `service.name` resource attribute. Default: 'logixia'. */\n serviceName?: string;\n /** `service.version` resource attribute. */\n serviceVersion?: string;\n /** `deployment.environment` resource attribute. */\n environment?: string;\n /** Extra resource attributes merged into the OTLP resource. */\n resourceAttributes?: Record<string, string | number | boolean>;\n /** Entries per batch / per POST. Default: 100. */\n batchSize?: number;\n /** Auto-flush interval (ms). Default: 5000. */\n flushIntervalMs?: number;\n /** Abort a request that has not finished after this many ms. Default: 10000. */\n requestTimeoutMs?: number;\n /** Max buffered entries; the oldest are dropped past this. Default: 10000. */\n maxBufferSize?: number;\n level?: string;\n}\n\nconst HEX_32 = /^[0-9a-f]{32}$/;\n\n/**\n * OTLP JSON wants a 32-char lowercase hex trace id. Dashed UUIDs are\n * normalised; anything else (or all zeros) returns undefined.\n */\nexport function toOtlpTraceId(id: string): string | undefined {\n const hex = id.replace(/-/g, '').toLowerCase();\n return HEX_32.test(hex) && hex !== '0'.repeat(32) ? hex : undefined;\n}\n\n/**\n * Map a logixia level name to an OTel SeverityNumber (1–24) and text.\n * Per the OTel logs SDK spec: TRACE=1, DEBUG=5, INFO=9, WARN=13, ERROR=17,\n * FATAL=21. Custom/unknown levels fall back to INFO (9).\n */\nexport function toOtelSeverity(level: string): { number: number; text: string } {\n switch (level.toLowerCase()) {\n case 'trace':\n return { number: 1, text: 'TRACE' };\n case 'verbose':\n return { number: 5, text: 'DEBUG' }; // verbose maps to DEBUG range\n case 'debug':\n return { number: 5, text: 'DEBUG' };\n case 'info':\n return { number: 9, text: 'INFO' };\n case 'warn':\n case 'warning':\n return { number: 13, text: 'WARN' };\n case 'error':\n return { number: 17, text: 'ERROR' };\n case 'fatal':\n return { number: 21, text: 'FATAL' };\n default:\n return { number: 9, text: 'INFO' };\n }\n}\n\n/** Coerce a JS value into an OTLP AnyValue. */\nfunction toAnyValue(value: unknown): Record<string, unknown> {\n if (typeof value === 'string') return { stringValue: value };\n if (typeof value === 'boolean') return { boolValue: value };\n if (typeof value === 'number') {\n return Number.isInteger(value) ? { intValue: value } : { doubleValue: value };\n }\n if (typeof value === 'bigint') return { stringValue: value.toString() };\n if (value === null || value === undefined) return { stringValue: '' };\n // Objects/arrays → JSON string (kvlistValue would be richer but stringValue is\n // universally accepted and avoids deep recursion / circular issues here).\n try {\n return { stringValue: stringifyForLog(value) };\n } catch {\n return { stringValue: String(value) };\n }\n}\n\n/** Build the OTLP KeyValue attribute list from a flat record. */\nfunction toAttributes(rec: Record<string, unknown>): Array<{ key: string; value: unknown }> {\n return Object.entries(rec).map(([key, value]) => ({ key, value: toAnyValue(value) }));\n}\n\nexport class OtlpLogTransport implements IAsyncTransport {\n public readonly name = 'otlp';\n public readonly level: string | undefined;\n\n private readonly url: string;\n private readonly headers: Record<string, string>;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private readonly requestTimeoutMs: number;\n private readonly resourceAttrs: Array<{ key: string; value: unknown }>;\n\n private readonly buffer: BatchBuffer<TransportLogEntry>;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(config: OtlpLogTransportConfig) {\n this.url = config.url;\n this.headers = config.headers ?? {};\n this.batchSize = config.batchSize ?? 100;\n this.flushIntervalMs = config.flushIntervalMs ?? 5000;\n this.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.level = config.level;\n this.buffer = new BatchBuffer<TransportLogEntry>({\n name: 'OtlpLogTransport',\n batchSize: this.batchSize,\n maxBufferSize: config.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE,\n send: (entries) => this.send(entries),\n secrets: () => this.secretValues(),\n });\n\n const resource: Record<string, unknown> = {\n 'service.name': config.serviceName ?? 'logixia',\n ...(config.serviceVersion ? { 'service.version': config.serviceVersion } : {}),\n ...(config.environment ? { 'deployment.environment': config.environment } : {}),\n ...(config.resourceAttributes ?? {}),\n };\n this.resourceAttrs = toAttributes(resource);\n\n protectSecrets(this, ['headers', 'url']);\n\n this.flushTimer = setInterval(() => {\n this.flush().catch(() => {});\n }, this.flushIntervalMs);\n if (this.flushTimer.unref) this.flushTimer.unref();\n }\n\n write(entry: TransportLogEntry): void {\n this.buffer.push(entry);\n this.buffer.flushIfFull();\n }\n\n /** Convert one entry into an OTLP LogRecord. */\n private toLogRecord(entry: TransportLogEntry): Record<string, unknown> {\n const sev = toOtelSeverity(entry.level);\n const tsNanos = String(entry.timestamp.getTime() * 1_000_000);\n\n const attrs: Record<string, unknown> = { ...(entry.data ?? {}) };\n if (entry.context !== undefined) attrs['context'] = entry.context;\n if (entry.appName !== undefined) attrs['app.name'] = entry.appName;\n if (entry.environment !== undefined) attrs['deployment.environment'] = entry.environment;\n\n const record: Record<string, unknown> = {\n timeUnixNano: tsNanos,\n observedTimeUnixNano: tsNanos,\n severityNumber: sev.number,\n severityText: sev.text,\n body: { stringValue: entry.message },\n attributes: toAttributes(attrs),\n };\n\n if (entry.traceId) {\n const traceId = toOtlpTraceId(entry.traceId);\n if (traceId) record['traceId'] = traceId;\n else\n (record['attributes'] as unknown[]).push({\n key: 'trace_id',\n value: { stringValue: entry.traceId },\n });\n }\n\n return record;\n }\n\n private buildPayload(entries: TransportLogEntry[]): string {\n return stringifyForLog({\n resourceLogs: [\n {\n resource: { attributes: this.resourceAttrs },\n scopeLogs: [\n {\n scope: { name: 'logixia' },\n logRecords: entries.map((e) => this.toLogRecord(e)),\n },\n ],\n },\n ],\n });\n }\n\n flush(): Promise<void> {\n return this.buffer.flush();\n }\n\n private secretValues(): string[] {\n return collectSecrets({ headers: this.headers, url: this.url });\n }\n\n private async send(entries: TransportLogEntry[]): Promise<void> {\n if (typeof fetch !== 'function') {\n internalWarn('OtlpLogTransport: global fetch unavailable — cannot export logs');\n return;\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);\n try {\n const res = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...this.headers },\n body: this.buildPayload(entries),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new HttpError(res.status, '', 'OTLP export');\n }\n } catch (err) {\n scrubError(err, this.secretValues());\n if (controller.signal.aborted) {\n throw new Error(`OTLP export timed out after ${this.requestTimeoutMs}ms`, { cause: err });\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async close(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n await this.buffer.close();\n }\n}\n","/**\n * Shared core for the chat-webhook transports (Slack, Discord).\n *\n * - entries inside `minIntervalMs` are batched into one message; entries past\n * `maxPerMessage` are dropped and reported to the payload builder as overflow\n * - the queue is bounded (BufferCap); the oldest entries go first\n * - HTTP 429 waits for Retry-After (bounded, cancelled by close()) and retries a\n * bounded number of times\n * - an entry that cannot be rendered is dropped alone; an unserializable batch or a\n * missing global fetch is dropped, never retried\n * - errors only ever name the webhook host, never the URL (the URL is a secret)\n */\n\nimport type { TransportLogEntry } from '../types/transport.types';\nimport { internalError, internalWarn } from '../utils/internal-log';\nimport { HttpError, isPermanentHttpError } from './batch-buffer';\nimport { BufferCap } from './buffer-cap';\n\nconst MAX_BACKOFF_MS = 30_000;\nconst DEFAULT_QUEUE_CAP = 1000;\nconst CLOSE_TIMEOUT_MS = 3000;\nconst OVERFLOW_WARN_MS = 5000;\nexport const DEFAULT_WEBHOOK_TIMEOUT_MS = 10_000;\nconst ZWSP = '';\n\nconst LEVEL_RANK: Record<string, number> = {\n fatal: 0,\n error: 1,\n warn: 2,\n warning: 2,\n info: 3,\n debug: 4,\n verbose: 5,\n trace: 6,\n};\n\nexport function resolveMinLevel(level: string | undefined, label: string): string {\n const resolved = (level ?? 'error').toLowerCase();\n if (!(resolved in LEVEL_RANK)) {\n throw new TypeError(`${label}: unknown level \"${String(level).slice(0, 40)}\"`);\n }\n return resolved;\n}\n\n/** Unknown (custom) entry levels pass, like the TransportManager does. */\nexport function meetsLevel(entryLevel: string, minLevel: string): boolean {\n const entryRank = LEVEL_RANK[entryLevel.toLowerCase()];\n return entryRank === undefined || entryRank <= (LEVEL_RANK[minLevel] ?? 1);\n}\n\nexport interface WebhookUrlRules {\n label: string;\n hostMatches: (host: string) => boolean;\n pathMatches: (path: string) => boolean;\n expected: string;\n allowCustomUrl: boolean | undefined;\n}\n\n/** Validates the secret URL. Error messages never contain it. */\nexport function parseWebhookUrl(raw: unknown, rules: WebhookUrlRules): URL {\n const { label, allowCustomUrl, hostMatches, pathMatches, expected } = rules;\n if (typeof raw !== 'string' || raw.length === 0) {\n throw new TypeError(`${label}: webhookUrl is required`);\n }\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new TypeError(`${label}: webhookUrl is not a valid URL`);\n }\n if (url.protocol !== 'https:') {\n throw new TypeError(`${label}: webhookUrl must use https:`);\n }\n if (url.username || url.password) {\n throw new TypeError(`${label}: webhookUrl must not contain credentials`);\n }\n if (!allowCustomUrl) {\n const host = url.hostname.toLowerCase();\n if (!hostMatches(host) || !pathMatches(url.pathname) || url.port) {\n throw new TypeError(\n `${label}: webhookUrl must be a ${expected} webhook (set allowCustomUrl: true to use another https endpoint)`\n );\n }\n }\n return url;\n}\n\nexport interface WebhookResponseLike {\n ok: boolean;\n status: number;\n headers?: { get(name: string): string | null } | undefined;\n body?: { cancel(): Promise<void> } | null | undefined;\n json?: () => Promise<unknown>;\n}\n\ninterface PostResult {\n ok: boolean;\n status: number;\n retryAfterMs: number | undefined;\n}\n\nexport interface WebhookQueueOptions<T> {\n label: string;\n url: URL;\n minIntervalMs: number | undefined;\n maxPerMessage: number;\n maxQueueSize: number | undefined;\n maxRetries: number | undefined;\n requestTimeoutMs: number | undefined;\n /** Renders one entry. A throw (or unserializable result) drops only that entry. */\n render: (entry: TransportLogEntry) => T;\n /**\n * Builds the JSON request body from the rendered entries. `overflow` counts\n * entries beyond `maxPerMessage` that were dropped; the body must say so.\n */\n assemble: (rendered: T[], overflow: number) => unknown;\n /** Reads the wait (ms) from a 429 response. Defaults to the Retry-After header. */\n retryAfterMs?: (res: WebhookResponseLike) => Promise<number | undefined>;\n}\n\nexport function retryAfterHeaderMs(res: WebhookResponseLike): number | undefined {\n const raw = res.headers?.get('retry-after');\n if (raw === null || raw === undefined || raw === '') return undefined;\n const seconds = Number(raw);\n return Number.isFinite(seconds) && seconds >= 0 ? seconds * 1000 : undefined;\n}\n\nfunction nonNegative(value: number | undefined, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : fallback;\n}\n\nfunction failureCode(err: unknown): string {\n const cause = (err as { cause?: { code?: unknown } } | null)?.cause;\n const code = cause?.code ?? (err as { code?: unknown } | null)?.code;\n if (typeof code === 'string') return code.slice(0, 40);\n return err instanceof Error ? err.name : 'error';\n}\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise<void>((resolve) => {\n if (signal.aborted) return resolve();\n const done = (): void => {\n clearTimeout(timer);\n signal.removeEventListener('abort', done);\n resolve();\n };\n const timer = setTimeout(done, ms);\n timer.unref?.();\n signal.addEventListener('abort', done, { once: true });\n });\n}\n\nasync function cancelBody(res: WebhookResponseLike): Promise<void> {\n try {\n await res.body?.cancel();\n } catch {\n // body already consumed or locked\n }\n}\n\n/**\n * Throttled queue for chat webhooks. It is not built on BatchBuffer because the\n * semantics differ: sends are spaced by `minIntervalMs` (leading edge, then one\n * message per window), a window sends one summarized message and drops the\n * overflow, 429 waits are cancellable by close(), and flush() surfaces send\n * errors. HttpError / isPermanentHttpError are shared with BatchBuffer.\n *\n * Entries past `maxPerMessage` in one window are not sent: the message carries a\n * \"… and N more\" line and an internal warning reports the count.\n */\nexport class WebhookQueue<T> {\n private items: TransportLogEntry[] = [];\n private readonly cap: BufferCap;\n private readonly host: string;\n private readonly httpLabel: string;\n private readonly minIntervalMs: number;\n private readonly maxRetries: number;\n private readonly timeoutMs: number;\n private timer: NodeJS.Timeout | null = null;\n private inFlight: Promise<void> | undefined;\n private nextAllowed = 0;\n private failures = 0;\n private closed = false;\n private readonly shutdown = new AbortController();\n private overflowPending = 0;\n private lastOverflowWarn = 0;\n private fetchWarned = false;\n\n constructor(private readonly opts: WebhookQueueOptions<T>) {\n this.host = opts.url.hostname;\n this.httpLabel = `${opts.label} (${this.host})`;\n this.minIntervalMs = nonNegative(opts.minIntervalMs, 1000);\n this.maxRetries = Math.floor(nonNegative(opts.maxRetries, 1));\n this.timeoutMs = nonNegative(opts.requestTimeoutMs, DEFAULT_WEBHOOK_TIMEOUT_MS);\n this.cap = new BufferCap(opts.label, opts.maxQueueSize, opts.maxPerMessage, DEFAULT_QUEUE_CAP);\n }\n\n get length(): number {\n return this.items.length;\n }\n\n push(entry: TransportLogEntry): void {\n if (this.closed) return;\n this.items.push(entry);\n this.cap.enforce(this.items);\n this.schedule();\n }\n\n flush(): Promise<void> {\n this.inFlight ??= this.drain().finally(() => {\n this.inFlight = undefined;\n });\n return this.inFlight;\n }\n\n /** Cancels rate-limit waits, then makes one best-effort send with a short timeout. */\n async close(): Promise<void> {\n this.closed = true;\n this.clearTimer();\n this.shutdown.abort();\n try {\n await this.inFlight;\n } catch {\n // already reported by the timer path\n }\n try {\n await this.flush();\n } catch (err) {\n internalError(`${this.opts.label} flush on close failed`, err);\n }\n this.reportOverflow(true);\n if (this.items.length > 0) {\n internalError(`${this.opts.label} closing with ${this.items.length} undelivered entries`);\n this.items = [];\n }\n }\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n\n private schedule(): void {\n if (this.timer || this.closed || this.items.length === 0) return;\n const delay = Math.max(0, this.nextAllowed - Date.now());\n this.timer = setTimeout(() => {\n this.timer = null;\n this.flush().catch((err) => internalError(`${this.opts.label} send failed`, err));\n }, delay);\n this.timer.unref?.();\n }\n\n private reportOverflow(force = false): void {\n const now = Date.now();\n if (this.overflowPending === 0 || (!force && now - this.lastOverflowWarn < OVERFLOW_WARN_MS)) {\n return;\n }\n const n = this.overflowPending;\n internalWarn(\n `${this.opts.label}: ${n} entr${n === 1 ? 'y' : 'ies'} over the per-message limit (${this.opts.maxPerMessage}) summarized in a \"... and N more\" line and not sent`\n );\n this.overflowPending = 0;\n this.lastOverflowWarn = now;\n }\n\n private render(batch: TransportLogEntry[]): T[] {\n const rendered: T[] = [];\n let bad = 0;\n for (const entry of batch) {\n try {\n const value = this.opts.render(entry);\n JSON.stringify(value);\n rendered.push(value);\n } catch (err) {\n bad += 1;\n if (bad === 1) {\n internalError(`${this.opts.label}: dropping an entry that cannot be rendered`, err);\n }\n }\n }\n if (bad > 1) {\n internalError(`${this.opts.label}: dropped ${bad} entries that cannot be rendered`);\n }\n return rendered;\n }\n\n private async drain(): Promise<void> {\n if (this.items.length === 0) return;\n if (typeof fetch !== 'function') {\n if (!this.fetchWarned) {\n this.fetchWarned = true;\n internalWarn(\n `${this.opts.label}: global fetch is unavailable (Node 18+ required); dropping entries`\n );\n }\n this.items = [];\n return;\n }\n const all = this.items;\n this.items = [];\n const batch = all.slice(0, this.opts.maxPerMessage);\n const overflow = all.length - batch.length;\n if (overflow > 0) {\n this.overflowPending += overflow;\n this.reportOverflow();\n }\n this.nextAllowed = Date.now() + this.minIntervalMs;\n try {\n const rendered = this.render(batch);\n if (rendered.length === 0 && overflow === 0) return;\n let body: string;\n try {\n body = JSON.stringify(this.opts.assemble(rendered, overflow));\n } catch (err) {\n internalError(`${this.opts.label}: dropping a batch that cannot be serialized`, err);\n return;\n }\n try {\n await this.sendWithRetry(body);\n this.failures = 0;\n } catch (err) {\n if (!isPermanentHttpError(err)) {\n this.items.unshift(...batch);\n this.cap.enforce(this.items);\n this.failures += 1;\n const backoff = Math.min(\n MAX_BACKOFF_MS,\n Math.max(1000, this.minIntervalMs) * 2 ** this.failures\n );\n this.nextAllowed = Math.max(this.nextAllowed, Date.now() + backoff);\n }\n throw err;\n }\n } finally {\n this.schedule();\n }\n }\n\n private async sendWithRetry(body: string): Promise<void> {\n for (let attempt = 0; ; attempt += 1) {\n const res = await this.post(body);\n if (res.ok) return;\n if (res.status !== 429) throw new HttpError(res.status, '', this.httpLabel);\n const waitMs = Math.min(\n MAX_BACKOFF_MS,\n Math.max(0, res.retryAfterMs ?? Math.max(1000, this.minIntervalMs))\n );\n this.nextAllowed = Math.max(this.nextAllowed, Date.now() + waitMs);\n if (attempt >= this.maxRetries || this.closed) {\n throw new HttpError(429, '', this.httpLabel);\n }\n await sleep(waitMs, this.shutdown.signal);\n if (this.shutdown.signal.aborted) {\n throw new Error(`${this.opts.label}: rate-limit wait cancelled by close()`);\n }\n }\n }\n\n private async readRetryAfter(res: WebhookResponseLike): Promise<number | undefined> {\n try {\n return this.opts.retryAfterMs ? await this.opts.retryAfterMs(res) : retryAfterHeaderMs(res);\n } catch {\n return undefined;\n }\n }\n\n private async post(body: string): Promise<PostResult> {\n const controller = new AbortController();\n const timeoutMs = this.closed ? Math.min(this.timeoutMs, CLOSE_TIMEOUT_MS) : this.timeoutMs;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = (await fetch(this.opts.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n redirect: 'error',\n signal: controller.signal,\n })) as WebhookResponseLike;\n let retryAfterMs: number | undefined;\n try {\n if (res.status === 429) retryAfterMs = await this.readRetryAfter(res);\n } finally {\n await cancelBody(res);\n }\n return { ok: res.ok, status: res.status, retryAfterMs };\n } catch (err) {\n // fetch errors may echo the request URL; keep only the host and a short code (no cause)\n // eslint-disable-next-line preserve-caught-error -- the cause can contain the secret URL\n throw new Error(\n `${this.opts.label}: request to ${this.host} failed (${controller.signal.aborted ? 'timeout' : failureCode(err)})`\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/** Cuts `text` to `max` chars without splitting a surrogate pair or a `&`-style entity. */\nexport function truncateText(text: string, max: number, ellipsis = '…'): string {\n if (text.length <= max) return text;\n let cut = text.slice(0, Math.max(0, max - ellipsis.length));\n cut = cut.replace(/&[a-z]{0,3}$/, '');\n if (/[\\uD800-\\uDBFF]$/.test(cut)) cut = cut.slice(0, -1);\n return cut + ellipsis;\n}\n\n/** Breaks code-fence and broadcast-mention sequences with a zero-width space. */\nexport function defuseText(text: string): string {\n return text\n .replace(/`{3,}/g, (m) => m.split('').join(ZWSP))\n .replace(/@(everyone|here|channel)/gi, `@${ZWSP}$1`);\n}\n\n/** Collapses control characters and newlines for single-line fields. */\nexport function singleLine(text: string): string {\n // eslint-disable-next-line no-control-regex\n return text.replace(/[\\u0000-\\u001f\\u007f]+/g, ' ').trim();\n}\n\n/** ISO string, or undefined for a missing or invalid timestamp. */\nexport function safeIso(date: unknown): string | undefined {\n return date instanceof Date && !Number.isNaN(date.getTime()) ? date.toISOString() : undefined;\n}\n","/**\n * Discord webhook transport.\n *\n * Sends error-level (by default) entries to a Discord channel as embeds.\n * Entries inside `minIntervalMs` are batched into one request (max 10 embeds;\n * the overflow is dropped and counted in the message `content`). Every request\n * carries `allowed_mentions: { parse: [] }` so logged data can never ping\n * @everyone, roles or users, and logged text has its markdown escaped.\n *\n * Limits follow https://discord.com/developers/docs/resources/message#embed-object-embed-limits\n *\n * The webhook URL is a secret: it is never logged and never appears in errors.\n *\n * @example\n * transports: { custom: [ new DiscordTransport({ webhookUrl: process.env.DISCORD_WEBHOOK_URL! }) ] }\n */\n\nimport type { IAsyncTransport, TransportLogEntry } from '../types/transport.types';\nimport { internalWarn } from '../utils/internal-log';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n DEFAULT_WEBHOOK_TIMEOUT_MS,\n defuseText,\n meetsLevel,\n parseWebhookUrl,\n resolveMinLevel,\n retryAfterHeaderMs,\n safeIso,\n singleLine,\n truncateText,\n WebhookQueue,\n type WebhookResponseLike,\n} from './webhook-queue';\n\nexport const DISCORD_TITLE_MAX = 256;\nexport const DISCORD_DESCRIPTION_MAX = 4096;\nexport const DISCORD_FIELD_VALUE_MAX = 1024;\nexport const DISCORD_EMBEDS_MAX = 10;\nexport const DISCORD_FIELDS_MAX = 25;\nexport const DISCORD_EMBED_TOTAL_MAX = 6000;\nexport const DISCORD_CONTENT_MAX = 2000;\nconst FIELD_VALUE_CAP = 64;\nconst DISCORD_FOOTER_MAX = 2048;\nconst FENCE_OVERHEAD = '```json\\n\\n```'.length;\nconst MIN_USEFUL_BODY = 20;\n\nexport interface DiscordEmbedField {\n name: string;\n value: string;\n inline?: boolean;\n}\n\nexport interface DiscordEmbed {\n title?: string;\n description?: string;\n color?: number;\n timestamp?: string;\n fields?: DiscordEmbedField[];\n [key: string]: unknown;\n}\n\nexport interface DiscordTransportConfig {\n /** Webhook URL (secret). Must be https on discord.com / discordapp.com unless `allowCustomUrl`. */\n webhookUrl: string;\n /** Minimum level to send. Default: 'error'. */\n level?: string;\n username?: string;\n /** https URL of the avatar shown for the webhook. */\n avatarUrl?: string;\n /** Entries within this window are batched into one request. Default: 1000. */\n minIntervalMs?: number;\n /**\n * Overrides the embed built for each entry. Limits are still enforced, but\n * escaping the content is the formatter's responsibility.\n */\n formatter?: (entry: TransportLogEntry) => DiscordEmbed;\n filter?: (entry: TransportLogEntry) => boolean;\n /** Accept an https webhook URL on any host (e.g. a proxy or Discord-compatible service). */\n allowCustomUrl?: boolean;\n /** Retries after an HTTP 429 (waits retry_after, max 30s). Default: 1. */\n maxRetries?: number;\n /** Max queued entries; the oldest are dropped past this. Default: 1000. */\n maxBufferSize?: number;\n requestTimeoutMs?: number;\n}\n\nexport const DISCORD_LEVEL_COLORS: Record<string, number> = {\n fatal: 0x992d22,\n error: 0xed4245,\n warn: 0xfee75c,\n warning: 0xfee75c,\n info: 0x3498db,\n debug: 0x95a5a6,\n verbose: 0x95a5a6,\n trace: 0x95a5a6,\n};\nconst DEFAULT_COLOR = 0x95a5a6;\n\n/** Escapes Discord markdown and defuses @everyone / @here and code fences. */\nexport function escapeDiscord(text: string): string {\n return defuseText(text.replace(/[\\\\*_~`|>#[\\]()]/g, '\\\\$&'));\n}\n\nfunction textLength(value: unknown, key: string): number {\n const text = (value as Record<string, unknown> | undefined)?.[key];\n return typeof text === 'string' ? text.length : 0;\n}\n\n/** Counts every text field Discord counts toward the 6000-character limit. */\nfunction embedChars(embed: DiscordEmbed): number {\n return (\n (embed.title?.length ?? 0) +\n (embed.description?.length ?? 0) +\n (embed.fields ?? []).reduce((n, f) => n + f.name.length + f.value.length, 0) +\n textLength(embed['footer'], 'text') +\n textLength(embed['author'], 'name')\n );\n}\n\n/** Shrinks one embed to `limit` chars: description first, then fields, footer/author, title. */\nfunction shrinkToFit(embed: DiscordEmbed, limit: number): void {\n const excess = () => embedChars(embed) - limit;\n if (excess() > 0 && embed.description) {\n const keep = embed.description.length - excess();\n if (keep > 0) embed.description = truncateText(embed.description, keep);\n else delete embed.description;\n }\n while (excess() > 0 && embed.fields?.length) embed.fields.pop();\n if (excess() > 0) {\n delete embed['footer'];\n delete embed['author'];\n }\n if (excess() > 0 && embed.title) {\n embed.title = truncateText(embed.title, Math.max(1, embed.title.length - excess()));\n }\n}\n\nfunction codeBlock(json: string, max: number): string {\n return `\\`\\`\\`json\\n${truncateText(\n json.replace(/`{3,}/g, (m) => m.split('').join('')),\n max\n )}\\n\\`\\`\\``;\n}\n\nfunction clampCustomEmbed(embed: DiscordEmbed): DiscordEmbed {\n const out: DiscordEmbed = { ...embed };\n if (typeof out.title === 'string') out.title = truncateText(out.title, DISCORD_TITLE_MAX);\n if (typeof out.description === 'string') {\n out.description = truncateText(out.description, DISCORD_DESCRIPTION_MAX);\n }\n if (Array.isArray(out.fields)) {\n out.fields = out.fields.slice(0, DISCORD_FIELDS_MAX).map((f) => ({\n ...f,\n name: truncateText(String(f.name), DISCORD_TITLE_MAX),\n value: truncateText(String(f.value), DISCORD_FIELD_VALUE_MAX),\n }));\n }\n const footer = out['footer'] as { text?: unknown } | undefined;\n if (footer && typeof footer.text === 'string') {\n out['footer'] = { ...footer, text: truncateText(footer.text, DISCORD_FOOTER_MAX) };\n }\n const author = out['author'] as { name?: unknown } | undefined;\n if (author && typeof author.name === 'string') {\n out['author'] = { ...author, name: truncateText(author.name, DISCORD_TITLE_MAX) };\n }\n return out;\n}\n\ninterface EmbedDraft {\n embed: DiscordEmbed;\n json: string | undefined;\n}\n\nexport class DiscordTransport implements IAsyncTransport {\n public readonly name = 'discord';\n public readonly level: string;\n public filter?: (entry: TransportLogEntry) => boolean;\n\n private readonly queue!: WebhookQueue<EmbedDraft>;\n private readonly username: string | undefined;\n private readonly avatarUrl: string | undefined;\n private readonly formatter: ((entry: TransportLogEntry) => DiscordEmbed) | undefined;\n\n constructor(config: DiscordTransportConfig) {\n const url = parseWebhookUrl(config.webhookUrl, {\n label: 'DiscordTransport',\n hostMatches: (h) =>\n ['discord.com', 'discordapp.com', 'ptb.discord.com', 'canary.discord.com'].includes(h),\n pathMatches: (p) => /^\\/api(\\/v\\d+)?\\/webhooks\\//.test(p),\n expected: 'discord.com',\n allowCustomUrl: config.allowCustomUrl,\n });\n if (config.avatarUrl !== undefined && !/^https:\\/\\//i.test(config.avatarUrl)) {\n throw new TypeError('DiscordTransport: avatarUrl must use https:');\n }\n this.level = resolveMinLevel(config.level, 'DiscordTransport');\n if (config.filter) this.filter = config.filter;\n this.username = config.username;\n this.avatarUrl = config.avatarUrl;\n this.formatter = config.formatter;\n const queue = new WebhookQueue<EmbedDraft>({\n label: 'DiscordTransport',\n url,\n minIntervalMs: config.minIntervalMs,\n maxPerMessage: DISCORD_EMBEDS_MAX,\n maxQueueSize: config.maxBufferSize,\n maxRetries: config.maxRetries,\n requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_WEBHOOK_TIMEOUT_MS,\n render: (entry) => this.draftFor(entry),\n assemble: (drafts, overflow) => this.buildPayload(drafts, overflow),\n retryAfterMs: readRetryAfter,\n });\n // non-enumerable so util.inspect / spreads of the transport never reach the secret URL\n Object.defineProperty(this, 'queue', { value: queue, enumerable: false });\n }\n\n write(entry: TransportLogEntry): void {\n if (!meetsLevel(entry.level, this.level)) return;\n // `filter` is applied by the TransportManager; it is not run again here\n this.queue.push(entry);\n }\n\n flush(): Promise<void> {\n return this.queue.flush();\n }\n\n close(): Promise<void> {\n return this.queue.close();\n }\n\n /** Never serialise the webhook URL (JSON.stringify, util.inspect). */\n toJSON(): Record<string, unknown> {\n return { name: this.name, level: this.level };\n }\n\n /** `showHidden` would otherwise print the non-enumerable queue (and its URL). */\n [Symbol.for('nodejs.util.inspect.custom')](): Record<string, unknown> {\n return this.toJSON();\n }\n\n private buildPayload(drafts: EmbedDraft[], overflow: number): Record<string, unknown> {\n const kept = this.fitToBudget(drafts);\n const dropped = overflow + (drafts.length - kept.length);\n\n const payload: Record<string, unknown> = {\n embeds: kept.map((d) => d.embed),\n allowed_mentions: { parse: [] },\n };\n if (dropped > 0) {\n payload['content'] = truncateText(\n `… and ${dropped} more entr${dropped === 1 ? 'y' : 'ies'} not shown`,\n DISCORD_CONTENT_MAX\n );\n }\n if (this.username) payload['username'] = truncateText(this.username, 80);\n if (this.avatarUrl) payload['avatar_url'] = this.avatarUrl;\n return payload;\n }\n\n /** Enforces the 6000-char total: drops trailing embeds if needed, then shares the rest among descriptions. */\n private fitToBudget(drafts: EmbedDraft[]): EmbedDraft[] {\n const kept = [...drafts];\n const base = () => kept.reduce((n, d) => n + embedChars(d.embed), 0);\n while (kept.length > 1 && base() > DISCORD_EMBED_TOTAL_MAX) kept.pop();\n const only = kept[0];\n if (only && base() > DISCORD_EMBED_TOTAL_MAX) shrinkToFit(only.embed, DISCORD_EMBED_TOTAL_MAX);\n const withData = kept.filter((d) => d.json !== undefined);\n if (withData.length === 0) return kept;\n const share = Math.floor((DISCORD_EMBED_TOTAL_MAX - base()) / withData.length);\n const body = Math.min(DISCORD_DESCRIPTION_MAX, share) - FENCE_OVERHEAD;\n for (const d of withData) {\n if (body >= MIN_USEFUL_BODY) d.embed.description = codeBlock(d.json!, body);\n }\n return kept;\n }\n\n private draftFor(entry: TransportLogEntry): EmbedDraft {\n if (this.formatter) {\n try {\n return { embed: clampCustomEmbed(this.formatter(entry)), json: undefined };\n } catch {\n internalWarn('DiscordTransport: formatter threw; using the default embed');\n }\n }\n return defaultDraft(entry);\n }\n}\n\nfunction defaultDraft(entry: TransportLogEntry): EmbedDraft {\n const title = `[${singleLine(entry.level).toUpperCase()}] ${escapeDiscord(singleLine(entry.message))}`;\n const candidates: Array<[string, string | undefined]> = [\n ['appName', entry.appName],\n ['environment', entry.environment],\n ['context', entry.context],\n ['traceId', entry.traceId],\n ];\n const fields: DiscordEmbedField[] = candidates\n .map(([name, value]) => [name, typeof value === 'string' ? singleLine(value) : ''] as const)\n .filter(([, value]) => value !== '')\n .map(([name, value]) => ({\n name,\n value: truncateText(escapeDiscord(value), FIELD_VALUE_CAP),\n inline: true,\n }));\n const embed: DiscordEmbed = {\n title: truncateText(title, DISCORD_TITLE_MAX),\n color: DISCORD_LEVEL_COLORS[entry.level.toLowerCase()] ?? DEFAULT_COLOR,\n fields,\n };\n const timestamp = safeIso(entry.timestamp);\n if (timestamp) embed.timestamp = timestamp;\n const json =\n entry.data && Object.keys(entry.data).length > 0 ? stringifyForLog(entry.data) : undefined;\n return { embed, json };\n}\n\nasync function readRetryAfter(res: WebhookResponseLike): Promise<number | undefined> {\n try {\n const body = (await res.json?.()) as { retry_after?: unknown } | undefined;\n const seconds = Number(body?.retry_after);\n if (body?.retry_after !== undefined && Number.isFinite(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n } catch {\n // fall through to the header\n }\n return retryAfterHeaderMs(res);\n}\n","/**\n * Slack incoming-webhook transport.\n *\n * Sends error-level (by default) entries to a Slack channel as Block Kit\n * messages. Entries inside `minIntervalMs` are batched into one message so a\n * log storm cannot flood the channel. All logged text is escaped for Slack\n * mrkdwn (`&`, `<`, `>`), which also disarms `<!channel>`, `<!here>` and\n * `<@U123>` mentions coming from logged data.\n *\n * The webhook URL is a secret: it is never logged and never appears in errors.\n *\n * @example\n * transports: { custom: [ new SlackTransport({ webhookUrl: process.env.SLACK_WEBHOOK_URL! }) ] }\n */\n\nimport type { IAsyncTransport, TransportLogEntry } from '../types/transport.types';\nimport { internalWarn } from '../utils/internal-log';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n DEFAULT_WEBHOOK_TIMEOUT_MS,\n defuseText,\n meetsLevel,\n parseWebhookUrl,\n resolveMinLevel,\n safeIso,\n singleLine,\n truncateText,\n WebhookQueue,\n} from './webhook-queue';\n\nexport const SLACK_HEADER_MAX = 150;\nexport const SLACK_DATA_MAX = 2500;\nconst SLACK_FIELD_MAX = 300;\nconst SLACK_TEXT_MAX = 1000;\nconst SLACK_MAX_BLOCKS = 50;\nconst SLACK_MAX_PER_MESSAGE = 10;\n\n/** A Slack message body as returned by a custom `formatter`. */\nexport interface SlackMessage {\n text?: string;\n blocks?: unknown[];\n [key: string]: unknown;\n}\n\nexport interface SlackTransportConfig {\n /** Incoming-webhook URL (secret). Must be https on hooks.slack.com unless `allowCustomUrl`. */\n webhookUrl: string;\n /** Minimum level to send. Default: 'error'. */\n level?: string;\n username?: string;\n iconEmoji?: string;\n /** Entries within this window are batched into one message. Default: 1000. */\n minIntervalMs?: number;\n /**\n * Overrides the message built for each entry. The results of one window are\n * merged: texts are joined and blocks concatenated (capped at 50 blocks).\n * Escaping the content is the formatter's responsibility.\n */\n formatter?: (entry: TransportLogEntry) => SlackMessage;\n filter?: (entry: TransportLogEntry) => boolean;\n /** Accept an https webhook URL on any host (e.g. a proxy or Slack-compatible service). */\n allowCustomUrl?: boolean;\n /** Retries after an HTTP 429 (waits Retry-After, max 30s). Default: 1. */\n maxRetries?: number;\n /** Max queued entries; the oldest are dropped past this. Default: 1000. */\n maxBufferSize?: number;\n requestTimeoutMs?: number;\n}\n\n/** Escapes the three characters Slack treats specially and defuses broadcast mentions. */\nexport function escapeSlack(text: string): string {\n return defuseText(text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'));\n}\n\nconst LEVEL_EMOJI: Record<string, string> = {\n fatal: ':rotating_light:',\n error: ':red_circle:',\n warn: ':warning:',\n warning: ':warning:',\n info: ':information_source:',\n};\n\nexport class SlackTransport implements IAsyncTransport {\n public readonly name = 'slack';\n public readonly level: string;\n public filter?: (entry: TransportLogEntry) => boolean;\n\n private readonly queue!: WebhookQueue<SlackMessage>;\n private readonly username: string | undefined;\n private readonly iconEmoji: string | undefined;\n private readonly formatter: ((entry: TransportLogEntry) => SlackMessage) | undefined;\n\n constructor(config: SlackTransportConfig) {\n const url = parseWebhookUrl(config.webhookUrl, {\n label: 'SlackTransport',\n hostMatches: (h) => h === 'hooks.slack.com' || h === 'hooks.slack-gov.com',\n pathMatches: (p) => p.startsWith('/services/') || p.startsWith('/triggers/'),\n expected: 'hooks.slack.com',\n allowCustomUrl: config.allowCustomUrl,\n });\n this.level = resolveMinLevel(config.level, 'SlackTransport');\n if (config.filter) this.filter = config.filter;\n this.username = config.username;\n this.iconEmoji = config.iconEmoji;\n this.formatter = config.formatter;\n const queue = new WebhookQueue<SlackMessage>({\n label: 'SlackTransport',\n url,\n minIntervalMs: config.minIntervalMs,\n maxPerMessage: SLACK_MAX_PER_MESSAGE,\n maxQueueSize: config.maxBufferSize,\n maxRetries: config.maxRetries,\n requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_WEBHOOK_TIMEOUT_MS,\n render: (entry) => this.messageFor(entry),\n assemble: (messages, overflow) => this.buildPayload(messages, overflow),\n });\n // non-enumerable so util.inspect / spreads of the transport never reach the secret URL\n Object.defineProperty(this, 'queue', { value: queue, enumerable: false });\n }\n\n write(entry: TransportLogEntry): void {\n if (!meetsLevel(entry.level, this.level)) return;\n // `filter` is applied by the TransportManager; it is not run again here\n this.queue.push(entry);\n }\n\n flush(): Promise<void> {\n return this.queue.flush();\n }\n\n close(): Promise<void> {\n return this.queue.close();\n }\n\n /** Never serialise the webhook URL (JSON.stringify, util.inspect). */\n toJSON(): Record<string, unknown> {\n return { name: this.name, level: this.level };\n }\n\n /** `showHidden` would otherwise print the non-enumerable queue (and its URL). */\n [Symbol.for('nodejs.util.inspect.custom')](): Record<string, unknown> {\n return this.toJSON();\n }\n\n private buildPayload(messages: SlackMessage[], overflow: number): Record<string, unknown> {\n const blocks = messages.flatMap((m) => m.blocks ?? []);\n const plural = overflow === 1 ? 'y' : 'ies';\n const counter = overflow > 0 ? `… and ${overflow} more entr${plural} not shown` : '';\n if (counter) {\n blocks.push({ type: 'context', elements: [{ type: 'mrkdwn', text: counter }] });\n }\n const text = [...messages.map((m) => m.text ?? ''), counter].filter(Boolean).join('\\n');\n const payload: Record<string, unknown> = {\n text: truncateText(text, SLACK_TEXT_MAX),\n blocks: blocks.slice(0, SLACK_MAX_BLOCKS),\n };\n if (this.username) payload['username'] = truncateText(this.username, 80);\n if (this.iconEmoji) payload['icon_emoji'] = this.iconEmoji;\n return payload;\n }\n\n private messageFor(entry: TransportLogEntry): SlackMessage {\n if (this.formatter) {\n try {\n return this.formatter(entry);\n } catch {\n internalWarn('SlackTransport: formatter threw; using the default message');\n }\n }\n return defaultMessage(entry);\n }\n}\n\nfunction defaultMessage(entry: TransportLogEntry): SlackMessage {\n const level = singleLine(entry.level).toUpperCase();\n const emoji = LEVEL_EMOJI[entry.level.toLowerCase()] ?? ':white_circle:';\n const headline = `[${level}] ${singleLine(entry.message)}`;\n const blocks: unknown[] = [\n {\n type: 'header',\n text: {\n type: 'plain_text',\n text: truncateText(escapeSlack(headline), SLACK_HEADER_MAX),\n emoji: false,\n },\n },\n ];\n\n const context = [\n ['app', entry.appName],\n ['env', entry.environment],\n ['context', entry.context],\n ['trace', entry.traceId],\n ['time', safeIso(entry.timestamp)],\n ]\n .map(([label, value]) => [label, typeof value === 'string' ? singleLine(value) : ''] as const)\n .filter(([, value]) => value !== '')\n .map(([label, value]) => ({\n type: 'mrkdwn',\n text: `*${label}:* ${truncateText(escapeSlack(value), SLACK_FIELD_MAX)}`,\n }));\n if (context.length > 0) blocks.push({ type: 'context', elements: context });\n\n if (entry.data && Object.keys(entry.data).length > 0) {\n const json = truncateText(escapeSlack(stringifyForLog(entry.data)), SLACK_DATA_MAX);\n blocks.push({ type: 'section', text: { type: 'mrkdwn', text: `\\`\\`\\`${json}\\`\\`\\`` } });\n }\n\n return {\n text: `${emoji} ${escapeSlack(truncateText(headline, SLACK_HEADER_MAX))}`,\n blocks,\n };\n}\n"],"mappings":"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"}
|