@alwaysmeticulous/redaction
Advanced tools
Comparing version 2.186.0 to 2.187.0
@@ -94,3 +94,128 @@ import { RecorderMiddleware, NetworkResponseMetadata } from "@alwaysmeticulous/sdk-bundles-api"; | ||
}) => string; | ||
export const redactEmail: (email: string) => string; | ||
export const redactUrl: (url: string) => string; | ||
export const redactPath: (path: string) => string; | ||
export const redactString: (str: string) => string; | ||
export type PatternBasedRedactor<KEY_TYPE extends string, VALUE_TYPE> = PostfixPatternBasedRedactor<KEY_TYPE, VALUE_TYPE> | ExactPatternBasedRedactor<KEY_TYPE, VALUE_TYPE>; | ||
export interface PostfixPatternBasedRedactor<KEY_TYPE extends string, VALUE_TYPE> { | ||
type: "key-postfix"; | ||
postfix: string; | ||
redactor: (value: VALUE_TYPE) => VALUE_TYPE; | ||
/** | ||
* This property is always undefined, but used to ensure type safety. | ||
*/ | ||
__keyType?: KEY_TYPE; | ||
} | ||
export interface ExactPatternBasedRedactor<KEY_TYPE extends string, VALUE_TYPE> { | ||
type: "key-exact"; | ||
key: KEY_TYPE; | ||
redactor: (value: VALUE_TYPE) => VALUE_TYPE; | ||
/** | ||
* This property is always undefined, but used to ensure type safety. | ||
*/ | ||
__keyType?: KEY_TYPE; | ||
} | ||
/** | ||
* Example: | ||
* | ||
* ``` | ||
* redactKeysEndingWith("name", asterixOut) | ||
* ``` | ||
* | ||
* Would redact `name` and `first_name` but not `firstName`. | ||
*/ | ||
export const redactKeysEndingWith: <POSTFIX_TYPE extends string, VALUE_TYPE>(postfix: string extends POSTFIX_TYPE ? never : POSTFIX_TYPE, redactor: (value: VALUE_TYPE) => VALUE_TYPE) => PatternBasedRedactor<`${string}${POSTFIX_TYPE}`, VALUE_TYPE>; | ||
export const redactKey: <KEY_TYPE extends string, VALUE_TYPE>(key: KEY_TYPE, redactor: (value: VALUE_TYPE) => VALUE_TYPE) => PatternBasedRedactor<KEY_TYPE, VALUE_TYPE>; | ||
export class PatternBasedRedactorSet<HANDLED_KEYS_TYPE extends string, VALUE_TYPE> { | ||
readonly redactors: PatternBasedRedactor<HANDLED_KEYS_TYPE, VALUE_TYPE>[]; | ||
private constructor(); | ||
static create<VALUE_TYPE>(): PatternBasedRedactorSet<never, VALUE_TYPE>; | ||
with<KEY_TYPE extends string>(redactor: PatternBasedRedactor<KEY_TYPE, VALUE_TYPE>): PatternBasedRedactorSet<HANDLED_KEYS_TYPE | KEY_TYPE, VALUE_TYPE>; | ||
withSet<KEY_TYPE extends string>(set: PatternBasedRedactorSet<KEY_TYPE, VALUE_TYPE>): PatternBasedRedactorSet<HANDLED_KEYS_TYPE | KEY_TYPE, VALUE_TYPE>; | ||
} | ||
/** | ||
* We include a default set of redactors here. Note that if you are using | ||
* redactNestedFields in typescript then if your objects include any string fields | ||
* that don't match the below list you'll still be forced at compile time to add an | ||
* explict redaction policy for them. | ||
*/ | ||
/** | ||
* We don't want to redact enum fields like "deserializerClassName", so we're | ||
* careful to only redact fields that are likely to be PII. | ||
*/ | ||
export const NAME_REDACTORS: PatternBasedRedactorSet<"name" | `${string}_name` | `${string}ullName` | `${string}irstname` | `${string}astname`, string>; | ||
export const URL_REDACTORS: PatternBasedRedactorSet<`${string}url` | `${string}uri` | `${string}link` | `${string}href` | `${string}Url` | `${string}Uri` | `${string}Link` | `${string}Href`, string>; | ||
export const OTHER_PII_REDACTORS: PatternBasedRedactorSet<"address" | `${string}addressLine1` | `${string}address_line_1` | `${string}homeAddress` | `${string}home_address` | `${string}postalAddress` | `${string}postal_address` | `${string}phone` | `${string}Phone` | `${string}phone_number` | `${string}ssn` | `${string}SSN` | `${string}username` | `${string}Username` | `${string}user_name` | `${string}credit_card` | `${string}creditCard` | `${string}credit_card_number` | `${string}creditCardNumber` | `${string}cvc` | `${string}CVC`, string>; | ||
export const FREE_TEXT_REDACTORS: PatternBasedRedactorSet<`${string}text` | `${string}description` | `${string}summary` | `${string}title`, string>; | ||
export const redactDateOfBirth: (_: Date) => Date; | ||
export const DOB_REDACTORS: PatternBasedRedactorSet<`${string}dob` | `${string}DOB` | `${string}date_of_birth` | `${string}dateOfBirth` | `${string}DateOfBirth` | `${string}birthDate` | `${string}BirthDate` | `${string}birth_date`, Date>; | ||
export const doNotRedact: <T>(value: T) => T; | ||
export const ID_REDACTORS: PatternBasedRedactorSet<"id" | `${string}Id` | `${string}ID` | `${string}_id` | `${string}uuid` | `${string}UUID` | `${string}uuidv4` | `${string}UUIDv4` | `${string}guid` | `${string}GUID` | `${string}Guid`, string>; | ||
export const TYPE_UNION_REDACTORS: PatternBasedRedactorSet<"type" | `${string}Type` | `${string}_type` | `${string}TYPE` | "kind" | `${string}Kind` | `${string}_kind`, string>; | ||
/** | ||
* We recommend not redacting fields like "created_at" or "updated_at" as | ||
* these are rarely sensitive, and preserving the original dates helps better | ||
* test your code's edge cases. | ||
*/ | ||
export const DATES_AS_STRINGS_THAT_DO_NOT_NEED_REDACTION: PatternBasedRedactorSet<`${string}ed_at` | `${string}edAt`, string>; | ||
export const ALL_STRING_FIELDS_THAT_DEFAULT_TO_NO_REDACTION: PatternBasedRedactorSet<"id" | `${string}Id` | `${string}ID` | `${string}_id` | `${string}uuid` | `${string}UUID` | `${string}uuidv4` | `${string}UUIDv4` | `${string}guid` | `${string}GUID` | `${string}Guid` | "type" | `${string}Type` | `${string}_type` | `${string}TYPE` | "kind" | `${string}Kind` | `${string}_kind` | `${string}ed_at` | `${string}edAt`, string>; | ||
export const ALL_DEFAULT_STRING_REDACTORS: PatternBasedRedactorSet<"name" | `${string}_name` | `${string}ullName` | `${string}irstname` | `${string}astname` | `${string}url` | `${string}uri` | `${string}link` | `${string}href` | `${string}Url` | `${string}Uri` | `${string}Link` | `${string}Href` | "address" | `${string}addressLine1` | `${string}address_line_1` | `${string}homeAddress` | `${string}home_address` | `${string}postalAddress` | `${string}postal_address` | `${string}phone` | `${string}Phone` | `${string}phone_number` | `${string}ssn` | `${string}SSN` | `${string}username` | `${string}Username` | `${string}user_name` | `${string}credit_card` | `${string}creditCard` | `${string}credit_card_number` | `${string}creditCardNumber` | `${string}cvc` | `${string}CVC` | `${string}text` | `${string}description` | `${string}summary` | `${string}title` | "id" | `${string}Id` | `${string}ID` | `${string}_id` | `${string}uuid` | `${string}UUID` | `${string}uuidv4` | `${string}UUIDv4` | `${string}guid` | `${string}GUID` | `${string}Guid` | "type" | `${string}Type` | `${string}_type` | `${string}TYPE` | "kind" | `${string}Kind` | `${string}_kind` | `${string}ed_at` | `${string}edAt`, string>; | ||
export const ALL_DEFAULT_DATE_REDACTORS: PatternBasedRedactorSet<`${string}dob` | `${string}DOB` | `${string}date_of_birth` | `${string}dateOfBirth` | `${string}DateOfBirth` | `${string}birthDate` | `${string}BirthDate` | `${string}birth_date`, Date>; | ||
type IsFixedStringUnion<T> = T extends string ? string extends T ? false : true : false; | ||
type WithoutNullOrUndefined<T> = T extends null | undefined ? never : T; | ||
type AllValues<T> = UnionToIntersection<T>[keyof UnionToIntersection<T>]; | ||
type RelevantPrimitiveFieldNames<T, PRIMATIVES_TO_REDACT = string | Date> = AllValues<{ | ||
[K in keyof T]: PrimitiveFieldNamesHelper<K, WithoutNullOrUndefined<T[K]>, PRIMATIVES_TO_REDACT>; | ||
}>; | ||
type PrimitiveFieldNamesHelper<K, V, PRIMATIVES_TO_REDACT> = IsFixedStringUnion<V> extends true ? never : V extends PRIMATIVES_TO_REDACT ? [K, V] : V extends Array<infer U> ? U extends PRIMATIVES_TO_REDACT ? [K, U] : RelevantPrimitiveFieldNames<U> : V extends object ? RelevantPrimitiveFieldNames<V> : never; | ||
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; | ||
type Redactor<T> = (value: T) => T; | ||
type ToRedactorObject<T> = T extends [infer K, infer V] ? K extends string ? { | ||
[P in K]: Redactor<V>; | ||
} : never : never; | ||
type TuplePairsToRedactorObject<T> = UnionToIntersection<ToRedactorObject<T>>; | ||
type RedactorsFor<T, PRIMATIVES_TO_REDACT = string> = TuplePairsToRedactorObject<RelevantPrimitiveFieldNames<T, PRIMATIVES_TO_REDACT>>; | ||
export class NestedFieldsRedactor<HANDLED_STRING_KEY_TYPES extends string, HANDLED_DATE_KEY_TYPES extends string> { | ||
private constructor(); | ||
static builder(): NestedFieldsRedactor<never, never>; | ||
/** | ||
* Provides an opinionated set of redactors that are useful for most use cases, | ||
* which can then be built upon. See {@link ALL_DEFAULT_STRING_REDACTORS} and | ||
* {@link ALL_DEFAULT_DATE_REDACTORS} for more details. | ||
* | ||
* (recommended) | ||
*/ | ||
static builderWithDefaults(): NestedFieldsRedactor<"name" | `${string}_name` | `${string}ullName` | `${string}irstname` | `${string}astname` | `${string}url` | `${string}uri` | `${string}link` | `${string}href` | `${string}Url` | `${string}Uri` | `${string}Link` | `${string}Href` | "address" | `${string}addressLine1` | `${string}address_line_1` | `${string}homeAddress` | `${string}home_address` | `${string}postalAddress` | `${string}postal_address` | `${string}phone` | `${string}Phone` | `${string}phone_number` | `${string}ssn` | `${string}SSN` | `${string}username` | `${string}Username` | `${string}user_name` | `${string}credit_card` | `${string}creditCard` | `${string}credit_card_number` | `${string}creditCardNumber` | `${string}cvc` | `${string}CVC` | `${string}text` | `${string}description` | `${string}summary` | `${string}title` | "id" | `${string}Id` | `${string}ID` | `${string}_id` | `${string}uuid` | `${string}UUID` | `${string}uuidv4` | `${string}UUIDv4` | `${string}guid` | `${string}GUID` | `${string}Guid` | "type" | `${string}Type` | `${string}_type` | `${string}TYPE` | "kind" | `${string}Kind` | `${string}_kind` | `${string}ed_at` | `${string}edAt`, `${string}dob` | `${string}DOB` | `${string}date_of_birth` | `${string}dateOfBirth` | `${string}DateOfBirth` | `${string}birthDate` | `${string}BirthDate` | `${string}birth_date`>; | ||
withPatternBasedStringRedactor<KEY_TYPE extends string>(redactor: PatternBasedRedactor<KEY_TYPE, string>): NestedFieldsRedactor<HANDLED_STRING_KEY_TYPES & KEY_TYPE, HANDLED_DATE_KEY_TYPES>; | ||
withPatternBasedStringRedactors<KEY_TYPE extends string>(set: PatternBasedRedactorSet<KEY_TYPE, string>): NestedFieldsRedactor<HANDLED_STRING_KEY_TYPES | KEY_TYPE, HANDLED_DATE_KEY_TYPES>; | ||
withPatternBasedDateRedactor<KEY_TYPE extends string>(redactor: PatternBasedRedactor<KEY_TYPE, Date>): NestedFieldsRedactor<HANDLED_STRING_KEY_TYPES, HANDLED_DATE_KEY_TYPES | KEY_TYPE>; | ||
withPatternBasedDateRedactors<KEY_TYPE extends string>(set: PatternBasedRedactorSet<KEY_TYPE, Date>): NestedFieldsRedactor<HANDLED_STRING_KEY_TYPES, HANDLED_DATE_KEY_TYPES | KEY_TYPE>; | ||
/** | ||
* Type safety: forces a redaction policy to be set for every unique nested string field name in the object. | ||
* Leaves redaction of dates, numbers and bigints as optional. | ||
*/ | ||
createRedactor<T>(opts: { | ||
strings: Omit<RedactorsFor<T>, HANDLED_STRING_KEY_TYPES>; | ||
dates?: Omit<Partial<RedactorsFor<T, Date>>, HANDLED_DATE_KEY_TYPES>; | ||
numbers?: Partial<RedactorsFor<T, number>>; | ||
bigints?: Partial<RedactorsFor<T, bigint>>; | ||
}): (value: T) => T; | ||
/** | ||
* Type safety: forces a redaction policy to be set for every unique nested string, date, number and bigint | ||
* field name in the object. | ||
*/ | ||
createRedactorStrict<T>(opts: { | ||
strings: Omit<RedactorsFor<T>, HANDLED_STRING_KEY_TYPES>; | ||
dates: Omit<RedactorsFor<T, Date>, HANDLED_DATE_KEY_TYPES>; | ||
numbers: RedactorsFor<T, number>; | ||
bigints: RedactorsFor<T, bigint>; | ||
}): (value: T) => T; | ||
redactNestedStringFieldsNonTypeSafe: <T>(opts: { | ||
strings: Record<string, Redactor<string>>; | ||
dates?: Record<string, Redactor<Date>>; | ||
numbers?: Record<string, Redactor<number>>; | ||
bigints?: Record<string, Redactor<bigint>>; | ||
}) => (value: T) => T; | ||
} | ||
//# sourceMappingURL=index.d.ts.map |
@@ -152,2 +152,294 @@ function $parcel$exportWildcard(dest, source) { | ||
var $042914f81553c43b$exports = {}; | ||
$parcel$export($042914f81553c43b$exports, "NestedFieldsRedactor", () => $042914f81553c43b$export$a0063b118a222d07); | ||
var $ae48da3a2344a35c$exports = {}; | ||
$parcel$export($ae48da3a2344a35c$exports, "NAME_REDACTORS", () => $ae48da3a2344a35c$export$881e5a319bd36ea7); | ||
$parcel$export($ae48da3a2344a35c$exports, "URL_REDACTORS", () => $ae48da3a2344a35c$export$3e8893cecd17a4cc); | ||
$parcel$export($ae48da3a2344a35c$exports, "OTHER_PII_REDACTORS", () => $ae48da3a2344a35c$export$8f52f6621375b80d); | ||
$parcel$export($ae48da3a2344a35c$exports, "FREE_TEXT_REDACTORS", () => $ae48da3a2344a35c$export$e0b3ed47ae4f0dc); | ||
$parcel$export($ae48da3a2344a35c$exports, "redactDateOfBirth", () => $ae48da3a2344a35c$export$f02f7a62000ad1ea); | ||
$parcel$export($ae48da3a2344a35c$exports, "DOB_REDACTORS", () => $ae48da3a2344a35c$export$68cebd559ee21cf4); | ||
$parcel$export($ae48da3a2344a35c$exports, "doNotRedact", () => $ae48da3a2344a35c$export$bd2d7180fd66e618); | ||
$parcel$export($ae48da3a2344a35c$exports, "ID_REDACTORS", () => $ae48da3a2344a35c$export$87067358f1774189); | ||
$parcel$export($ae48da3a2344a35c$exports, "TYPE_UNION_REDACTORS", () => $ae48da3a2344a35c$export$caaa893e9f0eec9); | ||
$parcel$export($ae48da3a2344a35c$exports, "DATES_AS_STRINGS_THAT_DO_NOT_NEED_REDACTION", () => $ae48da3a2344a35c$export$bc966719904e8832); | ||
$parcel$export($ae48da3a2344a35c$exports, "ALL_STRING_FIELDS_THAT_DEFAULT_TO_NO_REDACTION", () => $ae48da3a2344a35c$export$4289670f95f6df85); | ||
$parcel$export($ae48da3a2344a35c$exports, "ALL_DEFAULT_STRING_REDACTORS", () => $ae48da3a2344a35c$export$ce2c2712d7ae6215); | ||
$parcel$export($ae48da3a2344a35c$exports, "ALL_DEFAULT_DATE_REDACTORS", () => $ae48da3a2344a35c$export$b3ddb3c4a66dbc28); | ||
var $3c0b7b2278f26fd3$exports = {}; | ||
$parcel$export($3c0b7b2278f26fd3$exports, "redactString", () => $3c0b7b2278f26fd3$export$9791de86fcee0c4); | ||
var $f8461d0939ac236d$exports = {}; | ||
$parcel$export($f8461d0939ac236d$exports, "redactEmail", () => $f8461d0939ac236d$export$dfbb0fdec5fcbdcd); | ||
const $f8461d0939ac236d$export$dfbb0fdec5fcbdcd = (email)=>{ | ||
return email.split("@").map((str)=>str.split(".").map((subStr)=>$f8461d0939ac236d$var$redactComponent(subStr)).join(".")).join("@"); | ||
}; | ||
const $f8461d0939ac236d$var$redactComponent = (component)=>{ | ||
if ([ | ||
"com", | ||
"net", | ||
"org", | ||
"io", | ||
"ai" | ||
].includes(component)) return component; | ||
// We repeat the string "redacted", since asterixes may not work with all parsers | ||
// redacted___@redac.red | ||
return component.replace(/./g, "-"); | ||
}; | ||
var $92f61c316cc2970c$exports = {}; | ||
$parcel$export($92f61c316cc2970c$exports, "redactUrl", () => $92f61c316cc2970c$export$11317b2153d91092); | ||
$parcel$export($92f61c316cc2970c$exports, "redactPath", () => $92f61c316cc2970c$export$e7c955966789994b); | ||
const $92f61c316cc2970c$export$11317b2153d91092 = (url)=>{ | ||
try { | ||
const parsedUrl = new URL(url); | ||
parsedUrl.password = (0, $8775099367f3effc$export$62d597f0a8051e9a)(parsedUrl.password); | ||
parsedUrl.username = (0, $8775099367f3effc$export$62d597f0a8051e9a)(parsedUrl.username); | ||
parsedUrl.hostname = "redacted.com"; | ||
if (parsedUrl.hash.length > 0) parsedUrl.hash = "redactedHash"; | ||
if (parsedUrl.pathname.length > 0) parsedUrl.pathname = $92f61c316cc2970c$export$e7c955966789994b(parsedUrl.pathname); | ||
if (parsedUrl.searchParams.size > 0) { | ||
const numParams = parsedUrl.searchParams.size; | ||
parsedUrl.searchParams.forEach((key)=>{ | ||
parsedUrl.searchParams.delete(key); | ||
}); | ||
for(let i = 0; i < numParams; i++)parsedUrl.searchParams.set(`redactedParam${i + 1}`, "redacted"); | ||
} | ||
return parsedUrl.toString(); | ||
} catch (_e) { | ||
return (0, $8775099367f3effc$export$62d597f0a8051e9a)(url); | ||
} | ||
}; | ||
const $92f61c316cc2970c$export$e7c955966789994b = (path)=>{ | ||
return path.replace(/\/[^/]+/g, "/redacted"); | ||
}; | ||
const $3c0b7b2278f26fd3$export$9791de86fcee0c4 = (str)=>{ | ||
if (str.includes("@")) return (0, $f8461d0939ac236d$export$dfbb0fdec5fcbdcd)(str); | ||
if (str.startsWith("http://") || str.startsWith("https://")) return (0, $92f61c316cc2970c$export$11317b2153d91092)(str); | ||
// Check if it matches ISO 8601 format | ||
if (str.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/)) return new Date(0).toISOString(); | ||
// Common number formats (SSNs, phone numbers, currency, etc) | ||
if (str.match(/^[$£€¥#]?[\d \-_./]+[%]?$/)) return str.replace(/\d/g, "0"); | ||
return (0, $8775099367f3effc$export$62d597f0a8051e9a)(str); | ||
}; | ||
var $7b7fa2c19d7d6971$exports = {}; | ||
$parcel$export($7b7fa2c19d7d6971$exports, "redactKeysEndingWith", () => $7b7fa2c19d7d6971$export$7f66c2e43b8445a5); | ||
$parcel$export($7b7fa2c19d7d6971$exports, "redactKey", () => $7b7fa2c19d7d6971$export$5ce15c50c7ba440c); | ||
$parcel$export($7b7fa2c19d7d6971$exports, "PatternBasedRedactorSet", () => $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34); | ||
const $7b7fa2c19d7d6971$export$7f66c2e43b8445a5 = (postfix, redactor)=>{ | ||
return { | ||
type: "key-postfix", | ||
postfix: postfix, | ||
redactor: redactor | ||
}; | ||
}; | ||
const $7b7fa2c19d7d6971$export$5ce15c50c7ba440c = (key, redactor)=>{ | ||
return { | ||
type: "key-exact", | ||
key: key, | ||
redactor: redactor | ||
}; | ||
}; | ||
class $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34 { | ||
constructor(redactors){ | ||
this.redactors = redactors; | ||
} | ||
static create() { | ||
return new $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34([]); | ||
} | ||
with(redactor) { | ||
return new $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34([ | ||
...this.redactors, | ||
redactor | ||
]); | ||
} | ||
withSet(set) { | ||
return new $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34([ | ||
...this.redactors, | ||
...set.redactors | ||
]); | ||
} | ||
} | ||
const $ae48da3a2344a35c$export$881e5a319bd36ea7 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$5ce15c50c7ba440c)("name", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("_name", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("ullName", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("irstname", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("astname", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))); | ||
const $ae48da3a2344a35c$export$3e8893cecd17a4cc = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("url", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("uri", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("link", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("href", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Url", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Uri", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Link", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Href", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))); | ||
const $ae48da3a2344a35c$export$8f52f6621375b80d = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$5ce15c50c7ba440c)("address", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("addressLine1", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("address_line_1", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("homeAddress", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("home_address", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("postalAddress", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("postal_address", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("phone", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Phone", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("phone_number", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("ssn", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("SSN", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("username", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Username", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("user_name", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("credit_card", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("creditCard", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("credit_card_number", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("creditCardNumber", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("cvc", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("CVC", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))); | ||
const $ae48da3a2344a35c$export$e0b3ed47ae4f0dc = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("text", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("description", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("summary", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("title", (0, $3c0b7b2278f26fd3$export$9791de86fcee0c4))); | ||
const $ae48da3a2344a35c$export$f02f7a62000ad1ea = (_)=>{ | ||
return new Date(0); | ||
}; | ||
const $ae48da3a2344a35c$export$68cebd559ee21cf4 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("dob", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("DOB", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("date_of_birth", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("dateOfBirth", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("DateOfBirth", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("birthDate", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("BirthDate", $ae48da3a2344a35c$export$f02f7a62000ad1ea)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("birth_date", $ae48da3a2344a35c$export$f02f7a62000ad1ea)); | ||
const $ae48da3a2344a35c$export$bd2d7180fd66e618 = (value)=>value; | ||
const $ae48da3a2344a35c$export$87067358f1774189 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$5ce15c50c7ba440c)("id", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Id", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("ID", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("_id", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("uuid", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("UUID", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("uuidv4", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("UUIDv4", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("guid", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("GUID", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Guid", $ae48da3a2344a35c$export$bd2d7180fd66e618)); | ||
const $ae48da3a2344a35c$export$caaa893e9f0eec9 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$5ce15c50c7ba440c)("type", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Type", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("_type", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("TYPE", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$5ce15c50c7ba440c)("kind", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("Kind", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("_kind", $ae48da3a2344a35c$export$bd2d7180fd66e618)); | ||
const $ae48da3a2344a35c$export$bc966719904e8832 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("ed_at", $ae48da3a2344a35c$export$bd2d7180fd66e618)).with((0, $7b7fa2c19d7d6971$export$7f66c2e43b8445a5)("edAt", $ae48da3a2344a35c$export$bd2d7180fd66e618)); | ||
const $ae48da3a2344a35c$export$4289670f95f6df85 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().withSet($ae48da3a2344a35c$export$87067358f1774189).withSet($ae48da3a2344a35c$export$caaa893e9f0eec9).withSet($ae48da3a2344a35c$export$bc966719904e8832); | ||
const $ae48da3a2344a35c$export$ce2c2712d7ae6215 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().withSet($ae48da3a2344a35c$export$4289670f95f6df85).withSet($ae48da3a2344a35c$export$881e5a319bd36ea7).withSet($ae48da3a2344a35c$export$3e8893cecd17a4cc).withSet($ae48da3a2344a35c$export$8f52f6621375b80d).withSet($ae48da3a2344a35c$export$e0b3ed47ae4f0dc); | ||
const $ae48da3a2344a35c$export$b3ddb3c4a66dbc28 = (0, $7b7fa2c19d7d6971$export$8a444b6ebcf2fa34).create().withSet($ae48da3a2344a35c$export$68cebd559ee21cf4); | ||
class $042914f81553c43b$export$a0063b118a222d07 { | ||
constructor(stringRedactors, dateRedactors){ | ||
this.stringRedactors = stringRedactors; | ||
this.dateRedactors = dateRedactors; | ||
this.redactNestedStringFieldsNonTypeSafe = (opts)=>{ | ||
return $042914f81553c43b$var$createRedactor({ | ||
...opts, | ||
patternBasedRedactors: { | ||
strings: this.stringRedactors, | ||
dates: this.dateRedactors | ||
} | ||
}); | ||
}; | ||
} | ||
static builder() { | ||
return new $042914f81553c43b$export$a0063b118a222d07([], []); | ||
} | ||
/** | ||
* Provides an opinionated set of redactors that are useful for most use cases, | ||
* which can then be built upon. See {@link ALL_DEFAULT_STRING_REDACTORS} and | ||
* {@link ALL_DEFAULT_DATE_REDACTORS} for more details. | ||
* | ||
* (recommended) | ||
*/ static builderWithDefaults() { | ||
return new $042914f81553c43b$export$a0063b118a222d07([], []).withPatternBasedStringRedactors((0, $ae48da3a2344a35c$export$ce2c2712d7ae6215)).withPatternBasedDateRedactors((0, $ae48da3a2344a35c$export$b3ddb3c4a66dbc28)); | ||
} | ||
withPatternBasedStringRedactor(redactor) { | ||
return new $042914f81553c43b$export$a0063b118a222d07([ | ||
...this.stringRedactors, | ||
redactor | ||
], this.dateRedactors); | ||
} | ||
withPatternBasedStringRedactors(set) { | ||
return new $042914f81553c43b$export$a0063b118a222d07([ | ||
...this.stringRedactors, | ||
...set.redactors | ||
], this.dateRedactors); | ||
} | ||
withPatternBasedDateRedactor(redactor) { | ||
return new $042914f81553c43b$export$a0063b118a222d07(this.stringRedactors, [ | ||
...this.dateRedactors, | ||
redactor | ||
]); | ||
} | ||
withPatternBasedDateRedactors(set) { | ||
return new $042914f81553c43b$export$a0063b118a222d07(this.stringRedactors, [ | ||
...this.dateRedactors, | ||
...set.redactors | ||
]); | ||
} | ||
/** | ||
* Type safety: forces a redaction policy to be set for every unique nested string field name in the object. | ||
* Leaves redaction of dates, numbers and bigints as optional. | ||
*/ createRedactor(opts) { | ||
return $042914f81553c43b$var$createRedactor({ | ||
...opts, | ||
patternBasedRedactors: { | ||
strings: this.stringRedactors, | ||
dates: this.dateRedactors | ||
} | ||
}); | ||
} | ||
/** | ||
* Type safety: forces a redaction policy to be set for every unique nested string, date, number and bigint | ||
* field name in the object. | ||
*/ createRedactorStrict(opts) { | ||
return $042914f81553c43b$var$createRedactor({ | ||
...opts, | ||
patternBasedRedactors: { | ||
strings: this.stringRedactors, | ||
dates: this.dateRedactors | ||
} | ||
}); | ||
} | ||
} | ||
const $042914f81553c43b$var$createRedactor = ({ strings: strings , dates: dates , numbers: numbers , bigints: bigints , patternBasedRedactors: patternBasedRedactors })=>{ | ||
const redactFn = (value, key)=>{ | ||
if (value == null || typeof value === "boolean" || typeof value === "function" || typeof value === "symbol") return value; | ||
if (typeof value === "string") { | ||
const fieldRedactor = key && strings ? strings[key] : undefined; | ||
if (!fieldRedactor) { | ||
const patternBasedRedactor = key ? $042914f81553c43b$var$findApplicablePatternBasedRedactor(key, patternBasedRedactors.strings) : null; | ||
if (patternBasedRedactor) return patternBasedRedactor.redactor(value); | ||
return value; | ||
} | ||
return fieldRedactor(value); | ||
} | ||
if (typeof value === "number") { | ||
const fieldRedactor = key && numbers ? numbers[key] : undefined; | ||
if (!fieldRedactor) return value; | ||
return fieldRedactor(value); | ||
} | ||
if (typeof value === "bigint") { | ||
const fieldRedactor = key && bigints ? bigints[key] : undefined; | ||
if (!fieldRedactor) return value; | ||
return fieldRedactor(value); | ||
} | ||
if (value instanceof Date) { | ||
const fieldRedactor = key && dates ? dates[key] : undefined; | ||
if (!fieldRedactor) { | ||
const patternBasedRedactor = key ? $042914f81553c43b$var$findApplicablePatternBasedRedactor(key, patternBasedRedactors.dates) : null; | ||
if (patternBasedRedactor) return patternBasedRedactor.redactor(value); | ||
return value; | ||
} | ||
return fieldRedactor(value); | ||
} | ||
if (Array.isArray(value)) { | ||
let hasRedacted = false; | ||
const redactedValueEntries = value.map((value)=>{ | ||
// Note: we use the key of the array here, so if you have: | ||
// | ||
// { passwords: ["password1", "password2"] } | ||
// | ||
// and set a redactor for "passwords" then it will apply it to each password | ||
// in the array. | ||
const redacted = redactFn(value, key); | ||
if (redacted !== value) hasRedacted = true; | ||
return redacted; | ||
}); | ||
return hasRedacted ? redactedValueEntries : value; | ||
} | ||
if (typeof value === "object") { | ||
let hasRedacted = false; | ||
const redactedValueEntries = Object.entries(value).map(([key, value])=>{ | ||
const redacted = redactFn(value, key); | ||
if (redacted !== value) hasRedacted = true; | ||
return [ | ||
key, | ||
redacted | ||
]; | ||
}); | ||
return hasRedacted ? Object.fromEntries(redactedValueEntries) : value; | ||
} | ||
return value; | ||
}; | ||
return redactFn; | ||
}; | ||
const $042914f81553c43b$var$findApplicablePatternBasedRedactor = (key, redactors)=>{ | ||
return redactors.find((redactor)=>{ | ||
if (redactor.type === "key-postfix") return key.endsWith(redactor.postfix); | ||
if (redactor.type === "key-exact") return key === redactor.key; | ||
return false; | ||
}); | ||
}; | ||
$parcel$exportWildcard(module.exports, $2b0c4e9266a1cb23$exports); | ||
@@ -157,4 +449,10 @@ $parcel$exportWildcard(module.exports, $b0f92d410af6b950$exports); | ||
$parcel$exportWildcard(module.exports, $8775099367f3effc$exports); | ||
$parcel$exportWildcard(module.exports, $042914f81553c43b$exports); | ||
$parcel$exportWildcard(module.exports, $ae48da3a2344a35c$exports); | ||
$parcel$exportWildcard(module.exports, $7b7fa2c19d7d6971$exports); | ||
$parcel$exportWildcard(module.exports, $f8461d0939ac236d$exports); | ||
$parcel$exportWildcard(module.exports, $92f61c316cc2970c$exports); | ||
$parcel$exportWildcard(module.exports, $3c0b7b2278f26fd3$exports); | ||
//# sourceMappingURL=index.js.map |
@@ -136,5 +136,297 @@ function $parcel$export(e, n, v, s) { | ||
var $4a36c7f8b55737fa$exports = {}; | ||
$parcel$export($4a36c7f8b55737fa$exports, "NestedFieldsRedactor", () => $4a36c7f8b55737fa$export$a0063b118a222d07); | ||
var $453ce7387c3361c5$exports = {}; | ||
export {$ce0636e0a262f97f$export$68215425b6d5dd04 as dropRequestHeader, $9cbe6151f484425b$export$36a28ed6db1a9567 as transformJsonResponse, $9056f56aed8544e3$export$da8e8a01f8062d05 as redactRecursively, $39db114007ea6380$export$62d597f0a8051e9a as asterixOut}; | ||
$parcel$export($453ce7387c3361c5$exports, "NAME_REDACTORS", () => $453ce7387c3361c5$export$881e5a319bd36ea7); | ||
$parcel$export($453ce7387c3361c5$exports, "URL_REDACTORS", () => $453ce7387c3361c5$export$3e8893cecd17a4cc); | ||
$parcel$export($453ce7387c3361c5$exports, "OTHER_PII_REDACTORS", () => $453ce7387c3361c5$export$8f52f6621375b80d); | ||
$parcel$export($453ce7387c3361c5$exports, "FREE_TEXT_REDACTORS", () => $453ce7387c3361c5$export$e0b3ed47ae4f0dc); | ||
$parcel$export($453ce7387c3361c5$exports, "redactDateOfBirth", () => $453ce7387c3361c5$export$f02f7a62000ad1ea); | ||
$parcel$export($453ce7387c3361c5$exports, "DOB_REDACTORS", () => $453ce7387c3361c5$export$68cebd559ee21cf4); | ||
$parcel$export($453ce7387c3361c5$exports, "doNotRedact", () => $453ce7387c3361c5$export$bd2d7180fd66e618); | ||
$parcel$export($453ce7387c3361c5$exports, "ID_REDACTORS", () => $453ce7387c3361c5$export$87067358f1774189); | ||
$parcel$export($453ce7387c3361c5$exports, "TYPE_UNION_REDACTORS", () => $453ce7387c3361c5$export$caaa893e9f0eec9); | ||
$parcel$export($453ce7387c3361c5$exports, "DATES_AS_STRINGS_THAT_DO_NOT_NEED_REDACTION", () => $453ce7387c3361c5$export$bc966719904e8832); | ||
$parcel$export($453ce7387c3361c5$exports, "ALL_STRING_FIELDS_THAT_DEFAULT_TO_NO_REDACTION", () => $453ce7387c3361c5$export$4289670f95f6df85); | ||
$parcel$export($453ce7387c3361c5$exports, "ALL_DEFAULT_STRING_REDACTORS", () => $453ce7387c3361c5$export$ce2c2712d7ae6215); | ||
$parcel$export($453ce7387c3361c5$exports, "ALL_DEFAULT_DATE_REDACTORS", () => $453ce7387c3361c5$export$b3ddb3c4a66dbc28); | ||
var $e449d9aabbf31633$exports = {}; | ||
$parcel$export($e449d9aabbf31633$exports, "redactString", () => $e449d9aabbf31633$export$9791de86fcee0c4); | ||
var $75dc266028bacbb8$exports = {}; | ||
$parcel$export($75dc266028bacbb8$exports, "redactEmail", () => $75dc266028bacbb8$export$dfbb0fdec5fcbdcd); | ||
const $75dc266028bacbb8$export$dfbb0fdec5fcbdcd = (email)=>{ | ||
return email.split("@").map((str)=>str.split(".").map((subStr)=>$75dc266028bacbb8$var$redactComponent(subStr)).join(".")).join("@"); | ||
}; | ||
const $75dc266028bacbb8$var$redactComponent = (component)=>{ | ||
if ([ | ||
"com", | ||
"net", | ||
"org", | ||
"io", | ||
"ai" | ||
].includes(component)) return component; | ||
// We repeat the string "redacted", since asterixes may not work with all parsers | ||
// redacted___@redac.red | ||
return component.replace(/./g, "-"); | ||
}; | ||
var $3c0a2aa748c1be54$exports = {}; | ||
$parcel$export($3c0a2aa748c1be54$exports, "redactUrl", () => $3c0a2aa748c1be54$export$11317b2153d91092); | ||
$parcel$export($3c0a2aa748c1be54$exports, "redactPath", () => $3c0a2aa748c1be54$export$e7c955966789994b); | ||
const $3c0a2aa748c1be54$export$11317b2153d91092 = (url)=>{ | ||
try { | ||
const parsedUrl = new URL(url); | ||
parsedUrl.password = (0, $39db114007ea6380$export$62d597f0a8051e9a)(parsedUrl.password); | ||
parsedUrl.username = (0, $39db114007ea6380$export$62d597f0a8051e9a)(parsedUrl.username); | ||
parsedUrl.hostname = "redacted.com"; | ||
if (parsedUrl.hash.length > 0) parsedUrl.hash = "redactedHash"; | ||
if (parsedUrl.pathname.length > 0) parsedUrl.pathname = $3c0a2aa748c1be54$export$e7c955966789994b(parsedUrl.pathname); | ||
if (parsedUrl.searchParams.size > 0) { | ||
const numParams = parsedUrl.searchParams.size; | ||
parsedUrl.searchParams.forEach((key)=>{ | ||
parsedUrl.searchParams.delete(key); | ||
}); | ||
for(let i = 0; i < numParams; i++)parsedUrl.searchParams.set(`redactedParam${i + 1}`, "redacted"); | ||
} | ||
return parsedUrl.toString(); | ||
} catch (_e) { | ||
return (0, $39db114007ea6380$export$62d597f0a8051e9a)(url); | ||
} | ||
}; | ||
const $3c0a2aa748c1be54$export$e7c955966789994b = (path)=>{ | ||
return path.replace(/\/[^/]+/g, "/redacted"); | ||
}; | ||
const $e449d9aabbf31633$export$9791de86fcee0c4 = (str)=>{ | ||
if (str.includes("@")) return (0, $75dc266028bacbb8$export$dfbb0fdec5fcbdcd)(str); | ||
if (str.startsWith("http://") || str.startsWith("https://")) return (0, $3c0a2aa748c1be54$export$11317b2153d91092)(str); | ||
// Check if it matches ISO 8601 format | ||
if (str.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/)) return new Date(0).toISOString(); | ||
// Common number formats (SSNs, phone numbers, currency, etc) | ||
if (str.match(/^[$£€¥#]?[\d \-_./]+[%]?$/)) return str.replace(/\d/g, "0"); | ||
return (0, $39db114007ea6380$export$62d597f0a8051e9a)(str); | ||
}; | ||
var $c2da2f7939ccb281$exports = {}; | ||
$parcel$export($c2da2f7939ccb281$exports, "redactKeysEndingWith", () => $c2da2f7939ccb281$export$7f66c2e43b8445a5); | ||
$parcel$export($c2da2f7939ccb281$exports, "redactKey", () => $c2da2f7939ccb281$export$5ce15c50c7ba440c); | ||
$parcel$export($c2da2f7939ccb281$exports, "PatternBasedRedactorSet", () => $c2da2f7939ccb281$export$8a444b6ebcf2fa34); | ||
const $c2da2f7939ccb281$export$7f66c2e43b8445a5 = (postfix, redactor)=>{ | ||
return { | ||
type: "key-postfix", | ||
postfix: postfix, | ||
redactor: redactor | ||
}; | ||
}; | ||
const $c2da2f7939ccb281$export$5ce15c50c7ba440c = (key, redactor)=>{ | ||
return { | ||
type: "key-exact", | ||
key: key, | ||
redactor: redactor | ||
}; | ||
}; | ||
class $c2da2f7939ccb281$export$8a444b6ebcf2fa34 { | ||
constructor(redactors){ | ||
this.redactors = redactors; | ||
} | ||
static create() { | ||
return new $c2da2f7939ccb281$export$8a444b6ebcf2fa34([]); | ||
} | ||
with(redactor) { | ||
return new $c2da2f7939ccb281$export$8a444b6ebcf2fa34([ | ||
...this.redactors, | ||
redactor | ||
]); | ||
} | ||
withSet(set) { | ||
return new $c2da2f7939ccb281$export$8a444b6ebcf2fa34([ | ||
...this.redactors, | ||
...set.redactors | ||
]); | ||
} | ||
} | ||
const $453ce7387c3361c5$export$881e5a319bd36ea7 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$5ce15c50c7ba440c)("name", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("_name", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("ullName", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("irstname", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("astname", (0, $e449d9aabbf31633$export$9791de86fcee0c4))); | ||
const $453ce7387c3361c5$export$3e8893cecd17a4cc = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("url", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("uri", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("link", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("href", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Url", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Uri", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Link", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Href", (0, $e449d9aabbf31633$export$9791de86fcee0c4))); | ||
const $453ce7387c3361c5$export$8f52f6621375b80d = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$5ce15c50c7ba440c)("address", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("addressLine1", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("address_line_1", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("homeAddress", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("home_address", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("postalAddress", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("postal_address", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("phone", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Phone", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("phone_number", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("ssn", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("SSN", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("username", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Username", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("user_name", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("credit_card", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("creditCard", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("credit_card_number", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("creditCardNumber", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("cvc", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("CVC", (0, $e449d9aabbf31633$export$9791de86fcee0c4))); | ||
const $453ce7387c3361c5$export$e0b3ed47ae4f0dc = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("text", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("description", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("summary", (0, $e449d9aabbf31633$export$9791de86fcee0c4))).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("title", (0, $e449d9aabbf31633$export$9791de86fcee0c4))); | ||
const $453ce7387c3361c5$export$f02f7a62000ad1ea = (_)=>{ | ||
return new Date(0); | ||
}; | ||
const $453ce7387c3361c5$export$68cebd559ee21cf4 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("dob", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("DOB", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("date_of_birth", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("dateOfBirth", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("DateOfBirth", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("birthDate", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("BirthDate", $453ce7387c3361c5$export$f02f7a62000ad1ea)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("birth_date", $453ce7387c3361c5$export$f02f7a62000ad1ea)); | ||
const $453ce7387c3361c5$export$bd2d7180fd66e618 = (value)=>value; | ||
const $453ce7387c3361c5$export$87067358f1774189 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$5ce15c50c7ba440c)("id", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Id", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("ID", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("_id", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("uuid", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("UUID", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("uuidv4", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("UUIDv4", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("guid", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("GUID", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Guid", $453ce7387c3361c5$export$bd2d7180fd66e618)); | ||
const $453ce7387c3361c5$export$caaa893e9f0eec9 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$5ce15c50c7ba440c)("type", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Type", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("_type", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("TYPE", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$5ce15c50c7ba440c)("kind", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("Kind", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("_kind", $453ce7387c3361c5$export$bd2d7180fd66e618)); | ||
const $453ce7387c3361c5$export$bc966719904e8832 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("ed_at", $453ce7387c3361c5$export$bd2d7180fd66e618)).with((0, $c2da2f7939ccb281$export$7f66c2e43b8445a5)("edAt", $453ce7387c3361c5$export$bd2d7180fd66e618)); | ||
const $453ce7387c3361c5$export$4289670f95f6df85 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().withSet($453ce7387c3361c5$export$87067358f1774189).withSet($453ce7387c3361c5$export$caaa893e9f0eec9).withSet($453ce7387c3361c5$export$bc966719904e8832); | ||
const $453ce7387c3361c5$export$ce2c2712d7ae6215 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().withSet($453ce7387c3361c5$export$4289670f95f6df85).withSet($453ce7387c3361c5$export$881e5a319bd36ea7).withSet($453ce7387c3361c5$export$3e8893cecd17a4cc).withSet($453ce7387c3361c5$export$8f52f6621375b80d).withSet($453ce7387c3361c5$export$e0b3ed47ae4f0dc); | ||
const $453ce7387c3361c5$export$b3ddb3c4a66dbc28 = (0, $c2da2f7939ccb281$export$8a444b6ebcf2fa34).create().withSet($453ce7387c3361c5$export$68cebd559ee21cf4); | ||
class $4a36c7f8b55737fa$export$a0063b118a222d07 { | ||
constructor(stringRedactors, dateRedactors){ | ||
this.stringRedactors = stringRedactors; | ||
this.dateRedactors = dateRedactors; | ||
this.redactNestedStringFieldsNonTypeSafe = (opts)=>{ | ||
return $4a36c7f8b55737fa$var$createRedactor({ | ||
...opts, | ||
patternBasedRedactors: { | ||
strings: this.stringRedactors, | ||
dates: this.dateRedactors | ||
} | ||
}); | ||
}; | ||
} | ||
static builder() { | ||
return new $4a36c7f8b55737fa$export$a0063b118a222d07([], []); | ||
} | ||
/** | ||
* Provides an opinionated set of redactors that are useful for most use cases, | ||
* which can then be built upon. See {@link ALL_DEFAULT_STRING_REDACTORS} and | ||
* {@link ALL_DEFAULT_DATE_REDACTORS} for more details. | ||
* | ||
* (recommended) | ||
*/ static builderWithDefaults() { | ||
return new $4a36c7f8b55737fa$export$a0063b118a222d07([], []).withPatternBasedStringRedactors((0, $453ce7387c3361c5$export$ce2c2712d7ae6215)).withPatternBasedDateRedactors((0, $453ce7387c3361c5$export$b3ddb3c4a66dbc28)); | ||
} | ||
withPatternBasedStringRedactor(redactor) { | ||
return new $4a36c7f8b55737fa$export$a0063b118a222d07([ | ||
...this.stringRedactors, | ||
redactor | ||
], this.dateRedactors); | ||
} | ||
withPatternBasedStringRedactors(set) { | ||
return new $4a36c7f8b55737fa$export$a0063b118a222d07([ | ||
...this.stringRedactors, | ||
...set.redactors | ||
], this.dateRedactors); | ||
} | ||
withPatternBasedDateRedactor(redactor) { | ||
return new $4a36c7f8b55737fa$export$a0063b118a222d07(this.stringRedactors, [ | ||
...this.dateRedactors, | ||
redactor | ||
]); | ||
} | ||
withPatternBasedDateRedactors(set) { | ||
return new $4a36c7f8b55737fa$export$a0063b118a222d07(this.stringRedactors, [ | ||
...this.dateRedactors, | ||
...set.redactors | ||
]); | ||
} | ||
/** | ||
* Type safety: forces a redaction policy to be set for every unique nested string field name in the object. | ||
* Leaves redaction of dates, numbers and bigints as optional. | ||
*/ createRedactor(opts) { | ||
return $4a36c7f8b55737fa$var$createRedactor({ | ||
...opts, | ||
patternBasedRedactors: { | ||
strings: this.stringRedactors, | ||
dates: this.dateRedactors | ||
} | ||
}); | ||
} | ||
/** | ||
* Type safety: forces a redaction policy to be set for every unique nested string, date, number and bigint | ||
* field name in the object. | ||
*/ createRedactorStrict(opts) { | ||
return $4a36c7f8b55737fa$var$createRedactor({ | ||
...opts, | ||
patternBasedRedactors: { | ||
strings: this.stringRedactors, | ||
dates: this.dateRedactors | ||
} | ||
}); | ||
} | ||
} | ||
const $4a36c7f8b55737fa$var$createRedactor = ({ strings: strings , dates: dates , numbers: numbers , bigints: bigints , patternBasedRedactors: patternBasedRedactors })=>{ | ||
const redactFn = (value, key)=>{ | ||
if (value == null || typeof value === "boolean" || typeof value === "function" || typeof value === "symbol") return value; | ||
if (typeof value === "string") { | ||
const fieldRedactor = key && strings ? strings[key] : undefined; | ||
if (!fieldRedactor) { | ||
const patternBasedRedactor = key ? $4a36c7f8b55737fa$var$findApplicablePatternBasedRedactor(key, patternBasedRedactors.strings) : null; | ||
if (patternBasedRedactor) return patternBasedRedactor.redactor(value); | ||
return value; | ||
} | ||
return fieldRedactor(value); | ||
} | ||
if (typeof value === "number") { | ||
const fieldRedactor = key && numbers ? numbers[key] : undefined; | ||
if (!fieldRedactor) return value; | ||
return fieldRedactor(value); | ||
} | ||
if (typeof value === "bigint") { | ||
const fieldRedactor = key && bigints ? bigints[key] : undefined; | ||
if (!fieldRedactor) return value; | ||
return fieldRedactor(value); | ||
} | ||
if (value instanceof Date) { | ||
const fieldRedactor = key && dates ? dates[key] : undefined; | ||
if (!fieldRedactor) { | ||
const patternBasedRedactor = key ? $4a36c7f8b55737fa$var$findApplicablePatternBasedRedactor(key, patternBasedRedactors.dates) : null; | ||
if (patternBasedRedactor) return patternBasedRedactor.redactor(value); | ||
return value; | ||
} | ||
return fieldRedactor(value); | ||
} | ||
if (Array.isArray(value)) { | ||
let hasRedacted = false; | ||
const redactedValueEntries = value.map((value)=>{ | ||
// Note: we use the key of the array here, so if you have: | ||
// | ||
// { passwords: ["password1", "password2"] } | ||
// | ||
// and set a redactor for "passwords" then it will apply it to each password | ||
// in the array. | ||
const redacted = redactFn(value, key); | ||
if (redacted !== value) hasRedacted = true; | ||
return redacted; | ||
}); | ||
return hasRedacted ? redactedValueEntries : value; | ||
} | ||
if (typeof value === "object") { | ||
let hasRedacted = false; | ||
const redactedValueEntries = Object.entries(value).map(([key, value])=>{ | ||
const redacted = redactFn(value, key); | ||
if (redacted !== value) hasRedacted = true; | ||
return [ | ||
key, | ||
redacted | ||
]; | ||
}); | ||
return hasRedacted ? Object.fromEntries(redactedValueEntries) : value; | ||
} | ||
return value; | ||
}; | ||
return redactFn; | ||
}; | ||
const $4a36c7f8b55737fa$var$findApplicablePatternBasedRedactor = (key, redactors)=>{ | ||
return redactors.find((redactor)=>{ | ||
if (redactor.type === "key-postfix") return key.endsWith(redactor.postfix); | ||
if (redactor.type === "key-exact") return key === redactor.key; | ||
return false; | ||
}); | ||
}; | ||
export {$ce0636e0a262f97f$export$68215425b6d5dd04 as dropRequestHeader, $9cbe6151f484425b$export$36a28ed6db1a9567 as transformJsonResponse, $9056f56aed8544e3$export$da8e8a01f8062d05 as redactRecursively, $39db114007ea6380$export$62d597f0a8051e9a as asterixOut, $4a36c7f8b55737fa$export$a0063b118a222d07 as NestedFieldsRedactor, $453ce7387c3361c5$export$881e5a319bd36ea7 as NAME_REDACTORS, $453ce7387c3361c5$export$3e8893cecd17a4cc as URL_REDACTORS, $453ce7387c3361c5$export$8f52f6621375b80d as OTHER_PII_REDACTORS, $453ce7387c3361c5$export$e0b3ed47ae4f0dc as FREE_TEXT_REDACTORS, $453ce7387c3361c5$export$f02f7a62000ad1ea as redactDateOfBirth, $453ce7387c3361c5$export$68cebd559ee21cf4 as DOB_REDACTORS, $453ce7387c3361c5$export$bd2d7180fd66e618 as doNotRedact, $453ce7387c3361c5$export$87067358f1774189 as ID_REDACTORS, $453ce7387c3361c5$export$caaa893e9f0eec9 as TYPE_UNION_REDACTORS, $453ce7387c3361c5$export$bc966719904e8832 as DATES_AS_STRINGS_THAT_DO_NOT_NEED_REDACTION, $453ce7387c3361c5$export$4289670f95f6df85 as ALL_STRING_FIELDS_THAT_DEFAULT_TO_NO_REDACTION, $453ce7387c3361c5$export$ce2c2712d7ae6215 as ALL_DEFAULT_STRING_REDACTORS, $453ce7387c3361c5$export$b3ddb3c4a66dbc28 as ALL_DEFAULT_DATE_REDACTORS, $c2da2f7939ccb281$export$7f66c2e43b8445a5 as redactKeysEndingWith, $c2da2f7939ccb281$export$5ce15c50c7ba440c as redactKey, $c2da2f7939ccb281$export$8a444b6ebcf2fa34 as PatternBasedRedactorSet, $75dc266028bacbb8$export$dfbb0fdec5fcbdcd as redactEmail, $3c0a2aa748c1be54$export$11317b2153d91092 as redactUrl, $3c0a2aa748c1be54$export$e7c955966789994b as redactPath, $e449d9aabbf31633$export$9791de86fcee0c4 as redactString}; | ||
//# sourceMappingURL=module.js.map |
{ | ||
"name": "@alwaysmeticulous/redaction", | ||
"version": "2.186.0", | ||
"version": "2.187.0", | ||
"license": "ISC", | ||
@@ -45,3 +45,3 @@ "source": "src/index.ts", | ||
}, | ||
"gitHead": "e87ff02d6e974358abcd262d74855085fd01b8a8" | ||
"gitHead": "7886cd2eaf96f28b17380de065ca0fe87dd2604c" | ||
} |
152
README.md
@@ -5,4 +5,6 @@ # Redaction | ||
## Example Usage | ||
## Utilities for implementing redaction middleware | ||
### Example Usage | ||
```ts | ||
@@ -27,1 +29,149 @@ import { dropRequestHeader, transformJsonResponse, redactRecursively, asterixOut } from "@alwaysmeticulous/redaction"; | ||
``` | ||
## Utilties for redacting javascript objects | ||
To make it easier to redact large complex javascript types we provide a number of helpers. | ||
### asterixOut | ||
This ensures the redacted text is the same length and has the same whitespace as the original text, | ||
thereby allowing you to test the same layout cases. | ||
```ts | ||
import { asterixOut } from "@alwaysmeticulous/redaction"; | ||
const redacted = asterixOut("some sensitive text"); // returns "**** ********* ****" | ||
``` | ||
### redactString | ||
Redact string intelligently redacts the string by checking for common data formats. This reduces the | ||
risk of your app error'ing during the replay of Meticulous tests due to it failing to operate on the | ||
redacted data (e.g. "*******" is not a valid URL): | ||
```ts | ||
import { redactString } from "@alwaysmeticulous/redaction"; | ||
const redacted = redactString("some sensitive text"); // returns "**** ********* ****" | ||
const redacted2 = redactString("test@example.com"); // returns "----@-------.com" | ||
// etc. | ||
``` | ||
See [redactString.spec.ts](src/generic/__tests__/redact-string.spec.ts) for more examples. | ||
### NestedFieldsRedactor | ||
NestedFieldsRedactor allows you to specify a redaction policy for each distinct field name (for example 'ssn' or 'email'). It'll then recursively apply this redaction policy across all nested fields inside an object. Type safety | ||
ensures that compile time errors will be produced if you provide an object that has a field name (nested at any level | ||
inside the object) that you have not specified a redaction policy for. | ||
#### Basic Usage | ||
```ts | ||
import { transformJsonResponse, NestedFieldsRedactor, redactString } from "@alwaysmeticulous/redaction"; | ||
interface MyComplexApiType { | ||
details: { | ||
ssn: string; | ||
phoneNumbers: Array<{ mobile?: string; home?: string }>; | ||
}; | ||
// By default we do not require redacting boolean fields. | ||
isUSBased: boolean; | ||
} | ||
// Important: include your API type explictly in the call to createRedactor (`createRedactor<MyComplexApiType>`) | ||
const complexApiTypeRedactor = NestedFieldsRedactor.builder().createRedactor<MyComplexApiType>({ | ||
strings: { | ||
ssn: redactString, | ||
mobile: redactString, | ||
home: redactString, | ||
}, | ||
}); | ||
const middleware = [ | ||
transformJsonResponse({ | ||
urlRegExp: /https:\/\/api\.example\.com\/.*/, | ||
transform: (data: MyComplexApiType) => { | ||
return complexApiTypeRedactor(data); | ||
}, | ||
}), | ||
]; | ||
``` | ||
If you update MyComplexApiType to add a new `name` string field: | ||
```ts | ||
interface MyComplexApiType { | ||
name: string; // <<< ADDED | ||
details: { | ||
ssn: string; | ||
phoneNumbers: Array<{ mobile?: string; home?: string }>; | ||
}; | ||
isUSBased: boolean; | ||
} | ||
``` | ||
But don't add a corresponding redaction policy for the new `name` field to the 'createRedactor' call, then your | ||
code will fail to compile. This ensures that the redaction is exhaustive. | ||
`createRedactor` will force you to redact all non-enum string fields, but it won't force exhaustive redaction of | ||
other types of fields (dates, booleans, numbers, etc.). See `createRedactorStrict` if you need to enforce exhaustive | ||
redaction at compile time of additional data types. | ||
#### With Defaults | ||
We recommend however using `NestedFieldsRedactor.builderWithDefaults()`, which will provide default redactors | ||
for most common field names. If there are any string fields not covered by those defaults then the compiler will | ||
force you to specify a redaction policy for them: | ||
```ts | ||
const complexApiTypeRedactor = NestedFieldsRedactor.builderWithDefaults().createRedactor<MyComplexApiType>({ | ||
strings: { | ||
// Don't need to specify a redaction policy for `ssn` as it's covered by the defaults, | ||
// but we do need to specify a redaction policy for `mobile` and `home` as they're not covered by the defaults. | ||
mobile: redactString, | ||
home: redactString, | ||
}, | ||
}); | ||
``` | ||
#### Pattern Based Redactors | ||
You can also specify redactors that match field names that end with a given postfix, while preserving | ||
compile-time type safety. See [common-redactors.ts](src/generic/redact-nested-fields/common-redactors.ts) | ||
and [redact-nested-fields.ts](src/generic/redact-nested-fields/redact-nested-fields.ts) for some examples. | ||
### redactRecursively | ||
Recursively iterates through a JSON object applying the provided redaction function. See [redact-recursively.spec.ts](src/generic/__tests__/redact-recursively.spec.ts) for more details. | ||
This can be combined with `NestedFieldsRedactor` to provide extra safety. For example: | ||
```ts | ||
const complexApiTypeRedactor = NestedFieldsRedactor.builder().createRedactor<MyComplexApiType>({ | ||
strings: { | ||
ssn: redactString, | ||
mobile: redactString, | ||
home: redactString, | ||
}, | ||
}); | ||
const redactAnythingThatLooksLikeAnSSN = <T>(data: T) => redactRecursively( | ||
data, | ||
{ | ||
redactString: (str) => looksLikeAnSSN(str) ? asterixOut(str) : str, | ||
} | ||
); | ||
const middleware = [ | ||
transformJsonResponse({ | ||
urlRegExp: /https:\/\/api\.example\.com\/.*/, | ||
transform: (data: MyComplexApiType) => { | ||
return redactAnythingThatLooksLikeAnSSN(complexApiTypeRedactor(data)); | ||
}, | ||
}), | ||
]; | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
168200
1099
176
1