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