ws-guard-lite
v0.1.0
Published
Lightweight, ultra-low-latency validation and observability framework for WebSocket-based data streams
Maintainers
Readme
ws-guard-lite
Lightweight, ultra-low-latency validation and observability framework for WebSocket-based data streams.
Features
- 🚀 Ultra-fast: Hot-path overhead < 0.01ms per message
- 📱 Mobile-first: Designed for React Native and mobile web
- 🔄 Non-blocking: Parallel validation doesn't block UI/state updates
- 🛡️ Tiered validation: Zero-cost guards → metadata → schema validation
- 👷 Worker support: Optional Web Worker for async validation
- 📊 Observability: Detect empty data, stale messages, schema drift, data gaps
Installation
npm install ws-guard-liteQuick Start
import { createWSGuard } from 'ws-guard-lite';
const guard = createWSGuard({
mode: 'parallel', // Non-blocking validation
maxAgeMs: 500, // Flag stale data older than 500ms
requiredKeysByType: {
price_tick: ['price'],
order_update: ['id', 'status']
},
onViolation: (event) => {
console.warn('[WS-GUARD]', event.verdict, event.details);
}
});
// In your WebSocket handler
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
guard.observe(msg); // Async validation
applyState(msg); // UI updates immediately
};
// Cleanup when done
guard.destroy();Validation Modes
Parallel Mode (Default)
Messages flow to UI/state immediately. Validation runs alongside and issues are flagged via callbacks.
const guard = createWSGuard({
mode: 'parallel',
onViolation: (event) => {
// Log, report to analytics, etc.
console.warn('Validation issue:', event);
}
});Strict Mode
Use validate() for critical streams where invalid messages should be dropped.
const guard = createWSGuard({ mode: 'strict' });
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (guard.validate(msg)) {
applyState(msg); // Only valid messages reach state
}
};Validation Tiers
Tier 0 - Zero-Cost Guards (Hot Path)
Always runs, extremely fast:
null/undefineddetection- Empty object
{}detection - Empty array
[]detection
Tier 1 - Metadata Validation
Lightweight structural checks:
- Message type validation
- Timestamp freshness (
maxAgeMs) - Sequence gap detection (
sequenceKey)
Tier 2 - Schema Validation
Deeper content analysis:
- Required keys per message type
- Schema drift detection
- No-op update detection
Configuration
interface GuardConfig {
// Validation mode: 'parallel' | 'strict'
mode?: 'parallel' | 'strict';
// Execution: 'worker' | 'inline'
validation?: 'worker' | 'inline';
// Max message age before flagging as stale
maxAgeMs?: number;
// Required keys per message type
requiredKeysByType?: Record<string, string[]>;
// Key containing message type (default: 'type')
typeKey?: string;
// Key containing timestamp (default: 'timestamp')
timestampKey?: string;
// Key containing sequence number
sequenceKey?: string;
// Callback for violations
onViolation?: (event: ViolationEvent) => void;
// Enable no-op detection
detectNoOp?: boolean;
// Enable schema drift detection
detectDrift?: boolean;
}Verdicts
| Verdict | Description |
|---------|-------------|
| OK | Message passed all validation |
| EMPTY_PAYLOAD | Null, undefined, empty object, or empty array |
| STALE_DATA | Timestamp older than maxAgeMs |
| NO_OP_UPDATE | Message identical to previous (when detectNoOp: true) |
| SCHEMA_MISMATCH | Keys differ from baseline (when detectDrift: true) |
| DATA_GAP | Sequence number jump detected |
| MISSING_REQUIRED_KEYS | Required keys missing or null |
| INVALID_TYPE | Missing message type when requiredKeysByType configured |
Architecture
WebSocket
→ message parsing (user-owned)
→ ws-guard-lite
├─ Fast path → UI / state (non-blocking)
└─ Validation path (inline or worker, parallel)
→ emits validation events / flags
→ Application subscribes to validation signalsThe library never owns the WebSocket or application state. It only validates and reports.
Performance
- Hot path overhead: < 0.01ms per message
- Safe for 100-1000 messages/second
- No deep cloning, no JSON stringify
- No exceptions for control flow
License
MIT
