logixia 2.0.0 → 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 -2597
- package/dist/async-context-2mbUKhcl.mjs +132 -0
- package/dist/async-context-2mbUKhcl.mjs.map +1 -0
- package/dist/async-context-DUFMDYAr.js +148 -0
- package/dist/async-context-DUFMDYAr.js.map +1 -0
- package/dist/{azure-monitor.transport-CrvfHd9C.js → azure-monitor.transport-Bu4S2I2q.js} +32 -20
- package/dist/azure-monitor.transport-Bu4S2I2q.js.map +1 -0
- package/dist/{azure-monitor.transport-Cn_3Usvu.d.ts → azure-monitor.transport-Bvf7Xegt.d.ts} +3 -6
- package/dist/azure-monitor.transport-Bvf7Xegt.d.ts.map +1 -0
- package/dist/{azure-monitor.transport-CHnjVRF-.mjs → azure-monitor.transport-C1RWAumT.mjs} +27 -15
- package/dist/azure-monitor.transport-C1RWAumT.mjs.map +1 -0
- package/dist/{azure-monitor.transport-D7Da4RAb.d.mts → azure-monitor.transport-CbSHOnNX.d.mts} +3 -6
- package/dist/azure-monitor.transport-CbSHOnNX.d.mts.map +1 -0
- package/dist/azure.d.mts +1 -2
- package/dist/azure.d.ts +1 -2
- package/dist/azure.js +3 -6
- package/dist/azure.mjs +1 -6
- package/dist/{batch-buffer-PGvSgbmd.mjs → batch-buffer-BvXLDPlV.mjs} +21 -7
- package/dist/batch-buffer-BvXLDPlV.mjs.map +1 -0
- package/dist/{batch-buffer-BY-mRWIK.js → batch-buffer-C7Am4Mw-.js} +53 -40
- package/dist/batch-buffer-C7Am4Mw-.js.map +1 -0
- package/dist/browser.d.mts +47 -27
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.d.ts +47 -27
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +464 -62
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +465 -65
- package/dist/browser.mjs.map +1 -1
- package/dist/{builder-0gEzRopq.mjs → builder-DhNhvOkt.mjs} +307 -246
- package/dist/builder-DhNhvOkt.mjs.map +1 -0
- package/dist/{builder-D44QktIo.js → builder-yFvJrz7o.js} +435 -399
- package/dist/builder-yFvJrz7o.js.map +1 -0
- package/dist/cli/index.js +216 -125
- package/dist/cloudwatch.d.mts +1 -2
- package/dist/cloudwatch.d.ts +1 -2
- package/dist/cloudwatch.js +3 -7
- package/dist/cloudwatch.mjs +1 -7
- package/dist/{cloudwatch.transport-DsEq633o.d.ts → cloudwatch.transport-CQyT6U91.d.ts} +2 -6
- package/dist/cloudwatch.transport-CQyT6U91.d.ts.map +1 -0
- package/dist/{cloudwatch.transport-BO1ahxw-.js → cloudwatch.transport-Ch1Uae-0.js} +61 -36
- package/dist/cloudwatch.transport-Ch1Uae-0.js.map +1 -0
- package/dist/{cloudwatch.transport-UlyZFWMn.d.mts → cloudwatch.transport-CjVrI6S4.d.mts} +2 -6
- package/dist/cloudwatch.transport-CjVrI6S4.d.mts.map +1 -0
- package/dist/{cloudwatch.transport-DZ6ies7g.mjs → cloudwatch.transport-DZqF2xZO.mjs} +54 -28
- package/dist/cloudwatch.transport-DZqF2xZO.mjs.map +1 -0
- package/dist/{coerce.utils-Cu6IUTgX.mjs → coerce.utils-B_rEudCn.mjs} +3 -4
- package/dist/{coerce.utils-Cu6IUTgX.mjs.map → coerce.utils-B_rEudCn.mjs.map} +1 -1
- package/dist/{coerce.utils-B-LilukN.js → coerce.utils-C1C5sIX0.js} +8 -10
- package/dist/{coerce.utils-B-LilukN.js.map → coerce.utils-C1C5sIX0.js.map} +1 -1
- package/dist/correlation.d.mts +15 -69
- package/dist/correlation.d.mts.map +1 -1
- package/dist/correlation.d.ts +15 -69
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +69 -20
- package/dist/correlation.js.map +1 -1
- package/dist/correlation.mjs +67 -17
- package/dist/correlation.mjs.map +1 -1
- package/dist/{entry-fields-BvOLFlJ4.js → entry-fields-BSLkzw18.js} +16 -13
- package/dist/entry-fields-BSLkzw18.js.map +1 -0
- package/dist/{entry-fields-BJkuPnIg.mjs → entry-fields-J1OBi24o.mjs} +11 -7
- package/dist/entry-fields-J1OBi24o.mjs.map +1 -0
- package/dist/gcp.d.mts +1 -2
- package/dist/gcp.d.ts +1 -2
- package/dist/gcp.js +3 -7
- package/dist/gcp.mjs +1 -7
- package/dist/{gcp.transport-B7oc97sG.d.ts → gcp.transport-BCIvdFV-.d.ts} +5 -8
- package/dist/gcp.transport-BCIvdFV-.d.ts.map +1 -0
- package/dist/{gcp.transport-GrJurKo8.d.mts → gcp.transport-D9SdLPwP.d.mts} +5 -8
- package/dist/gcp.transport-D9SdLPwP.d.mts.map +1 -0
- package/dist/{gcp.transport-DBX5TPIy.mjs → gcp.transport-DVCmnA3b.mjs} +59 -16
- package/dist/gcp.transport-DVCmnA3b.mjs.map +1 -0
- package/dist/{gcp.transport-CHV8MGgz.js → gcp.transport-Dy2Lf8FI.js} +64 -22
- 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-3mw5gaCw.d.mts → index-BSTtFcQ6.d.mts} +142 -13
- package/dist/index-BSTtFcQ6.d.mts.map +1 -0
- package/dist/{index-DhIoploR.d.ts → index-CFDGkI8n.d.ts} +142 -13
- package/dist/index-CFDGkI8n.d.ts.map +1 -0
- package/dist/index.d.mts +114 -217
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +113 -216
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +182 -279
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +160 -256
- package/dist/index.mjs.map +1 -1
- package/dist/internal-log-Bg4V1cPg.mjs +170 -0
- package/dist/internal-log-Bg4V1cPg.mjs.map +1 -0
- package/dist/internal-log-By4Govmu.js +223 -0
- package/dist/internal-log-By4Govmu.js.map +1 -0
- package/dist/{logitron-logger-UVeN-mQm.d.ts → logitron-logger-D22Yb61K.d.mts} +121 -100
- package/dist/logitron-logger-D22Yb61K.d.mts.map +1 -0
- package/dist/{logitron-logger-BFDSO8Io.d.mts → logitron-logger-D_MYYrQt.d.ts} +121 -100
- package/dist/logitron-logger-D_MYYrQt.d.ts.map +1 -0
- package/dist/middleware.d.mts +13 -28
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +13 -28
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +20 -81
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +17 -79
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +37 -48
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +37 -48
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +124 -135
- package/dist/nest.js.map +1 -1
- package/dist/nest.mjs +69 -78
- package/dist/nest.mjs.map +1 -1
- package/dist/{transport.manager-BiuCAJd2.mjs → otel-Dt5riXuE.mjs} +275 -117
- package/dist/otel-Dt5riXuE.mjs.map +1 -0
- package/dist/{transport.manager-CXbKKdVE.js → otel-DyeH6DVR.js} +373 -178
- 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/{trace.utils-CvXgaiQT.mjs → request-trace-BgNykH9M.mjs} +40 -9
- package/dist/request-trace-BgNykH9M.mjs.map +1 -0
- package/dist/{trace.utils-DpBOLDtq.js → request-trace-ByujsUZk.js} +117 -77
- package/dist/request-trace-ByujsUZk.js.map +1 -0
- package/dist/rolldown-runtime-D3PmRqjj.mjs +4 -0
- package/dist/{safe-stringify-DJ66tW5I.mjs → safe-stringify-B5p5ktFe.mjs} +39 -15
- package/dist/safe-stringify-B5p5ktFe.mjs.map +1 -0
- package/dist/{safe-stringify-DWo3aZp_.js → safe-stringify-J3sh-7YM.js} +59 -36
- package/dist/safe-stringify-J3sh-7YM.js.map +1 -0
- package/dist/{search-C4V0OMEn.js → search-CRjhHxe9.js} +319 -92
- package/dist/search-CRjhHxe9.js.map +1 -0
- package/dist/{search-CNh9uVwR.d.ts → search-DA3ft3X5.d.mts} +5 -22
- package/dist/search-DA3ft3X5.d.mts.map +1 -0
- package/dist/{search-BFbu_oVn.mjs → search-DAXKE-P9.mjs} +289 -62
- package/dist/search-DAXKE-P9.mjs.map +1 -0
- package/dist/{search-DXANsQ2n.d.mts → search-DEl3Pe47.d.ts} +5 -22
- package/dist/search-DEl3Pe47.d.ts.map +1 -0
- package/dist/search.d.mts +2 -4
- package/dist/search.d.ts +2 -4
- package/dist/search.js +3 -4
- package/dist/search.mjs +1 -4
- package/dist/secret-config-CmK2wVkr.js +272 -0
- package/dist/secret-config-CmK2wVkr.js.map +1 -0
- package/dist/secret-config-Dhb6pqTU.mjs +210 -0
- package/dist/secret-config-Dhb6pqTU.mjs.map +1 -0
- package/dist/{slack.transport-CXjQYOes.d.ts → slack.transport-BDyENuR0.d.mts} +56 -9
- package/dist/slack.transport-BDyENuR0.d.mts.map +1 -0
- package/dist/{slack.transport-Bzw7sucI.mjs → slack.transport-BTEwsREY.mjs} +263 -31
- package/dist/slack.transport-BTEwsREY.mjs.map +1 -0
- package/dist/{slack.transport-BZzoXDPn.d.mts → slack.transport-C6E0l4kw.d.ts} +56 -9
- package/dist/slack.transport-C6E0l4kw.d.ts.map +1 -0
- package/dist/{slack.transport-BfJRouB2.js → slack.transport-UbYvOdKx.js} +286 -42
- package/dist/slack.transport-UbYvOdKx.js.map +1 -0
- package/dist/testing.d.mts +13 -11
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.d.ts +13 -11
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +41 -7
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +40 -6
- package/dist/testing.mjs.map +1 -1
- package/dist/{transport.types-CGoHpWQR.d.ts → transport.types-CzJq4IrF.d.mts} +14 -5
- package/dist/transport.types-CzJq4IrF.d.mts.map +1 -0
- package/dist/{transport.types-BMnurPcc.d.mts → transport.types-CzJq4IrF.d.ts} +14 -5
- package/dist/transport.types-CzJq4IrF.d.ts.map +1 -0
- package/dist/transports.d.mts +39 -41
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +39 -41
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +19 -22
- package/dist/transports.mjs +7 -13
- package/dist/worker-entry.js +438 -107
- package/dist/worker.d.mts +1 -2
- package/dist/worker.d.ts +1 -2
- package/dist/worker.js +3 -4
- package/dist/worker.mjs +1 -4
- package/dist/{worker.transport-JvGPog3C.d.mts → worker.transport-B9mCQSM1.d.ts} +7 -6
- package/dist/worker.transport-B9mCQSM1.d.ts.map +1 -0
- package/dist/{worker.transport-CdzSZJmw.d.ts → worker.transport-Bl8lFRck.d.mts} +7 -6
- package/dist/worker.transport-Bl8lFRck.d.mts.map +1 -0
- package/dist/{worker.transport-lPxO2MVL.mjs → worker.transport-BmmOKb1-.mjs} +43 -10
- package/dist/worker.transport-BmmOKb1-.mjs.map +1 -0
- package/dist/{worker.transport-BdPxu3PN.js → worker.transport-DxxbqQCG.js} +48 -15
- package/dist/worker.transport-DxxbqQCG.js.map +1 -0
- package/package.json +51 -75
- package/dist/async-context-BzJrbfQs.mjs +0 -72
- package/dist/async-context-BzJrbfQs.mjs.map +0 -1
- package/dist/async-context-DyQQYq3I.js +0 -92
- package/dist/async-context-DyQQYq3I.js.map +0 -1
- package/dist/azure-monitor.transport-CHnjVRF-.mjs.map +0 -1
- package/dist/azure-monitor.transport-Cn_3Usvu.d.ts.map +0 -1
- package/dist/azure-monitor.transport-CrvfHd9C.js.map +0 -1
- package/dist/azure-monitor.transport-D7Da4RAb.d.mts.map +0 -1
- package/dist/batch-buffer-BY-mRWIK.js.map +0 -1
- package/dist/batch-buffer-PGvSgbmd.mjs.map +0 -1
- package/dist/builder-0gEzRopq.mjs.map +0 -1
- package/dist/builder-D44QktIo.js.map +0 -1
- package/dist/chunk-DLSkYcPk.mjs +0 -7
- package/dist/chunk-nOFOJqeH.js +0 -30
- package/dist/cloudwatch.transport-BO1ahxw-.js.map +0 -1
- package/dist/cloudwatch.transport-DZ6ies7g.mjs.map +0 -1
- package/dist/cloudwatch.transport-DsEq633o.d.ts.map +0 -1
- package/dist/cloudwatch.transport-UlyZFWMn.d.mts.map +0 -1
- package/dist/entry-fields-BJkuPnIg.mjs.map +0 -1
- package/dist/entry-fields-BvOLFlJ4.js.map +0 -1
- package/dist/gcp.transport-B7oc97sG.d.ts.map +0 -1
- package/dist/gcp.transport-CHV8MGgz.js.map +0 -1
- package/dist/gcp.transport-DBX5TPIy.mjs.map +0 -1
- package/dist/gcp.transport-GrJurKo8.d.mts.map +0 -1
- package/dist/index-3mw5gaCw.d.mts.map +0 -1
- package/dist/index-DhIoploR.d.ts.map +0 -1
- package/dist/internal-log-BUJYMZbE.js +0 -70
- package/dist/internal-log-BUJYMZbE.js.map +0 -1
- package/dist/internal-log-Cm8SOWSV.mjs +0 -52
- package/dist/internal-log-Cm8SOWSV.mjs.map +0 -1
- package/dist/logitron-logger-BFDSO8Io.d.mts.map +0 -1
- package/dist/logitron-logger-UVeN-mQm.d.ts.map +0 -1
- package/dist/safe-stringify-DJ66tW5I.mjs.map +0 -1
- package/dist/safe-stringify-DWo3aZp_.js.map +0 -1
- package/dist/search-BFbu_oVn.mjs.map +0 -1
- package/dist/search-C4V0OMEn.js.map +0 -1
- package/dist/search-CNh9uVwR.d.ts.map +0 -1
- package/dist/search-DXANsQ2n.d.mts.map +0 -1
- package/dist/slack.transport-BZzoXDPn.d.mts.map +0 -1
- package/dist/slack.transport-BfJRouB2.js.map +0 -1
- package/dist/slack.transport-Bzw7sucI.mjs.map +0 -1
- package/dist/slack.transport-CXjQYOes.d.ts.map +0 -1
- package/dist/trace.utils-CvXgaiQT.mjs.map +0 -1
- package/dist/trace.utils-DpBOLDtq.js.map +0 -1
- package/dist/transport.manager-BiuCAJd2.mjs.map +0 -1
- package/dist/transport.manager-CXbKKdVE.js.map +0 -1
- package/dist/transport.types-BMnurPcc.d.mts.map +0 -1
- package/dist/transport.types-CGoHpWQR.d.ts.map +0 -1
- package/dist/worker.transport-BdPxu3PN.js.map +0 -1
- package/dist/worker.transport-CdzSZJmw.d.ts.map +0 -1
- package/dist/worker.transport-JvGPog3C.d.mts.map +0 -1
- package/dist/worker.transport-lPxO2MVL.mjs.map +0 -1
package/dist/worker-entry.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// \0rolldown/runtime.js
|
|
2
2
|
var __create = Object.create;
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -15,26 +15,19 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
19
|
value: mod,
|
|
20
20
|
enumerable: true
|
|
21
21
|
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
22
|
let node_worker_threads = require("node:worker_threads");
|
|
25
|
-
node_worker_threads = __toESM(node_worker_threads);
|
|
26
23
|
let node_fs = require("node:fs");
|
|
27
24
|
node_fs = __toESM(node_fs);
|
|
28
25
|
let node_path = require("node:path");
|
|
29
26
|
node_path = __toESM(node_path);
|
|
30
27
|
let node_stream_promises = require("node:stream/promises");
|
|
31
|
-
node_stream_promises = __toESM(node_stream_promises);
|
|
32
28
|
let node_util = require("node:util");
|
|
33
|
-
node_util = __toESM(node_util);
|
|
34
29
|
let node_zlib = require("node:zlib");
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//#region src/utils/coerce.utils.ts
|
|
30
|
+
// src/utils/coerce.utils.ts
|
|
38
31
|
/**
|
|
39
32
|
* Defensive value coercion helpers for Logixia.
|
|
40
33
|
*
|
|
@@ -68,9 +61,55 @@ function safeToString(value) {
|
|
|
68
61
|
} catch {}
|
|
69
62
|
return `[${((_constructor = value.constructor) === null || _constructor === void 0 ? void 0 : _constructor.name) ?? "object"}]`;
|
|
70
63
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
// src/utils/own-property.ts
|
|
65
|
+
/**
|
|
66
|
+
* True for the one key that must never be assigned with `target[key] = value`.
|
|
67
|
+
*
|
|
68
|
+
* Assigning `constructor` or `prototype` on a fresh plain object only creates an
|
|
69
|
+
* own property, which is harmless. Only `__proto__` invokes the prototype setter.
|
|
70
|
+
*/
|
|
71
|
+
function isProtoKey(key) {
|
|
72
|
+
return key === "__proto__";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Copy `value` onto `target[key]` as an own, enumerable data property.
|
|
76
|
+
*
|
|
77
|
+
* Normal keys use a plain assignment, which is the fast path. `__proto__` goes
|
|
78
|
+
* through `Object.defineProperty` so that a key taken from logged or parsed data
|
|
79
|
+
* becomes an own property instead of replacing the object's prototype.
|
|
80
|
+
*/
|
|
81
|
+
function assignOwn(target, key, value) {
|
|
82
|
+
if (key === "__proto__") Object.defineProperty(target, key, {
|
|
83
|
+
value,
|
|
84
|
+
enumerable: true,
|
|
85
|
+
writable: true,
|
|
86
|
+
configurable: true
|
|
87
|
+
});
|
|
88
|
+
else target[key] = value;
|
|
89
|
+
}
|
|
90
|
+
// src/utils/safe-stringify.ts
|
|
91
|
+
/**
|
|
92
|
+
* logixia — robust JSON serialization for log payloads.
|
|
93
|
+
*
|
|
94
|
+
* Modern Winston/Pino already neutralize circular refs to `[Circular]` (via
|
|
95
|
+
* safe-stable-stringify / fast-safe-stringify), so merely "surviving cycles" is
|
|
96
|
+
* not a differentiator. This goes one notch further:
|
|
97
|
+
*
|
|
98
|
+
* - **BigInt** → serialized (as a string by default; JSON.stringify throws on
|
|
99
|
+
* BigInt, which silently breaks logging of e.g. DB bigint ids).
|
|
100
|
+
* - **Deterministic key order** (optional) so identical objects hash/diff equal.
|
|
101
|
+
* - **True decycle** (optional) — replace repeated references with JSONPath
|
|
102
|
+
* `$ref` pointers that round-trip back to the original object graph, instead
|
|
103
|
+
* of the lossy `[Circular]` tag. Useful when you need to reconstruct shared
|
|
104
|
+
* structure downstream.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* safeStringify({ id: 10n, self: obj }); // → BigInt + cycle safe
|
|
109
|
+
* safeStringify(graph, { decycle: true }); // → round-trippable $ref pointers
|
|
110
|
+
* const back = retrocycle(JSON.parse(json)); // → reconstruct shared refs
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
74
113
|
/** Build a JSONPath like `$["a"][0]["b"]` for a decycle pointer. */
|
|
75
114
|
function jsonPath(parts) {
|
|
76
115
|
let path = "$";
|
|
@@ -100,10 +139,7 @@ function safeStringify(value, options = {}) {
|
|
|
100
139
|
const rec = val;
|
|
101
140
|
const keys = deterministic ? Object.keys(rec).sort() : Object.keys(rec);
|
|
102
141
|
const obj = {};
|
|
103
|
-
for (const k of keys)
|
|
104
|
-
if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
|
|
105
|
-
obj[k] = transform(rec[k]);
|
|
106
|
-
}
|
|
142
|
+
for (const k of keys) assignOwn(obj, k, transform(rec[k]));
|
|
107
143
|
out = obj;
|
|
108
144
|
}
|
|
109
145
|
seen.delete(val);
|
|
@@ -128,10 +164,7 @@ function decycleValue(value, bigint = "string") {
|
|
|
128
164
|
if (Array.isArray(val)) return val.map((item, i) => walk(item, [...path, i]));
|
|
129
165
|
const rec = val;
|
|
130
166
|
const obj = {};
|
|
131
|
-
for (const k of Object.keys(rec))
|
|
132
|
-
if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
|
|
133
|
-
obj[k] = walk(rec[k], [...path, k]);
|
|
134
|
-
}
|
|
167
|
+
for (const k of Object.keys(rec)) assignOwn(obj, k, walk(rec[k], [...path, k]));
|
|
135
168
|
return obj;
|
|
136
169
|
};
|
|
137
170
|
return walk(value, []);
|
|
@@ -154,9 +187,7 @@ function stringifyForLog(value) {
|
|
|
154
187
|
}
|
|
155
188
|
}
|
|
156
189
|
}
|
|
157
|
-
|
|
158
|
-
//#endregion
|
|
159
|
-
//#region src/utils/sanitize.utils.ts
|
|
190
|
+
// src/utils/sanitize.utils.ts
|
|
160
191
|
/**
|
|
161
192
|
* Control-character stripping for text-mode log output.
|
|
162
193
|
*
|
|
@@ -172,11 +203,8 @@ const VISIBLE_ESCAPES = {
|
|
|
172
203
|
function stripControlChars(value) {
|
|
173
204
|
return value.replace(CONTROL_CHARS_RE, (ch) => VISIBLE_ESCAPES[ch] ?? "");
|
|
174
205
|
}
|
|
175
|
-
|
|
176
|
-
//#endregion
|
|
177
|
-
//#region src/transports/entry-fields.ts
|
|
206
|
+
// src/transports/entry-fields.ts
|
|
178
207
|
const PAYLOAD_PREFIX = "data_";
|
|
179
|
-
const UNSAFE_KEYS = new Set(["__proto__"]);
|
|
180
208
|
/**
|
|
181
209
|
* Copies `core` and then the user payload into one object. The core fields stay
|
|
182
210
|
* authoritative: a payload key that matches a core key (even one whose value is
|
|
@@ -184,14 +212,19 @@ const UNSAFE_KEYS = new Set(["__proto__"]);
|
|
|
184
212
|
* prefix is repeated until the name is free of core keys and of every other
|
|
185
213
|
* payload key, so the result does not depend on key order and a payload's own
|
|
186
214
|
* `data_level` stays where it is.
|
|
215
|
+
*
|
|
216
|
+
* Exception: a payload `traceId` equal to the core `traceId` is a duplicate (the
|
|
217
|
+
* context middleware copies the trace id into the payload) and is dropped rather
|
|
218
|
+
* than emitted again as `data_traceId`. A different value is still kept.
|
|
187
219
|
*/
|
|
188
220
|
function mergeCoreFields(core, data, extraReserved = []) {
|
|
189
221
|
const merged = { ...core };
|
|
190
222
|
if (!data) return merged;
|
|
191
|
-
const reserved = new Set([...Object.keys(core), ...extraReserved]);
|
|
223
|
+
const reserved = /* @__PURE__ */ new Set([...Object.keys(core), ...extraReserved]);
|
|
192
224
|
const payloadKeys = new Set(Object.keys(data));
|
|
193
225
|
for (const key of payloadKeys) {
|
|
194
|
-
if (
|
|
226
|
+
if (isProtoKey(key)) continue;
|
|
227
|
+
if (key === "traceId" && core["traceId"] !== void 0 && data[key] === core["traceId"]) continue;
|
|
195
228
|
let target = key;
|
|
196
229
|
if (reserved.has(target)) do
|
|
197
230
|
target = `${PAYLOAD_PREFIX}${target}`;
|
|
@@ -200,9 +233,7 @@ function mergeCoreFields(core, data, extraReserved = []) {
|
|
|
200
233
|
}
|
|
201
234
|
return merged;
|
|
202
235
|
}
|
|
203
|
-
|
|
204
|
-
//#endregion
|
|
205
|
-
//#region src/transports/console.transport.ts
|
|
236
|
+
// src/transports/console.transport.ts
|
|
206
237
|
/**
|
|
207
238
|
* Writes log entries to stdout (info/debug/verbose) and stderr (error/warn).
|
|
208
239
|
*
|
|
@@ -212,32 +243,13 @@ function mergeCoreFields(core, data, extraReserved = []) {
|
|
|
212
243
|
* transports: { console: { format: 'json' } }
|
|
213
244
|
*/
|
|
214
245
|
var ConsoleTransport = class ConsoleTransport {
|
|
215
|
-
static #_ = this.COLORS = new Map([
|
|
216
|
-
["black", "\x1B[30m"],
|
|
217
|
-
["red", "\x1B[31m"],
|
|
218
|
-
["green", "\x1B[32m"],
|
|
219
|
-
["yellow", "\x1B[33m"],
|
|
220
|
-
["blue", "\x1B[34m"],
|
|
221
|
-
["magenta", "\x1B[35m"],
|
|
222
|
-
["cyan", "\x1B[36m"],
|
|
223
|
-
["white", "\x1B[37m"],
|
|
224
|
-
["gray", "\x1B[90m"],
|
|
225
|
-
["grey", "\x1B[90m"],
|
|
226
|
-
["brightred", "\x1B[91m"],
|
|
227
|
-
["brightgreen", "\x1B[92m"],
|
|
228
|
-
["brightyellow", "\x1B[93m"],
|
|
229
|
-
["brightblue", "\x1B[94m"],
|
|
230
|
-
["brightmagenta", "\x1B[95m"],
|
|
231
|
-
["brightcyan", "\x1B[96m"],
|
|
232
|
-
["brightwhite", "\x1B[97m"],
|
|
233
|
-
["reset", "\x1B[0m"]
|
|
234
|
-
]);
|
|
235
246
|
static sanitize(value) {
|
|
236
247
|
return stripControlChars(safeToString(value));
|
|
237
248
|
}
|
|
238
249
|
constructor(config = {}) {
|
|
239
250
|
this.config = config;
|
|
240
251
|
this.name = "console";
|
|
252
|
+
this.level = config.level;
|
|
241
253
|
if (config.filter) this.filter = config.filter;
|
|
242
254
|
}
|
|
243
255
|
write(entry) {
|
|
@@ -300,10 +312,28 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
300
312
|
close() {
|
|
301
313
|
return Promise.resolve();
|
|
302
314
|
}
|
|
315
|
+
static #_ = () => this.COLORS = /* @__PURE__ */ new Map([
|
|
316
|
+
["black", "\x1B[30m"],
|
|
317
|
+
["red", "\x1B[31m"],
|
|
318
|
+
["green", "\x1B[32m"],
|
|
319
|
+
["yellow", "\x1B[33m"],
|
|
320
|
+
["blue", "\x1B[34m"],
|
|
321
|
+
["magenta", "\x1B[35m"],
|
|
322
|
+
["cyan", "\x1B[36m"],
|
|
323
|
+
["white", "\x1B[37m"],
|
|
324
|
+
["gray", "\x1B[90m"],
|
|
325
|
+
["grey", "\x1B[90m"],
|
|
326
|
+
["brightred", "\x1B[91m"],
|
|
327
|
+
["brightgreen", "\x1B[92m"],
|
|
328
|
+
["brightyellow", "\x1B[93m"],
|
|
329
|
+
["brightblue", "\x1B[94m"],
|
|
330
|
+
["brightmagenta", "\x1B[95m"],
|
|
331
|
+
["brightcyan", "\x1B[96m"],
|
|
332
|
+
["brightwhite", "\x1B[97m"],
|
|
333
|
+
["reset", "\x1B[0m"]
|
|
334
|
+
]);
|
|
303
335
|
};
|
|
304
|
-
|
|
305
|
-
//#endregion
|
|
306
|
-
//#region src/utils/internal-log.ts
|
|
336
|
+
// src/utils/internal-log.ts
|
|
307
337
|
/**
|
|
308
338
|
* Internal logging helpers for use within the logixia library itself.
|
|
309
339
|
*
|
|
@@ -322,14 +352,26 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
322
352
|
* behavior was previously unreliable because the value was frozen at load.
|
|
323
353
|
*/
|
|
324
354
|
function isSilent() {
|
|
325
|
-
|
|
355
|
+
var _process$env;
|
|
356
|
+
if (typeof process !== "undefined" && ((_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.LOGIXIA_SILENT_INTERNAL) === "1") return true;
|
|
357
|
+
const flag = globalThis["LOGIXIA_SILENT_INTERNAL"];
|
|
358
|
+
return flag === "1" || flag === 1 || flag === true;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Write a line to stderr, falling back to the matching console method where
|
|
362
|
+
* `process` is unavailable (browsers, Cloudflare Workers, Deno without Node compat).
|
|
363
|
+
*/
|
|
364
|
+
function writeLine(method, line) {
|
|
365
|
+
var _process$stderr;
|
|
366
|
+
if (typeof process !== "undefined" && typeof ((_process$stderr = process.stderr) === null || _process$stderr === void 0 ? void 0 : _process$stderr.write) === "function") process.stderr.write(`${line}\n`);
|
|
367
|
+
else if (typeof console !== "undefined" && typeof console[method] === "function") console[method](line);
|
|
326
368
|
}
|
|
327
369
|
/**
|
|
328
370
|
* Emit an internal warning to stderr.
|
|
329
371
|
* Use when something is misconfigured but logixia can continue operating.
|
|
330
372
|
*/
|
|
331
373
|
function internalWarn(message) {
|
|
332
|
-
if (!isSilent())
|
|
374
|
+
if (!isSilent()) writeLine("warn", `[logixia:warn] ${message}`);
|
|
333
375
|
}
|
|
334
376
|
/**
|
|
335
377
|
* Emit an internal error to stderr.
|
|
@@ -340,12 +382,10 @@ function internalError(message, error) {
|
|
|
340
382
|
let errStr = "";
|
|
341
383
|
if (error instanceof Error) errStr = ` — ${error.message}`;
|
|
342
384
|
else if (error != null) errStr = ` — ${String(error)}`;
|
|
343
|
-
|
|
385
|
+
writeLine("error", `[logixia:error] ${message}${errStr}`);
|
|
344
386
|
}
|
|
345
387
|
}
|
|
346
|
-
|
|
347
|
-
//#endregion
|
|
348
|
-
//#region src/transports/buffer-cap.ts
|
|
388
|
+
// src/transports/buffer-cap.ts
|
|
349
389
|
const DEFAULT_BUFFER_CAP = 1e4;
|
|
350
390
|
const DROP_WARN_INTERVAL_MS$1 = 5e3;
|
|
351
391
|
/**
|
|
@@ -361,8 +401,10 @@ var BufferCap = class {
|
|
|
361
401
|
this.dropped = 0;
|
|
362
402
|
this.lastWarning = 0;
|
|
363
403
|
let max = fallback;
|
|
364
|
-
if (requested !== void 0)
|
|
365
|
-
|
|
404
|
+
if (requested !== void 0) {
|
|
405
|
+
if (Number.isInteger(requested) && requested >= 1) max = requested;
|
|
406
|
+
else internalWarn(`${name}: maxBufferSize ${String(requested)} is not a positive integer; using ${fallback}`);
|
|
407
|
+
}
|
|
366
408
|
this.max = Math.max(max, batchSize);
|
|
367
409
|
}
|
|
368
410
|
/** Drops the oldest items beyond the cap, in place. */
|
|
@@ -384,9 +426,256 @@ var BufferCap = class {
|
|
|
384
426
|
this.lastWarning = now;
|
|
385
427
|
}
|
|
386
428
|
};
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
429
|
+
// src/utils/sensitive-names.ts
|
|
430
|
+
/**
|
|
431
|
+
* The one list of sensitive names. Log redaction (redact.utils), the HTTP logger
|
|
432
|
+
* middleware and transport secret handling (transports/secret-config) all read it,
|
|
433
|
+
* so the lists cannot drift. No imports: safe from any module, including browser code.
|
|
434
|
+
*/
|
|
435
|
+
/** Field names redacted by name, wherever they appear in logged data. */
|
|
436
|
+
const SENSITIVE_KEY_NAMES = [
|
|
437
|
+
"password",
|
|
438
|
+
"passwd",
|
|
439
|
+
"secret",
|
|
440
|
+
"token",
|
|
441
|
+
"apiKey",
|
|
442
|
+
"api_key",
|
|
443
|
+
"accessToken",
|
|
444
|
+
"access_token",
|
|
445
|
+
"refreshToken",
|
|
446
|
+
"refresh_token",
|
|
447
|
+
"authorization",
|
|
448
|
+
"credentials",
|
|
449
|
+
"privateKey",
|
|
450
|
+
"private_key",
|
|
451
|
+
"clientSecret",
|
|
452
|
+
"client_secret",
|
|
453
|
+
"cookie",
|
|
454
|
+
"set-cookie",
|
|
455
|
+
"x-api-key",
|
|
456
|
+
"session",
|
|
457
|
+
"proxy-authorization",
|
|
458
|
+
"x-auth-token",
|
|
459
|
+
"x-access-token",
|
|
460
|
+
"aws_secret_access_key",
|
|
461
|
+
"awsSecretAccessKey",
|
|
462
|
+
"secretAccessKey"
|
|
463
|
+
];
|
|
464
|
+
/**
|
|
465
|
+
* Extra names that only mean "secret" inside transport configuration, where
|
|
466
|
+
* short words like `key` or `signature` are credentials, not log fields.
|
|
467
|
+
*/
|
|
468
|
+
const TRANSPORT_CONFIG_SECRET_NAMES = [
|
|
469
|
+
"writeKey",
|
|
470
|
+
"apiSecret",
|
|
471
|
+
"connectionString",
|
|
472
|
+
"sessionToken",
|
|
473
|
+
"passphrase",
|
|
474
|
+
"signature",
|
|
475
|
+
"pwd",
|
|
476
|
+
"pfx",
|
|
477
|
+
"cert",
|
|
478
|
+
"key",
|
|
479
|
+
"auth"
|
|
480
|
+
];
|
|
481
|
+
/** Query-string parameters whose values are never logged. */
|
|
482
|
+
const DEFAULT_REDACT_QUERY_PARAMS = [
|
|
483
|
+
"token",
|
|
484
|
+
"access_token",
|
|
485
|
+
"refresh_token",
|
|
486
|
+
"code",
|
|
487
|
+
"password",
|
|
488
|
+
"secret",
|
|
489
|
+
"api_key",
|
|
490
|
+
"apikey",
|
|
491
|
+
"key",
|
|
492
|
+
"signature",
|
|
493
|
+
"sig",
|
|
494
|
+
"auth"
|
|
495
|
+
];
|
|
496
|
+
// src/transports/secret-config.ts
|
|
497
|
+
/**
|
|
498
|
+
* Keeps credentials out of serialized transport output and error text.
|
|
499
|
+
*
|
|
500
|
+
* `protectSecrets()` replaces each listed field with a non-enumerable accessor backed
|
|
501
|
+
* by a WeakMap, whether or not the field is assigned yet, so later assignments (a
|
|
502
|
+
* connection opened on first write, a refreshed token) stay hidden too. It also
|
|
503
|
+
* installs `toJSON()` and a Node inspect hook returning a redacted view: scalar
|
|
504
|
+
* fields stay for debugging, secret-looking keys become '[REDACTED]', URLs lose
|
|
505
|
+
* userinfo, query and fragment. No Node imports, so browser bundles can use it.
|
|
506
|
+
*/
|
|
507
|
+
const REDACTED = "[REDACTED]";
|
|
508
|
+
const INSPECT_CUSTOM = Symbol.for("nodejs.util.inspect.custom");
|
|
509
|
+
const MAX_DEPTH = 4;
|
|
510
|
+
const MIN_SECRET_LENGTH = 4;
|
|
511
|
+
const SCHEME_PREFIX = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
512
|
+
/** `scheme://userinfo@`: userinfo runs to the LAST `@` before the path, so `p@ss` is covered. */
|
|
513
|
+
const USERINFO = /(\b[a-z][a-z0-9+.-]*:\/\/)[^\s/?#]*@/gi;
|
|
514
|
+
function normalizeName(name) {
|
|
515
|
+
return name.toLowerCase().replaceAll("-", "").replaceAll("_", "");
|
|
516
|
+
}
|
|
517
|
+
const SECRET_NAMES = [...SENSITIVE_KEY_NAMES, ...TRANSPORT_CONFIG_SECRET_NAMES].map(normalizeName);
|
|
518
|
+
const QUERY_NAMES = new Set(DEFAULT_REDACT_QUERY_PARAMS.map(normalizeName));
|
|
519
|
+
/** Exact match for short names (`key`, `pfx`), suffix match for longer ones (`azureClientSecret`). */
|
|
520
|
+
function isSecretKey(key) {
|
|
521
|
+
const name = normalizeName(key);
|
|
522
|
+
return SECRET_NAMES.some((n) => name === n || n.length >= 5 && name.endsWith(n));
|
|
523
|
+
}
|
|
524
|
+
function isUrlKey(key) {
|
|
525
|
+
return /url|uri|endpoint|href/i.test(key);
|
|
526
|
+
}
|
|
527
|
+
function isPlainObject(value) {
|
|
528
|
+
const proto = Object.getPrototypeOf(value);
|
|
529
|
+
return proto === Object.prototype || proto === null;
|
|
530
|
+
}
|
|
531
|
+
function safeDecode(value) {
|
|
532
|
+
try {
|
|
533
|
+
return decodeURIComponent(value.replaceAll("+", " "));
|
|
534
|
+
} catch {
|
|
535
|
+
return value;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
/** Absolute URL: `scheme://host` only. Relative or unparseable: path kept, query and fragment cut. */
|
|
539
|
+
function redactUrl(raw) {
|
|
540
|
+
if (typeof raw !== "string") return `${raw.protocol}//${raw.host}`;
|
|
541
|
+
if (SCHEME_PREFIX.test(raw)) try {
|
|
542
|
+
const url = new URL(raw);
|
|
543
|
+
return `${url.protocol}//${url.host}`;
|
|
544
|
+
} catch {
|
|
545
|
+
return REDACTED;
|
|
546
|
+
}
|
|
547
|
+
return raw.split(/[?#]/, 1)[0] ?? "";
|
|
548
|
+
}
|
|
549
|
+
function redactHeaders(headers) {
|
|
550
|
+
if (!headers || typeof headers !== "object") return headers;
|
|
551
|
+
return Object.fromEntries(Object.keys(headers).map((name) => [name, REDACTED]));
|
|
552
|
+
}
|
|
553
|
+
/** Redacted deep copy of a config-like value. Never throws, never returns a secret. */
|
|
554
|
+
function redactConfig(value, depth = 0, key = "") {
|
|
555
|
+
var _value$constructor;
|
|
556
|
+
if (value === null || value === void 0) return value;
|
|
557
|
+
if (typeof value === "string") return SCHEME_PREFIX.test(value) || isUrlKey(key) ? redactUrl(value) : value;
|
|
558
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
559
|
+
if (typeof value === "function") return "[Function]";
|
|
560
|
+
if (typeof value !== "object") return "[Unserializable]";
|
|
561
|
+
if (typeof URL !== "undefined" && value instanceof URL) return redactUrl(value);
|
|
562
|
+
if (Array.isArray(value)) return depth >= MAX_DEPTH ? "[Array]" : value.map((v) => redactConfig(v, depth + 1, key));
|
|
563
|
+
if (!isPlainObject(value) || depth >= MAX_DEPTH) return `[${((_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name) ?? "Object"}]`;
|
|
564
|
+
const out = {};
|
|
565
|
+
for (const [name, inner] of Object.entries(value)) if (isSecretKey(name)) assignOwn(out, name, inner === void 0 ? void 0 : REDACTED);
|
|
566
|
+
else if (name.toLowerCase() === "headers") assignOwn(out, name, redactHeaders(inner));
|
|
567
|
+
else assignOwn(out, name, redactConfig(inner, depth + 1, name));
|
|
568
|
+
return out;
|
|
569
|
+
}
|
|
570
|
+
const hiddenKeys = /* @__PURE__ */ new WeakMap();
|
|
571
|
+
const hiddenValues = /* @__PURE__ */ new WeakMap();
|
|
572
|
+
function viewOf(target) {
|
|
573
|
+
var _target$constructor;
|
|
574
|
+
const hidden = hiddenKeys.get(target) ?? /* @__PURE__ */ new Set();
|
|
575
|
+
const values = hiddenValues.get(target);
|
|
576
|
+
const view = { class: (_target$constructor = target.constructor) === null || _target$constructor === void 0 ? void 0 : _target$constructor.name };
|
|
577
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(target), ...hidden])) {
|
|
578
|
+
const inner = hidden.has(key) ? values === null || values === void 0 ? void 0 : values.get(key) : target[key];
|
|
579
|
+
if (isSecretKey(key)) view[key] = inner === void 0 ? void 0 : REDACTED;
|
|
580
|
+
else if (key.toLowerCase() === "headers") view[key] = redactHeaders(inner);
|
|
581
|
+
else if (inner !== null && typeof inner === "object" && !hidden.has(key) && !(inner instanceof URL)) view[key] = "[Object]";
|
|
582
|
+
else if (hidden.has(key) && typeof inner === "string" && !isUrlKey(key)) view[key] = REDACTED;
|
|
583
|
+
else view[key] = redactConfig(inner, 0, key);
|
|
584
|
+
}
|
|
585
|
+
return view;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Hides `keys` on `target` (assigned or not yet) and gives it a redacted `toJSON()` /
|
|
589
|
+
* inspect view. Fields stay readable and writable. Safe to call more than once.
|
|
590
|
+
* Throws when the target cannot carry the protection (frozen or sealed), instead of
|
|
591
|
+
* silently leaving the secret enumerable.
|
|
592
|
+
*/
|
|
593
|
+
function protectSecrets(target, keys) {
|
|
594
|
+
if (!Object.isExtensible(target)) {
|
|
595
|
+
var _target$constructor2;
|
|
596
|
+
throw new TypeError(`protectSecrets: ${((_target$constructor2 = target.constructor) === null || _target$constructor2 === void 0 ? void 0 : _target$constructor2.name) ?? "object"} is not extensible`);
|
|
597
|
+
}
|
|
598
|
+
let hidden = hiddenKeys.get(target);
|
|
599
|
+
let values = hiddenValues.get(target);
|
|
600
|
+
if (!hidden || !values) {
|
|
601
|
+
hidden = /* @__PURE__ */ new Set();
|
|
602
|
+
values = /* @__PURE__ */ new Map();
|
|
603
|
+
hiddenKeys.set(target, hidden);
|
|
604
|
+
hiddenValues.set(target, values);
|
|
605
|
+
const view = () => viewOf(target);
|
|
606
|
+
Object.defineProperty(target, "toJSON", {
|
|
607
|
+
value: view,
|
|
608
|
+
enumerable: false,
|
|
609
|
+
configurable: true
|
|
610
|
+
});
|
|
611
|
+
Object.defineProperty(target, INSPECT_CUSTOM, {
|
|
612
|
+
value: view,
|
|
613
|
+
enumerable: false,
|
|
614
|
+
configurable: true
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
const store = values;
|
|
618
|
+
for (const key of keys) {
|
|
619
|
+
if (hidden.has(key)) continue;
|
|
620
|
+
const desc = Object.getOwnPropertyDescriptor(target, key);
|
|
621
|
+
if (desc && !desc.configurable) throw new TypeError(`protectSecrets: "${key}" is not configurable`);
|
|
622
|
+
if (desc && "value" in desc) store.set(key, desc.value);
|
|
623
|
+
hidden.add(key);
|
|
624
|
+
Object.defineProperty(target, key, {
|
|
625
|
+
enumerable: false,
|
|
626
|
+
configurable: true,
|
|
627
|
+
get: () => store.get(key),
|
|
628
|
+
set: (next) => void store.set(key, next)
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
/** The raw, decoded and percent-encoded spellings of a secret. */
|
|
633
|
+
function variantsOf(secret) {
|
|
634
|
+
return [
|
|
635
|
+
secret,
|
|
636
|
+
safeDecode(secret),
|
|
637
|
+
encodeURIComponent(secret),
|
|
638
|
+
encodeURI(secret)
|
|
639
|
+
];
|
|
640
|
+
}
|
|
641
|
+
/** Secret parts of a URL string: the password and the values of sensitive query parameters. */
|
|
642
|
+
function urlSecrets(raw) {
|
|
643
|
+
const text = typeof raw === "string" ? raw : raw.href;
|
|
644
|
+
const out = [];
|
|
645
|
+
const userinfo = new RegExp(USERINFO.source, "i").exec(text);
|
|
646
|
+
if (userinfo) {
|
|
647
|
+
const info = text.slice(userinfo[1].length, userinfo.index + userinfo[0].length - 1);
|
|
648
|
+
const colon = info.indexOf(":");
|
|
649
|
+
if (colon !== -1) out.push(info.slice(colon + 1));
|
|
650
|
+
}
|
|
651
|
+
const queryStart = text.indexOf("?");
|
|
652
|
+
if (queryStart !== -1) {
|
|
653
|
+
const query = text.slice(queryStart + 1).split("#", 1)[0] ?? "";
|
|
654
|
+
for (const pair of query.split("&")) {
|
|
655
|
+
const eq = pair.indexOf("=");
|
|
656
|
+
if (eq > 0 && QUERY_NAMES.has(normalizeName(safeDecode(pair.slice(0, eq))))) out.push(pair.slice(eq + 1));
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return out.flatMap(variantsOf);
|
|
660
|
+
}
|
|
661
|
+
/** Replaces URL userinfo and every spelling of the given secret values in `text`. */
|
|
662
|
+
function scrubSecrets(text, secrets) {
|
|
663
|
+
let out = text.replace(USERINFO, `$1${REDACTED}@`);
|
|
664
|
+
const all = new Set(secrets.flatMap((s) => s && s.length >= MIN_SECRET_LENGTH ? variantsOf(s) : []));
|
|
665
|
+
for (const secret of [...all].sort((a, b) => b.length - a.length)) if (secret.length >= MIN_SECRET_LENGTH) out = out.split(secret).join(REDACTED);
|
|
666
|
+
return out;
|
|
667
|
+
}
|
|
668
|
+
/** Scrubs message, stack and the cause chain of `err` in place; returns it. */
|
|
669
|
+
function scrubError(err, secrets, depth = 0) {
|
|
670
|
+
if (!(err instanceof Error) || depth > 3) return err;
|
|
671
|
+
try {
|
|
672
|
+
err.message = scrubSecrets(err.message, secrets);
|
|
673
|
+
if (err.stack) err.stack = scrubSecrets(err.stack, secrets);
|
|
674
|
+
scrubError(err.cause, secrets, depth + 1);
|
|
675
|
+
} catch {}
|
|
676
|
+
return err;
|
|
677
|
+
}
|
|
678
|
+
// src/transports/database.transport.ts
|
|
390
679
|
/**
|
|
391
680
|
* Validates that a SQL identifier (table/index name) contains only safe characters.
|
|
392
681
|
* Prevents SQL injection via user-supplied table names.
|
|
@@ -409,7 +698,7 @@ const PG_DATA_CLASSES = [
|
|
|
409
698
|
"23",
|
|
410
699
|
"54"
|
|
411
700
|
];
|
|
412
|
-
const MYSQL_DATA_CODES = new Set([
|
|
701
|
+
const MYSQL_DATA_CODES = /* @__PURE__ */ new Set([
|
|
413
702
|
"ER_DATA_TOO_LONG",
|
|
414
703
|
"ER_TRUNCATED_WRONG_VALUE",
|
|
415
704
|
"ER_TRUNCATED_WRONG_VALUE_FOR_FIELD",
|
|
@@ -419,7 +708,7 @@ const MYSQL_DATA_CODES = new Set([
|
|
|
419
708
|
"ER_INVALID_JSON_TEXT",
|
|
420
709
|
"ER_INVALID_CHARACTER_STRING"
|
|
421
710
|
]);
|
|
422
|
-
const MYSQL_DATA_ERRNOS = new Set([
|
|
711
|
+
const MYSQL_DATA_ERRNOS = /* @__PURE__ */ new Set([
|
|
423
712
|
1048,
|
|
424
713
|
1062,
|
|
425
714
|
1264,
|
|
@@ -428,12 +717,12 @@ const MYSQL_DATA_ERRNOS = new Set([
|
|
|
428
717
|
1406,
|
|
429
718
|
3140
|
|
430
719
|
]);
|
|
431
|
-
const SQLITE_DATA_CODES = new Set([
|
|
720
|
+
const SQLITE_DATA_CODES = /* @__PURE__ */ new Set([
|
|
432
721
|
"SQLITE_CONSTRAINT",
|
|
433
722
|
"SQLITE_TOOBIG",
|
|
434
723
|
"SQLITE_MISMATCH"
|
|
435
724
|
]);
|
|
436
|
-
const MONGO_DATA_CODES = new Set([
|
|
725
|
+
const MONGO_DATA_CODES = /* @__PURE__ */ new Set([
|
|
437
726
|
2,
|
|
438
727
|
121,
|
|
439
728
|
10334,
|
|
@@ -495,13 +784,23 @@ var DatabaseTransport = class {
|
|
|
495
784
|
this.name = "database";
|
|
496
785
|
this.batch = [];
|
|
497
786
|
this.isConnected = false;
|
|
787
|
+
protectSecrets(this, ["config", "connection"]);
|
|
498
788
|
this.batchSize = config.batchSize || 100;
|
|
499
789
|
this.flushInterval = config.flushInterval || 5e3;
|
|
500
790
|
this.cap = new BufferCap("DatabaseTransport", config.maxBufferSize, this.batchSize);
|
|
791
|
+
this.level = config.level;
|
|
501
792
|
if (config.filter) this.filter = config.filter;
|
|
502
793
|
if (config.table) validateSqlIdentifier(config.table, "table");
|
|
503
794
|
this.setupFlushTimer();
|
|
504
795
|
}
|
|
796
|
+
secretValues() {
|
|
797
|
+
const { connectionString, password } = this.config;
|
|
798
|
+
return [
|
|
799
|
+
connectionString,
|
|
800
|
+
password,
|
|
801
|
+
...connectionString ? urlSecrets(connectionString) : []
|
|
802
|
+
];
|
|
803
|
+
}
|
|
505
804
|
async write(entry) {
|
|
506
805
|
if (!this.isConnected) await this.connect();
|
|
507
806
|
this.addToBatch(entry);
|
|
@@ -562,6 +861,13 @@ var DatabaseTransport = class {
|
|
|
562
861
|
this.cap.enforce(this.batch);
|
|
563
862
|
}
|
|
564
863
|
async writeEntries(entries) {
|
|
864
|
+
try {
|
|
865
|
+
await this.writeEntriesUnscrubbed(entries);
|
|
866
|
+
} catch (error) {
|
|
867
|
+
throw scrubError(error, this.secretValues());
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
async writeEntriesUnscrubbed(entries) {
|
|
565
871
|
switch (this.config.type) {
|
|
566
872
|
case "mongodb":
|
|
567
873
|
await this.flushToMongoDB(entries);
|
|
@@ -640,13 +946,12 @@ var DatabaseTransport = class {
|
|
|
640
946
|
case "mysql":
|
|
641
947
|
await this.connectMySQL();
|
|
642
948
|
break;
|
|
643
|
-
case "sqlite":
|
|
644
|
-
await this.connectSQLite();
|
|
645
|
-
break;
|
|
949
|
+
case "sqlite": await this.connectSQLite();
|
|
646
950
|
}
|
|
647
951
|
this.isConnected = true;
|
|
648
952
|
} catch (error) {
|
|
649
953
|
this.isConnected = false;
|
|
954
|
+
scrubError(error, this.secretValues());
|
|
650
955
|
throw new Error(`Database connection failed: ${error}`, { cause: error });
|
|
651
956
|
}
|
|
652
957
|
}
|
|
@@ -655,7 +960,8 @@ var DatabaseTransport = class {
|
|
|
655
960
|
const { MongoClient } = await import("mongodb").catch(() => {
|
|
656
961
|
throw new Error("MongoDB driver not installed. Run: npm install mongodb");
|
|
657
962
|
});
|
|
658
|
-
|
|
963
|
+
const connectionString = this.config.connectionString || `mongodb://${this.config.host}:${this.config.port}/${this.config.database}`;
|
|
964
|
+
this.connection = new MongoClient(connectionString);
|
|
659
965
|
await this.connection.connect();
|
|
660
966
|
await this.connection.db(this.config.database).admin().ping();
|
|
661
967
|
} catch (error) {
|
|
@@ -767,12 +1073,13 @@ var DatabaseTransport = class {
|
|
|
767
1073
|
entry.environment
|
|
768
1074
|
].map((value, column) => stripNul(column === 3 ? stripJsonNulEscape(value) : value))), POSTGRES_ROWS_PER_INSERT);
|
|
769
1075
|
const insertChunk = async (rows) => {
|
|
1076
|
+
const placeholders = rows.map((_, i) => {
|
|
1077
|
+
return `(${Array.from({ length: POSTGRES_COLUMNS }, (_unused, c) => `$${i * POSTGRES_COLUMNS + c + 1}`).join(", ")})`;
|
|
1078
|
+
}).join(", ");
|
|
770
1079
|
const query = `
|
|
771
1080
|
INSERT INTO ${tableName}
|
|
772
1081
|
(timestamp, level, message, payload, context, trace_id, app_name, environment)
|
|
773
|
-
VALUES ${
|
|
774
|
-
return `(${Array.from({ length: POSTGRES_COLUMNS }, (_unused, c) => `$${i * POSTGRES_COLUMNS + c + 1}`).join(", ")})`;
|
|
775
|
-
}).join(", ")}
|
|
1082
|
+
VALUES ${placeholders}
|
|
776
1083
|
`;
|
|
777
1084
|
await this.connection.query(query, rows.flat());
|
|
778
1085
|
};
|
|
@@ -936,9 +1243,7 @@ var DatabaseTransport = class {
|
|
|
936
1243
|
case "mysql":
|
|
937
1244
|
await this.connection.end();
|
|
938
1245
|
break;
|
|
939
|
-
case "sqlite":
|
|
940
|
-
await this.connection.close();
|
|
941
|
-
break;
|
|
1246
|
+
case "sqlite": await this.connection.close();
|
|
942
1247
|
}
|
|
943
1248
|
this.isConnected = false;
|
|
944
1249
|
}
|
|
@@ -979,9 +1284,7 @@ var DatabaseTransport = class {
|
|
|
979
1284
|
}
|
|
980
1285
|
}
|
|
981
1286
|
};
|
|
982
|
-
|
|
983
|
-
//#endregion
|
|
984
|
-
//#region src/transports/file.transport.ts
|
|
1287
|
+
// src/transports/file.transport.ts
|
|
985
1288
|
const appendFile = (0, node_util.promisify)(node_fs.appendFile);
|
|
986
1289
|
const rename = (0, node_util.promisify)(node_fs.rename);
|
|
987
1290
|
const unlink = (0, node_util.promisify)(node_fs.unlink);
|
|
@@ -1244,7 +1547,6 @@ var FileTransport = class {
|
|
|
1244
1547
|
csvField(entry.traceId),
|
|
1245
1548
|
csvField(stringifyForLog(entry.data || {}))
|
|
1246
1549
|
].join(",");
|
|
1247
|
-
case "text":
|
|
1248
1550
|
default: return `${entry.timestamp.toISOString()} [${stripControlChars(safeToString(entry.level)).toUpperCase()}] ${stripControlChars(safeToString(entry.message))}${entry.data ? " " + stringifyForLog(entry.data) : ""}`;
|
|
1249
1551
|
}
|
|
1250
1552
|
}
|
|
@@ -1270,22 +1572,22 @@ var FileTransport = class {
|
|
|
1270
1572
|
await this.append(content);
|
|
1271
1573
|
return;
|
|
1272
1574
|
}
|
|
1273
|
-
let chunk
|
|
1575
|
+
let chunk = "";
|
|
1274
1576
|
let chunkBytes = 0;
|
|
1275
1577
|
for (const entry of entries) {
|
|
1276
1578
|
const line = this.formatEntry(entry) + "\n";
|
|
1277
1579
|
const lineBytes = Buffer.byteLength(line);
|
|
1278
1580
|
const used = this.bytesWritten + chunkBytes;
|
|
1279
1581
|
if (used > 0 && used + lineBytes > this.maxBytes) {
|
|
1280
|
-
if (chunk
|
|
1281
|
-
chunk
|
|
1582
|
+
if (chunk) await this.append(chunk, chunkBytes);
|
|
1583
|
+
chunk = "";
|
|
1282
1584
|
chunkBytes = 0;
|
|
1283
1585
|
await this.rotateFile();
|
|
1284
1586
|
}
|
|
1285
|
-
chunk
|
|
1587
|
+
chunk += line;
|
|
1286
1588
|
chunkBytes += lineBytes;
|
|
1287
1589
|
}
|
|
1288
|
-
if (chunk
|
|
1590
|
+
if (chunk) await this.append(chunk, chunkBytes);
|
|
1289
1591
|
}
|
|
1290
1592
|
async append(content, bytes = Buffer.byteLength(content)) {
|
|
1291
1593
|
await appendFile(this.currentFilePath, content, { mode: this.fileMode });
|
|
@@ -1314,7 +1616,7 @@ var FileTransport = class {
|
|
|
1314
1616
|
}
|
|
1315
1617
|
parseInterval(interval) {
|
|
1316
1618
|
const match = /^(\d{1,6})([hdwmy])$/i.exec(interval.trim());
|
|
1317
|
-
if (!match) return
|
|
1619
|
+
if (!match) return 864e5;
|
|
1318
1620
|
const value = Number.parseInt(match[1] || "1", 10);
|
|
1319
1621
|
switch ((match[2] || "h").toLowerCase()) {
|
|
1320
1622
|
case "h": return value * 60 * 60 * 1e3;
|
|
@@ -1429,12 +1731,41 @@ var FileTransport = class {
|
|
|
1429
1731
|
this.reportDropped(0);
|
|
1430
1732
|
}
|
|
1431
1733
|
};
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1734
|
+
// src/transports/level-filter.ts
|
|
1735
|
+
/** Severity values of the built-in levels; lower is more severe (same scale as the logger). */
|
|
1736
|
+
const BUILTIN_LEVEL_VALUES = {
|
|
1737
|
+
error: 0,
|
|
1738
|
+
warn: 1,
|
|
1739
|
+
info: 2,
|
|
1740
|
+
debug: 3,
|
|
1741
|
+
trace: 4,
|
|
1742
|
+
verbose: 5
|
|
1743
|
+
};
|
|
1744
|
+
/** Built-in levels plus the logger's custom `levelOptions.levels`. */
|
|
1745
|
+
function buildLevelValues(custom) {
|
|
1746
|
+
return new Map([...Object.entries(BUILTIN_LEVEL_VALUES), ...Object.entries(custom ?? {})]);
|
|
1747
|
+
}
|
|
1748
|
+
function lookup(values, level) {
|
|
1749
|
+
return values.get(level) ?? values.get(level.toLowerCase());
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Whether an entry at `level` passes a transport's minimum `threshold`, using the
|
|
1753
|
+
* logger's scale (an entry passes when its value is <= the threshold's value).
|
|
1754
|
+
* The logger has already rejected unknown entry levels, so an unknown entry level
|
|
1755
|
+
* or threshold here does not filter.
|
|
1756
|
+
*/
|
|
1757
|
+
function meetsTransportLevel(threshold, level, values) {
|
|
1758
|
+
if (!threshold) return true;
|
|
1759
|
+
const min = lookup(values, threshold);
|
|
1760
|
+
const actual = lookup(values, level);
|
|
1761
|
+
if (min === void 0 || actual === void 0) return true;
|
|
1762
|
+
return actual <= min;
|
|
1763
|
+
}
|
|
1764
|
+
// src/transports/worker-entry.ts
|
|
1435
1765
|
const port = node_worker_threads.parentPort;
|
|
1436
1766
|
if (!port) throw new Error("worker-entry must run inside a worker thread");
|
|
1437
|
-
const { transportType, transportConfig } = node_worker_threads.workerData;
|
|
1767
|
+
const { transportType, transportConfig, levels } = node_worker_threads.workerData;
|
|
1768
|
+
const levelValues = buildLevelValues(levels);
|
|
1438
1769
|
function createTransport() {
|
|
1439
1770
|
const config = transportConfig;
|
|
1440
1771
|
switch (transportType) {
|
|
@@ -1458,16 +1789,18 @@ const flushTransport = async () => {
|
|
|
1458
1789
|
if (typeof transport.flush === "function") await transport.flush();
|
|
1459
1790
|
};
|
|
1460
1791
|
async function handle(msg) {
|
|
1461
|
-
if (msg.type === "write")
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1792
|
+
if (msg.type === "write") {
|
|
1793
|
+
if (!meetsTransportLevel(transport.level, msg.entry.level, levelValues)) return;
|
|
1794
|
+
try {
|
|
1795
|
+
await transport.write(msg.entry);
|
|
1796
|
+
} catch (err) {
|
|
1797
|
+
port === null || port === void 0 || port.postMessage({
|
|
1798
|
+
type: "write-error",
|
|
1799
|
+
error: errorMessage(err),
|
|
1800
|
+
entry: msg.entry
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
} else if (msg.type === "flush") try {
|
|
1471
1804
|
await flushTransport();
|
|
1472
1805
|
port === null || port === void 0 || port.postMessage({ type: "flushed" });
|
|
1473
1806
|
} catch (err) {
|
|
@@ -1489,5 +1822,3 @@ port.on("message", (msg) => {
|
|
|
1489
1822
|
queue = queue.then(() => handle(msg));
|
|
1490
1823
|
});
|
|
1491
1824
|
port.postMessage({ type: "ready" });
|
|
1492
|
-
|
|
1493
|
-
//#endregion
|