logixia 2.0.8 → 2.0.10

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.
@@ -6,7 +6,6 @@ import { n as internalLog, r as internalWarn, t as internalError } from "./inter
6
6
  import { t as safeToString } from "./coerce.utils-B_rEudCn.mjs";
7
7
  import { i as stringifyForLog } from "./safe-stringify--7gbe95n.mjs";
8
8
  import { c as TransportManager, n as _getOtelPayloadIfEnabled, r as _isOtelBridgeEnabled, v as stripControlChars } from "./otel-DOuwGPCd.mjs";
9
- import buildFastStringify from "fast-json-stringify";
10
9
  import { constants } from "node:os";
11
10
  // src/types/index.ts
12
11
  const LogLevel = {
@@ -194,6 +193,16 @@ const EXTRA_FIELDS = [
194
193
  "port",
195
194
  "type"
196
195
  ];
196
+ const SKIPPED_FIELDS = /* @__PURE__ */ new Set([
197
+ "name",
198
+ "message",
199
+ "stack",
200
+ "cause",
201
+ "errors",
202
+ ...EXTRA_FIELDS
203
+ ]);
204
+ const NO_OPTIONS = Object.freeze({});
205
+ const NO_FIELDS = [];
197
206
  /**
198
207
  * Serialize an Error into a plain JSON-safe object, including:
199
208
  * - `name`, `message`, `stack`
@@ -202,8 +211,8 @@ const EXTRA_FIELDS = [
202
211
  * - standard Node.js error fields (`code`, `statusCode`, `errno`, …)
203
212
  * - any other enumerable own properties
204
213
  */
205
- function serializeError(error, options = {}) {
206
- const { includeStack = true, maxDepth = 5, excludeFields = [] } = options;
214
+ function serializeError(error, options = NO_OPTIONS) {
215
+ const { includeStack = true, maxDepth = 5, excludeFields = NO_FIELDS } = options;
207
216
  return _serializeError(error, includeStack, maxDepth, excludeFields, 0, /* @__PURE__ */ new WeakSet());
208
217
  }
209
218
  function _serializeError(error, includeStack, maxDepth, excludeFields, depth, seen) {
@@ -231,16 +240,8 @@ function _serializeError(error, includeStack, maxDepth, excludeFields, depth, se
231
240
  const aggregateError = error;
232
241
  if (Array.isArray(aggregateError.errors)) serialized.errors = aggregateError.errors.map((e) => e instanceof Error ? _serializeError(e, includeStack, maxDepth, excludeFields, depth + 1, seen) : serializeValue(e, maxDepth - depth - 1, seen));
233
242
  const errorRecord = error;
234
- for (const field of EXTRA_FIELDS) if (!excludeFields.includes(field) && field in error && errorRecord[field] !== void 0) serialized[field] = errorRecord[field];
235
- const skip = /* @__PURE__ */ new Set([
236
- "name",
237
- "message",
238
- "stack",
239
- "cause",
240
- "errors",
241
- ...EXTRA_FIELDS,
242
- ...excludeFields
243
- ]);
243
+ for (const field of EXTRA_FIELDS) if (!excludeFields.includes(field) && errorRecord[field] !== void 0) serialized[field] = errorRecord[field];
244
+ const skip = excludeFields.length === 0 ? SKIPPED_FIELDS : /* @__PURE__ */ new Set([...SKIPPED_FIELDS, ...excludeFields]);
244
245
  for (const key of Object.getOwnPropertyNames(error)) {
245
246
  if (skip.has(key)) continue;
246
247
  try {
@@ -1033,23 +1034,6 @@ function warnOnReservedLevelNames(levels) {
1033
1034
  * - Feature 4: Cause-chain error serialization (handled in error.utils)
1034
1035
  * - Feature 5: Adaptive log level based on NODE_ENV / CI detection
1035
1036
  */
1036
- const _fastStringifyEntry = buildFastStringify({
1037
- type: "object",
1038
- properties: {
1039
- timestamp: { type: "string" },
1040
- level: { type: "string" },
1041
- appName: { type: "string" },
1042
- environment: { type: "string" },
1043
- message: { type: "string" },
1044
- context: { type: "string" },
1045
- traceId: { type: "string" },
1046
- payload: {
1047
- type: "object",
1048
- additionalProperties: true
1049
- }
1050
- },
1051
- additionalProperties: true
1052
- });
1053
1037
  let _tsCacheMs = 0;
1054
1038
  let _tsCacheStr = "";
1055
1039
  function nowIso() {
@@ -1060,6 +1044,43 @@ function nowIso() {
1060
1044
  }
1061
1045
  return _tsCacheStr;
1062
1046
  }
1047
+ const RESOLVED = Promise.resolve();
1048
+ const JSON_STRING_FIELDS = [
1049
+ "timestamp",
1050
+ "level",
1051
+ "appName",
1052
+ "environment",
1053
+ "message",
1054
+ "context",
1055
+ "traceId"
1056
+ ];
1057
+ function toJsonString(value) {
1058
+ if (value === null) return "";
1059
+ if (value instanceof Date) return value.toISOString();
1060
+ if (value instanceof RegExp) return value.source;
1061
+ return String(value);
1062
+ }
1063
+ function toJsonEntry(entry) {
1064
+ const record = entry;
1065
+ let copy;
1066
+ for (const field of JSON_STRING_FIELDS) {
1067
+ const value = record[field];
1068
+ if (value !== void 0 && typeof value !== "string") {
1069
+ copy ??= { ...record };
1070
+ copy[field] = toJsonString(value);
1071
+ }
1072
+ }
1073
+ const payload = entry.payload;
1074
+ if (payload !== void 0 && (payload === null || typeof payload !== "object" || Array.isArray(payload))) {
1075
+ copy ??= { ...record };
1076
+ copy["payload"] = Object.assign({}, payload);
1077
+ }
1078
+ return copy ?? entry;
1079
+ }
1080
+ function toContextLabel(context) {
1081
+ if (context === void 0 || context === null) return "";
1082
+ return typeof context === "string" ? context : safeToString(context);
1083
+ }
1063
1084
  function namespacePatternToRegex(pattern) {
1064
1085
  const escaped = pattern.split(".").map((s) => s === "*" ? "[^.]+" : s.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&")).join("\\.");
1065
1086
  return new RegExp(`^${escaped}$`);
@@ -1141,6 +1162,11 @@ var LogixiaLogger = class LogixiaLogger {
1141
1162
  this._hasContextData = false;
1142
1163
  this._formattedLevels = /* @__PURE__ */ new Map();
1143
1164
  this._formattedAppName = "";
1165
+ this._jsonHeads = /* @__PURE__ */ new Map();
1166
+ this._jsonHeadsApp = "";
1167
+ this._jsonHeadsEnv = "";
1168
+ this._jsonContextKey = void 0;
1169
+ this._jsonContext = "";
1144
1170
  this._hasRedact = false;
1145
1171
  this._nsSeenVersion = 0;
1146
1172
  this._parent = parent;
@@ -1198,7 +1224,7 @@ var LogixiaLogger = class LogixiaLogger {
1198
1224
  payload: "[payload]",
1199
1225
  timeTaken: "[time_taken_MS]"
1200
1226
  };
1201
- this.context = context ?? "";
1227
+ this.context = toContextLabel(context);
1202
1228
  protectSecrets(this, ["config"]);
1203
1229
  if (parent) {
1204
1230
  this.transportManager = parent.transportManager;
@@ -1241,9 +1267,7 @@ var LogixiaLogger = class LogixiaLogger {
1241
1267
  var _this$config$levelOpt3, _this$config$levelOpt4;
1242
1268
  warnOnReservedLevelNames((_this$config$levelOpt3 = this.config.levelOptions) === null || _this$config$levelOpt3 === void 0 ? void 0 : _this$config$levelOpt3.levels);
1243
1269
  if ((_this$config$levelOpt4 = this.config.levelOptions) === null || _this$config$levelOpt4 === void 0 ? void 0 : _this$config$levelOpt4.levels) {
1244
- for (const levelName of Object.keys(this.config.levelOptions.levels)) if (!this[levelName.toLowerCase()]) this[levelName.toLowerCase()] = async (message, data) => {
1245
- await this.logLevel(levelName.toLowerCase(), message, data);
1246
- };
1270
+ for (const levelName of Object.keys(this.config.levelOptions.levels)) if (!this[levelName.toLowerCase()]) this[levelName.toLowerCase()] = (message, data) => this.logLevel(levelName.toLowerCase(), message, data);
1247
1271
  }
1248
1272
  }
1249
1273
  /**
@@ -1345,40 +1369,53 @@ var LogixiaLogger = class LogixiaLogger {
1345
1369
  * (name, message, stack) under `data.error`; a string is logged as-is.
1346
1370
  * `data` is merged into the entry payload.
1347
1371
  */
1348
- async error(messageOrError, data) {
1349
- if (isError(messageOrError)) await this.log("error", messageOrError.message, {
1350
- ...data,
1351
- error: serializeError(messageOrError)
1352
- });
1353
- else await this.log("error", messageOrError, data);
1372
+ error(messageOrError, data) {
1373
+ try {
1374
+ return isError(messageOrError) ? this._run("error", messageOrError.message, {
1375
+ ...data,
1376
+ error: serializeError(messageOrError)
1377
+ }) : this._run("error", messageOrError, data);
1378
+ } catch (error) {
1379
+ return Promise.reject(error);
1380
+ }
1354
1381
  }
1355
1382
  /** Log `message` at `warn` level; `data` is merged into the entry payload. */
1356
- async warn(message, data) {
1357
- await this.log("warn", message, data);
1383
+ warn(message, data) {
1384
+ return this._run("warn", message, data);
1358
1385
  }
1359
1386
  /** Log `message` at `info` level; `data` is merged into the entry payload. */
1360
- async info(message, data) {
1361
- await this.log("info", message, data);
1387
+ info(message, data) {
1388
+ return this._run("info", message, data);
1362
1389
  }
1363
1390
  /** Log `message` at `debug` level; `data` is merged into the entry payload. */
1364
- async debug(message, data) {
1365
- await this.log("debug", message, data);
1391
+ debug(message, data) {
1392
+ return this._run("debug", message, data);
1366
1393
  }
1367
1394
  /** Log `message` at `trace` level; `data` is merged into the entry payload. */
1368
- async trace(message, data) {
1369
- await this.log("trace", message, data);
1395
+ trace(message, data) {
1396
+ return this._run("trace", message, data);
1370
1397
  }
1371
1398
  /** Log `message` at `verbose` level; `data` is merged into the entry payload. */
1372
- async verbose(message, data) {
1373
- await this.log("verbose", message, data);
1399
+ verbose(message, data) {
1400
+ return this._run("verbose", message, data);
1374
1401
  }
1375
1402
  /**
1376
1403
  * Log at an arbitrary level name, including custom levels. Levels below the
1377
1404
  * active threshold are dropped, as are level names that are not registered
1378
1405
  * in `levelOptions.levels` (and are not built-in).
1379
1406
  */
1380
- async logLevel(level, message, data) {
1381
- await this.log(level, message, data);
1407
+ logLevel(level, message, data) {
1408
+ return this._run(level, message, data);
1409
+ }
1410
+ _run(level, message, data) {
1411
+ try {
1412
+ return this._settle(this.log(level, message, data));
1413
+ } catch (error) {
1414
+ return Promise.reject(error);
1415
+ }
1416
+ }
1417
+ _settle(out) {
1418
+ return out ?? RESOLVED;
1382
1419
  }
1383
1420
  /** Start a named timer; finish it with {@link timeEnd}. Reusing a label restarts it. */
1384
1421
  time(label) {
@@ -1684,13 +1721,15 @@ var LogixiaLogger = class LogixiaLogger {
1684
1721
  await this._pluginRegistry.runOnShutdown();
1685
1722
  deregisterFromShutdown(this);
1686
1723
  }
1687
- async log(level, message, rawData) {
1688
- if (this.config.silent) return;
1724
+ /** Returns a Promise only when a plugin or a transport is asynchronous. */
1725
+ log(level, message, rawData) {
1726
+ const config = this.config;
1727
+ if (config.silent) return;
1689
1728
  if (!this.shouldLog(level)) return;
1690
1729
  const data = rawData instanceof Error ? { error: serializeError(rawData) } : rawData;
1691
1730
  const alsContext = LogixiaContext.get();
1692
1731
  let activeTraceId;
1693
- if (this.config.traceId) {
1732
+ if (config.traceId) {
1694
1733
  const ctxTraceId = alsContext === null || alsContext === void 0 ? void 0 : alsContext.traceId;
1695
1734
  activeTraceId = TraceContext.instance.getCurrentTraceId() ?? (typeof ctxTraceId === "string" ? ctxTraceId : void 0);
1696
1735
  }
@@ -1698,7 +1737,7 @@ var LogixiaLogger = class LogixiaLogger {
1698
1737
  const hasAls = alsContext !== void 0 && Object.keys(alsContext).length > 0;
1699
1738
  const otelFields = _isOtelBridgeEnabled() ? _getOtelPayloadIfEnabled() : void 0;
1700
1739
  const hasOtel = otelFields !== void 0 && Object.keys(otelFields).length > 0;
1701
- const traceId = this.config.traceId ? activeTraceId ?? this.fallbackTraceId : void 0;
1740
+ const traceId = config.traceId ? activeTraceId ?? this.fallbackTraceId : void 0;
1702
1741
  let mergedData;
1703
1742
  if (hasAls) {
1704
1743
  const als = { ...alsContext };
@@ -1725,7 +1764,7 @@ var LogixiaLogger = class LogixiaLogger {
1725
1764
  let payload;
1726
1765
  if (rawPayload !== void 0 && rawPayload !== null) {
1727
1766
  if (this._hasRedact) try {
1728
- payload = applyRedaction(rawPayload, this.config.redact) ?? rawPayload;
1767
+ payload = applyRedaction(rawPayload, config.redact) ?? rawPayload;
1729
1768
  } catch (error) {
1730
1769
  internalError("Redaction failed", error);
1731
1770
  payload = { redaction: REDACTION_FAILED };
@@ -1734,7 +1773,7 @@ var LogixiaLogger = class LogixiaLogger {
1734
1773
  }
1735
1774
  let safeMessage = message;
1736
1775
  if (this._hasRedact) try {
1737
- safeMessage = applyRedactionToString(message, this.config.redact);
1776
+ safeMessage = applyRedactionToString(message, config.redact);
1738
1777
  } catch (error) {
1739
1778
  internalError("Redaction failed", error);
1740
1779
  safeMessage = REDACTION_FAILED;
@@ -1742,20 +1781,20 @@ var LogixiaLogger = class LogixiaLogger {
1742
1781
  const entry = {
1743
1782
  timestamp: nowIso(),
1744
1783
  level,
1745
- appName: this.config.appName ?? "App",
1746
- environment: this.config.environment ?? "development",
1784
+ appName: config.appName ?? "App",
1785
+ environment: config.environment ?? "development",
1747
1786
  message: safeMessage
1748
1787
  };
1749
1788
  if (this.context) entry.context = this.context;
1750
- if (payload !== void 0) entry.payload = payload;
1751
1789
  if (traceId !== void 0) entry.traceId = traceId;
1752
- let finalEntry = entry;
1753
- if (this._pluginRegistry.size > 0) {
1754
- finalEntry = await this._pluginRegistry.runOnLog(entry);
1755
- if (finalEntry === null) return;
1756
- }
1757
- const out = this.output(finalEntry, level);
1758
- if (out !== void 0) await out;
1790
+ if (payload !== void 0) entry.payload = payload;
1791
+ if (this._pluginRegistry.size > 0) return this._logThroughPlugins(entry, level);
1792
+ return this.output(entry, level);
1793
+ }
1794
+ async _logThroughPlugins(entry, level) {
1795
+ const finalEntry = await this._pluginRegistry.runOnLog(entry);
1796
+ if (finalEntry === null) return;
1797
+ await this.output(finalEntry, level);
1759
1798
  }
1760
1799
  /**
1761
1800
  * Hot-path level check: a single Map lookup + integer compare.
@@ -1797,19 +1836,27 @@ var LogixiaLogger = class LogixiaLogger {
1797
1836
  return this.getLevel();
1798
1837
  }
1799
1838
  formatLog(entry) {
1800
- var _this$config$format2, _this$config$format3, _this$config$format4;
1801
- if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) try {
1802
- return _fastStringifyEntry(entry);
1803
- } catch {
1804
- return stringifyForLog(entry);
1839
+ const format = this.config.format;
1840
+ if (format === null || format === void 0 ? void 0 : format.json) {
1841
+ if (this._pluginRegistry.size === 0) try {
1842
+ const line = this._buildJsonLine(entry);
1843
+ if (line !== void 0) return line;
1844
+ } catch {}
1845
+ let jsonEntry = entry;
1846
+ try {
1847
+ jsonEntry = toJsonEntry(entry);
1848
+ return JSON.stringify(jsonEntry);
1849
+ } catch {
1850
+ return stringifyForLog(jsonEntry);
1851
+ }
1805
1852
  }
1806
1853
  let formatted = "";
1807
- const doColorize = ((_this$config$format3 = this.config.format) === null || _this$config$format3 === void 0 ? void 0 : _this$config$format3.colorize) ?? true;
1854
+ const doColorize = (format === null || format === void 0 ? void 0 : format.colorize) ?? true;
1808
1855
  const gray = doColorize ? this._colorMap.get("gray") : "";
1809
1856
  const cyan = doColorize ? this._colorMap.get("cyan") : "";
1810
1857
  const yellow = doColorize ? this._colorMap.get("yellow") : "";
1811
1858
  const reset = doColorize ? this._colorMap.get("reset") : "";
1812
- if (((_this$config$format4 = this.config.format) === null || _this$config$format4 === void 0 ? void 0 : _this$config$format4.timestamp) !== false && this._fieldCache.get("timestamp") !== false) formatted += `${gray}[${entry.timestamp}]${reset} `;
1859
+ if ((format === null || format === void 0 ? void 0 : format.timestamp) !== false && this._fieldCache.get("timestamp") !== false) formatted += `${gray}[${entry.timestamp}]${reset} `;
1813
1860
  if (this._fieldCache.get("level") !== false) formatted += this._formattedLevels.get(entry.level) ?? `[${entry.level.toUpperCase()}] `;
1814
1861
  formatted += this._formattedAppName;
1815
1862
  if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${stripControlChars(String(entry.traceId))}]${reset} `;
@@ -1818,9 +1865,46 @@ var LogixiaLogger = class LogixiaLogger {
1818
1865
  if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${stringifyForLog(entry.payload)}`;
1819
1866
  return formatted;
1820
1867
  }
1868
+ /**
1869
+ * The same bytes JSON.stringify(entry) gives for an entry log() built, without
1870
+ * walking the fixed fields. Returns undefined when a field has an unexpected type.
1871
+ */
1872
+ _buildJsonLine(entry) {
1873
+ const { timestamp, level, appName, environment, message, context, traceId, payload } = entry;
1874
+ if (typeof timestamp !== "string" || typeof message !== "string" || typeof appName !== "string" || typeof environment !== "string") return;
1875
+ if (appName !== this._jsonHeadsApp || environment !== this._jsonHeadsEnv) {
1876
+ this._jsonHeads.clear();
1877
+ this._jsonHeadsApp = appName;
1878
+ this._jsonHeadsEnv = environment;
1879
+ }
1880
+ let head = this._jsonHeads.get(level);
1881
+ if (head === void 0) {
1882
+ if (typeof level !== "string") return void 0;
1883
+ head = `,"level":${JSON.stringify(level)},"appName":${JSON.stringify(appName)},"environment":${JSON.stringify(environment)},"message":`;
1884
+ this._jsonHeads.set(level, head);
1885
+ }
1886
+ let line = `{"timestamp":"${timestamp}"${head}${JSON.stringify(message)}`;
1887
+ if (context !== void 0) {
1888
+ if (typeof context !== "string") return void 0;
1889
+ if (context !== this._jsonContextKey) {
1890
+ this._jsonContextKey = context;
1891
+ this._jsonContext = `,"context":${JSON.stringify(context)}`;
1892
+ }
1893
+ line += this._jsonContext;
1894
+ }
1895
+ if (traceId !== void 0) {
1896
+ if (typeof traceId !== "string") return void 0;
1897
+ line += `,"traceId":${JSON.stringify(traceId)}`;
1898
+ }
1899
+ if (payload !== void 0) {
1900
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload) || typeof payload.toJSON === "function") return;
1901
+ line += `,"payload":${JSON.stringify(payload)}`;
1902
+ }
1903
+ return `${line}}`;
1904
+ }
1821
1905
  colorize(text, color) {
1822
- var _this$config$format5;
1823
- if (!((_this$config$format5 = this.config.format) === null || _this$config$format5 === void 0 ? void 0 : _this$config$format5.colorize)) return text;
1906
+ var _this$config$format2;
1907
+ if (!((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.colorize)) return text;
1824
1908
  return `${this._colorMap.get(color.toLowerCase()) ?? this._colorMap.get("white")}${text}${this._colorMap.get("reset")}`;
1825
1909
  }
1826
1910
  /**
@@ -1872,9 +1956,7 @@ function createLogger(config, context) {
1872
1956
  const logger = new LogixiaLogger(config, context);
1873
1957
  const mutableLogger = logger;
1874
1958
  if ((_config$levelOptions3 = config.levelOptions) === null || _config$levelOptions3 === void 0 ? void 0 : _config$levelOptions3.levels) {
1875
- for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = async (message, data) => {
1876
- await logger.logLevel(levelName, message, data);
1877
- };
1959
+ for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = (message, data) => logger.logLevel(levelName, message, data);
1878
1960
  }
1879
1961
  return logger;
1880
1962
  }
@@ -2103,4 +2185,4 @@ var ErrorResponseBuilder = class {
2103
2185
  };
2104
2186
  export { DEFAULT_LOG_COLORS as C, DEFAULT_CONFIG as S, LogLevel as T, serializeError as _, isLogixiaException as a, globalPluginRegistry as b, _shutdownRegistrySize as c, registerForShutdown as d, resetShutdownHandlers as f, normalizeError as g, isError as h, LogixiaException as i, deregisterFromShutdown as l, redactObject as m, generateRequestId as n, LogixiaLogger as o, applyRedaction as p, generateTraceId as r, createLogger as s, ErrorResponseBuilder as t, flushOnExit as u, serializeNestedErrors as v, DEFAULT_LOG_LEVELS as w, usePlugin as x, PluginRegistry as y };
2105
2187
 
2106
- //# sourceMappingURL=builder-DKL7WcIN.mjs.map
2188
+ //# sourceMappingURL=builder-Bj3mDeBw.mjs.map