field-redactor 1.0.0

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/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ v22.13.0
package/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @mologna
package/README.md ADDED
@@ -0,0 +1,677 @@
1
+ # FieldRedactor
2
+
3
+ A utility `npm` module for redacting sensitive data from JSON objects using complex, recursive evaluation logic.
4
+
5
+ It can redact JSON values based on Regular Expression matching of key values, custom object logic for PII values identified by fields other than their key, deeply redact sensitive objects, and other PII redaction strategies that more simplistic approaches cannot handle.
6
+
7
+ # History
8
+ In many instances, redaction of sensitive data from log output is fairly straightforward and can be accomplished through existing redaction libraries. However, I often encountered scenarios where such simplistic approaches were not sufficient. Take, for example, the following object:
9
+
10
+ ```json
11
+ {
12
+ "name": "email",
13
+ "type": "String",
14
+ "value": "foo.bar@example.com"
15
+ }
16
+ ```
17
+
18
+ If this object is placed in a data set with many others, and only some of these objects contain PII, redaction becomes quite troublesome. One could redact all `value` fields from these objects - but this merely renders the log output useless for debugging or tracing, as all values are now redacted. The value of the `name` field determines whether or not the `value` field should be redacted. I often found myself writing custom logic to make this determination, which led to brittle code that was difficult to maintain. In the end I decided to write a new, highly configurable plug-and-play solution that could redact sensitive data in various manners while requiring only minor configuration tweaks. Enter FieldRedactor!
19
+
20
+ ## Basic Usage
21
+ Basic usage of the FieldRedactor is straightforward but not recommended. Object redaction can be performed either in-place or return the redacted object:
22
+
23
+ ```typescript
24
+ import { FieldRedactor } from 'field-redactor';
25
+ const myJsonObject = { foo: "bar", fizz: null };
26
+ const fieldRedactor = new FieldRedactor();
27
+
28
+ // return redacted result
29
+ const result = await fieldRedactor.redact(myJsonObject);
30
+ console.log(myJsonObject); // { foo: "bar", fizz: null }
31
+ console.log(result); // { foo: "REDACTED", fizz: null }
32
+
33
+ // redact in place
34
+ await fieldRedactor.redactInPlace(myJsonObject);
35
+ console.log(myJsonObject); // { foo: "REDACTED", fizz: null }
36
+ ```
37
+ > **Note:** `null` and `undefined` values are not redacted by default.
38
+
39
+
40
+
41
+ ## Customization
42
+ The true power of this tool comes from its customization. FieldRedactor can be customized to redact only primtive values for certain keys, deeply redact others, while stringifying and fully redacting other keys. The redactor itself can be configured, and "Custom Objects" can be specified to handle certain object shapes in a highly specific and configurable way.
43
+
44
+ ### Overview
45
+ | Config Field | Type | Default | Effect |
46
+ |-----------------------|---------------------------------|--------------------------------|-----------------------------------------------------------------------|
47
+ | `redactor` | `(val: any) => Promise<string>` | `(val) => Promise.resolve("REDACTED")` | The function to use when redacting values. |
48
+ | `secretKeys` | `RegExp[]` | `null` | Specifies which values at any level of the JSON object should be redacted. Objects are not deeply redacted, but primitive values in arrays are. If not specified, all values are considered secret. |
49
+ | `deepSecretKeys` | `RegExp[]` | `[]` | Specifies keys at any level of the JSON object to be deeply redacted. All values within matching objects are fully redacted unless matching a custom object. |
50
+ | `fullSecretKeys` | `RegExp[]` | `[]` | Specifies keys at any level of the JSON object to be stringified and fully redacted. Primarily used for objects and arrays. |
51
+ | `customObjects` | `CustomObject[]` | `[]` | Specifies custom objects requiring fine-tuned redaction logic, such as referencing sibling keys. See the "Custom Objects" section for details. |
52
+ | `ignoreBooleans` | `boolean` | `false` | If `true`, booleans will not be redacted even if secret. |
53
+ | `ignoreNullOrUndefined` | `boolean` | `true` | If `true`, `null` and `undefined` values will not be redacted. |
54
+
55
+ ### `redactor` Configuration
56
+ Configures the redactor function used when a secret is encountered. Users should typically provide this configuration.
57
+
58
+ #### Details
59
+ - **Type:** `(val: any) => Promise<string>`
60
+ - **Effect:** The function used to redact values.
61
+ - Value can only be null or undefined if `ignoreNullOrUndefined` is set to false.
62
+ - Defaults to `() => Promise.resolve('REDACTED')`.
63
+
64
+ #### Example
65
+ ##### Code
66
+ ```typescript
67
+ import { FieldRedactor } from 'field-redactor';
68
+ import * as crypto from 'crypto';
69
+ const redactor: Redactor = (val: any) => Promise.resolve(crypto.createHash('sha256').update(val.toString()).digest('hex'));
70
+ const fieldRedactor = new FieldRedactor({
71
+ redactor
72
+ });
73
+ const result = await redactor.redact({foo: "bar"});
74
+ console.log(result);
75
+ ```
76
+
77
+ ##### Output
78
+ ```bash
79
+ 'fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9'
80
+ ```
81
+
82
+ ### `secretKeys` Configuration
83
+ Used to specify primitive that should be redacted. If none of `secretKeys`, `deepSecretKeys`, or `fullSecretKeys` specified then all values are considered secret. Users should almost always specify at least one of these three fields. Has the lowest precedence of all configurable secret fields.
84
+
85
+ #### Details
86
+ - **Type:** `RegExp[]`
87
+ - **Default:** All values considered secret
88
+ - If `deepSecretKeys` or `fullSecretKeys` specified, defaults to `[]`
89
+ - **Effect:** Matches keys in objects or child objects and redacts their values, if primitive. Arrays are processed recursively, with primitives redacted.
90
+ - If the value is an object it will be assessed using the same logic, regardless of if its key value is a secret.
91
+ - if an array value is an object it will be assessed using the same logic, regardless of if its key value is a secret.
92
+ - Has lowest precedence when compared to `deepSecretKeys`, `fullSecretKeys`, and `customObjects` configurations.
93
+
94
+ #### Example
95
+ ##### Code
96
+ ```typescript
97
+ import { FieldRedactor } from 'field-redactor';
98
+ const myJsonObject = {
99
+ timestamp: "2024-12-01T22:07:26.448Z",
100
+ userId: 271,
101
+ contactInfo: {
102
+ email: "foo.bar@example.com",
103
+ firstName: "Foo",
104
+ lastName: "Bar",
105
+ Salutation: "Mr.",
106
+ preference: "email",
107
+ lastUpdated: "2024-12-01T22:07:26.448Z"
108
+ },
109
+ someSecretData: ["fizz", "buzz", { deep: "is not redacted", name: "foobar" }],
110
+ hobbies: ["Basketball", "Baseball", "Tennis"]
111
+ }
112
+ const fieldRedactor = new FieldRedactor({
113
+ secretKeys: [/email/i, /name/i, /someSecretData/i, /contactInfo/i],
114
+ });
115
+ const result = await fieldRedactor.redact(myJsonObject);
116
+ console.log(result);
117
+ ```
118
+
119
+ ##### Output
120
+ ```json
121
+ {
122
+ "timestamp": "2024-12-01T22:07:26.448Z",
123
+ "userId": 271,
124
+ "contactInfo": {
125
+ "email": "REDACTED",
126
+ "firstName": "REDACTED",
127
+ "lastName": "REDACTED",
128
+ "Salutation": "Mr.",
129
+ "preference": "email",
130
+ "lastUpdated": "2024-12-01T22:07:26.448Z"
131
+ },
132
+ "someSecretData": ["REDACTED", "REDACTED", { "deep": "is not redacted", "name": "REDACTED" }],
133
+ "hobbies": ["Basketball", "Baseball", "Tennis"]
134
+ }
135
+ ```
136
+
137
+ > - contactInfo was not redacted despite being a RegExp match as it is not a primitive.
138
+ > - `email`, `firstName`, and `lastName` fields were redacted in contactInfo as they matched RegExes
139
+ > - primitives in `someSecretData` array value were redacted
140
+ > - object in `someSecretData` was evaluated separate from primitives in the same array
141
+
142
+ ### `deepSecretKeys` Configuration
143
+ Used to specify secrets which should be deeply redacted. Values which are objects or arrays will have all their values redacted, including child objects and arrays, unless identified as a `fullSecretKey` or `customObject` which take higher precedence.
144
+
145
+ #### Details
146
+ - **Type:** `RegExp[]`
147
+ - **Default:** `[]`
148
+ - **Effect:** Matches keys in objects or child objects and deeply redacts all values, including values in child objects or objects within arrays.
149
+ - Has higher precedence than `secretKeys` but lower precedence than `fullSecretKeys` and `customObjects`.
150
+
151
+ #### Example
152
+ ##### Code
153
+ ```typescript
154
+ import { FieldRedactor } from 'field-redactor';
155
+ const myJsonObject = {
156
+ timestamp: "2024-12-01T22:07:26.448Z",
157
+ userId: 271,
158
+ contactInfo: {
159
+ email: "foo.bar@example.com",
160
+ firstName: "Foo",
161
+ lastName: "Bar",
162
+ Salutation: "Mr.",
163
+ preference: "email",
164
+ lastUpdated: "2024-12-01T22:07:26.448Z",
165
+ lastUpdatedBy: {
166
+ firstName: "John",
167
+ lastName: "Doe",
168
+ id: "12345"
169
+ }
170
+ },
171
+ someSecretData: ["fizz", "buzz", { deep: "FOO", name: "BAR" }],
172
+ hobbies: ["Basketball", "Baseball", "Tennis", {contactInfo: "foobar"}]
173
+ }
174
+ const fieldRedactor = new FieldRedactor({
175
+ deepSecretKeys: [/someSecretData/i, /contactInfo/i]
176
+ });
177
+ const result = await fieldRedactor.redact(myJsonObject);
178
+ console.log(result);
179
+ ```
180
+
181
+ ##### Output
182
+ ```json
183
+ {
184
+ "timestamp": "2024-12-01T22:07:26.448Z",
185
+ "userId": 271,
186
+ "contactInfo": {
187
+ "email": "REDACTED",
188
+ "firstName": "REDACTED",
189
+ "lastName": "REDACTED",
190
+ "Salutation": "REDACTED",
191
+ "preference": "REDACTED",
192
+ "lastUpdated": "REDACTED",
193
+ "lastUpdatedBy": {
194
+ "firstName": "REDACTED",
195
+ "lastName": "REDACTED",
196
+ "id": "REDACTED"
197
+ }
198
+ },
199
+ "someSecretData": ["REDACTED", "REDACTED", { "deep": "REDACTED", "name": "REDACTED" }],
200
+ "hobbies": ["Basketball", "Baseball", "Tennis", { "contactInfo": "REDACTED" }]
201
+ }
202
+ ```
203
+ > - All values in `contactInfo` were redacted, including deep children
204
+ > - All values in `someSecretData` were redacted, including object values
205
+
206
+ ### `fullSecretKeys` Configuration
207
+ Specifies values which should be stringified and passed to the redactor function. Has higher precedence than other secret types but lower precedence than `customObjects`. However, if value is stringified and contains a child object which is a custom object then it will, by definition, not be noticed.
208
+
209
+ #### Details
210
+ - **Type:** `RegExp[]`
211
+ - **Default:** `[]`
212
+ - **Effect:** Matches keys in objects or child objects and stringifies and fully redacts their values.
213
+ - Has higher precedence than `secretKeys` and `deepSecretKeys` but lower precedence than `customObjects`.
214
+
215
+ #### Example
216
+ ##### Code
217
+ ```typescript
218
+ import { FieldRedactor } from 'field-redactor';
219
+
220
+ const myJsonObject = {
221
+ timestamp: "2024-12-01T22:07:26.448Z",
222
+ userId: 271,
223
+ contactInfo: {
224
+ email: "foo.bar@example.com",
225
+ firstName: "Foo",
226
+ lastName: "Bar",
227
+ Salutation: "Mr.",
228
+ preference: "email",
229
+ lastUpdated: "2024-12-01T22:07:26.448Z"
230
+ },
231
+ someSecretData: ["fizz", "buzz", { deep: "foo", name: "bar" }],
232
+ hobbies: ["Basketball", "Baseball", "Tennis"]
233
+ }
234
+ const fieldRedactor = new FieldRedactor({
235
+ fullSecretKeys: [/someSecretData/i, /contactInfo/i],
236
+ });
237
+ const result = await fieldRedactor.redact(myJsonObject);
238
+ console.log(result);
239
+ ```
240
+
241
+ ##### Output
242
+ ```json
243
+ {
244
+ "timestamp": "2024-12-01T22:07:26.448Z",
245
+ "userId": 271,
246
+ "contactInfo": "REDACTED",
247
+ "someSecretData": "REDACTED",
248
+ "hobbies": ["Basketball", "Baseball", "Tennis"]
249
+ }
250
+ ```
251
+ > - Entirity of `contactInfo` was redacted.
252
+ > - Entirity of `someSecretData` was redacted.
253
+
254
+ ### `customObjects` Configuration
255
+ **One of the most powerful features of this library and why it was written in the first place.** Combining `secretKeys`, `deepSecretKeys`, `fullSecretKeys`, and `customObjects` yields a powerful and highly customizable redaction tool capable of conditionally redacting a broad variety of input JSON objects correctly according to a single schema configuration.
256
+
257
+ #### Details
258
+ - **Type:** `CustomObject` (See `CustomObject` Schema Section)
259
+ - **Default:** `[]`
260
+ - **Effect:** Any object that matches the schema will be considered a custom object and redacted based on the schema configuration.
261
+ - Priority supercedes all others. If a `CustomObject` is nested inside a `deepSecretKey` value then the `CustomObject` configuration takes precedence.
262
+ - If a `CustomObject` is found inside another `CustomObject` then the new `CustomObject` takes precedence.
263
+
264
+ #### `CustomObject` Schema
265
+ A custom object takes the following format:
266
+ ```typescript
267
+ {
268
+ [key]: CustomObjectMatchType | string
269
+ }
270
+ ```
271
+
272
+ - `key`
273
+ - **Type:** `string`
274
+ - **Effect:** Specifies the key for a custom object
275
+ - `value`:
276
+ - **Type:** `CustomObjectMatchType | string`
277
+ - **Effect:** Specifies how the value should be redacted
278
+ - `string` - checks if the sibling key with this name has a value which is a `secretKey`, `deepSecretKey`, or `fullSecretKey` and redacts accordingly
279
+ - `CustomObjectMatchType` - Redacts according to the match type. See `CustomObjectMatchType` Enum Section.
280
+
281
+
282
+ #### `CustomObjectMatchType` Enum
283
+ | Key | Description |
284
+ | --- | ----------- |
285
+ | `Full` | Stringify value and redact. Functions identical to `fullSecretKeys`. |
286
+ | `Deep` | Redact if primitive, deeply redact all values and children if object or array. Functions identical to `deepSecretKeys`. |
287
+ | `Shallow` | Redact if primitive or array of primitives and revery to normal evaluation if object or array contains object. Functions identical to `secretKeys`. |
288
+ | `Pass` | Do not redact if primitive value and revert to normal rules if an object. |
289
+ | `Ignore` | Do not redact if primitive and skip evaluation entirely if object or array. |
290
+
291
+ #### Example
292
+ ```typescript
293
+ import { FieldRedactor } from 'field-redactor';
294
+
295
+ const myCustomObject = {
296
+ name: CustomObjectMatchType.Ignore,
297
+ type: CustomObjectMatchType.Ignore,
298
+ significance: CustomObjectMatchType.Ignore,
299
+ shallowValue: "name",
300
+ deepValue: "type",
301
+ fullValue: "significance"
302
+ shallow: CustomObjectMatchType.Shallow,
303
+ deep: CustomObjectMatchType.Deep,
304
+ full: CustomObjectMatchType.Full,
305
+ pass: CustomObjectMatchType.Pass,
306
+ ignore: CustomObjectMatchType.Ignore
307
+ };
308
+
309
+ const myJsonObject = {
310
+ timestamp: "2024-12-01T22:07:26.448Z",
311
+ userId: 271,
312
+ data: [
313
+ {
314
+ name: "email",
315
+ type: "Secure",
316
+ significance: "meta"
317
+ shallowValue: "foo.bar@example.com",
318
+ deepValue: "foobar",
319
+ fullValue: "hello",
320
+ shallow: "hello",
321
+ deep: "hello",
322
+ full: "hello",
323
+ pass: "hello",
324
+ ignore: "hello"
325
+ },
326
+ {
327
+ name: "email",
328
+ type: "Secure",
329
+ significance: "meta",
330
+ shallowValue: {
331
+ hello: "world",
332
+ email: "foobar"
333
+ },
334
+ deepValue: {
335
+ hello: "world",
336
+ email: "foobar"
337
+ },
338
+ deepValue: {
339
+ hello: "world",
340
+ email: "foobar"
341
+ },
342
+ shallow: {
343
+ hello: "world",
344
+ email: "foobar"
345
+ },
346
+ deep: {
347
+ hello: "world",
348
+ email: "foobar"
349
+ },
350
+ full: {
351
+ hello: "world",
352
+ email: "foobar"
353
+ },
354
+ pass: {
355
+ hello: "world",
356
+ email: "foobar"
357
+ },
358
+ ignore: {
359
+ hello: "world",
360
+ email: "foobar"
361
+ }
362
+ }
363
+ ]
364
+ };
365
+ const fieldRedactor = new FieldRedactor({
366
+ secretKeys: [/email/],
367
+ deepSecretKeys: [/secure/i],
368
+ fullSecretKeys: [/meta/i],
369
+ customObjects: [myCustomObject]
370
+ });
371
+ const result = await fieldRedactor.redact(myJsonObject);
372
+ console.log(result);
373
+ ```
374
+
375
+ ##### Output
376
+ ```json
377
+ {
378
+ "timestamp": "2024-12-01T22:07:26.448Z",
379
+ "userId": 271,
380
+ "data": [
381
+ {
382
+ "name": "email",
383
+ "type": "Secure",
384
+ "shallowValue": "REDACTED",
385
+ "deepValue": "REDACTED",
386
+ "fullValue": "REDACTED",
387
+ "shallow": "REDACTED",
388
+ "deep": "REDACTED",
389
+ "full": "REDACTED",
390
+ "pass": "hello",
391
+ "ignore": "hello"
392
+ },
393
+ {
394
+ "name": "email",
395
+ "type": "Secure",
396
+ "shallowValue": {
397
+ "hello": "world",
398
+ "email": "REDACTED"
399
+ },
400
+ "deepValue": {
401
+ "hello": "REDACTED",
402
+ "email": "REDACTED"
403
+ },
404
+ "fullValue": "REDACTED",
405
+ "shallow": {
406
+ "hello": "world",
407
+ "email": "REDACTED"
408
+ },
409
+ "deep": {
410
+ "hello": "REDACTED",
411
+ "email": "REDACTED"
412
+ },
413
+ "full": "REDACTED",
414
+ "pass": {
415
+ "hello": "world",
416
+ "email": "REDACTED"
417
+ },
418
+ "ignore": {
419
+ "hello": "world",
420
+ "email": "foobar"
421
+ }
422
+ }
423
+ ]
424
+ };
425
+ ```
426
+ > - Both objects in the data array matched the custom object and were redacted accordingly
427
+ > - The first object contains only primitives whereas the second contains objects to highlight the differences
428
+ > - `name` and `type` field were never redacted in either object because `CustomObjectMatchType` was `Ignore`
429
+ > - `shallowValue`, `deepValue`, and `fullValue` had string key specifiers which matched a `shallowKey`, `deepSecretKey`, and `fullSecretKey`, respectively, and were redacted according to those rules.
430
+ > - `shallow`, `deep`, `full`, `pass`, and `ignore` fields were redacted according to their `CustomObjectMatchType` value specified in the schema.
431
+
432
+ ### `ignoreBooleans` Configuration
433
+ - **Type:** `boolean`
434
+ - **Default:** `false`
435
+ - **Effect:** Specifies if boolean values should be redacted.
436
+
437
+ ### Example
438
+ #### Code
439
+ ```typescript
440
+ import { FieldRedactor } from 'field-redactor';
441
+
442
+ const myJsonObject = {
443
+ foo: "bar",
444
+ fizz: false,
445
+ buzz: true
446
+ };
447
+ const fieldRedactor = new FieldRedactor({
448
+ ignoreBooleans: true,
449
+ secretKeys: [/foo/, /fizz/, /buzz/]
450
+ });
451
+
452
+ const result = await fieldRedactor.redact(myJsonObject);
453
+ console.log(result);
454
+ ```
455
+
456
+ #### Output
457
+ ```json
458
+ {
459
+ "foo": "REDACTED",
460
+ "fizz": false,
461
+ "buzz": true
462
+ }
463
+ ```
464
+
465
+ ### `ignoreNullOrUndefined` Configuration
466
+ - **Type:** `boolean`
467
+ - **Default:** `true`
468
+ - **Effect:** Specifies if null or undefined values shold be redacted.
469
+ - *Note: Ensure custom redaction function can appropriately handle null or undefined if set to false.*
470
+
471
+ ### Example
472
+ #### Code
473
+ ```typescript
474
+ const myJsonObject = {
475
+ foo: "bar",
476
+ fizz: null,
477
+ buzz: undefined
478
+ };
479
+ const fieldRedactor = new FieldRedactor({
480
+ ignoreNullOrUndefined: false
481
+ });
482
+
483
+ const result = await fieldRedactor.redact(myJsonObject);
484
+ console.log(result);
485
+ ```
486
+ #### Output
487
+ ```json
488
+ {
489
+ "foo": "REDACTED",
490
+ "fizz": "REDACTED",
491
+ "buzz": "REDACTED"
492
+ }
493
+ ```
494
+
495
+ ## Full Example
496
+ The following example illustrates the power and utility of this library when conditionally redacting JSON output for logging or other purposes. It allows users to specify the manner of redaction, which fields should be redacted and how, and specify custom object schemas with highly configurable redaction logic based on sibling keys or set rules. I find it a quite useful tool!
497
+
498
+ ##### Code
499
+ ```typescript
500
+ import { FieldRedactor } from 'field-redactor';
501
+ const myRedactor = (text: string) => Promise.resolve("REDACTED");
502
+ const metadataCustomObject: CustomObject = {
503
+ name: CustomObjectMatchTypes.Pass,
504
+ type: CustomObjectMatchTypes.Pass,
505
+ id: CustomObjectMatchTypes.Shallow,
506
+ value: "name"
507
+ };
508
+
509
+ const actionsCustomObject: CustomObject = {
510
+ userId: CustomObjectMatchTypes.Pass,
511
+ field: CustomObjectMatchTypes.Pass,
512
+ action: CustomObjectMatchTypes.Pass,
513
+ value: "field"
514
+ }
515
+
516
+ const fieldRedactor: FieldRedactor = new FieldRedactor({
517
+ redactor: myRedactor,
518
+ secretKeys: [/email/, /name/i, /someSecretData/, /children/],
519
+ deepSecretKeys: [/accountInfo/i, /someDeepSecretData/i, /privateInfo/i],
520
+ customObjects: [metadataCustomObject, actionsCustomObject],
521
+ ignoreNullOrUndefined: false
522
+ });
523
+
524
+ const myJsonObjectToRedact = {
525
+ timestamp: "2024-12-01T22:07:26.448Z",
526
+ userId: 271,
527
+ contactInfo: {
528
+ email: "foo.bar@example.com",
529
+ salutation: "Mr.",
530
+ firstName: "Foo",
531
+ lastName: "Bar",
532
+ dob: "1980-01-01",
533
+ backupEmail: undefined,
534
+ preference: "email",
535
+ lastUpdated: "2024-12-01T22:07:26.448Z"
536
+ },
537
+ someSecretData: ["fizz", "buzz", { deep: "is not redacted", name: "foobar" }],
538
+ accountInfo: {
539
+ balance: 123.45,
540
+ institution: "FizzBuz International"
541
+ information: {
542
+ routingNumber: 11111111,
543
+ acctNumber: 222222
544
+ }
545
+ },
546
+ actions: [
547
+ {
548
+ userId: 271,
549
+ field: "email",
550
+ action: "CREATE",
551
+ value: "foo.bar@example.com"
552
+ },
553
+ {
554
+ userId: 271,
555
+ field: "preference",
556
+ action: "UPDATE",
557
+ value: "email"
558
+ }
559
+ ],
560
+ metadata: [
561
+ {
562
+ name: "mdn",
563
+ type: "Number",
564
+ id: 12,
565
+ value: 16151112222
566
+ },
567
+ {
568
+ name: "children",
569
+ type: "Array",
570
+ id: 20,
571
+ value: ["John", "Paul","Ringo", "George"]
572
+ },
573
+ {
574
+ name: "traceId",
575
+ type: "String",
576
+ id: 10,
577
+ value: "1234-6587"
578
+ },
579
+ {
580
+ name: "privateInfo",
581
+ type: "Object",
582
+ id: 20,
583
+ value: {
584
+ mySecretThings: {
585
+ a: "foo",
586
+ b: "bar"
587
+ }
588
+ }
589
+ }
590
+ ],
591
+ hobbies: ["Basketball", "Baseball", "Tennis"],
592
+ someDeepSecretData: ["fizz", "buzz", { deep: "is redacted", name: "foobar" }],
593
+ someFullSecretData: {
594
+ foo: "bar"
595
+ },
596
+ someFullSecretData2: ["a", 1, "12"]
597
+ };
598
+
599
+ const result = await fieldRedactor.redact(myJsonObject);
600
+ console.log(result);
601
+ ```
602
+
603
+ ##### Output
604
+ ```json
605
+ {
606
+ "timestamp": "2024-12-01T22:07:26.448Z",
607
+ "userId": 271,
608
+ "contactInfo": {
609
+ "email": "REDACTED",
610
+ "salutation": "Mr.",
611
+ "firstName": "REDACTED",
612
+ "lastName": "REDACTED",
613
+ "dob": "REDACTED",
614
+ "backupEmail": "REDACTED",
615
+ "preference": "email",
616
+ "lastUpdated": "2024-12-01T22:07:26.448Z",
617
+ },
618
+ "someSecretData": ["REDACTED", "REDACTED", { "deep": "is not redacted", "name": "REDACTED" }],
619
+ "accountInfo": {
620
+ "balance": "REDACTED",
621
+ "institution": "REDACTED",
622
+ "information": {
623
+ "routingNumber": "REDACTED",
624
+ "acctNumber": "REDACTED"
625
+ }
626
+ },
627
+ "actions": [
628
+ {
629
+ "userId": 271,
630
+ "field": "email",
631
+ "action": "CREATE",
632
+ "value": "REDACTED"
633
+ },
634
+ {
635
+ "userId": 271,
636
+ "field": "preference",
637
+ "action": "UPDATE",
638
+ "value": "email"
639
+ }
640
+ ],
641
+ "metadata": [
642
+ {
643
+ "name": "mdn",
644
+ "type": "Number",
645
+ "id": "REDACTED",
646
+ "value": "REDACTED"
647
+ },
648
+ {
649
+ "name": "children",
650
+ "type": "Array",
651
+ "id": "REDACTED",
652
+ "value": ["REDACTED", "REDACTED", "REDACTED", "REDACTED"]
653
+ },
654
+ {
655
+ "name": "traceId",
656
+ "type": "String",
657
+ "id": 10,
658
+ "value": "1234-6587"
659
+ },
660
+ {
661
+ "name": "privateInfo",
662
+ "type": "Object",
663
+ "id": "REDACTED",
664
+ "value": {
665
+ "mySecretThings": {
666
+ "a": "REDACTED",
667
+ "b": "REDACTED"
668
+ }
669
+ }
670
+ }
671
+ ],
672
+ "hobbies": ["Basketball", "Baseball", "Tennis"],
673
+ "someDeepSecretData": ["REDACTED", "REDACTED", { "deep": "REDACTED", "name": "REDACTED" }],
674
+ "someFullSecretData": "REDACTED",
675
+ "someFullSecretData2": "REDACTED"
676
+ }
677
+ ```
@@ -0,0 +1,22 @@
1
+ import { CustomObject } from './types';
2
+ /**
3
+ * Utility for determining if a given object matches a CustomObject schema.
4
+ */
5
+ export declare class CustomObjectChecker {
6
+ private customObjects;
7
+ /**
8
+ * Creates a CustomObjectChecker with the specified CustomObjects.
9
+ * @param customObjects The CustomObjects to check against.
10
+ */
11
+ constructor(customObjects?: CustomObject[]);
12
+ /**
13
+ * Determines if the input value matches any of the custom objects provided in the constructor.
14
+ * @param value The value to compare against the custom objects.
15
+ * @returns A matching custom object if one exists, otherwise undefined.
16
+ */
17
+ getMatchingCustomObject(value: any): CustomObject | undefined;
18
+ private isCustomObject;
19
+ private customObjectDoesNotHaveExtraKeys;
20
+ private validateCustomObjects;
21
+ }
22
+ //# sourceMappingURL=customObjectChecker.d.ts.map