Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rehydra.ai/llms.txt

Use this file to discover all available pages before exploring further.

For applications that need to persist PII maps across requests or page reloads (like chat applications), Rehydra provides session-based storage.

Storage Providers

ProviderEnvironmentPersistenceUse Case
InMemoryPIIStorageProviderAllNoneDevelopment, testing
SQLitePIIStorageProviderNode.js, BunFile-basedServer-side applications
IndexedDBPIIStorageProviderBrowserBrowser storageClient-side applications
SQLitePIIStorageProvider is not available in browser builds. Use IndexedDBPIIStorageProvider for browser applications.

Important: Storage Requires Sessions

The storage provider is only used when you call anonymizer.session(). Direct anonymize() calls return the PII map but don’t save it:
// ❌ Storage NOT used - you must handle the PII map yourself
const result = await anonymizer.anonymize('Hello John!');
// result.piiMap is returned but NOT saved to storage

// ✅ Storage IS used - auto-saves and auto-loads
const session = anonymizer.session('conversation-123');
const result = await session.anonymize('Hello John!');
// result.piiMap is automatically saved to storage

Session Example

import { 
  createAnonymizer,
  InMemoryKeyProvider,
  SQLitePIIStorageProvider,  // or IndexedDBPIIStorageProvider for browser
} from 'rehydra';

// 1. Setup storage (once at app start)
const storage = new SQLitePIIStorageProvider('./pii-maps.db');
await storage.initialize();

// 2. Create anonymizer with storage and key provider
const anonymizer = createAnonymizer({
  ner: { mode: 'quantized' },
  keyProvider: new InMemoryKeyProvider(),
  piiStorageProvider: storage,
});
await anonymizer.initialize();

// 3. Create a session for each conversation
const session = anonymizer.session('conversation-123');

// 4. Anonymize - auto-saves to storage
const result = await session.anonymize('Hello John Smith from Acme Corp!');
console.log(result.anonymizedText);
// "Hello <PII type="PERSON" id="1"/> from <PII type="ORG" id="1"/>!"

// 5. Later (even after app restart): rehydrate - auto-loads and decrypts
const translated = await translateAPI(result.anonymizedText);
const original = await session.rehydrate(translated);
console.log(original);
// "Hello John Smith from Acme Corp!"

Multiple Conversations

Each session ID maps to a separate stored PII map:
// Different chat sessions
const aliceChat = anonymizer.session('user-alice-chat');
const bobChat = anonymizer.session('user-bob-chat');

await aliceChat.anonymize('Alice: Contact me at alice@example.com');
await bobChat.anonymize('Bob: My number is +49 30 123456');

// Each session has independent storage
await aliceChat.rehydrate(translatedText1);  // Uses Alice's PII map
await bobChat.rehydrate(translatedText2);    // Uses Bob's PII map

Multi-Message Conversations

Within a session, entity IDs are consistent across multiple anonymize() calls:
const session = anonymizer.session('chat-123');

// Message 1: User provides contact info
const msg1 = await session.anonymize('Contact me at user@example.com');
// → "Contact me at <PII type="EMAIL" id="1"/>"

// Message 2: References same email + new one  
const msg2 = await session.anonymize('CC: user@example.com and admin@example.com');
// → "CC: <PII type="EMAIL" id="1"/> and <PII type="EMAIL" id="2"/>"
//        ↑ Same ID (reused)                ↑ New ID

// All messages can be rehydrated correctly
await session.rehydrate(msg1.anonymizedText);  // ✓
await session.rehydrate(msg2.anonymizedText);  // ✓

Session Interface

interface AnonymizerSession {
  readonly sessionId: string;
  
  // Anonymize text and save to storage
  anonymize(
    text: string, 
    locale?: string, 
    policy?: Partial<AnonymizationPolicy>
  ): Promise<AnonymizationResult>;
  
  // Load PII map and restore original values
  rehydrate(text: string): Promise<string>;
  
  // Load stored PII map
  load(): Promise<StoredPIIMap | null>;
  
  // Delete session from storage
  delete(): Promise<boolean>;
  
  // Check if session exists
  exists(): Promise<boolean>;
}

SQLite Provider (Node.js / Bun)

import { SQLitePIIStorageProvider } from 'rehydra';

// File-based database
const storage = new SQLitePIIStorageProvider('./data/pii-maps.db');
await storage.initialize();

// Or in-memory for testing
const testStorage = new SQLitePIIStorageProvider(':memory:');
await testStorage.initialize();
Dependencies:
  • Bun: Uses built-in bun:sqlite (no additional install)
  • Node.js: Requires better-sqlite3:
npm install better-sqlite3

IndexedDB Provider (Browser)

import { 
  createAnonymizer,
  InMemoryKeyProvider,
  IndexedDBPIIStorageProvider,
} from 'rehydra';

// Custom database name (defaults to 'rehydra-pii-storage')
const storage = new IndexedDBPIIStorageProvider('my-app-pii');

const anonymizer = createAnonymizer({
  ner: { mode: 'quantized' },
  keyProvider: new InMemoryKeyProvider(),
  piiStorageProvider: storage,
});
await anonymizer.initialize();

// Use sessions as usual
const session = anonymizer.session('browser-chat-123');

Data Retention

Entries persist forever by default. Manage data with:
// Delete entries older than 7 days
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const deletedCount = await storage.cleanup(sevenDaysAgo);

// Delete specific session
await session.delete();

// List all stored sessions
const sessionIds = await storage.list();

Storage Provider Interface

Implement custom storage:
interface PIIStorageProvider {
  initialize(): Promise<void>;
  save(sessionId: string, data: StoredPIIMap): Promise<void>;
  load(sessionId: string): Promise<StoredPIIMap | null>;
  delete(sessionId: string): Promise<boolean>;
  exists(sessionId: string): Promise<boolean>;
  list(options?: ListOptions): Promise<string[]>;
  cleanup(olderThan: Date): Promise<number>;
  close(): Promise<void>;
}

Without Storage (Simple One-Off Usage)

For simple use cases without persistence:
import { 
  createAnonymizer, 
  decryptPIIMap, 
  rehydrate, 
  InMemoryKeyProvider 
} from 'rehydra';

const keyProvider = new InMemoryKeyProvider();
const anonymizer = createAnonymizer({
  ner: { mode: 'quantized' },
  keyProvider,
});
await anonymizer.initialize();

// Anonymize
const result = await anonymizer.anonymize('Hello John Smith!');

// Translate
const translated = await translateAPI(result.anonymizedText);

// Rehydrate manually
const key = await keyProvider.getKey();
const piiMap = await decryptPIIMap(result.piiMap, key);
const original = rehydrate(translated, piiMap);

Next Steps

Browser Usage

Storage considerations for browsers

Encryption

Understand PII map encryption