@logtape/redaction 2.2.0-dev.679 → 2.2.0-dev.683

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/field.cjs CHANGED
@@ -1,9 +1,11 @@
1
1
  const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const require_traversal = require('./traversal.cjs');
2
3
  const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
3
4
 
4
5
  //#region src/field.ts
5
6
  const metaLogger = (0, __logtape_logtape.getLogger)(["logtape", "meta"]);
6
7
  let reportingRedactionFailure = false;
8
+ let reportingRedactionLimit = false;
7
9
  /**
8
10
  * Default field patterns for redaction. These patterns will match
9
11
  * common sensitive fields such as passwords, tokens, and personal
@@ -54,15 +56,16 @@ const DEFAULT_REDACT_FIELDS = [
54
56
  function redactByField(sink, options = DEFAULT_REDACT_FIELDS) {
55
57
  const opts = Array.isArray(options) ? { fieldPatterns: options } : options;
56
58
  const wrapped = (record) => {
57
- const redactedProperties = redactProperties(record.properties, opts);
59
+ const context = createFieldRedactionContext(opts);
60
+ const redactedProperties = redactProperties(record.properties, opts, context.visited, 0, context);
58
61
  let redactedMessage = record.message;
59
62
  if (typeof record.rawMessage === "string") {
60
63
  const placeholders = extractPlaceholderNames(record.rawMessage);
61
64
  const { redactedIndices, wildcardIndices } = getRedactedPlaceholderIndices(placeholders, opts.fieldPatterns);
62
- redactedMessage = redactMessageArray(record.message, placeholders, redactedIndices, wildcardIndices, redactedProperties, opts.action);
65
+ redactedMessage = redactMessageArray(record.message, placeholders, redactedIndices, wildcardIndices, redactedProperties, opts.action, context.exceededLimits.size > 0);
63
66
  } else {
64
67
  const redactedValues = getRedactedValues(record.properties, redactedProperties);
65
- if (redactedValues.size > 0) redactedMessage = redactMessageByValues(record.message, redactedValues);
68
+ if (redactedValues.size > 0 || context.exceededLimits.size > 0) redactedMessage = redactMessageByValues(record.message, redactedValues, context.exceededLimits.size > 0);
66
69
  }
67
70
  sink({
68
71
  ...record,
@@ -146,18 +149,19 @@ function redactByFieldAsync(sink, options) {
146
149
  return wrapped;
147
150
  }
148
151
  async function redactLogRecordAsync(record, options) {
149
- const redactedProperties = await redactPropertiesAsync(record.properties, options);
152
+ const context = createFieldRedactionContext(options);
153
+ const redactedProperties = await redactPropertiesAsync(record.properties, options, context.visited, 0, context);
150
154
  if (typeof record.rawMessage === "string") {
151
155
  const placeholders = extractPlaceholderNames(record.rawMessage);
152
156
  const { redactedIndices, wildcardIndices } = getRedactedPlaceholderIndices(placeholders, options.fieldPatterns);
153
157
  return {
154
- message: await redactMessageArrayAsync(record.message, placeholders, redactedIndices, wildcardIndices, redactedProperties, options.action),
158
+ message: await redactMessageArrayAsync(record.message, placeholders, redactedIndices, wildcardIndices, redactedProperties, options.action, context.exceededLimits.size > 0),
155
159
  properties: redactedProperties
156
160
  };
157
161
  }
158
162
  let redactedMessage = record.message;
159
163
  const redactedValues = getRedactedValues(record.properties, redactedProperties);
160
- if (redactedValues.size > 0) redactedMessage = redactMessageByValues(record.message, redactedValues);
164
+ if (redactedValues.size > 0 || context.exceededLimits.size > 0) redactedMessage = redactMessageByValues(record.message, redactedValues, context.exceededLimits.size > 0);
161
165
  return {
162
166
  message: redactedMessage,
163
167
  properties: redactedProperties
@@ -172,6 +176,25 @@ function reportRedactionFailure(error) {
172
176
  reportingRedactionFailure = false;
173
177
  }
174
178
  }
179
+ function reportRedactionLimitExceeded(limit, limits) {
180
+ if (reportingRedactionLimit || typeof metaLogger.warn !== "function") return;
181
+ try {
182
+ reportingRedactionLimit = true;
183
+ metaLogger.warn("Redaction traversal exceeded {limit}; replacing or omitting remaining data to keep logging bounded.", {
184
+ limit,
185
+ ...limits
186
+ });
187
+ } catch {} finally {
188
+ reportingRedactionLimit = false;
189
+ }
190
+ }
191
+ function createFieldRedactionContext(options, visited = /* @__PURE__ */ new Map()) {
192
+ return require_traversal.createRedactionTraversalContext(options, reportRedactionLimitExceeded, visited);
193
+ }
194
+ function reportLimitOnce(context, limit) {
195
+ if (context.exceededLimits.has(limit)) return;
196
+ context.reportLimitExceeded(limit);
197
+ }
175
198
  /**
176
199
  * Creates an asynchronous pseudonymizer based on HMAC using the Web Crypto API.
177
200
  *
@@ -217,19 +240,27 @@ async function createHmacPseudonymizer(options) {
217
240
  * @returns The redacted properties.
218
241
  * @since 0.10.0
219
242
  */
220
- function redactProperties(properties, options, visited = /* @__PURE__ */ new Map()) {
243
+ function redactProperties(properties, options, visited = /* @__PURE__ */ new Map(), depth = 0, context = createFieldRedactionContext(options, visited)) {
221
244
  if (visited.has(properties)) return visited.get(properties);
222
245
  const copy = {};
223
246
  visited.set(properties, copy);
224
- for (const field of Object.keys(properties)) {
247
+ const fields = Object.keys(properties);
248
+ if (fields.length > context.limits.maxProperties) reportLimitOnce(context, "maxProperties");
249
+ for (const field of fields.slice(0, context.limits.maxProperties)) {
225
250
  if (shouldFieldRedacted(field, options.fieldPatterns)) {
226
251
  if (typeof options.action === "function") setProperty(copy, field, options.action(properties[field]));
227
252
  continue;
228
253
  }
229
254
  const value = properties[field];
230
- if (Array.isArray(value)) setProperty(copy, field, redactArray(value, options, visited));
255
+ if (Array.isArray(value)) if (depth + 1 > context.limits.maxDepth) {
256
+ reportLimitOnce(context, "maxDepth");
257
+ setProperty(copy, field, require_traversal.redactionTruncatedValue);
258
+ } else setProperty(copy, field, redactArray(value, options, visited, depth + 1, context));
231
259
  else if (typeof value === "object" && value !== null) if (isBuiltInObject(value)) setProperty(copy, field, value);
232
- else setProperty(copy, field, redactProperties(value, options, visited));
260
+ else if (depth + 1 > context.limits.maxDepth) {
261
+ reportLimitOnce(context, "maxDepth");
262
+ setProperty(copy, field, require_traversal.redactionTruncatedValue);
263
+ } else setProperty(copy, field, redactProperties(value, options, visited, depth + 1, context));
233
264
  else setProperty(copy, field, value);
234
265
  }
235
266
  return copy;
@@ -242,22 +273,30 @@ function redactProperties(properties, options, visited = /* @__PURE__ */ new Map
242
273
  * @returns The redacted properties.
243
274
  * @since 2.1.0
244
275
  */
245
- async function redactPropertiesAsync(properties, options, visited = /* @__PURE__ */ new Map()) {
276
+ async function redactPropertiesAsync(properties, options, visited = /* @__PURE__ */ new Map(), depth = 0, context = createFieldRedactionContext(options, visited)) {
246
277
  if (visited.has(properties)) return visited.get(properties);
247
278
  const copy = {};
248
279
  visited.set(properties, copy);
249
280
  const fields = [];
250
281
  const values = [];
251
- for (const field of Object.keys(properties)) {
282
+ const propertyFields = Object.keys(properties);
283
+ if (propertyFields.length > context.limits.maxProperties) reportLimitOnce(context, "maxProperties");
284
+ for (const field of propertyFields.slice(0, context.limits.maxProperties)) {
252
285
  fields.push(field);
253
286
  if (shouldFieldRedacted(field, options.fieldPatterns)) {
254
287
  values.push(Promise.resolve(options.action(properties[field])));
255
288
  continue;
256
289
  }
257
290
  const value = properties[field];
258
- if (Array.isArray(value)) values.push(redactArrayAsync(value, options, visited));
291
+ if (Array.isArray(value)) if (depth + 1 > context.limits.maxDepth) {
292
+ reportLimitOnce(context, "maxDepth");
293
+ values.push(Promise.resolve(require_traversal.redactionTruncatedValue));
294
+ } else values.push(redactArrayAsync(value, options, visited, depth + 1, context));
259
295
  else if (typeof value === "object" && value !== null) if (isBuiltInObject(value)) values.push(Promise.resolve(value));
260
- else values.push(redactPropertiesAsync(value, options, visited));
296
+ else if (depth + 1 > context.limits.maxDepth) {
297
+ reportLimitOnce(context, "maxDepth");
298
+ values.push(Promise.resolve(require_traversal.redactionTruncatedValue));
299
+ } else values.push(redactPropertiesAsync(value, options, visited, depth + 1, context));
261
300
  else values.push(Promise.resolve(value));
262
301
  }
263
302
  const redactedValues = await Promise.all(values);
@@ -280,36 +319,52 @@ function setProperty(object, field, value) {
280
319
  * @param visited Map of visited objects to prevent circular reference issues.
281
320
  * @returns A new array with redacted values.
282
321
  */
283
- function redactArray(array, options, visited) {
322
+ function redactArray(array, options, visited, depth, context) {
284
323
  if (visited.has(array)) return visited.get(array);
285
324
  const copy = [];
286
- copy.length = array.length;
325
+ const length = Math.min(array.length, context.limits.maxProperties);
326
+ copy.length = length;
287
327
  visited.set(array, copy);
288
- for (let i = 0; i < array.length; i++) {
328
+ if (array.length > context.limits.maxProperties) reportLimitOnce(context, "maxProperties");
329
+ for (let i = 0; i < length; i++) {
289
330
  if (!(i in array)) continue;
290
331
  const item = array[i];
291
- if (Array.isArray(item)) copy[i] = redactArray(item, options, visited);
332
+ if (Array.isArray(item)) if (depth + 1 > context.limits.maxDepth) {
333
+ reportLimitOnce(context, "maxDepth");
334
+ copy[i] = require_traversal.redactionTruncatedValue;
335
+ } else copy[i] = redactArray(item, options, visited, depth + 1, context);
292
336
  else if (typeof item === "object" && item !== null) if (isBuiltInObject(item)) copy[i] = item;
293
- else copy[i] = redactProperties(item, options, visited);
337
+ else if (depth + 1 > context.limits.maxDepth) {
338
+ reportLimitOnce(context, "maxDepth");
339
+ copy[i] = require_traversal.redactionTruncatedValue;
340
+ } else copy[i] = redactProperties(item, options, visited, depth + 1, context);
294
341
  else copy[i] = item;
295
342
  }
296
343
  return copy;
297
344
  }
298
- async function redactArrayAsync(array, options, visited) {
345
+ async function redactArrayAsync(array, options, visited, depth, context) {
299
346
  if (visited.has(array)) return visited.get(array);
300
347
  const copy = [];
301
- copy.length = array.length;
348
+ const length = Math.min(array.length, context.limits.maxProperties);
349
+ copy.length = length;
302
350
  visited.set(array, copy);
303
351
  const itemPromises = [];
304
- for (let i = 0; i < array.length; i++) {
352
+ if (array.length > context.limits.maxProperties) reportLimitOnce(context, "maxProperties");
353
+ for (let i = 0; i < length; i++) {
305
354
  if (!(i in array)) {
306
355
  itemPromises.push(Promise.resolve(void 0));
307
356
  continue;
308
357
  }
309
358
  const item = array[i];
310
- if (Array.isArray(item)) itemPromises.push(redactArrayAsync(item, options, visited));
359
+ if (Array.isArray(item)) if (depth + 1 > context.limits.maxDepth) {
360
+ reportLimitOnce(context, "maxDepth");
361
+ itemPromises.push(Promise.resolve(require_traversal.redactionTruncatedValue));
362
+ } else itemPromises.push(redactArrayAsync(item, options, visited, depth + 1, context));
311
363
  else if (typeof item === "object" && item !== null) if (isBuiltInObject(item)) itemPromises.push(Promise.resolve(item));
312
- else itemPromises.push(redactPropertiesAsync(item, options, visited));
364
+ else if (depth + 1 > context.limits.maxDepth) {
365
+ reportLimitOnce(context, "maxDepth");
366
+ itemPromises.push(Promise.resolve(require_traversal.redactionTruncatedValue));
367
+ } else itemPromises.push(redactPropertiesAsync(item, options, visited, depth + 1, context));
313
368
  else itemPromises.push(Promise.resolve(item));
314
369
  }
315
370
  const redactedItems = await Promise.all(itemPromises);
@@ -464,7 +519,7 @@ function getRedactedPlaceholderIndices(placeholders, fieldPatterns) {
464
519
  * @param action The redaction action.
465
520
  * @returns New message array with redacted values.
466
521
  */
467
- function redactMessageArray(message, placeholders, redactedIndices, wildcardIndices, redactedProperties, action) {
522
+ function redactMessageArray(message, placeholders, redactedIndices, wildcardIndices, redactedProperties, action, truncateUnmappedValues = false) {
468
523
  const result = [];
469
524
  let placeholderIndex = 0;
470
525
  for (let i = 0; i < message.length; i++) if (i % 2 === 0) result.push(message[i]);
@@ -476,13 +531,14 @@ function redactMessageArray(message, placeholders, redactedIndices, wildcardIndi
476
531
  const placeholderName = placeholders[placeholderIndex];
477
532
  const redactedValue = getPathValue(redactedProperties, placeholderName);
478
533
  if (redactedValue.found) result.push(redactedValue.value);
534
+ else if (truncateUnmappedValues) result.push(require_traversal.redactionTruncatedValue);
479
535
  else result.push(message[i]);
480
536
  }
481
537
  placeholderIndex++;
482
538
  }
483
539
  return result;
484
540
  }
485
- async function redactMessageArrayAsync(message, placeholders, redactedIndices, wildcardIndices, redactedProperties, action) {
541
+ async function redactMessageArrayAsync(message, placeholders, redactedIndices, wildcardIndices, redactedProperties, action, truncateUnmappedValues = false) {
486
542
  const result = [];
487
543
  const tasks = [];
488
544
  let placeholderIndex = 0;
@@ -499,6 +555,7 @@ async function redactMessageArrayAsync(message, placeholders, redactedIndices, w
499
555
  const placeholderName = placeholders[placeholderIndex];
500
556
  const redactedValue = getPathValue(redactedProperties, placeholderName);
501
557
  if (redactedValue.found) result.push(redactedValue.value);
558
+ else if (truncateUnmappedValues) result.push(require_traversal.redactionTruncatedValue);
502
559
  else result.push(message[i]);
503
560
  }
504
561
  placeholderIndex++;
@@ -526,7 +583,7 @@ function getPathValue(properties, path) {
526
583
  * @param map The map to populate with original -> redacted value pairs.
527
584
  */
528
585
  function collectRedactedValues(original, redacted, map) {
529
- for (const key of Object.keys(original)) {
586
+ for (const key of Object.keys(redacted)) {
530
587
  const origVal = original[key];
531
588
  const redVal = redacted[key];
532
589
  if (origVal !== redVal) map.set(origVal, redVal);
@@ -551,13 +608,14 @@ function getRedactedValues(original, redacted) {
551
608
  * @param redactedValues Map of original -> redacted values.
552
609
  * @returns New message array with redacted values.
553
610
  */
554
- function redactMessageByValues(message, redactedValues) {
555
- if (redactedValues.size === 0) return message;
611
+ function redactMessageByValues(message, redactedValues, truncateUnmappedValues = false) {
612
+ if (redactedValues.size === 0 && !truncateUnmappedValues) return message;
556
613
  const result = [];
557
614
  for (let i = 0; i < message.length; i++) if (i % 2 === 0) result.push(message[i]);
558
615
  else {
559
616
  const val = message[i];
560
617
  if (redactedValues.has(val)) result.push(redactedValues.get(val));
618
+ else if (truncateUnmappedValues) result.push(require_traversal.redactionTruncatedValue);
561
619
  else result.push(val);
562
620
  }
563
621
  return result;
package/dist/field.d.cts CHANGED
@@ -1,3 +1,4 @@
1
+ import { RedactionTraversalOptions } from "./traversal.cjs";
1
2
  import { Sink } from "@logtape/logtape";
2
3
 
3
4
  //#region src/field.d.ts
@@ -41,7 +42,7 @@ declare const DEFAULT_REDACT_FIELDS: FieldPatterns;
41
42
  * the {@link redactByField} function.
42
43
  * @since 0.10.0
43
44
  */
44
- interface FieldRedactionOptions {
45
+ interface FieldRedactionOptions extends RedactionTraversalOptions {
45
46
  /**
46
47
  * The field patterns to match against. This can be an array of
47
48
  * strings or regular expressions. If a field matches any of the
@@ -60,13 +61,25 @@ interface FieldRedactionOptions {
60
61
  * @default `"delete"`
61
62
  */
62
63
  readonly action?: FieldRedactionAction;
64
+ /**
65
+ * Maximum recursion depth for object and array traversal.
66
+ * @default `20`
67
+ * @since 2.2.0
68
+ */
69
+ readonly maxDepth?: number;
70
+ /**
71
+ * Maximum number of properties or array elements to process per object.
72
+ * @default `1000`
73
+ * @since 2.2.0
74
+ */
75
+ readonly maxProperties?: number;
63
76
  }
64
77
  /**
65
78
  * Options for asynchronously redacting fields in a {@link LogRecord}. Used by
66
79
  * the {@link redactByFieldAsync} function.
67
80
  * @since 2.1.0
68
81
  */
69
- interface AsyncFieldRedactionOptions {
82
+ interface AsyncFieldRedactionOptions extends RedactionTraversalOptions {
70
83
  /**
71
84
  * The field patterns to match against. This can be an array of
72
85
  * strings or regular expressions. If a field matches any of the
@@ -77,6 +90,18 @@ interface AsyncFieldRedactionOptions {
77
90
  * The asynchronous action to perform on the matched fields.
78
91
  */
79
92
  readonly action: AsyncFieldRedactionAction;
93
+ /**
94
+ * Maximum recursion depth for object and array traversal.
95
+ * @default `20`
96
+ * @since 2.2.0
97
+ */
98
+ readonly maxDepth?: number;
99
+ /**
100
+ * Maximum number of properties or array elements to process per object.
101
+ * @default `1000`
102
+ * @since 2.2.0
103
+ */
104
+ readonly maxProperties?: number;
80
105
  }
81
106
  /**
82
107
  * Options for the {@link createHmacPseudonymizer} function.
@@ -1 +1 @@
1
- {"version":3,"file":"field.d.cts","names":[],"sources":["../src/field.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AAOA;AAMA;AAMY,KAnBA,YAAA,GAmBA,MAAyB,GAnBD,MAmBC;AAQrC;AAWA;AAqBA;;;AAmBoB,KAvER,aAAA,GAAgB,YAuER,EAAA;AAAoB;AAQxC;;;AAWmB,KApFP,oBAAA,GAoFO,QAAA,GAAA,CAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,OAAA,CAAA;AAAyB;AAO5C;;;AAIsC,KAzF1B,yBAAA,GAyF0B,CAAA,KAAA,EAAA,OAAA,EAAA,GAvFjC,WAuFiC,CAAA,OAAA,CAAA;;AAAuB;AAgD7D;;AACQ,KAlII,iBAAA,GAkIJ,CAAA,KAAA,EAAA,OAAA,EAAA,GAlI4C,OAkI5C,CAAA,MAAA,CAAA;;;;;;;AAEL,cAzHU,qBAyHV,EAzHiC,aAyHjC;;;;;AAAiD;AA0EpC,UA9KC,qBAAA,CA8KiB;EAAA;;;;;;EACuB,SAC9C,aAAA,EAzKe,aAyKf;EAA0B;;AACZ;AAkIzB;;;;;AAEU;;oBAlSU;;;;;;;UAQH,0BAAA;;;;;;0BAMS;;;;mBAKP;;;;;;UAOF,wBAAA;;;;yBAIQ,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDpC,aAAA,OACR,OAAO,OAAO,aAAa,OAAO,2BAC/B,wBAAwB,gBAChC,OAAO,OAAO,aAAa,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0ErB,kBAAA,OACR,OAAO,OAAO,aAAa,OAAO,0BAC/B,6BACR,OAAO;;;;;;;;;;;;;iBAkIY,uBAAA,UACX,2BACR,QAAQ"}
1
+ {"version":3,"file":"field.d.cts","names":[],"sources":["../src/field.ts"],"sourcesContent":[],"mappings":";;;;;;;AAeA;AAOA;AAMA;AAMY,KAnBA,YAAA,GAmBA,MAAyB,GAnBD,MAmBC;AAQrC;AAYA;AAqBA;;;AAmBoB,KAxER,aAAA,GAAgB,YAwER,EAAA;;AAnBoD;AAyCxE;;AAM0B,KA9Fd,oBAAA,GA8Fc,QAAA,GAAA,CAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,OAAA,CAAA;;;AANmD;AAgC7E;AAAyC,KAlH7B,yBAAA,GAkH6B,CAAA,KAAA,EAAA,OAAA,EAAA,GAhHpC,WAgHoC,CAAA,OAAA,CAAA;;;;AAIoB;AAgD7C,KA9JJ,iBAAA,GA8JiB,CAAA,KAAA,EAAA,OAAA,EAAA,GA9JuB,OA8JvB,CAAA,MAAA,CAAA;;;;;;;AAElB,cApJE,qBAoJF,EApJyB,aAoJzB;;;;;;AAC0B,UAhIpB,qBAAA,SAA8B,yBAgIV,CAAA;EAAe;AAsFpD;;;;;EACgC,SAAG,aAAA,EAhNT,aAgNS;EAAI;;;;AAEd;AAgLzB;;;;;EAEU,SAAA,MAAA,CAAA,EAxXU,oBAwXV;;;;;;;;;;;;;;;;;;;UAlWO,0BAAA,SAAmC;;;;;;0BAM1B;;;;mBAKP;;;;;;;;;;;;;;;;;;UAqBF,wBAAA;;;;yBAIQ,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDpC,aAAA,OACR,OAAO,OAAO,aAAa,OAAO,2BAC/B,wBAAwB,gBAChC,OAAO,OAAO,aAAa,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsFrB,kBAAA,OACR,OAAO,OAAO,aAAa,OAAO,0BAC/B,6BACR,OAAO;;;;;;;;;;;;;iBAgLY,uBAAA,UACX,2BACR,QAAQ"}
package/dist/field.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { RedactionTraversalOptions } from "./traversal.js";
1
2
  import { Sink } from "@logtape/logtape";
2
3
 
3
4
  //#region src/field.d.ts
@@ -41,7 +42,7 @@ declare const DEFAULT_REDACT_FIELDS: FieldPatterns;
41
42
  * the {@link redactByField} function.
42
43
  * @since 0.10.0
43
44
  */
44
- interface FieldRedactionOptions {
45
+ interface FieldRedactionOptions extends RedactionTraversalOptions {
45
46
  /**
46
47
  * The field patterns to match against. This can be an array of
47
48
  * strings or regular expressions. If a field matches any of the
@@ -60,13 +61,25 @@ interface FieldRedactionOptions {
60
61
  * @default `"delete"`
61
62
  */
62
63
  readonly action?: FieldRedactionAction;
64
+ /**
65
+ * Maximum recursion depth for object and array traversal.
66
+ * @default `20`
67
+ * @since 2.2.0
68
+ */
69
+ readonly maxDepth?: number;
70
+ /**
71
+ * Maximum number of properties or array elements to process per object.
72
+ * @default `1000`
73
+ * @since 2.2.0
74
+ */
75
+ readonly maxProperties?: number;
63
76
  }
64
77
  /**
65
78
  * Options for asynchronously redacting fields in a {@link LogRecord}. Used by
66
79
  * the {@link redactByFieldAsync} function.
67
80
  * @since 2.1.0
68
81
  */
69
- interface AsyncFieldRedactionOptions {
82
+ interface AsyncFieldRedactionOptions extends RedactionTraversalOptions {
70
83
  /**
71
84
  * The field patterns to match against. This can be an array of
72
85
  * strings or regular expressions. If a field matches any of the
@@ -77,6 +90,18 @@ interface AsyncFieldRedactionOptions {
77
90
  * The asynchronous action to perform on the matched fields.
78
91
  */
79
92
  readonly action: AsyncFieldRedactionAction;
93
+ /**
94
+ * Maximum recursion depth for object and array traversal.
95
+ * @default `20`
96
+ * @since 2.2.0
97
+ */
98
+ readonly maxDepth?: number;
99
+ /**
100
+ * Maximum number of properties or array elements to process per object.
101
+ * @default `1000`
102
+ * @since 2.2.0
103
+ */
104
+ readonly maxProperties?: number;
80
105
  }
81
106
  /**
82
107
  * Options for the {@link createHmacPseudonymizer} function.
@@ -1 +1 @@
1
- {"version":3,"file":"field.d.ts","names":[],"sources":["../src/field.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AAOA;AAMA;AAMY,KAnBA,YAAA,GAmBA,MAAyB,GAnBD,MAmBC;AAQrC;AAWA;AAqBA;;;AAmBoB,KAvER,aAAA,GAAgB,YAuER,EAAA;AAAoB;AAQxC;;;AAWmB,KApFP,oBAAA,GAoFO,QAAA,GAAA,CAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,OAAA,CAAA;AAAyB;AAO5C;;;AAIsC,KAzF1B,yBAAA,GAyF0B,CAAA,KAAA,EAAA,OAAA,EAAA,GAvFjC,WAuFiC,CAAA,OAAA,CAAA;;AAAuB;AAgD7D;;AACQ,KAlII,iBAAA,GAkIJ,CAAA,KAAA,EAAA,OAAA,EAAA,GAlI4C,OAkI5C,CAAA,MAAA,CAAA;;;;;;;AAEL,cAzHU,qBAyHV,EAzHiC,aAyHjC;;;;;AAAiD;AA0EpC,UA9KC,qBAAA,CA8KiB;EAAA;;;;;;EACuB,SAC9C,aAAA,EAzKe,aAyKf;EAA0B;;AACZ;AAkIzB;;;;;AAEU;;oBAlSU;;;;;;;UAQH,0BAAA;;;;;;0BAMS;;;;mBAKP;;;;;;UAOF,wBAAA;;;;yBAIQ,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDpC,aAAA,OACR,OAAO,OAAO,aAAa,OAAO,2BAC/B,wBAAwB,gBAChC,OAAO,OAAO,aAAa,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0ErB,kBAAA,OACR,OAAO,OAAO,aAAa,OAAO,0BAC/B,6BACR,OAAO;;;;;;;;;;;;;iBAkIY,uBAAA,UACX,2BACR,QAAQ"}
1
+ {"version":3,"file":"field.d.ts","names":[],"sources":["../src/field.ts"],"sourcesContent":[],"mappings":";;;;;;;AAeA;AAOA;AAMA;AAMY,KAnBA,YAAA,GAmBA,MAAyB,GAnBD,MAqB/B;AAML;AAYA;AAqBA;;;AAmBoB,KAxER,aAAA,GAAgB,YAwER,EAAA;;AAnBoD;AAyCxE;;AAM0B,KA9Fd,oBAAA,GA8Fc,QAAA,GAAA,CAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,OAAA,CAAA;;;AANmD;AAgC7E;AAAyC,KAlH7B,yBAAA,GAkH6B,CAAA,KAAA,EAAA,OAAA,EAAA,GAhHpC,WAgHoC,CAAA,OAAA,CAAA;;;;AAIoB;AAgD7C,KA9JJ,iBAAA,GA8JiB,CAAA,KAAA,EAAA,OAAA,EAAA,GA9JuB,OA8JvB,CAAA,MAAA,CAAA;;;;;;;AAElB,cApJE,qBAoJF,EApJyB,aAoJzB;;;;;;AAC0B,UAhIpB,qBAAA,SAA8B,yBAgIV,CAAA;EAAe;AAsFpD;;;;;EACgC,SAAG,aAAA,EAhNT,aAgNS;EAAI;;;;AAEd;AAgLzB;;;;;EAEU,SAAA,MAAA,CAAA,EAxXU,oBAwXV;;;;;;;;;;;;;;;;;;;UAlWO,0BAAA,SAAmC;;;;;;0BAM1B;;;;mBAKP;;;;;;;;;;;;;;;;;;UAqBF,wBAAA;;;;yBAIQ,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDpC,aAAA,OACR,OAAO,OAAO,aAAa,OAAO,2BAC/B,wBAAwB,gBAChC,OAAO,OAAO,aAAa,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsFrB,kBAAA,OACR,OAAO,OAAO,aAAa,OAAO,0BAC/B,6BACR,OAAO;;;;;;;;;;;;;iBAgLY,uBAAA,UACX,2BACR,QAAQ"}