guardz-event
Version:
Type-safe event handling with runtime validation using guardz for unsafe data from 3rd parties
138 lines • 6.45 kB
TypeScript
import type { TypeGuardFn } from 'guardz';
export interface EventOptions<T> {
onSuccess: (data: T) => void;
onError?: (message: string) => void;
onTypeMismatch?: (message: string) => void;
onSecurityViolation?: (origin: string, message: string) => void;
tolerance?: boolean;
allowedOrigins?: string[];
allowedSources?: string[];
identifier?: string;
}
export interface EventGuardOptions<T> extends EventOptions<T> {
guard: TypeGuardFn<T>;
}
/**
* Create a safe event handler for any event type
* Usage: window.addEventListener('message', onEvent('message', isChatMessage, { onSuccess: handleData }))
*/
export declare function onEvent<T>(eventType: string, guard: TypeGuardFn<T>, options: EventOptions<T>): (event: Event) => void;
/**
* Create a safe message event handler
* Usage: window.addEventListener('message', onMessage(isChatMessage, { onSuccess: handleData }))
*/
export declare function onMessage<T>(guard: TypeGuardFn<T>, options: EventOptions<T>): (event: MessageEvent) => void;
/**
* Create a safe DOM event handler
* Usage: element.addEventListener('click', onClick(isClickData, { onSuccess: handleClick }))
*/
export declare function onClick<T>(guard: TypeGuardFn<T>, options: EventOptions<T>): (event: Event) => void;
/**
* Create a safe custom event handler
* Usage: element.addEventListener('custom-event', onCustom('custom-event', isCustomData, { onSuccess: handleData }))
*/
export declare function onCustom<T>(eventType: string, guard: TypeGuardFn<T>, options: EventOptions<T>): (event: CustomEvent) => void;
/**
* Create a safe storage event handler
* Usage: window.addEventListener('storage', onStorage(isStorageData, { onSuccess: handleStorage }))
*/
export declare function onStorage<T>(guard: TypeGuardFn<T>, options: EventOptions<T>): (event: StorageEvent) => void;
export declare class EventGuard<T = unknown> {
private eventType;
private guard?;
private options;
type(eventType: string): EventGuard<T>;
validate<U>(guard: TypeGuardFn<U>): EventGuard<U>;
onSuccess(callback: (data: T) => void): EventGuard<T>;
onError(callback: (message: string) => void): EventGuard<T>;
onTypeMismatch(callback: (message: string) => void): EventGuard<T>;
onSecurityViolation(callback: (origin: string, message: string) => void): EventGuard<T>;
tolerance(enabled?: boolean): EventGuard<T>;
allowedOrigins(origins: string[]): EventGuard<T>;
allowedSources(sources: string[]): EventGuard<T>;
identifier(id: string): EventGuard<T>;
build(): (event: Event) => void;
}
/**
* Create a fluent event guard builder
* Usage: eventGuard().type('message').validate(isChatMessage).onSuccess(handleData).build()
*/
export declare function eventGuard<T = unknown>(): EventGuard<T>;
export interface UseEventOptions<T> extends Omit<EventOptions<T>, 'onSuccess'> {
onSuccess?: (data: T) => void;
}
export interface UseEventResult<T> {
data: T | null;
error: string | null;
isLoading: boolean;
refetch: () => void;
}
/**
* React hook for safe event handling
* Usage: const { data, error } = useEvent('message', isChatMessage, { tolerance: true })
*
* Note: This is a framework-agnostic implementation. For React integration,
* you would need to wrap this with React's useEffect and useState hooks.
*
* Example React implementation:
* ```tsx
* function useSafeEvent<T>(eventType: string, guard: TypeGuardFn<T>, options: UseEventOptions<T> = {}) {
* const [data, setData] = useState<T | null>(null);
* const [error, setError] = useState<string | null>(null);
* const [isLoading, setIsLoading] = useState(false);
*
* useEffect(() => {
* const handler = onEvent(eventType, guard, {
* onSuccess: (data) => {
* setData(data);
* setError(null);
* setIsLoading(false);
* options.onSuccess?.(data);
* },
* onError: (message) => {
* setError(message);
* setIsLoading(false);
* options.onError?.(message);
* },
* onTypeMismatch: options.onTypeMismatch,
* onSecurityViolation: options.onSecurityViolation,
* tolerance: options.tolerance,
* allowedOrigins: options.allowedOrigins,
* allowedSources: options.allowedSources,
* identifier: options.identifier,
* });
*
* // Add event listener
* window.addEventListener(eventType, handler);
*
* // Cleanup
* return () => window.removeEventListener(eventType, handler);
* }, [eventType, guard, options]);
*
* return { data, error, isLoading, refetch: () => setIsLoading(true) };
* }
* ```
*/
export declare function useEvent<T>(eventType: string, guard: TypeGuardFn<T>, options?: UseEventOptions<T>): UseEventResult<T>;
/**
* Create a safe event handler with minimal configuration
* Usage: window.addEventListener('message', safeHandler(isChatMessage, handleData))
*/
export declare function safeHandler<T>(guard: TypeGuardFn<T>, onSuccess: (data: T) => void, onError?: (message: string) => void): (event: Event) => void;
/**
* Create a safe event handler with tolerance mode
* Usage: window.addEventListener('message', safeTolerant(isChatMessage, handleData, handleError))
*/
export declare function safeTolerant<T>(guard: TypeGuardFn<T>, onSuccess: (data: T) => void, onError?: (message: string) => void): (event: Event) => void;
/**
* Infer the event data type from a guard function
*/
export type InferEventData<T> = T extends TypeGuardFn<infer U> ? U : never;
/**
* Create a typed event handler factory
*/
export declare function createTypedHandler<T>(guard: TypeGuardFn<T>): (options: EventOptions<T>) => (event: Event) => void;
export { safeDOMEvent, safeWebSocket, safeEventSource, safeEvent, SafeEventBuilder, safe, createSafeEventContext, type SafeEventContext, type SafeEventContextConfig, type InferEventDataType, createTypedSafeDOMEvent, createTypedSafePostMessage, createTypedSafeWebSocket, createTypedSafeEventSource, createTypedSafeCustomEvent, createTypedSafeStorageEvent, safePostMessageListener, safeWebSocketListener, safeDOMEventListener, safeEventSourceListener, safeCustomEventListener, safeStorageEventListener, type SafeEventListenerConfig, type ErgonomicEventListenerConfig, type ErrorContext, } from './utils/safe-event-never-throws';
export * from './utils/additional-sources';
export { Status } from './domain/event/Status';
//# sourceMappingURL=index.d.ts.map