logixia 2.0.8 → 2.0.9

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,8 +6,6 @@ const require_internal_log = require("./internal-log-DwqTjhpb.js");
6
6
  const require_coerce_utils = require("./coerce.utils-C1C5sIX0.js");
7
7
  const require_safe_stringify = require("./safe-stringify-CN7icp8S.js");
8
8
  const require_otel = require("./otel-ChnVYRLA.js");
9
- let fast_json_stringify = require("fast-json-stringify");
10
- fast_json_stringify = require_secret_config.__toESM(fast_json_stringify);
11
9
  let node_os = require("node:os");
12
10
  // src/types/index.ts
13
11
  const LogLevel = {
@@ -195,6 +193,16 @@ const EXTRA_FIELDS = [
195
193
  "port",
196
194
  "type"
197
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 = [];
198
206
  /**
199
207
  * Serialize an Error into a plain JSON-safe object, including:
200
208
  * - `name`, `message`, `stack`
@@ -203,8 +211,8 @@ const EXTRA_FIELDS = [
203
211
  * - standard Node.js error fields (`code`, `statusCode`, `errno`, …)
204
212
  * - any other enumerable own properties
205
213
  */
206
- function serializeError(error, options = {}) {
207
- const { includeStack = true, maxDepth = 5, excludeFields = [] } = options;
214
+ function serializeError(error, options = NO_OPTIONS) {
215
+ const { includeStack = true, maxDepth = 5, excludeFields = NO_FIELDS } = options;
208
216
  return _serializeError(error, includeStack, maxDepth, excludeFields, 0, /* @__PURE__ */ new WeakSet());
209
217
  }
210
218
  function _serializeError(error, includeStack, maxDepth, excludeFields, depth, seen) {
@@ -232,16 +240,8 @@ function _serializeError(error, includeStack, maxDepth, excludeFields, depth, se
232
240
  const aggregateError = error;
233
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));
234
242
  const errorRecord = error;
235
- for (const field of EXTRA_FIELDS) if (!excludeFields.includes(field) && field in error && errorRecord[field] !== void 0) serialized[field] = errorRecord[field];
236
- const skip = /* @__PURE__ */ new Set([
237
- "name",
238
- "message",
239
- "stack",
240
- "cause",
241
- "errors",
242
- ...EXTRA_FIELDS,
243
- ...excludeFields
244
- ]);
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]);
245
245
  for (const key of Object.getOwnPropertyNames(error)) {
246
246
  if (skip.has(key)) continue;
247
247
  try {
@@ -1034,23 +1034,6 @@ function warnOnReservedLevelNames(levels) {
1034
1034
  * - Feature 4: Cause-chain error serialization (handled in error.utils)
1035
1035
  * - Feature 5: Adaptive log level based on NODE_ENV / CI detection
1036
1036
  */
1037
- const _fastStringifyEntry = (0, fast_json_stringify.default)({
1038
- type: "object",
1039
- properties: {
1040
- timestamp: { type: "string" },
1041
- level: { type: "string" },
1042
- appName: { type: "string" },
1043
- environment: { type: "string" },
1044
- message: { type: "string" },
1045
- context: { type: "string" },
1046
- traceId: { type: "string" },
1047
- payload: {
1048
- type: "object",
1049
- additionalProperties: true
1050
- }
1051
- },
1052
- additionalProperties: true
1053
- });
1054
1037
  let _tsCacheMs = 0;
1055
1038
  let _tsCacheStr = "";
1056
1039
  function nowIso() {
@@ -1061,6 +1044,39 @@ function nowIso() {
1061
1044
  }
1062
1045
  return _tsCacheStr;
1063
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
+ }
1064
1080
  function namespacePatternToRegex(pattern) {
1065
1081
  const escaped = pattern.split(".").map((s) => s === "*" ? "[^.]+" : s.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&")).join("\\.");
1066
1082
  return new RegExp(`^${escaped}$`);
@@ -1142,6 +1158,11 @@ var LogixiaLogger = class LogixiaLogger {
1142
1158
  this._hasContextData = false;
1143
1159
  this._formattedLevels = /* @__PURE__ */ new Map();
1144
1160
  this._formattedAppName = "";
1161
+ this._jsonHeads = /* @__PURE__ */ new Map();
1162
+ this._jsonHeadsApp = "";
1163
+ this._jsonHeadsEnv = "";
1164
+ this._jsonContextKey = void 0;
1165
+ this._jsonContext = "";
1145
1166
  this._hasRedact = false;
1146
1167
  this._nsSeenVersion = 0;
1147
1168
  this._parent = parent;
@@ -1242,9 +1263,7 @@ var LogixiaLogger = class LogixiaLogger {
1242
1263
  var _this$config$levelOpt3, _this$config$levelOpt4;
1243
1264
  warnOnReservedLevelNames((_this$config$levelOpt3 = this.config.levelOptions) === null || _this$config$levelOpt3 === void 0 ? void 0 : _this$config$levelOpt3.levels);
1244
1265
  if ((_this$config$levelOpt4 = this.config.levelOptions) === null || _this$config$levelOpt4 === void 0 ? void 0 : _this$config$levelOpt4.levels) {
1245
- for (const levelName of Object.keys(this.config.levelOptions.levels)) if (!this[levelName.toLowerCase()]) this[levelName.toLowerCase()] = async (message, data) => {
1246
- await this.logLevel(levelName.toLowerCase(), message, data);
1247
- };
1266
+ 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);
1248
1267
  }
1249
1268
  }
1250
1269
  /**
@@ -1346,40 +1365,53 @@ var LogixiaLogger = class LogixiaLogger {
1346
1365
  * (name, message, stack) under `data.error`; a string is logged as-is.
1347
1366
  * `data` is merged into the entry payload.
1348
1367
  */
1349
- async error(messageOrError, data) {
1350
- if (isError(messageOrError)) await this.log("error", messageOrError.message, {
1351
- ...data,
1352
- error: serializeError(messageOrError)
1353
- });
1354
- else await this.log("error", messageOrError, data);
1368
+ error(messageOrError, data) {
1369
+ try {
1370
+ return isError(messageOrError) ? this._run("error", messageOrError.message, {
1371
+ ...data,
1372
+ error: serializeError(messageOrError)
1373
+ }) : this._run("error", messageOrError, data);
1374
+ } catch (error) {
1375
+ return Promise.reject(error);
1376
+ }
1355
1377
  }
1356
1378
  /** Log `message` at `warn` level; `data` is merged into the entry payload. */
1357
- async warn(message, data) {
1358
- await this.log("warn", message, data);
1379
+ warn(message, data) {
1380
+ return this._run("warn", message, data);
1359
1381
  }
1360
1382
  /** Log `message` at `info` level; `data` is merged into the entry payload. */
1361
- async info(message, data) {
1362
- await this.log("info", message, data);
1383
+ info(message, data) {
1384
+ return this._run("info", message, data);
1363
1385
  }
1364
1386
  /** Log `message` at `debug` level; `data` is merged into the entry payload. */
1365
- async debug(message, data) {
1366
- await this.log("debug", message, data);
1387
+ debug(message, data) {
1388
+ return this._run("debug", message, data);
1367
1389
  }
1368
1390
  /** Log `message` at `trace` level; `data` is merged into the entry payload. */
1369
- async trace(message, data) {
1370
- await this.log("trace", message, data);
1391
+ trace(message, data) {
1392
+ return this._run("trace", message, data);
1371
1393
  }
1372
1394
  /** Log `message` at `verbose` level; `data` is merged into the entry payload. */
1373
- async verbose(message, data) {
1374
- await this.log("verbose", message, data);
1395
+ verbose(message, data) {
1396
+ return this._run("verbose", message, data);
1375
1397
  }
1376
1398
  /**
1377
1399
  * Log at an arbitrary level name, including custom levels. Levels below the
1378
1400
  * active threshold are dropped, as are level names that are not registered
1379
1401
  * in `levelOptions.levels` (and are not built-in).
1380
1402
  */
1381
- async logLevel(level, message, data) {
1382
- await this.log(level, message, data);
1403
+ logLevel(level, message, data) {
1404
+ return this._run(level, message, data);
1405
+ }
1406
+ _run(level, message, data) {
1407
+ try {
1408
+ return this._settle(this.log(level, message, data));
1409
+ } catch (error) {
1410
+ return Promise.reject(error);
1411
+ }
1412
+ }
1413
+ _settle(out) {
1414
+ return out ?? RESOLVED;
1383
1415
  }
1384
1416
  /** Start a named timer; finish it with {@link timeEnd}. Reusing a label restarts it. */
1385
1417
  time(label) {
@@ -1685,13 +1717,15 @@ var LogixiaLogger = class LogixiaLogger {
1685
1717
  await this._pluginRegistry.runOnShutdown();
1686
1718
  deregisterFromShutdown(this);
1687
1719
  }
1688
- async log(level, message, rawData) {
1689
- if (this.config.silent) return;
1720
+ /** Returns a Promise only when a plugin or a transport is asynchronous. */
1721
+ log(level, message, rawData) {
1722
+ const config = this.config;
1723
+ if (config.silent) return;
1690
1724
  if (!this.shouldLog(level)) return;
1691
1725
  const data = rawData instanceof Error ? { error: serializeError(rawData) } : rawData;
1692
1726
  const alsContext = require_async_context.LogixiaContext.get();
1693
1727
  let activeTraceId;
1694
- if (this.config.traceId) {
1728
+ if (config.traceId) {
1695
1729
  const ctxTraceId = alsContext === null || alsContext === void 0 ? void 0 : alsContext.traceId;
1696
1730
  activeTraceId = require_request_trace.TraceContext.instance.getCurrentTraceId() ?? (typeof ctxTraceId === "string" ? ctxTraceId : void 0);
1697
1731
  }
@@ -1699,7 +1733,7 @@ var LogixiaLogger = class LogixiaLogger {
1699
1733
  const hasAls = alsContext !== void 0 && Object.keys(alsContext).length > 0;
1700
1734
  const otelFields = require_otel._isOtelBridgeEnabled() ? require_otel._getOtelPayloadIfEnabled() : void 0;
1701
1735
  const hasOtel = otelFields !== void 0 && Object.keys(otelFields).length > 0;
1702
- const traceId = this.config.traceId ? activeTraceId ?? this.fallbackTraceId : void 0;
1736
+ const traceId = config.traceId ? activeTraceId ?? this.fallbackTraceId : void 0;
1703
1737
  let mergedData;
1704
1738
  if (hasAls) {
1705
1739
  const als = { ...alsContext };
@@ -1726,7 +1760,7 @@ var LogixiaLogger = class LogixiaLogger {
1726
1760
  let payload;
1727
1761
  if (rawPayload !== void 0 && rawPayload !== null) {
1728
1762
  if (this._hasRedact) try {
1729
- payload = applyRedaction(rawPayload, this.config.redact) ?? rawPayload;
1763
+ payload = applyRedaction(rawPayload, config.redact) ?? rawPayload;
1730
1764
  } catch (error) {
1731
1765
  require_internal_log.internalError("Redaction failed", error);
1732
1766
  payload = { redaction: REDACTION_FAILED };
@@ -1735,7 +1769,7 @@ var LogixiaLogger = class LogixiaLogger {
1735
1769
  }
1736
1770
  let safeMessage = message;
1737
1771
  if (this._hasRedact) try {
1738
- safeMessage = applyRedactionToString(message, this.config.redact);
1772
+ safeMessage = applyRedactionToString(message, config.redact);
1739
1773
  } catch (error) {
1740
1774
  require_internal_log.internalError("Redaction failed", error);
1741
1775
  safeMessage = REDACTION_FAILED;
@@ -1743,20 +1777,20 @@ var LogixiaLogger = class LogixiaLogger {
1743
1777
  const entry = {
1744
1778
  timestamp: nowIso(),
1745
1779
  level,
1746
- appName: this.config.appName ?? "App",
1747
- environment: this.config.environment ?? "development",
1780
+ appName: config.appName ?? "App",
1781
+ environment: config.environment ?? "development",
1748
1782
  message: safeMessage
1749
1783
  };
1750
1784
  if (this.context) entry.context = this.context;
1751
- if (payload !== void 0) entry.payload = payload;
1752
1785
  if (traceId !== void 0) entry.traceId = traceId;
1753
- let finalEntry = entry;
1754
- if (this._pluginRegistry.size > 0) {
1755
- finalEntry = await this._pluginRegistry.runOnLog(entry);
1756
- if (finalEntry === null) return;
1757
- }
1758
- const out = this.output(finalEntry, level);
1759
- if (out !== void 0) await out;
1786
+ if (payload !== void 0) entry.payload = payload;
1787
+ if (this._pluginRegistry.size > 0) return this._logThroughPlugins(entry, level);
1788
+ return this.output(entry, level);
1789
+ }
1790
+ async _logThroughPlugins(entry, level) {
1791
+ const finalEntry = await this._pluginRegistry.runOnLog(entry);
1792
+ if (finalEntry === null) return;
1793
+ await this.output(finalEntry, level);
1760
1794
  }
1761
1795
  /**
1762
1796
  * Hot-path level check: a single Map lookup + integer compare.
@@ -1798,19 +1832,27 @@ var LogixiaLogger = class LogixiaLogger {
1798
1832
  return this.getLevel();
1799
1833
  }
1800
1834
  formatLog(entry) {
1801
- var _this$config$format2, _this$config$format3, _this$config$format4;
1802
- if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) try {
1803
- return _fastStringifyEntry(entry);
1804
- } catch {
1805
- return require_safe_stringify.stringifyForLog(entry);
1835
+ const format = this.config.format;
1836
+ if (format === null || format === void 0 ? void 0 : format.json) {
1837
+ if (this._pluginRegistry.size === 0) try {
1838
+ const line = this._buildJsonLine(entry);
1839
+ if (line !== void 0) return line;
1840
+ } catch {}
1841
+ let jsonEntry = entry;
1842
+ try {
1843
+ jsonEntry = toJsonEntry(entry);
1844
+ return JSON.stringify(jsonEntry);
1845
+ } catch {
1846
+ return require_safe_stringify.stringifyForLog(jsonEntry);
1847
+ }
1806
1848
  }
1807
1849
  let formatted = "";
1808
- const doColorize = ((_this$config$format3 = this.config.format) === null || _this$config$format3 === void 0 ? void 0 : _this$config$format3.colorize) ?? true;
1850
+ const doColorize = (format === null || format === void 0 ? void 0 : format.colorize) ?? true;
1809
1851
  const gray = doColorize ? this._colorMap.get("gray") : "";
1810
1852
  const cyan = doColorize ? this._colorMap.get("cyan") : "";
1811
1853
  const yellow = doColorize ? this._colorMap.get("yellow") : "";
1812
1854
  const reset = doColorize ? this._colorMap.get("reset") : "";
1813
- 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} `;
1855
+ if ((format === null || format === void 0 ? void 0 : format.timestamp) !== false && this._fieldCache.get("timestamp") !== false) formatted += `${gray}[${entry.timestamp}]${reset} `;
1814
1856
  if (this._fieldCache.get("level") !== false) formatted += this._formattedLevels.get(entry.level) ?? `[${entry.level.toUpperCase()}] `;
1815
1857
  formatted += this._formattedAppName;
1816
1858
  if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${require_otel.stripControlChars(String(entry.traceId))}]${reset} `;
@@ -1819,9 +1861,46 @@ var LogixiaLogger = class LogixiaLogger {
1819
1861
  if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${require_safe_stringify.stringifyForLog(entry.payload)}`;
1820
1862
  return formatted;
1821
1863
  }
1864
+ /**
1865
+ * The same bytes JSON.stringify(entry) gives for an entry log() built, without
1866
+ * walking the fixed fields. Returns undefined when a field has an unexpected type.
1867
+ */
1868
+ _buildJsonLine(entry) {
1869
+ const { timestamp, level, appName, environment, message, context, traceId, payload } = entry;
1870
+ if (typeof timestamp !== "string" || typeof message !== "string" || typeof appName !== "string" || typeof environment !== "string") return;
1871
+ if (appName !== this._jsonHeadsApp || environment !== this._jsonHeadsEnv) {
1872
+ this._jsonHeads.clear();
1873
+ this._jsonHeadsApp = appName;
1874
+ this._jsonHeadsEnv = environment;
1875
+ }
1876
+ let head = this._jsonHeads.get(level);
1877
+ if (head === void 0) {
1878
+ if (typeof level !== "string") return void 0;
1879
+ head = `,"level":${JSON.stringify(level)},"appName":${JSON.stringify(appName)},"environment":${JSON.stringify(environment)},"message":`;
1880
+ this._jsonHeads.set(level, head);
1881
+ }
1882
+ let line = `{"timestamp":"${timestamp}"${head}${JSON.stringify(message)}`;
1883
+ if (context !== void 0) {
1884
+ if (typeof context !== "string") return void 0;
1885
+ if (context !== this._jsonContextKey) {
1886
+ this._jsonContextKey = context;
1887
+ this._jsonContext = `,"context":${JSON.stringify(context)}`;
1888
+ }
1889
+ line += this._jsonContext;
1890
+ }
1891
+ if (traceId !== void 0) {
1892
+ if (typeof traceId !== "string") return void 0;
1893
+ line += `,"traceId":${JSON.stringify(traceId)}`;
1894
+ }
1895
+ if (payload !== void 0) {
1896
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload) || typeof payload.toJSON === "function") return;
1897
+ line += `,"payload":${JSON.stringify(payload)}`;
1898
+ }
1899
+ return `${line}}`;
1900
+ }
1822
1901
  colorize(text, color) {
1823
- var _this$config$format5;
1824
- if (!((_this$config$format5 = this.config.format) === null || _this$config$format5 === void 0 ? void 0 : _this$config$format5.colorize)) return text;
1902
+ var _this$config$format2;
1903
+ if (!((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.colorize)) return text;
1825
1904
  return `${this._colorMap.get(color.toLowerCase()) ?? this._colorMap.get("white")}${text}${this._colorMap.get("reset")}`;
1826
1905
  }
1827
1906
  /**
@@ -1873,9 +1952,7 @@ function createLogger(config, context) {
1873
1952
  const logger = new LogixiaLogger(config, context);
1874
1953
  const mutableLogger = logger;
1875
1954
  if ((_config$levelOptions3 = config.levelOptions) === null || _config$levelOptions3 === void 0 ? void 0 : _config$levelOptions3.levels) {
1876
- for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = async (message, data) => {
1877
- await logger.logLevel(levelName, message, data);
1878
- };
1955
+ for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = (message, data) => logger.logLevel(levelName, message, data);
1879
1956
  }
1880
1957
  return logger;
1881
1958
  }
@@ -2253,4 +2330,4 @@ Object.defineProperty(exports, "usePlugin", {
2253
2330
  }
2254
2331
  });
2255
2332
 
2256
- //# sourceMappingURL=builder-BTzvPGHN.js.map
2333
+ //# sourceMappingURL=builder-Bs0qkfkY.js.map