@dysonic/web-replay-core
v0.1.0
Published
Shared core primitives for web replay capture and export
Readme
@dysonic/web-replay-core
Shared core primitives for the web-replay monorepo. Provides recording lifecycle management, circular event buffering, and privacy masking utilities that all other packages build on.
Installation
npm install @dysonic/web-replay-coreCore Concepts
RecorderCore
The central orchestrator. It wires together a RecorderAdapter (the event source) and a SessionBuffer (the ring buffer), and tracks session metadata.
import { RecorderCore } from '@dysonic/web-replay-core';
const recorder = new RecorderCore(
{
source: 'pc-sdk', // 'extension' | 'h5-sdk' | 'pc-sdk'
maxMinutes: 5, // keep up to 5 minutes of events (max 10)
maxBytes: 5 * 1024 * 1024, // keep up to 5 MB of events
maskRules: [], // optional CSS-selector-based masking rules
},
// optional context overrides:
{
getPageUrl: () => window.location.href,
getPageTitle: () => document.title,
getUserAgent: () => navigator.userAgent,
getViewport: () => ({ width: window.innerWidth, height: window.innerHeight }),
getSessionId: () => 'my-custom-id',
},
);Lifecycle
recorder.start(adapter); // begin recording; adapter supplies events
recorder.pause(); // stop buffering events (adapter stays active)
recorder.resume(); // resume buffering
recorder.stop(); // tear down adapter; buffer is retained
recorder.clear(); // discard buffered events
const envelope = recorder.flush(); // export a ReplayEnvelope snapshot
recorder.getState(); // { active: boolean, paused: boolean }Custom events
recorder.addCustomEvent('error', { message: 'Something broke', lineno: 42 });
recorder.addCustomEvent('network', { url: '/api/data', status: 200, durationMs: 120 });
recorder.addCustomEvent('route', { action: 'pushState', url: '/new-page' });
recorder.addCustomEvent('lifecycle', { visibility: 'hidden' });RecorderAdapter
The interface that bridges an event source (e.g. rrweb) to RecorderCore. Implement start and return a cleanup function.
import { RecorderAdapter } from '@dysonic/web-replay-core';
const myAdapter: RecorderAdapter<MyEvent> = {
start(emit) {
const unsubscribe = myEventSource.on('event', (e) => emit(e));
return unsubscribe; // called by recorder.stop()
},
};RingBuffer / SessionBuffer
RingBuffer<TEvent> is the underlying time- and size-bounded circular buffer. SessionBuffer wraps two RingBuffer instances — one for rrweb events and one for custom events — and provides the export() method that produces a ReplayEnvelope.
import { RingBuffer, SessionBuffer } from '@dysonic/web-replay-core';
const buf = new RingBuffer<MyEvent>({ maxMinutes: 5, maxBytes: 5_242_880 });
buf.push({ timestamp: Date.now(), sizeEstimate: 256, event: myEvent });
buf.list(); // events within the configured window
buf.snapshot(); // { records, totalBytes }
buf.clear();ReplayEnvelope
The exported data format. Produced by recorder.flush() or sessionBuffer.export().
interface ReplayEnvelope<TEvent> {
format: string; // 'web-replay-debugger'
schemaVersion: string; // '1.0.0'
meta: SessionMeta;
rrwebEvents: TEvent[];
customEvents: CustomEvent[];
exportedAt: number; // Unix ms timestamp
}Privacy utilities
import { shouldMaskField, maskText, maskValue } from '@dysonic/web-replay-core';
shouldMaskField('password'); // true — matches built-in sensitive pattern
maskText('secret123'); // '***'
maskValue('phone', '13800000000', maskRules, '#login-form input');Built-in sensitive field pattern matches: password, passwd, pwd, phone, mobile, idcard, identity, token.
Configuration defaults
| Option | Default | Max |
|---|---|---|
| maxMinutes | 5 | 10 |
| maxBytes | 5 MB | — |
| Mask replacement | '***' | — |
License
MIT
