guardz-event
Version:
Type-safe event handling with runtime validation using guardz for unsafe data from 3rd parties
233 lines • 10.1 kB
TypeScript
import type { TypeGuardFn } from 'guardz';
import { Status } from '../domain/event/Status';
export { Status };
export type EventResult<T> = {
status: Status.SUCCESS;
data: T;
} | {
status: Status.ERROR;
code: number;
message: string;
};
/**
* Configuration for safe event handling that never throws
*/
export interface SafeEventConfig<T> {
/** Type guard function to validate event data */
guard: TypeGuardFn<T>;
/** Enable tolerance mode (default: false) */
tolerance?: boolean;
/** Identifier for error context (default: event type) */
identifier?: string;
/** Error callback - only used in tolerance mode */
onError?: (error: string, context: ErrorContext) => void;
/** Validate event structure */
validateEvent?: boolean;
/** Timeout in milliseconds for async operations */
timeout?: number;
/** Allowed origins for security validation */
allowedOrigins?: string[];
/** Allowed sources for security validation */
allowedSources?: string[];
}
/**
* Configuration for ergonomic event listeners
*/
export interface SafeEventListenerConfig<T> {
/** Type guard function to validate event data */
guard: TypeGuardFn<T>;
/** Enable tolerance mode (default: false) */
tolerance?: boolean;
/** Allowed origins for security validation */
allowedOrigins?: string[];
/** Allowed sources for security validation */
allowedSources?: string[];
/** Callback for type mismatch errors */
onTypeMismatch?: (errorMessage: string) => void;
/** Callback for security violations */
onSecurityViolation?: (origin: string, message: string) => void;
/** Callback for other errors */
onError?: (error: string, context: ErrorContext) => void;
}
/**
* Configuration for ergonomic event listeners (without guard parameter)
*/
export interface ErgonomicEventListenerConfig<T = unknown> {
/** Enable tolerance mode (default: false) */
tolerance?: boolean;
/** Allowed origins for security validation */
allowedOrigins?: string[];
/** Allowed sources for security validation */
allowedSources?: string[];
/** Callback for type mismatch errors */
onTypeMismatch?: (errorMessage: string) => void;
/** Callback for security violations */
onSecurityViolation?: (origin: string, message: string) => void;
/** Callback for other errors */
onError?: (error: string, context: ErrorContext) => void;
}
export interface ErrorContext {
type: 'validation' | 'security' | 'timeout' | 'unknown';
eventType: string;
origin?: string;
source?: string;
originalError?: unknown;
identifier?: string;
}
/**
* Safe PostMessage event listener with callback-based API
* Usage: window.addEventListener('message', safePostMessageListener(isUserMessage, { tolerance: true, onTypeMismatch: console.warn }));
*/
export declare function safePostMessageListener<T>(guard: TypeGuardFn<T>, config: ErgonomicEventListenerConfig<T> & {
onSuccess: (data: T) => void;
onError?: (result: {
status: Status.ERROR;
code: number;
message: string;
}) => void;
}): (event: MessageEvent) => void;
/**
* Safe WebSocket event listener with callback-based API
* Usage: ws.addEventListener('message', safeWebSocketListener(isWSData, { onSuccess: handleWSData }));
*/
export declare function safeWebSocketListener<T>(guard: TypeGuardFn<T>, config: ErgonomicEventListenerConfig<T> & {
onSuccess: (data: T) => void;
onError?: (result: {
status: Status.ERROR;
code: number;
message: string;
}) => void;
}): (event: MessageEvent) => void;
/**
* Safe DOM event listener with callback-based API
* Usage: element.addEventListener('click', safeDOMEventListener(isClickData, { onSuccess: handleClick }));
*/
export declare function safeDOMEventListener<T>(guard: TypeGuardFn<T>, config: ErgonomicEventListenerConfig<T> & {
onSuccess: (data: T) => void;
onError?: (result: {
status: Status.ERROR;
code: number;
message: string;
}) => void;
}): (event: Event) => void;
/**
* Safe EventSource event listener with callback-based API
* Usage: eventSource.addEventListener('message', safeEventSourceListener(isSSEData, { onSuccess: handleSSEData }));
*/
export declare function safeEventSourceListener<T>(guard: TypeGuardFn<T>, config: ErgonomicEventListenerConfig<T> & {
onSuccess: (data: T) => void;
onError?: (result: {
status: Status.ERROR;
code: number;
message: string;
}) => void;
}): (event: MessageEvent) => void;
/**
* Safe CustomEvent listener with callback-based API
* Usage: element.addEventListener('customEvent', safeCustomEventListener(isCustomData, { onSuccess: handleCustomData }));
*/
export declare function safeCustomEventListener<T>(guard: TypeGuardFn<T>, config: ErgonomicEventListenerConfig<T> & {
onSuccess: (data: T) => void;
onError?: (result: {
status: Status.ERROR;
code: number;
message: string;
}) => void;
}): (event: CustomEvent) => void;
/**
* Safe StorageEvent listener with callback-based API
* Usage: window.addEventListener('storage', safeStorageEventListener(isStorageData, { onSuccess: handleStorageData }));
*/
export declare function safeStorageEventListener<T>(guard: TypeGuardFn<T>, config: ErgonomicEventListenerConfig<T> & {
onSuccess: (data: T) => void;
onError?: (result: {
status: Status.ERROR;
code: number;
message: string;
}) => void;
}): (event: StorageEvent) => void;
/**
* Safe DOM event handler (legacy API)
*/
export declare function safeDOMEvent<T>(config: SafeEventConfig<T>): (event: Event) => EventResult<T>;
/**
* Safe PostMessage handler (legacy API)
*/
export declare function safePostMessage<T>(config: SafeEventConfig<T>): (event: MessageEvent) => EventResult<T>;
/**
* Safe WebSocket handler (legacy API)
*/
export declare function safeWebSocket<T>(config: SafeEventConfig<T>): (event: MessageEvent) => EventResult<T>;
/**
* Safe EventSource handler (legacy API)
*/
export declare function safeEventSource<T>(config: SafeEventConfig<T>): (event: MessageEvent) => EventResult<T>;
/**
* Safe CustomEvent handler (legacy API)
*/
export declare function safeCustomEvent<T>(config: SafeEventConfig<T>): (event: CustomEvent) => EventResult<T>;
/**
* Safe StorageEvent handler (legacy API)
*/
export declare function safeStorageEvent<T>(config: SafeEventConfig<T>): (event: StorageEvent) => EventResult<T>;
/**
* Generic safe event handler (legacy API)
*/
export declare function safeEvent<T>(eventConfig: {
event: Event;
} & SafeEventConfig<T>): Promise<EventResult<T>>;
export declare class SafeEventBuilder<T = unknown> {
private config;
private eventType;
domEvent(eventType: string): SafeEventBuilder<T>;
postMessage(): SafeEventBuilder<T>;
webSocket(): SafeEventBuilder<T>;
eventSource(): SafeEventBuilder<T>;
customEvent(eventType: string): SafeEventBuilder<T>;
storageEvent(): SafeEventBuilder<T>;
guard<U>(guardFn: TypeGuardFn<U>): SafeEventBuilder<U>;
tolerance(enabled?: boolean): SafeEventBuilder<T>;
identifier(id: string): SafeEventBuilder<T>;
timeout(ms: number): SafeEventBuilder<T>;
allowedOrigins(origins: string[]): SafeEventBuilder<T>;
allowedSources(sources: string[]): SafeEventBuilder<T>;
onError(callback: (error: string, context: ErrorContext) => void): SafeEventBuilder<T>;
createHandler(): ((event: MessageEvent) => EventResult<T>) | ((event: StorageEvent) => EventResult<T>) | ((event: CustomEvent) => EventResult<T>) | ((event: Event) => EventResult<T>);
}
export declare function safe(): SafeEventBuilder;
export interface SafeEventContextConfig {
defaultTolerance?: boolean;
allowedOrigins?: string[];
allowedSources?: string[];
defaultTimeout?: number;
onError?: (error: string, context: ErrorContext) => void;
}
export interface SafeEventContext {
domEvent<T>(eventType: string, config: Omit<SafeEventConfig<T>, 'guard'> & {
guard: TypeGuardFn<T>;
}): (event: Event) => EventResult<T>;
postMessage<T>(config: Omit<SafeEventConfig<T>, 'guard'> & {
guard: TypeGuardFn<T>;
}): (event: MessageEvent) => EventResult<T>;
webSocket<T>(config: Omit<SafeEventConfig<T>, 'guard'> & {
guard: TypeGuardFn<T>;
}): (event: MessageEvent) => EventResult<T>;
eventSource<T>(config: Omit<SafeEventConfig<T>, 'guard'> & {
guard: TypeGuardFn<T>;
}): (event: MessageEvent) => EventResult<T>;
customEvent<T>(eventType: string, config: Omit<SafeEventConfig<T>, 'guard'> & {
guard: TypeGuardFn<T>;
}): (event: CustomEvent) => EventResult<T>;
storageEvent<T>(config: Omit<SafeEventConfig<T>, 'guard'> & {
guard: TypeGuardFn<T>;
}): (event: StorageEvent) => EventResult<T>;
}
export declare function createSafeEventContext(contextConfig?: SafeEventContextConfig): SafeEventContext;
export type InferEventDataType<T> = T extends TypeGuardFn<infer U> ? U : never;
export declare function createTypedSafeDOMEvent<T>(guard: TypeGuardFn<T>): (config: Omit<SafeEventConfig<T>, "guard">) => (event: Event) => EventResult<T>;
export declare function createTypedSafePostMessage<T>(guard: TypeGuardFn<T>): (config: Omit<SafeEventConfig<T>, "guard">) => (event: MessageEvent) => EventResult<T>;
export declare function createTypedSafeWebSocket<T>(guard: TypeGuardFn<T>): (config: Omit<SafeEventConfig<T>, "guard">) => (event: MessageEvent) => EventResult<T>;
export declare function createTypedSafeEventSource<T>(guard: TypeGuardFn<T>): (config: Omit<SafeEventConfig<T>, "guard">) => (event: MessageEvent) => EventResult<T>;
export declare function createTypedSafeCustomEvent<T>(guard: TypeGuardFn<T>): (config: Omit<SafeEventConfig<T>, "guard">) => (event: CustomEvent) => EventResult<T>;
export declare function createTypedSafeStorageEvent<T>(guard: TypeGuardFn<T>): (config: Omit<SafeEventConfig<T>, "guard">) => (event: StorageEvent) => EventResult<T>;
//# sourceMappingURL=safe-event-never-throws.d.ts.map