purgo
Version:
Zero-config PHI-scrubber for browser and Node.js
66 lines (65 loc) • 1.86 kB
JavaScript
// src/core.ts
var BUILT_IN_PATTERNS = {
// Email addresses
email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
// Phone numbers (various formats)
phone: /(\+\d{1,2}\s?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}/g,
// Social Security Numbers
ssn: /\b\d{3}[-]?\d{2}[-]?\d{4}\b/g,
// Medical Record Numbers (generic pattern, can be customized)
mrn: /\b\d{6,10}\b/g,
// ICD-10 codes
icd10: /\b[A-Z]\d{2}(\.[A-Z0-9]{1,4})?\b/g
};
var DEFAULT_CENSOR = () => "***";
var globalConfig = {
patterns: [],
censor: DEFAULT_CENSOR
};
function initRedactionEngine(options = {}) {
const patterns = options.patterns || ["email", "phone", "ssn", "mrn", "icd10"];
const regexPatterns = patterns.map((pattern) => {
if (typeof pattern === "string") {
return BUILT_IN_PATTERNS[pattern] || new RegExp(pattern, "g");
}
return pattern;
});
globalConfig = {
patterns: regexPatterns,
censor: options.censor || DEFAULT_CENSOR
};
}
function redactString(value) {
if (typeof value !== "string")
return value;
let result = value;
for (const patternTemplate of globalConfig.patterns) {
const pattern = new RegExp(patternTemplate.source, patternTemplate.flags);
result = result.replace(pattern, (match) => globalConfig.censor(match));
}
return result;
}
function redact(value) {
if (value === null || value === void 0)
return value;
if (typeof value !== "object") {
return typeof value === "string" ? redactString(value) : value;
}
if (Array.isArray(value)) {
return value.map((item) => redact(item));
}
const result = {};
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = redact(value[key]);
}
}
return result;
}
initRedactionEngine();
export {
BUILT_IN_PATTERNS,
initRedactionEngine,
redact,
redactString
};