@loggerjs/processors 0.5.1 → 0.5.3

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/dist/index.js CHANGED
@@ -1,24 +1,58 @@
1
1
  import { createBoundContext, createMiddleware, eventToRecord, incrementLoggerMetaCounter, recordToEvent, toLevelName, toLevelValue, withLogEventRoute } from "@loggerjs/core";
2
+ //#region src/error-fields.ts
3
+ const NATIVE_ERROR_FIELDS = ["cause", "errors"];
4
+ function hiddenErrorFields(value) {
5
+ const fields = [];
6
+ for (const field of NATIVE_ERROR_FIELDS) {
7
+ const descriptor = Object.getOwnPropertyDescriptor(value, field);
8
+ if (descriptor && !descriptor.enumerable) fields.push(field);
9
+ }
10
+ return fields;
11
+ }
12
+ function defineHidden(target, field, value) {
13
+ Object.defineProperty(target, field, {
14
+ value,
15
+ writable: true,
16
+ enumerable: false,
17
+ configurable: true
18
+ });
19
+ }
20
+ function dotPath(path, field) {
21
+ return path ? `${path}.${field}` : field;
22
+ }
23
+ //#endregion
2
24
  //#region src/redact.ts
25
+ function keyName$1(key) {
26
+ if (typeof key === "symbol") return key.description ?? key.toString();
27
+ return String(key);
28
+ }
29
+ function ownEnumerableEntries$1(value) {
30
+ return Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key)).map((key) => [key, value[key]]);
31
+ }
3
32
  function matchesKey(key, path, value, matchers) {
33
+ const name = keyName$1(key);
4
34
  return matchers.some((matcher) => {
5
- if (typeof matcher === "string") return matcher.toLowerCase() === key.toLowerCase();
35
+ if (typeof matcher === "symbol") return matcher === key;
36
+ if (typeof matcher === "string") return matcher.toLowerCase() === name.toLowerCase();
6
37
  if (matcher instanceof RegExp) {
7
38
  matcher.lastIndex = 0;
8
- const keyMatches = matcher.test(key);
39
+ const keyMatches = matcher.test(name);
9
40
  matcher.lastIndex = 0;
10
41
  return keyMatches || matcher.test(path);
11
42
  }
12
- return matcher(key, path, value);
43
+ return matcher(name, path, value);
13
44
  });
14
45
  }
15
46
  function pathMatches(path, paths) {
16
47
  return paths.includes(path);
17
48
  }
49
+ function shouldRedact(key, path, value, options) {
50
+ return matchesKey(key, path, value, options.keys ?? []) || pathMatches(path, options.paths ?? []);
51
+ }
18
52
  function redactValue(value, options, path = "", depth = 0, seen = /* @__PURE__ */ new WeakMap()) {
19
53
  if (value === null || value === void 0) return value;
20
54
  if (typeof value !== "object") return value;
21
- if (depth >= options.maxDepth) return value;
55
+ if (depth >= options.maxDepth) return options.replacement;
22
56
  if (seen.has(value)) return seen.get(value);
23
57
  if (Array.isArray(value)) {
24
58
  const out = [];
@@ -26,14 +60,67 @@ function redactValue(value, options, path = "", depth = 0, seen = /* @__PURE__ *
26
60
  for (let index = 0; index < value.length; index += 1) out[index] = redactValue(value[index], options, `${path}[${index}]`, depth + 1, seen);
27
61
  return out;
28
62
  }
29
- if (value instanceof Error) return value;
30
63
  if (value instanceof Date) return value;
31
- const input = value;
64
+ if (value instanceof Error) {
65
+ const entries = ownEnumerableEntries$1(value);
66
+ const hiddenFields = hiddenErrorFields(value);
67
+ if (entries.length === 0 && hiddenFields.length === 0) return value;
68
+ const errorOut = Object.create(Object.getPrototypeOf(value));
69
+ seen.set(value, errorOut);
70
+ defineHidden(errorOut, "message", value.message);
71
+ defineHidden(errorOut, "stack", value.stack);
72
+ for (const field of hiddenFields) {
73
+ const child = value[field];
74
+ const childPath = dotPath(path, field);
75
+ if (shouldRedact(field, childPath, child, options)) {
76
+ if (options.remove) continue;
77
+ defineHidden(errorOut, field, options.replacement);
78
+ continue;
79
+ }
80
+ defineHidden(errorOut, field, redactValue(child, options, childPath, depth + 1, seen));
81
+ }
82
+ for (const [key, child] of entries) {
83
+ const childPath = dotPath(path, keyName$1(key));
84
+ if (shouldRedact(key, childPath, child, options)) {
85
+ if (options.remove) continue;
86
+ errorOut[key] = options.replacement;
87
+ } else errorOut[key] = redactValue(child, options, childPath, depth + 1, seen);
88
+ }
89
+ return errorOut;
90
+ }
91
+ if (value instanceof Map) {
92
+ const mapOut = /* @__PURE__ */ new Map();
93
+ seen.set(value, mapOut);
94
+ for (const [key, child] of value) {
95
+ if (typeof key === "string" || typeof key === "symbol") {
96
+ const childPath = dotPath(path, keyName$1(key));
97
+ if (shouldRedact(key, childPath, child, options)) {
98
+ if (options.remove) continue;
99
+ mapOut.set(key, options.replacement);
100
+ continue;
101
+ }
102
+ mapOut.set(key, redactValue(child, options, childPath, depth + 1, seen));
103
+ continue;
104
+ }
105
+ mapOut.set(key, redactValue(child, options, path, depth + 1, seen));
106
+ }
107
+ return mapOut;
108
+ }
109
+ if (value instanceof Set) {
110
+ const setOut = /* @__PURE__ */ new Set();
111
+ seen.set(value, setOut);
112
+ let index = 0;
113
+ for (const child of value) {
114
+ setOut.add(redactValue(child, options, `${path}[${index}]`, depth + 1, seen));
115
+ index += 1;
116
+ }
117
+ return setOut;
118
+ }
32
119
  const out = {};
33
120
  seen.set(value, out);
34
- for (const [key, child] of Object.entries(input)) {
35
- const childPath = path ? `${path}.${key}` : key;
36
- if (matchesKey(key, childPath, child, options.keys ?? []) || pathMatches(childPath, options.paths ?? [])) {
121
+ for (const [key, child] of ownEnumerableEntries$1(value)) {
122
+ const childPath = dotPath(path, keyName$1(key));
123
+ if (shouldRedact(key, childPath, child, options)) {
37
124
  if (options.remove) continue;
38
125
  out[key] = options.replacement;
39
126
  } else out[key] = redactValue(child, options, childPath, depth + 1, seen);
@@ -1023,6 +1110,13 @@ function isAsciiAlphaNumeric(code) {
1023
1110
  function hasChar(code, chars) {
1024
1111
  return chars.includes(String.fromCharCode(code));
1025
1112
  }
1113
+ function keyName(key) {
1114
+ if (typeof key === "symbol") return key.description ?? key.toString();
1115
+ return String(key);
1116
+ }
1117
+ function ownEnumerableEntries(value) {
1118
+ return Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key)).map((key) => [key, value[key]]);
1119
+ }
1026
1120
  function isEmailLocalChar(code) {
1027
1121
  return isAsciiAlphaNumeric(code) || hasChar(code, "._%+-");
1028
1122
  }
@@ -1088,12 +1182,14 @@ function redactEmailAddresses(input, path, options) {
1088
1182
  };
1089
1183
  }
1090
1184
  function matcherMatches(matcher, key, path, value) {
1091
- if (typeof matcher === "string") return matcher.toLowerCase() === key.toLowerCase();
1185
+ const name = keyName(key);
1186
+ if (typeof matcher === "symbol") return matcher === key;
1187
+ if (typeof matcher === "string") return matcher.toLowerCase() === name.toLowerCase();
1092
1188
  if (matcher instanceof RegExp) {
1093
1189
  matcher.lastIndex = 0;
1094
- return matcher.test(key) || matcher.test(path);
1190
+ return matcher.test(name) || matcher.test(path);
1095
1191
  }
1096
- return matcher(key, path, value);
1192
+ return matcher(name, path, value);
1097
1193
  }
1098
1194
  function matchesAny(matchers, key, path, value) {
1099
1195
  return matchers.some((matcher) => matcherMatches(matcher, key, path, value));
@@ -1134,6 +1230,12 @@ function guardString(input, path, options) {
1134
1230
  changed: changed || value !== input
1135
1231
  };
1136
1232
  }
1233
+ function guardErrorString(input, path, options) {
1234
+ return typeof input === "string" ? guardString(input, path, options) : {
1235
+ value: input,
1236
+ changed: false
1237
+ };
1238
+ }
1137
1239
  function guardValue(value, path, key, depth, options, seen) {
1138
1240
  if (matchesAny(options.denyKeys, key, path, value) && !matchesAny(options.allowKeys, key, path, value)) return {
1139
1241
  value: redact(path, "deny-key", options),
@@ -1152,10 +1254,72 @@ function guardValue(value, path, key, depth, options, seen) {
1152
1254
  value: seen.get(value),
1153
1255
  changed: true
1154
1256
  };
1155
- if (value instanceof Date || value instanceof Error) return {
1257
+ if (value instanceof Date) return {
1156
1258
  value,
1157
1259
  changed: false
1158
1260
  };
1261
+ if (value instanceof Error) {
1262
+ const message = guardErrorString(value.message, dotPath(path, "message"), options);
1263
+ const stack = guardErrorString(value.stack, dotPath(path, "stack"), options);
1264
+ const fieldChanged = message.changed || stack.changed;
1265
+ const entries = ownEnumerableEntries(value);
1266
+ const hiddenFields = hiddenErrorFields(value);
1267
+ if (entries.length === 0 && hiddenFields.length === 0 && !fieldChanged) return {
1268
+ value,
1269
+ changed: false
1270
+ };
1271
+ const errorOut = Object.create(Object.getPrototypeOf(value));
1272
+ seen.set(value, errorOut);
1273
+ defineHidden(errorOut, "message", message.value);
1274
+ defineHidden(errorOut, "stack", stack.value);
1275
+ let changed = fieldChanged;
1276
+ for (const field of hiddenFields) {
1277
+ const childPath = dotPath(path, field);
1278
+ const child = guardValue(value[field], childPath, field, depth + 1, options, seen);
1279
+ defineHidden(errorOut, field, child.value);
1280
+ changed ||= child.changed;
1281
+ }
1282
+ for (const [childKey, childValue] of entries) {
1283
+ const child = guardValue(childValue, dotPath(path, keyName(childKey)), childKey, depth + 1, options, seen);
1284
+ errorOut[childKey] = child.value;
1285
+ changed ||= child.changed;
1286
+ }
1287
+ return {
1288
+ value: changed ? errorOut : value,
1289
+ changed
1290
+ };
1291
+ }
1292
+ if (value instanceof Map) {
1293
+ const mapOut = /* @__PURE__ */ new Map();
1294
+ seen.set(value, mapOut);
1295
+ let changed = false;
1296
+ for (const [mapKey, mapValue] of value) {
1297
+ const isNamedKey = typeof mapKey === "string" || typeof mapKey === "symbol";
1298
+ const child = guardValue(mapValue, isNamedKey ? dotPath(path, keyName(mapKey)) : path, isNamedKey ? mapKey : key, depth + 1, options, seen);
1299
+ mapOut.set(mapKey, child.value);
1300
+ changed ||= child.changed;
1301
+ }
1302
+ return {
1303
+ value: changed ? mapOut : value,
1304
+ changed
1305
+ };
1306
+ }
1307
+ if (value instanceof Set) {
1308
+ const setOut = /* @__PURE__ */ new Set();
1309
+ seen.set(value, setOut);
1310
+ let changed = false;
1311
+ let index = 0;
1312
+ for (const item of value) {
1313
+ const child = guardValue(item, `${path}[${index}]`, String(index), depth + 1, options, seen);
1314
+ setOut.add(child.value);
1315
+ changed ||= child.changed;
1316
+ index += 1;
1317
+ }
1318
+ return {
1319
+ value: changed ? setOut : value,
1320
+ changed
1321
+ };
1322
+ }
1159
1323
  if (Array.isArray(value)) {
1160
1324
  const out = [];
1161
1325
  seen.set(value, out);
@@ -1170,12 +1334,11 @@ function guardValue(value, path, key, depth, options, seen) {
1170
1334
  changed
1171
1335
  };
1172
1336
  }
1173
- const input = value;
1174
1337
  const out = {};
1175
1338
  seen.set(value, out);
1176
1339
  let changed = false;
1177
- for (const [childKey, childValue] of Object.entries(input)) {
1178
- const child = guardValue(childValue, path ? `${path}.${childKey}` : childKey, childKey, depth + 1, options, seen);
1340
+ for (const [childKey, childValue] of ownEnumerableEntries(value)) {
1341
+ const child = guardValue(childValue, dotPath(path, keyName(childKey)), childKey, depth + 1, options, seen);
1179
1342
  out[childKey] = child.value;
1180
1343
  changed ||= child.changed;
1181
1344
  }