guardz-event
Version:
Type-safe event handling with runtime validation using guardz for unsafe data from 3rd parties
122 lines • 4.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeEventSourceListener = safeEventSourceListener;
const guardz_1 = require("guardz");
const Status_1 = require("../../domain/event/Status");
/**
* Safe EventSource event listener with callback-based API
* Usage: eventSource.addEventListener('message', safeEventSourceListener(isSSEData, { onSuccess: handleSSEData }));
*/
function safeEventSourceListener(guard, config) {
return (event) => {
const result = executeEventSourceValidation(event, {
guard,
tolerance: config.tolerance,
allowedOrigins: config.allowedOrigins,
allowedSources: config.allowedSources,
onError: (error, context) => {
// In tolerance mode, call onTypeMismatch for validation errors
if (config.tolerance && context.type === 'validation' && config.onTypeMismatch) {
config.onTypeMismatch(error);
}
else if (config.onError) {
config.onError(error, context);
}
}
});
if (result.status === Status_1.Status.SUCCESS) {
config.onSuccess(result.data);
}
else {
if (result.code === 500 && config.onTypeMismatch) {
config.onTypeMismatch(result.message);
}
else if (config.onError) {
config.onError(result);
}
}
};
}
/**
* Execute EventSource validation with the given configuration
*/
function executeEventSourceValidation(event, config) {
try {
// EventSource specific validation
if (event.target instanceof EventSource) {
const es = event.target;
if (es.readyState === EventSource.CLOSED) {
return {
status: Status_1.Status.ERROR,
code: 500,
message: 'EventSource is closed'
};
}
}
// Extract data from EventSource message
const data = event.data;
// Validate event structure
if (config.validateEvent && (typeof data === 'undefined' || data === null)) {
const errorMessage = 'EventSource event has no data';
if (config.onError) {
config.onError(errorMessage, {
type: 'validation',
eventType: 'message'
});
}
return {
status: Status_1.Status.ERROR,
code: 400,
message: errorMessage
};
}
// Type validation
const validationResult = config.tolerance
? (0, guardz_1.guardWithTolerance)(data, config.guard, {
identifier: config.identifier || 'EventSource data',
callbackOnError: (error) => {
if (config.onError) {
config.onError(error, {
type: 'validation',
eventType: 'message'
});
}
}
})
: config.guard(data);
if (!validationResult) {
const errorMessage = `EventSource data validation failed: ${config.identifier || 'EventSource data'}`;
if (config.onError) {
config.onError(errorMessage, {
type: 'validation',
eventType: 'message'
});
}
return {
status: Status_1.Status.ERROR,
code: 500,
message: errorMessage
};
}
return {
status: Status_1.Status.SUCCESS,
data: data
};
}
catch (error) {
const errorMessage = `EventSource validation error: ${error instanceof Error ? error.message : 'Unknown error'}`;
if (config.onError) {
config.onError(errorMessage, {
type: 'unknown',
eventType: 'message',
originalError: error
});
}
return {
status: Status_1.Status.ERROR,
code: 500,
message: errorMessage
};
}
}
//# sourceMappingURL=EventSourceListener.js.map