- β
Utilize the full controll of
CustomEventswith a custom API - β
End-to-end type safety; validate event payload at runtime via your provided
Zodschema - β
Framework agnostic; runs on any
JavaScriptenvironment - β
Supports all
CustomEventnative properties and methods inherited by theEventinterface - β Middleware support for event processing
- β Less than 1kb minified and gzipped
Install zod-custom-events using your favorite package manager or CDN, then include it in your project:
# Install with npm
npm install zod-custom-events
# Install with pnpm
pnpm add zod-custom-events
# Install with yarn
yarn add zod-custom-events
# Install with bun
bun add zod-custom-events# Install in a node project
npx jsr add @georgecht/zod-custom-events
# Install in a deno project
deno add jsr:@georgecht/zod-custom-events
# Install in a bun project
bunx jsr add @georgecht/zod-custom-events<!-- Via jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/zod-custom-events@latest/dist/index.min.js"></script>
<!-- Via unpkg -->
<script src="https://www.unpkg.com/zod-custom-events/dist/index.min.js"></script>Here's a basic example of how to use zod-custom-events:
import { z } from 'zod';
import { EventController } from 'zod-custom-events';
// Define your event schema
const userSchema = z.object({
id: z.number(),
email: z.email(),
});
// Create an event controller
const userEventController = new EventController(userSchema, 'user-event');
// Subscribe to the event
userEventController.subscribe((event) => {
console.log('Received user event:', event.detail);
});
// Dispatch an event
userEventController.dispatch({
id: 123,
email: 'my@email.com',
});
// Cleanup
userEventController.unsubscribe();The API reference is available on GitHub.
The main class for managing custom events. The EventController<T extends ZodSchema> extends the CustomEvent interface with a detail property of type T. Meaning it will match the CustomEvent interface and infer all the functionality.
constructor(schema: T, eventName: string, options?: EventControllerOptions<T>)Creates a new EventController instance.
schema- The Zod schema for validating the event payload.eventName- The name of the custom event.optionsoptional - Configuration options for theEventController.
import { z } from 'zod';
import { EventController } from 'zod-custom-events';
const schema = z.object({
name: z.string(),
});
const controller = new EventController(schema, 'myEvent', {
onError: ({ error }) => console.error('Validation error:', error),
onDispatch: ({ payload }) => console.log('Dispatching event with payload:', payload),
});elementoptional - The element to bind the event to. Defaults towindow.onErroroptional - Error handler for validation errors.onDispatchoptional - Callback function called before dispatching the event.onSubscribeoptional - Callback function called when the event listener is added.onUnsubscribeoptional - Callback function called when the event listener is removed.
Subscribe to the event.
subscribe(listener: (event: TypedCustomEvent<EventPayload<T>>) => void, options?: AddEventListenerOptions): voidlistener- The function to be called when the event is triggered.options- Optional parameters for the event listener.
onceoptional - A boolean value indicating that thelistenershould be invoked at mostonceafter being added. Iftrue, thelistenerwould be automatically removed when invoked.passiveoptional - A boolean indicating whether the event listener is apassivelistener. If set totrue, indicates that the function specified by listener will never callpreventDefault(). If a passive listener callspreventDefault(), nothing will happen and a console warning may be generated.signaloptional - AnAbortSignalto signal when the listener should be removed.
controller.subscribe((event) => {
console.log('Received user event:', event.detail);
});// With abort signal and once option
const abortController = new AbortController();
const { signal } = abortController;
controller.subscribe((event) => {
console.log('Received user event:', event.detail);
}, { signal, once: true });
// Later in the code
abortController.abort();Removes the previously registered event listener for the event.
unsubscribe(options?: EventListenerOptions): voidoptionsoptional - Optional parameters to match the event listener.
captureoptional - A boolean value indicating that events of this type will be dispatched to the registeredlistenerbefore being dispatched to anyEventTargetbeneath it in the DOM tree.
controller.unsubscribe();Dispatches the event, validating its payload using the Zod schema and applying middleware.
dispatch(payload: EventPayload<T>, eventInitDict?: CustomEventInit<EventPayload<T>>): Promise<void>payload- The data associated with the event. Validated against theZodschema initially provided.eventInitDictoptional - Optional parameters for initializing the event.
bubblesoptional - A boolean value indicating whether or not the event can bubble through the DOM.cancelableoptional - A boolean value indicating whether the event can be cancelled.composedoptional - A boolean value indicating whether the event will trigger listeners outside of a shadow root (seeEvent.composedfor more details).
controller.dispatch({
id: 1,
name: 'John Doe',
}, {
bubbles: true
});Sets a condition for the event, allowing control over whether the event is dispatched.
refine(condition: (payload: EventPayload<T>) => boolean, callback?: (ctx: EventPayloadContext<T>) => void): voidcondition- A function that takes the event payload as input and returns a boolean.callbackoptional - An optional callback function to be called when the condition is not met.
controller.refine(
(payload) => payload.id > 0,
(ctx) => {
const { payload } = ctx;
console.log("Invalid user ID:", payload.id)
}
);Updates the EventController options.
update(options: Partial<EventControllerOptions<T>>): voidoptionsoptional - New configuration options for theEventController.
const controller = new EventController(schema, 'myEvent');
// Later in the code
controller.update({
onError: ({ error }) => console.warn('New error handler:', error),
onDispatch: ({ payload }) => console.log('New dispatch handler:', payload),
});Adds a middleware function to the event processing pipeline.
use(middleware: Middleware<EventPayload<T>>): voidmiddleware- A function that processes the event context and calls the next middleware.
controller.use(async (ctx, next) => {
console.log("Processing user event:", ctx.payload);
await next();
});Contributions are welcome! Please open an issue or submit a pull request.
This project is licensed under the MIT License. See the LICENSE file for more details.
