@logtape/redaction 0.11.0 → 0.12.0-dev.182
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/deno.json +34 -0
- package/dist/field.cjs +101 -0
- package/dist/field.d.cts +88 -0
- package/dist/field.d.cts.map +1 -0
- package/{types → dist}/field.d.ts +29 -33
- package/dist/field.d.ts.map +1 -0
- package/dist/field.js +100 -0
- package/dist/field.js.map +1 -0
- package/dist/mod.cjs +11 -0
- package/dist/mod.d.cts +3 -0
- package/dist/mod.d.ts +3 -0
- package/dist/mod.js +4 -0
- package/dist/pattern.cjs +75 -0
- package/dist/pattern.d.cts +126 -0
- package/dist/pattern.d.cts.map +1 -0
- package/{types → dist}/pattern.d.ts +27 -21
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +70 -0
- package/dist/pattern.js.map +1 -0
- package/field.test.ts +217 -0
- package/field.ts +164 -0
- package/mod.ts +8 -0
- package/package.json +28 -25
- package/pattern.test.ts +351 -0
- package/pattern.ts +209 -0
- package/tsdown.config.ts +11 -0
- package/esm/field.js +0 -112
- package/esm/mod.js +0 -2
- package/esm/package.json +0 -3
- package/esm/pattern.js +0 -84
- package/script/field.js +0 -118
- package/script/mod.js +0 -21
- package/script/package.json +0 -3
- package/script/pattern.js +0 -88
- package/types/_dnt.test_shims.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/_constants.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/_diff.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/_format.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_equals.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_exists.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_false.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_is_error.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_match.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_throws.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/assertion_error.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/assert/0.222.1/equal.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/fmt/0.222.1/colors.d.ts.map +0 -1
- package/types/field.d.ts.map +0 -1
- package/types/field.test.d.ts.map +0 -1
- package/types/mod.d.ts +0 -3
- package/types/mod.d.ts.map +0 -1
- package/types/pattern.d.ts.map +0 -1
- package/types/pattern.test.d.ts.map +0 -1
package/deno.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@logtape/redaction",
|
|
3
|
+
"version": "0.12.0-dev.182+c0393214",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"exports": "./mod.ts",
|
|
6
|
+
"exclude": [
|
|
7
|
+
"coverage/",
|
|
8
|
+
"npm/",
|
|
9
|
+
".dnt-import-map.json"
|
|
10
|
+
],
|
|
11
|
+
"tasks": {
|
|
12
|
+
"build": "pnpm build",
|
|
13
|
+
"test": "deno test",
|
|
14
|
+
"test:node": {
|
|
15
|
+
"dependencies": [
|
|
16
|
+
"build"
|
|
17
|
+
],
|
|
18
|
+
"command": "node --experimental-transform-types --test"
|
|
19
|
+
},
|
|
20
|
+
"test:bun": {
|
|
21
|
+
"dependencies": [
|
|
22
|
+
"build"
|
|
23
|
+
],
|
|
24
|
+
"command": "bun test"
|
|
25
|
+
},
|
|
26
|
+
"test-all": {
|
|
27
|
+
"dependencies": [
|
|
28
|
+
"test",
|
|
29
|
+
"test:node",
|
|
30
|
+
"test:bun"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/field.cjs
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
|
|
2
|
+
//#region field.ts
|
|
3
|
+
/**
|
|
4
|
+
* Default field patterns for redaction. These patterns will match
|
|
5
|
+
* common sensitive fields such as passwords, tokens, and personal
|
|
6
|
+
* information.
|
|
7
|
+
* @since 0.10.0
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_REDACT_FIELDS = [
|
|
10
|
+
/pass(?:code|phrase|word)/i,
|
|
11
|
+
/secret/i,
|
|
12
|
+
/token/i,
|
|
13
|
+
/key/i,
|
|
14
|
+
/credential/i,
|
|
15
|
+
/auth/i,
|
|
16
|
+
/signature/i,
|
|
17
|
+
/sensitive/i,
|
|
18
|
+
/private/i,
|
|
19
|
+
/ssn/i,
|
|
20
|
+
/email/i,
|
|
21
|
+
/phone/i,
|
|
22
|
+
/address/i
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Redacts properties in a {@link LogRecord} based on the provided field
|
|
26
|
+
* patterns and action.
|
|
27
|
+
*
|
|
28
|
+
* Note that it is a decorator which wraps the sink and redacts properties
|
|
29
|
+
* before passing them to the sink.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { getConsoleSink } from "@logtape/logtape";
|
|
34
|
+
* import { redactByField } from "@logtape/redaction";
|
|
35
|
+
*
|
|
36
|
+
* const sink = redactByField(getConsoleSink());
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @param sink The sink to wrap.
|
|
40
|
+
* @param options The redaction options.
|
|
41
|
+
* @returns The wrapped sink.
|
|
42
|
+
* @since 0.10.0
|
|
43
|
+
*/
|
|
44
|
+
function redactByField(sink, options = DEFAULT_REDACT_FIELDS) {
|
|
45
|
+
const opts = Array.isArray(options) ? { fieldPatterns: options } : options;
|
|
46
|
+
const wrapped = (record) => {
|
|
47
|
+
sink({
|
|
48
|
+
...record,
|
|
49
|
+
properties: redactProperties(record.properties, opts)
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
if (Symbol.dispose in sink) wrapped[Symbol.dispose] = sink[Symbol.dispose];
|
|
53
|
+
if (Symbol.asyncDispose in sink) wrapped[Symbol.asyncDispose] = sink[Symbol.asyncDispose];
|
|
54
|
+
return wrapped;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Redacts properties from an object based on specified field patterns.
|
|
58
|
+
*
|
|
59
|
+
* This function creates a shallow copy of the input object and applies
|
|
60
|
+
* redaction rules to its properties. For properties that match the redaction
|
|
61
|
+
* patterns, the function either removes them or transforms their values based
|
|
62
|
+
* on the provided action.
|
|
63
|
+
*
|
|
64
|
+
* The redaction process is recursive and will be applied to nested objects
|
|
65
|
+
* as well, allowing for deep redaction of sensitive data in complex object
|
|
66
|
+
* structures.
|
|
67
|
+
* @param properties The properties to redact.
|
|
68
|
+
* @param options The redaction options.
|
|
69
|
+
* @returns The redacted properties.
|
|
70
|
+
* @since 0.10.0
|
|
71
|
+
*/
|
|
72
|
+
function redactProperties(properties, options) {
|
|
73
|
+
const copy = { ...properties };
|
|
74
|
+
for (const field in copy) {
|
|
75
|
+
if (shouldFieldRedacted(field, options.fieldPatterns)) {
|
|
76
|
+
if (options.action == null || options.action === "delete") delete copy[field];
|
|
77
|
+
else copy[field] = options.action(copy[field]);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const value = copy[field];
|
|
81
|
+
if (typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) copy[field] = redactProperties(value, options);
|
|
82
|
+
}
|
|
83
|
+
return copy;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Checks if a field should be redacted based on the provided field patterns.
|
|
87
|
+
* @param field The field name to check.
|
|
88
|
+
* @param fieldPatterns The field patterns to match against.
|
|
89
|
+
* @returns `true` if the field should be redacted, `false` otherwise.
|
|
90
|
+
* @since 0.10.0
|
|
91
|
+
*/
|
|
92
|
+
function shouldFieldRedacted(field, fieldPatterns) {
|
|
93
|
+
for (const fieldPattern of fieldPatterns) if (typeof fieldPattern === "string") {
|
|
94
|
+
if (fieldPattern === field) return true;
|
|
95
|
+
} else if (fieldPattern.test(field)) return true;
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
exports.DEFAULT_REDACT_FIELDS = DEFAULT_REDACT_FIELDS;
|
|
101
|
+
exports.redactByField = redactByField;
|
package/dist/field.d.cts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Sink } from "@logtape/logtape";
|
|
2
|
+
|
|
3
|
+
//#region field.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The type for a field pattern used in redaction. A string or a regular
|
|
7
|
+
* expression that matches field names.
|
|
8
|
+
* @since 0.10.0
|
|
9
|
+
*/
|
|
10
|
+
type FieldPattern = string | RegExp;
|
|
11
|
+
/**
|
|
12
|
+
* An array of field patterns used for redaction. Each pattern can be
|
|
13
|
+
* a string or a regular expression that matches field names.
|
|
14
|
+
* @since 0.10.0
|
|
15
|
+
*/
|
|
16
|
+
type FieldPatterns = FieldPattern[];
|
|
17
|
+
/**
|
|
18
|
+
* Default field patterns for redaction. These patterns will match
|
|
19
|
+
* common sensitive fields such as passwords, tokens, and personal
|
|
20
|
+
* information.
|
|
21
|
+
* @since 0.10.0
|
|
22
|
+
*/
|
|
23
|
+
declare const DEFAULT_REDACT_FIELDS: FieldPatterns;
|
|
24
|
+
/**
|
|
25
|
+
* Options for redacting fields in a {@link LogRecord}. Used by
|
|
26
|
+
* the {@link redactByField} function.
|
|
27
|
+
* @since 0.10.0
|
|
28
|
+
*/
|
|
29
|
+
interface FieldRedactionOptions {
|
|
30
|
+
/**
|
|
31
|
+
* The field patterns to match against. This can be an array of
|
|
32
|
+
* strings or regular expressions. If a field matches any of the
|
|
33
|
+
* patterns, it will be redacted.
|
|
34
|
+
* @defaultValue {@link DEFAULT_REDACT_FIELDS}
|
|
35
|
+
*/
|
|
36
|
+
readonly fieldPatterns: FieldPatterns;
|
|
37
|
+
/**
|
|
38
|
+
* The action to perform on the matched fields. If not provided,
|
|
39
|
+
* the default action is to delete the field from the properties.
|
|
40
|
+
* If a function is provided, it will be called with the
|
|
41
|
+
* value of the field, and the return value will be used to replace
|
|
42
|
+
* the field in the properties.
|
|
43
|
+
* If the action is `"delete"`, the field will be removed from the
|
|
44
|
+
* properties.
|
|
45
|
+
* @default `"delete"`
|
|
46
|
+
*/
|
|
47
|
+
readonly action?: "delete" | ((value: unknown) => unknown);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Redacts properties in a {@link LogRecord} based on the provided field
|
|
51
|
+
* patterns and action.
|
|
52
|
+
*
|
|
53
|
+
* Note that it is a decorator which wraps the sink and redacts properties
|
|
54
|
+
* before passing them to the sink.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { getConsoleSink } from "@logtape/logtape";
|
|
59
|
+
* import { redactByField } from "@logtape/redaction";
|
|
60
|
+
*
|
|
61
|
+
* const sink = redactByField(getConsoleSink());
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @param sink The sink to wrap.
|
|
65
|
+
* @param options The redaction options.
|
|
66
|
+
* @returns The wrapped sink.
|
|
67
|
+
* @since 0.10.0
|
|
68
|
+
*/
|
|
69
|
+
declare function redactByField(sink: Sink | Sink & Disposable | Sink & AsyncDisposable, options?: FieldRedactionOptions | FieldPatterns): Sink | Sink & Disposable | Sink & AsyncDisposable;
|
|
70
|
+
/**
|
|
71
|
+
* Redacts properties from an object based on specified field patterns.
|
|
72
|
+
*
|
|
73
|
+
* This function creates a shallow copy of the input object and applies
|
|
74
|
+
* redaction rules to its properties. For properties that match the redaction
|
|
75
|
+
* patterns, the function either removes them or transforms their values based
|
|
76
|
+
* on the provided action.
|
|
77
|
+
*
|
|
78
|
+
* The redaction process is recursive and will be applied to nested objects
|
|
79
|
+
* as well, allowing for deep redaction of sensitive data in complex object
|
|
80
|
+
* structures.
|
|
81
|
+
* @param properties The properties to redact.
|
|
82
|
+
* @param options The redaction options.
|
|
83
|
+
* @returns The redacted properties.
|
|
84
|
+
* @since 0.10.0
|
|
85
|
+
*/
|
|
86
|
+
//#endregion
|
|
87
|
+
export { DEFAULT_REDACT_FIELDS, FieldPattern, FieldPatterns, FieldRedactionOptions, redactByField };
|
|
88
|
+
//# sourceMappingURL=field.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.d.cts","names":[],"sources":["../field.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AAOA;AAQA;AAqBiB,KApCL,YAAA,GAoCK,MAAqB,GApCF,MA2CV;AAmC1B;;;;;AACmC,KAxEvB,aAAA,GAAgB,YAwEO,EAAA;;;;;;;AAEL,cAlEjB,qBAkEiB,EAlEM,aAkEN;;AAAsB;;;;UA7CnC,qBAAA;;;;;;;0BAOS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCV,aAAA,OACR,OAAO,OAAO,aAAa,OAAO,2BAC/B,wBAAwB,gBAChC,OAAO,OAAO,aAAa,OAAO"}
|
|
@@ -1,47 +1,50 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Sink } from "@logtape/logtape";
|
|
2
|
+
|
|
3
|
+
//#region field.d.ts
|
|
4
|
+
|
|
2
5
|
/**
|
|
3
6
|
* The type for a field pattern used in redaction. A string or a regular
|
|
4
7
|
* expression that matches field names.
|
|
5
8
|
* @since 0.10.0
|
|
6
9
|
*/
|
|
7
|
-
|
|
10
|
+
type FieldPattern = string | RegExp;
|
|
8
11
|
/**
|
|
9
12
|
* An array of field patterns used for redaction. Each pattern can be
|
|
10
13
|
* a string or a regular expression that matches field names.
|
|
11
14
|
* @since 0.10.0
|
|
12
15
|
*/
|
|
13
|
-
|
|
16
|
+
type FieldPatterns = FieldPattern[];
|
|
14
17
|
/**
|
|
15
18
|
* Default field patterns for redaction. These patterns will match
|
|
16
19
|
* common sensitive fields such as passwords, tokens, and personal
|
|
17
20
|
* information.
|
|
18
21
|
* @since 0.10.0
|
|
19
22
|
*/
|
|
20
|
-
|
|
23
|
+
declare const DEFAULT_REDACT_FIELDS: FieldPatterns;
|
|
21
24
|
/**
|
|
22
25
|
* Options for redacting fields in a {@link LogRecord}. Used by
|
|
23
26
|
* the {@link redactByField} function.
|
|
24
27
|
* @since 0.10.0
|
|
25
28
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
interface FieldRedactionOptions {
|
|
30
|
+
/**
|
|
31
|
+
* The field patterns to match against. This can be an array of
|
|
32
|
+
* strings or regular expressions. If a field matches any of the
|
|
33
|
+
* patterns, it will be redacted.
|
|
34
|
+
* @defaultValue {@link DEFAULT_REDACT_FIELDS}
|
|
35
|
+
*/
|
|
36
|
+
readonly fieldPatterns: FieldPatterns;
|
|
37
|
+
/**
|
|
38
|
+
* The action to perform on the matched fields. If not provided,
|
|
39
|
+
* the default action is to delete the field from the properties.
|
|
40
|
+
* If a function is provided, it will be called with the
|
|
41
|
+
* value of the field, and the return value will be used to replace
|
|
42
|
+
* the field in the properties.
|
|
43
|
+
* If the action is `"delete"`, the field will be removed from the
|
|
44
|
+
* properties.
|
|
45
|
+
* @default `"delete"`
|
|
46
|
+
*/
|
|
47
|
+
readonly action?: "delete" | ((value: unknown) => unknown);
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Redacts properties in a {@link LogRecord} based on the provided field
|
|
@@ -63,7 +66,7 @@ export interface FieldRedactionOptions {
|
|
|
63
66
|
* @returns The wrapped sink.
|
|
64
67
|
* @since 0.10.0
|
|
65
68
|
*/
|
|
66
|
-
|
|
69
|
+
declare function redactByField(sink: Sink | Sink & Disposable | Sink & AsyncDisposable, options?: FieldRedactionOptions | FieldPatterns): Sink | Sink & Disposable | Sink & AsyncDisposable;
|
|
67
70
|
/**
|
|
68
71
|
* Redacts properties from an object based on specified field patterns.
|
|
69
72
|
*
|
|
@@ -80,13 +83,6 @@ export declare function redactByField(sink: Sink | Sink & Disposable | Sink & As
|
|
|
80
83
|
* @returns The redacted properties.
|
|
81
84
|
* @since 0.10.0
|
|
82
85
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* Checks if a field should be redacted based on the provided field patterns.
|
|
86
|
-
* @param field The field name to check.
|
|
87
|
-
* @param fieldPatterns The field patterns to match against.
|
|
88
|
-
* @returns `true` if the field should be redacted, `false` otherwise.
|
|
89
|
-
* @since 0.10.0
|
|
90
|
-
*/
|
|
91
|
-
export declare function shouldFieldRedacted(field: string, fieldPatterns: FieldPatterns): boolean;
|
|
86
|
+
//#endregion
|
|
87
|
+
export { DEFAULT_REDACT_FIELDS, FieldPattern, FieldPatterns, FieldRedactionOptions, redactByField };
|
|
92
88
|
//# sourceMappingURL=field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.d.ts","names":[],"sources":["../field.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AAOA;AAQA;AAqBiB,KApCL,YAAA,GAoCK,MAAqB,GApCF,MA2CV;AAmC1B;;;;;AACmC,KAxEvB,aAAA,GAAgB,YAwEO,EAAA;;;;;;;AAEL,cAlEjB,qBAkEiB,EAlEM,aAkEN;;AAAsB;;;;UA7CnC,qBAAA;;;;;;;0BAOS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCV,aAAA,OACR,OAAO,OAAO,aAAa,OAAO,2BAC/B,wBAAwB,gBAChC,OAAO,OAAO,aAAa,OAAO"}
|
package/dist/field.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//#region field.ts
|
|
2
|
+
/**
|
|
3
|
+
* Default field patterns for redaction. These patterns will match
|
|
4
|
+
* common sensitive fields such as passwords, tokens, and personal
|
|
5
|
+
* information.
|
|
6
|
+
* @since 0.10.0
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_REDACT_FIELDS = [
|
|
9
|
+
/pass(?:code|phrase|word)/i,
|
|
10
|
+
/secret/i,
|
|
11
|
+
/token/i,
|
|
12
|
+
/key/i,
|
|
13
|
+
/credential/i,
|
|
14
|
+
/auth/i,
|
|
15
|
+
/signature/i,
|
|
16
|
+
/sensitive/i,
|
|
17
|
+
/private/i,
|
|
18
|
+
/ssn/i,
|
|
19
|
+
/email/i,
|
|
20
|
+
/phone/i,
|
|
21
|
+
/address/i
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Redacts properties in a {@link LogRecord} based on the provided field
|
|
25
|
+
* patterns and action.
|
|
26
|
+
*
|
|
27
|
+
* Note that it is a decorator which wraps the sink and redacts properties
|
|
28
|
+
* before passing them to the sink.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { getConsoleSink } from "@logtape/logtape";
|
|
33
|
+
* import { redactByField } from "@logtape/redaction";
|
|
34
|
+
*
|
|
35
|
+
* const sink = redactByField(getConsoleSink());
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @param sink The sink to wrap.
|
|
39
|
+
* @param options The redaction options.
|
|
40
|
+
* @returns The wrapped sink.
|
|
41
|
+
* @since 0.10.0
|
|
42
|
+
*/
|
|
43
|
+
function redactByField(sink, options = DEFAULT_REDACT_FIELDS) {
|
|
44
|
+
const opts = Array.isArray(options) ? { fieldPatterns: options } : options;
|
|
45
|
+
const wrapped = (record) => {
|
|
46
|
+
sink({
|
|
47
|
+
...record,
|
|
48
|
+
properties: redactProperties(record.properties, opts)
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
if (Symbol.dispose in sink) wrapped[Symbol.dispose] = sink[Symbol.dispose];
|
|
52
|
+
if (Symbol.asyncDispose in sink) wrapped[Symbol.asyncDispose] = sink[Symbol.asyncDispose];
|
|
53
|
+
return wrapped;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Redacts properties from an object based on specified field patterns.
|
|
57
|
+
*
|
|
58
|
+
* This function creates a shallow copy of the input object and applies
|
|
59
|
+
* redaction rules to its properties. For properties that match the redaction
|
|
60
|
+
* patterns, the function either removes them or transforms their values based
|
|
61
|
+
* on the provided action.
|
|
62
|
+
*
|
|
63
|
+
* The redaction process is recursive and will be applied to nested objects
|
|
64
|
+
* as well, allowing for deep redaction of sensitive data in complex object
|
|
65
|
+
* structures.
|
|
66
|
+
* @param properties The properties to redact.
|
|
67
|
+
* @param options The redaction options.
|
|
68
|
+
* @returns The redacted properties.
|
|
69
|
+
* @since 0.10.0
|
|
70
|
+
*/
|
|
71
|
+
function redactProperties(properties, options) {
|
|
72
|
+
const copy = { ...properties };
|
|
73
|
+
for (const field in copy) {
|
|
74
|
+
if (shouldFieldRedacted(field, options.fieldPatterns)) {
|
|
75
|
+
if (options.action == null || options.action === "delete") delete copy[field];
|
|
76
|
+
else copy[field] = options.action(copy[field]);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const value = copy[field];
|
|
80
|
+
if (typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) copy[field] = redactProperties(value, options);
|
|
81
|
+
}
|
|
82
|
+
return copy;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Checks if a field should be redacted based on the provided field patterns.
|
|
86
|
+
* @param field The field name to check.
|
|
87
|
+
* @param fieldPatterns The field patterns to match against.
|
|
88
|
+
* @returns `true` if the field should be redacted, `false` otherwise.
|
|
89
|
+
* @since 0.10.0
|
|
90
|
+
*/
|
|
91
|
+
function shouldFieldRedacted(field, fieldPatterns) {
|
|
92
|
+
for (const fieldPattern of fieldPatterns) if (typeof fieldPattern === "string") {
|
|
93
|
+
if (fieldPattern === field) return true;
|
|
94
|
+
} else if (fieldPattern.test(field)) return true;
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
export { DEFAULT_REDACT_FIELDS, redactByField };
|
|
100
|
+
//# sourceMappingURL=field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.js","names":["DEFAULT_REDACT_FIELDS: FieldPatterns","sink: Sink | Sink & Disposable | Sink & AsyncDisposable","options: FieldRedactionOptions | FieldPatterns","record: LogRecord","properties: Record<string, unknown>","options: FieldRedactionOptions","field: string","fieldPatterns: FieldPatterns"],"sources":["../field.ts"],"sourcesContent":["import type { LogRecord, Sink } from \"@logtape/logtape\";\n\n/**\n * The type for a field pattern used in redaction. A string or a regular\n * expression that matches field names.\n * @since 0.10.0\n */\nexport type FieldPattern = string | RegExp;\n\n/**\n * An array of field patterns used for redaction. Each pattern can be\n * a string or a regular expression that matches field names.\n * @since 0.10.0\n */\nexport type FieldPatterns = FieldPattern[];\n\n/**\n * Default field patterns for redaction. These patterns will match\n * common sensitive fields such as passwords, tokens, and personal\n * information.\n * @since 0.10.0\n */\nexport const DEFAULT_REDACT_FIELDS: FieldPatterns = [\n /pass(?:code|phrase|word)/i,\n /secret/i,\n /token/i,\n /key/i,\n /credential/i,\n /auth/i,\n /signature/i,\n /sensitive/i,\n /private/i,\n /ssn/i,\n /email/i,\n /phone/i,\n /address/i,\n];\n\n/**\n * Options for redacting fields in a {@link LogRecord}. Used by\n * the {@link redactByField} function.\n * @since 0.10.0\n */\nexport interface FieldRedactionOptions {\n /**\n * The field patterns to match against. This can be an array of\n * strings or regular expressions. If a field matches any of the\n * patterns, it will be redacted.\n * @defaultValue {@link DEFAULT_REDACT_FIELDS}\n */\n readonly fieldPatterns: FieldPatterns;\n\n /**\n * The action to perform on the matched fields. If not provided,\n * the default action is to delete the field from the properties.\n * If a function is provided, it will be called with the\n * value of the field, and the return value will be used to replace\n * the field in the properties.\n * If the action is `\"delete\"`, the field will be removed from the\n * properties.\n * @default `\"delete\"`\n */\n readonly action?: \"delete\" | ((value: unknown) => unknown);\n}\n\n/**\n * Redacts properties in a {@link LogRecord} based on the provided field\n * patterns and action.\n *\n * Note that it is a decorator which wraps the sink and redacts properties\n * before passing them to the sink.\n *\n * @example\n * ```ts\n * import { getConsoleSink } from \"@logtape/logtape\";\n * import { redactByField } from \"@logtape/redaction\";\n *\n * const sink = redactByField(getConsoleSink());\n * ```\n *\n * @param sink The sink to wrap.\n * @param options The redaction options.\n * @returns The wrapped sink.\n * @since 0.10.0\n */\nexport function redactByField(\n sink: Sink | Sink & Disposable | Sink & AsyncDisposable,\n options: FieldRedactionOptions | FieldPatterns = DEFAULT_REDACT_FIELDS,\n): Sink | Sink & Disposable | Sink & AsyncDisposable {\n const opts = Array.isArray(options) ? { fieldPatterns: options } : options;\n const wrapped = (record: LogRecord) => {\n sink({ ...record, properties: redactProperties(record.properties, opts) });\n };\n if (Symbol.dispose in sink) wrapped[Symbol.dispose] = sink[Symbol.dispose];\n if (Symbol.asyncDispose in sink) {\n wrapped[Symbol.asyncDispose] = sink[Symbol.asyncDispose];\n }\n return wrapped;\n}\n\n/**\n * Redacts properties from an object based on specified field patterns.\n *\n * This function creates a shallow copy of the input object and applies\n * redaction rules to its properties. For properties that match the redaction\n * patterns, the function either removes them or transforms their values based\n * on the provided action.\n *\n * The redaction process is recursive and will be applied to nested objects\n * as well, allowing for deep redaction of sensitive data in complex object\n * structures.\n * @param properties The properties to redact.\n * @param options The redaction options.\n * @returns The redacted properties.\n * @since 0.10.0\n */\nexport function redactProperties(\n properties: Record<string, unknown>,\n options: FieldRedactionOptions,\n): Record<string, unknown> {\n const copy = { ...properties };\n for (const field in copy) {\n if (shouldFieldRedacted(field, options.fieldPatterns)) {\n if (options.action == null || options.action === \"delete\") {\n delete copy[field];\n } else {\n copy[field] = options.action(copy[field]);\n }\n continue;\n }\n const value = copy[field];\n // Check if value is a vanilla object:\n if (\n typeof value === \"object\" && value !== null &&\n (Object.getPrototypeOf(value) === Object.prototype ||\n Object.getPrototypeOf(value) === null)\n ) {\n // @ts-ignore: value is always Record<string, unknown>\n copy[field] = redactProperties(value, options);\n }\n }\n return copy;\n}\n\n/**\n * Checks if a field should be redacted based on the provided field patterns.\n * @param field The field name to check.\n * @param fieldPatterns The field patterns to match against.\n * @returns `true` if the field should be redacted, `false` otherwise.\n * @since 0.10.0\n */\nexport function shouldFieldRedacted(\n field: string,\n fieldPatterns: FieldPatterns,\n): boolean {\n for (const fieldPattern of fieldPatterns) {\n if (typeof fieldPattern === \"string\") {\n if (fieldPattern === field) return true;\n } else {\n if (fieldPattern.test(field)) return true;\n }\n }\n return false;\n}\n"],"mappings":";;;;;;;AAsBA,MAAaA,wBAAuC;CAClD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD;;;;;;;;;;;;;;;;;;;;;AAiDD,SAAgB,cACdC,MACAC,UAAiD,uBACE;CACnD,MAAM,OAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,eAAe,QAAS,IAAG;CACnE,MAAM,UAAU,CAACC,WAAsB;AACrC,OAAK;GAAE,GAAG;GAAQ,YAAY,iBAAiB,OAAO,YAAY,KAAK;EAAE,EAAC;CAC3E;AACD,KAAI,OAAO,WAAW,KAAM,SAAQ,OAAO,WAAW,KAAK,OAAO;AAClE,KAAI,OAAO,gBAAgB,KACzB,SAAQ,OAAO,gBAAgB,KAAK,OAAO;AAE7C,QAAO;AACR;;;;;;;;;;;;;;;;;AAkBD,SAAgB,iBACdC,YACAC,SACyB;CACzB,MAAM,OAAO,EAAE,GAAG,WAAY;AAC9B,MAAK,MAAM,SAAS,MAAM;AACxB,MAAI,oBAAoB,OAAO,QAAQ,cAAc,EAAE;AACrD,OAAI,QAAQ,UAAU,QAAQ,QAAQ,WAAW,SAC/C,QAAO,KAAK;OAEZ,MAAK,SAAS,QAAQ,OAAO,KAAK,OAAO;AAE3C;EACD;EACD,MAAM,QAAQ,KAAK;AAEnB,aACS,UAAU,YAAY,UAAU,SACtC,OAAO,eAAe,MAAM,KAAK,OAAO,aACvC,OAAO,eAAe,MAAM,KAAK,MAGnC,MAAK,SAAS,iBAAiB,OAAO,QAAQ;CAEjD;AACD,QAAO;AACR;;;;;;;;AASD,SAAgB,oBACdC,OACAC,eACS;AACT,MAAK,MAAM,gBAAgB,cACzB,YAAW,iBAAiB,UAC1B;MAAI,iBAAiB,MAAO,QAAO;CAAK,WAEpC,aAAa,KAAK,MAAM,CAAE,QAAO;AAGzC,QAAO;AACR"}
|
package/dist/mod.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const require_field = require('./field.cjs');
|
|
2
|
+
const require_pattern = require('./pattern.cjs');
|
|
3
|
+
|
|
4
|
+
exports.CREDIT_CARD_NUMBER_PATTERN = require_pattern.CREDIT_CARD_NUMBER_PATTERN;
|
|
5
|
+
exports.DEFAULT_REDACT_FIELDS = require_field.DEFAULT_REDACT_FIELDS;
|
|
6
|
+
exports.EMAIL_ADDRESS_PATTERN = require_pattern.EMAIL_ADDRESS_PATTERN;
|
|
7
|
+
exports.JWT_PATTERN = require_pattern.JWT_PATTERN;
|
|
8
|
+
exports.KR_RRN_PATTERN = require_pattern.KR_RRN_PATTERN;
|
|
9
|
+
exports.US_SSN_PATTERN = require_pattern.US_SSN_PATTERN;
|
|
10
|
+
exports.redactByField = require_field.redactByField;
|
|
11
|
+
exports.redactByPattern = require_pattern.redactByPattern;
|
package/dist/mod.d.cts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DEFAULT_REDACT_FIELDS, FieldPattern, FieldPatterns, FieldRedactionOptions, redactByField } from "./field.cjs";
|
|
2
|
+
import { CREDIT_CARD_NUMBER_PATTERN, EMAIL_ADDRESS_PATTERN, JWT_PATTERN, KR_RRN_PATTERN, RedactionPattern, RedactionPatterns, US_SSN_PATTERN, redactByPattern } from "./pattern.cjs";
|
|
3
|
+
export { CREDIT_CARD_NUMBER_PATTERN, DEFAULT_REDACT_FIELDS, EMAIL_ADDRESS_PATTERN, FieldPattern, FieldPatterns, FieldRedactionOptions, JWT_PATTERN, KR_RRN_PATTERN, RedactionPattern, RedactionPatterns, US_SSN_PATTERN, redactByField, redactByPattern };
|
package/dist/mod.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DEFAULT_REDACT_FIELDS, FieldPattern, FieldPatterns, FieldRedactionOptions, redactByField } from "./field.js";
|
|
2
|
+
import { CREDIT_CARD_NUMBER_PATTERN, EMAIL_ADDRESS_PATTERN, JWT_PATTERN, KR_RRN_PATTERN, RedactionPattern, RedactionPatterns, US_SSN_PATTERN, redactByPattern } from "./pattern.js";
|
|
3
|
+
export { CREDIT_CARD_NUMBER_PATTERN, DEFAULT_REDACT_FIELDS, EMAIL_ADDRESS_PATTERN, FieldPattern, FieldPatterns, FieldRedactionOptions, JWT_PATTERN, KR_RRN_PATTERN, RedactionPattern, RedactionPatterns, US_SSN_PATTERN, redactByField, redactByPattern };
|
package/dist/mod.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_REDACT_FIELDS, redactByField } from "./field.js";
|
|
2
|
+
import { CREDIT_CARD_NUMBER_PATTERN, EMAIL_ADDRESS_PATTERN, JWT_PATTERN, KR_RRN_PATTERN, US_SSN_PATTERN, redactByPattern } from "./pattern.js";
|
|
3
|
+
|
|
4
|
+
export { CREDIT_CARD_NUMBER_PATTERN, DEFAULT_REDACT_FIELDS, EMAIL_ADDRESS_PATTERN, JWT_PATTERN, KR_RRN_PATTERN, US_SSN_PATTERN, redactByField, redactByPattern };
|
package/dist/pattern.cjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
|
|
2
|
+
//#region pattern.ts
|
|
3
|
+
/**
|
|
4
|
+
* A redaction pattern for email addresses.
|
|
5
|
+
* @since 0.10.0
|
|
6
|
+
*/
|
|
7
|
+
const EMAIL_ADDRESS_PATTERN = {
|
|
8
|
+
pattern: /[\p{L}0-9.!#$%&'*+/=?^_`{|}~-]+@[\p{L}0-9](?:[\p{L}0-9-]{0,61}[\p{L}0-9])?(?:\.[\p{L}0-9](?:[\p{L}0-9-]{0,61}[\p{L}0-9])?)+/gu,
|
|
9
|
+
replacement: "REDACTED@EMAIL.ADDRESS"
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A redaction pattern for credit card numbers (including American Express).
|
|
13
|
+
* @since 0.10.0
|
|
14
|
+
*/
|
|
15
|
+
const CREDIT_CARD_NUMBER_PATTERN = {
|
|
16
|
+
pattern: /(?:\d{4}-){3}\d{4}|(?:\d{4}-){2}\d{6}/g,
|
|
17
|
+
replacement: "XXXX-XXXX-XXXX-XXXX"
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* A redaction pattern for U.S. Social Security numbers.
|
|
21
|
+
* @since 0.10.0
|
|
22
|
+
*/
|
|
23
|
+
const US_SSN_PATTERN = {
|
|
24
|
+
pattern: /\d{3}-\d{2}-\d{4}/g,
|
|
25
|
+
replacement: "XXX-XX-XXXX"
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A redaction pattern for South Korean resident registration numbers
|
|
29
|
+
* (住民登錄番號).
|
|
30
|
+
* @since 0.10.0
|
|
31
|
+
*/
|
|
32
|
+
const KR_RRN_PATTERN = {
|
|
33
|
+
pattern: /\d{6}-\d{7}/g,
|
|
34
|
+
replacement: "XXXXXX-XXXXXXX"
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* A redaction pattern for JSON Web Tokens (JWT).
|
|
38
|
+
* @since 0.10.0
|
|
39
|
+
*/
|
|
40
|
+
const JWT_PATTERN = {
|
|
41
|
+
pattern: /eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/g,
|
|
42
|
+
replacement: "[JWT REDACTED]"
|
|
43
|
+
};
|
|
44
|
+
function redactByPattern(formatter, patterns) {
|
|
45
|
+
for (const { pattern } of patterns) if (!pattern.global) throw new TypeError(`Pattern ${pattern} does not have the global flag set.`);
|
|
46
|
+
function replaceString(str) {
|
|
47
|
+
for (const p of patterns) str = typeof p.replacement === "string" ? str.replaceAll(p.pattern, p.replacement) : str.replaceAll(p.pattern, p.replacement);
|
|
48
|
+
return str;
|
|
49
|
+
}
|
|
50
|
+
function replaceObject(object) {
|
|
51
|
+
if (typeof object === "string") return replaceString(object);
|
|
52
|
+
else if (Array.isArray(object)) return object.map(replaceObject);
|
|
53
|
+
else if (typeof object === "object" && object !== null) {
|
|
54
|
+
if (Object.getPrototypeOf(object) === Object.prototype || Object.getPrototypeOf(object) === null) {
|
|
55
|
+
const redacted = {};
|
|
56
|
+
for (const key in object) redacted[key] = replaceObject(object[key]);
|
|
57
|
+
return redacted;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return object;
|
|
61
|
+
}
|
|
62
|
+
return (record) => {
|
|
63
|
+
const output = formatter(record);
|
|
64
|
+
if (typeof output === "string") return replaceString(output);
|
|
65
|
+
return output.map(replaceObject);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
exports.CREDIT_CARD_NUMBER_PATTERN = CREDIT_CARD_NUMBER_PATTERN;
|
|
71
|
+
exports.EMAIL_ADDRESS_PATTERN = EMAIL_ADDRESS_PATTERN;
|
|
72
|
+
exports.JWT_PATTERN = JWT_PATTERN;
|
|
73
|
+
exports.KR_RRN_PATTERN = KR_RRN_PATTERN;
|
|
74
|
+
exports.US_SSN_PATTERN = US_SSN_PATTERN;
|
|
75
|
+
exports.redactByPattern = redactByPattern;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { ConsoleFormatter, TextFormatter } from "@logtape/logtape";
|
|
2
|
+
|
|
3
|
+
//#region pattern.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A redaction pattern, which is a pair of regular expression and replacement
|
|
7
|
+
* string or function.
|
|
8
|
+
* @since 0.10.0
|
|
9
|
+
*/
|
|
10
|
+
interface RedactionPattern {
|
|
11
|
+
/**
|
|
12
|
+
* The regular expression to match against. Note that it must have the
|
|
13
|
+
* `g` (global) flag set, otherwise it will throw a `TypeError`.
|
|
14
|
+
*/
|
|
15
|
+
readonly pattern: RegExp;
|
|
16
|
+
/**
|
|
17
|
+
* The replacement string or function. If the replacement is a function,
|
|
18
|
+
* it will be called with the matched string and any capture groups (the same
|
|
19
|
+
* signature as `String.prototype.replaceAll()`).
|
|
20
|
+
*/
|
|
21
|
+
readonly replacement: string | ((match: string, ...rest: readonly any[]) => string);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A redaction pattern for email addresses.
|
|
25
|
+
* @since 0.10.0
|
|
26
|
+
*/
|
|
27
|
+
declare const EMAIL_ADDRESS_PATTERN: RedactionPattern;
|
|
28
|
+
/**
|
|
29
|
+
* A redaction pattern for credit card numbers (including American Express).
|
|
30
|
+
* @since 0.10.0
|
|
31
|
+
*/
|
|
32
|
+
declare const CREDIT_CARD_NUMBER_PATTERN: RedactionPattern;
|
|
33
|
+
/**
|
|
34
|
+
* A redaction pattern for U.S. Social Security numbers.
|
|
35
|
+
* @since 0.10.0
|
|
36
|
+
*/
|
|
37
|
+
declare const US_SSN_PATTERN: RedactionPattern;
|
|
38
|
+
/**
|
|
39
|
+
* A redaction pattern for South Korean resident registration numbers
|
|
40
|
+
* (住民登錄番號).
|
|
41
|
+
* @since 0.10.0
|
|
42
|
+
*/
|
|
43
|
+
declare const KR_RRN_PATTERN: RedactionPattern;
|
|
44
|
+
/**
|
|
45
|
+
* A redaction pattern for JSON Web Tokens (JWT).
|
|
46
|
+
* @since 0.10.0
|
|
47
|
+
*/
|
|
48
|
+
declare const JWT_PATTERN: RedactionPattern;
|
|
49
|
+
/**
|
|
50
|
+
* A list of {@link RedactionPattern}s.
|
|
51
|
+
* @since 0.10.0
|
|
52
|
+
*/
|
|
53
|
+
type RedactionPatterns = readonly RedactionPattern[];
|
|
54
|
+
/**
|
|
55
|
+
* Applies data redaction to a {@link TextFormatter}.
|
|
56
|
+
*
|
|
57
|
+
* Note that there are some built-in redaction patterns:
|
|
58
|
+
*
|
|
59
|
+
* - {@link CREDIT_CARD_NUMBER_PATTERN}
|
|
60
|
+
* - {@link EMAIL_ADDRESS_PATTERN}
|
|
61
|
+
* - {@link JWT_PATTERN}
|
|
62
|
+
* - {@link KR_RRN_PATTERN}
|
|
63
|
+
* - {@link US_SSN_PATTERN}
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { getFileSink } from "@logtape/file";
|
|
68
|
+
* import { getAnsiColorFormatter } from "@logtape/logtape";
|
|
69
|
+
* import {
|
|
70
|
+
* CREDIT_CARD_NUMBER_PATTERN,
|
|
71
|
+
* EMAIL_ADDRESS_PATTERN,
|
|
72
|
+
* JWT_PATTERN,
|
|
73
|
+
* redactByPattern,
|
|
74
|
+
* } from "@logtape/redaction";
|
|
75
|
+
*
|
|
76
|
+
* const formatter = redactByPattern(getAnsiConsoleFormatter(), [
|
|
77
|
+
* CREDIT_CARD_NUMBER_PATTERN,
|
|
78
|
+
* EMAIL_ADDRESS_PATTERN,
|
|
79
|
+
* JWT_PATTERN,
|
|
80
|
+
* ]);
|
|
81
|
+
* const sink = getFileSink("my-app.log", { formatter });
|
|
82
|
+
* ```
|
|
83
|
+
* @param formatter The text formatter to apply redaction to.
|
|
84
|
+
* @param patterns The redaction patterns to apply.
|
|
85
|
+
* @returns The redacted text formatter.
|
|
86
|
+
* @since 0.10.0
|
|
87
|
+
*/
|
|
88
|
+
declare function redactByPattern(formatter: TextFormatter, patterns: RedactionPatterns): TextFormatter;
|
|
89
|
+
/**
|
|
90
|
+
* Applies data redaction to a {@link ConsoleFormatter}.
|
|
91
|
+
*
|
|
92
|
+
* Note that there are some built-in redaction patterns:
|
|
93
|
+
*
|
|
94
|
+
* - {@link CREDIT_CARD_NUMBER_PATTERN}
|
|
95
|
+
* - {@link EMAIL_ADDRESS_PATTERN}
|
|
96
|
+
* - {@link JWT_PATTERN}
|
|
97
|
+
* - {@link KR_RRN_PATTERN}
|
|
98
|
+
* - {@link US_SSN_PATTERN}
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* import { defaultConsoleFormatter, getConsoleSink } from "@logtape/logtape";
|
|
103
|
+
* import {
|
|
104
|
+
* CREDIT_CARD_NUMBER_PATTERN,
|
|
105
|
+
* EMAIL_ADDRESS_PATTERN,
|
|
106
|
+
* JWT_PATTERN,
|
|
107
|
+
* redactByPattern,
|
|
108
|
+
* } from "@logtape/redaction";
|
|
109
|
+
*
|
|
110
|
+
* const formatter = redactByPattern(defaultConsoleFormatter, [
|
|
111
|
+
* CREDIT_CARD_NUMBER_PATTERN,
|
|
112
|
+
* EMAIL_ADDRESS_PATTERN,
|
|
113
|
+
* JWT_PATTERN,
|
|
114
|
+
* ]);
|
|
115
|
+
* const sink = getConsoleSink({ formatter });
|
|
116
|
+
* ```
|
|
117
|
+
* @param formatter The console formatter to apply redaction to.
|
|
118
|
+
* @param patterns The redaction patterns to apply.
|
|
119
|
+
* @returns The redacted console formatter.
|
|
120
|
+
* @since 0.10.0
|
|
121
|
+
*/
|
|
122
|
+
declare function redactByPattern(formatter: ConsoleFormatter, patterns: RedactionPatterns): ConsoleFormatter;
|
|
123
|
+
//# sourceMappingURL=pattern.d.ts.map
|
|
124
|
+
//#endregion
|
|
125
|
+
export { CREDIT_CARD_NUMBER_PATTERN, EMAIL_ADDRESS_PATTERN, JWT_PATTERN, KR_RRN_PATTERN, RedactionPattern, RedactionPatterns, US_SSN_PATTERN, redactByPattern };
|
|
126
|
+
//# sourceMappingURL=pattern.d.cts.map
|