JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q25362F
  • License MIT

Zero-config PHI-scrubber for browser and Node.js

Package Exports

  • purgo
  • purgo/core
  • purgo/node
  • purgo/redact

Readme

Purgo

Purgo Logo

npm version Bundle Size Tests Passing CI TypeScript License: MIT npm downloads

Purgo is a zero-config, client-side log-scrubbing library that prevents Protected Health Information (PHI) from leaking into browser consoles, DevTools, and network debuggers.

  • 🔒 HIPAA-Friendly: Automatically redacts PHI from logs and network requests
  • 🪶 Lightweight: < 7 kB gzip
  • Fast: < 3% runtime overhead
  • 🔌 Zero-Config: Works out-of-the-box with React, Next.js, Vue, and vanilla JS
  • 🧩 Extensible: Add custom patterns and redaction strategies

Installation

npm install purgo
# or
yarn add purgo
# or
pnpm add purgo

Quick Start

Browser (Zero-Config)

// Just import it - that's it!
import 'purgo';

// Now all console logs and network requests will be automatically scrubbed
console.log('Patient email: patient@example.com'); // Outputs: "Patient email: ***"

Custom Configuration

import { purgo } from 'purgo';

purgo({
  targets: ['console', 'fetch', 'xhr'],
  patterns: ['email', 'ssn', /\b\d{7,8}-[A-Z]{2}\b/], // Built-in + custom patterns
  censor: (match) => '[REDACTED]' + match.slice(-2)   // Custom redaction
});

Direct Redaction Helper

import { redact } from 'purgo';

const patientData = {
  name: 'John Doe',
  email: 'john.doe@example.com',
  ssn: '123-45-6789'
};

const safeData = redact(patientData);
// Result: { name: 'John Doe', email: '***', ssn: '***' }

Core Module (No Auto-Patching)

If you want just the redaction functionality without any automatic patching of global objects:

import { redact, initRedactionEngine } from 'purgo/core';

// Optional: customize the redaction engine
initRedactionEngine({
  patterns: ['email', 'phone', 'ssn', /\b[A-Z]{2}-\d{6}\b/g],
  censor: (match) => `[REDACTED-${match.slice(-2)}]`
});

// Explicitly redact values
const email = "patient@example.com";
console.log(redact(email)); // Outputs: "[REDACTED-om]"

Node.js Support

// Auto-patch process.stdout
import 'purgo/node';

// Direct use with console.log or process.stdout.write
console.log('Patient email: patient@example.com'); // Outputs: "Patient email: ***"
process.stdout.write('SSN: 123-45-6789\n');       // Outputs: "SSN: ***"

Node.js with Custom Configuration

For more control, you can combine the auto-patching with custom configuration:

// Use the Node.js module for auto-patching
import 'purgo/node';
// Import the core module for custom configuration
import { initRedactionEngine } from 'purgo/core';

// Configure the redaction engine with custom patterns and redaction style
initRedactionEngine({
  patterns: ['email', 'ssn', /\b\d{7,8}-[A-Z]{2}\b/], // Built-in + custom patterns
  censor: (match) => '[REDACTED]' + match.slice(-2)   // Custom redaction style
});

// Test with various sensitive data
const email = 'test@test.com';
const ssn = '123456789';

console.log("Email: ", email);  // Outputs: "Email: [REDACTED]om"
console.log("SSN: ", ssn);      // Outputs: "SSN: [REDACTED]89"

Express Integration

// app.js
import express from 'express';
import 'purgo/node';
import { initRedactionEngine } from 'purgo/core';

// Configure Purgo with custom patterns and redaction
initRedactionEngine({
  patterns: ['email', 'ssn', 'phone', /\b\d{7,8}-[A-Z]{2}\b/],
  censor: (match) => '[REDACTED]' + match.slice(-2)
});

const app = express();
app.use(express.json());

// Example route that handles PHI
app.post('/api/patient', (req, res) => {
  // PHI in request body will be automatically redacted in logs
  console.log('Received patient data:', req.body);

  // Process the data (using the original, unredacted data)
  const patientId = savePatient(req.body);

  // Log with PHI (will be automatically redacted)
  console.log(`Created patient with email ${req.body.email}`);

  res.json({ success: true, patientId });
});

// Server logs will show:
// Received patient data: { name: 'Jane Doe', email: '[REDACTED]om', ssn: '[REDACTED]21' }
// Created patient with email [REDACTED]om

Pino Logger Integration

Pino is a popular structured logger for Node.js that's commonly used in healthcare applications. Purgo provides a dedicated integration:

import { pinoRedactor } from 'purgo/node';
import pino from 'pino';

const logger = pino({
  redact: pinoRedactor({
    paths: ['req.body.ssn', 'req.body.email', 'patient.mrn']
  })
});

// Logs will have PHI automatically redacted
logger.info({
  req: { body: { email: 'patient@example.com' } }
});

Framework Integration Examples

React

// In your entry file (e.g., main.jsx or index.jsx)
import 'purgo';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Next.js 14

// app/layout.tsx
import 'purgo';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

Purgo v0.1.2+ includes special handling for Next.js environments to ensure compatibility with the App Router and Server Components architecture.

Vue 3

// main.js
import 'purgo';
import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');

Vanilla JS (via script tag)

<script src="https://unpkg.com/purgo/dist/index.global.js"></script>
<script>
  // Purgo is automatically initialized
  console.log('Patient SSN: 123-45-6789'); // Outputs: "Patient SSN: ***"
</script>

API Reference

purgo(options?)

Initializes Purgo with custom options.

interface PurgoOptions {
  targets?: Array<'console' | 'fetch' | 'xhr'>;
  patterns?: Array<RegExp | string>;
  censor?: (match: string) => string;
  hashMode?: boolean;
}

Note: When using ES modules, we recommend using the auto-patching import (import 'purgo') or the combined approach with import 'purgo/node' and import { initRedactionEngine } from 'purgo/core' rather than the named import (import { purgo } from 'purgo'), which may cause issues in some environments.

  • targets: Array of targets to patch (default: ['console', 'fetch', 'xhr'])
  • patterns: Array of built-in pattern names or custom RegExp objects (default: ['email', 'phone', 'ssn', 'mrn', 'icd10'])
  • censor: Function to transform matched content (default: () => '***')
  • hashMode: Enable SHA-256 hashing of censored tokens for correlation (default: false)

Built-in Patterns

  • email: Email addresses
  • phone: Phone numbers in various formats
  • ssn: Social Security Numbers
  • mrn: Medical Record Numbers
  • icd10: ICD-10 diagnosis codes

redact(value)

Redacts PHI from any value while preserving structure.

function redact<T>(value: T): T;

Core Module: import from 'purgo/core'

The core module provides just the redaction functionality without any automatic patching of global objects.

import { redact, initRedactionEngine } from 'purgo/core';

This is useful when:

  • You want more control over what gets redacted
  • You want to avoid patching global objects
  • You're using a framework that doesn't work well with patched globals
  • You need to customize the redaction behavior extensively

As of v0.1.2, all modules include full TypeScript declarations for improved developer experience.

Node.js: pinoRedactor(options)

Creates a redactor for use with Pino logger.

interface PinoRedactorOptions {
  paths: string[];
  additionalPatterns?: Array<RegExp | string>;
  censor?: (match: string) => string;
}

Performance

Purgo is designed to be lightweight and fast:

  • Bundle Size: < 7 kB gzip
  • Runtime Overhead: < 3% compared to raw operations
  • Redaction Speed: ≤ 40 µs to redact a 5 kB string on M1 2.8 GHz

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details on how to contribute to this project.

License

MIT License - see LICENSE for details.

A ready-to-sign Business Associate Agreement (BAA) template is available in the legal directory.