@justwant/event
v0.1.0
Published
Typed event bus. Root = defineEvent, createEventBus. /primitive = createPrimitiveEventBus (primitive).
Maintainers
Readme
@justwant/event
Typed, in-process event bus. Root = typed API. /primitive = primitive.
Installation
bun add @justwant/event
# or
npm install @justwant/event
# or
pnpm add @justwant/eventUsage — @justwant/event (typed, default)
import { defineEvent, createEventBus } from "@justwant/event";
const UserCreated = defineEvent("user.created", (id: string, email: string) => ({ id, email }));
const OrderPlaced = defineEvent("order.placed", (orderId: string) => ({ orderId }));
const bus = createEventBus({ events: [UserCreated, OrderPlaced] });
// Emit (TypedEvent or string literal with autocomplete)
bus.emit(UserCreated, "1", "[email protected]");
bus.emit("user.created", "1", "[email protected]");
// Listen (TypedEvent or string literal with typed payload)
bus.listen(UserCreated, ({ id, email }) => console.log(id, email));
bus.listen("user.created", ({ id, email }) => console.log(id, email));
// Once
bus.listenOnce(UserCreated, handler);
// Unlisten
bus.unlisten(UserCreated, handler);defineEvent(name, builder) — the builder's args become emit args, its return value is the payload.
Wildcard patterns (default: enabled)
When wildcard is true (default), listen and listenOnce accept patterns to subscribe to event families:
const UserCreated = defineEvent("user.created", (id: string) => ({ id }));
const UserUpdated = defineEvent("user.updated", (id: string, name: string) => ({ id, name }));
const OrderPlaced = defineEvent("order.placed", (orderId: string) => ({ orderId }));
const bus = createEventBus({ events: [UserCreated, UserUpdated, OrderPlaced] });
// Listen to all user.* events — payload is { id: string } | { id: string; name: string }
bus.listen("user.*", (payload) => console.log(payload));
// Listen to all events
bus.listen("*", (payload) => console.log(payload));Patterns are inferred from event names: user.created and user.updated yield user.*. TypeScript infers the payload union automatically.
Wildcard user.* matches user.created, user.updated (prefix + suffix) but NOT bare user (no suffix). * matches all events.
To disable: createEventBus({ events: [...], wildcard: false }).
Usage — @justwant/event/primitive
For dynamic event names (runtime, no schema):
import { createPrimitiveEventBus } from "@justwant/event/primitive";
const bus = createPrimitiveEventBus();
bus.emit("user.created", { id: "1", email: "[email protected]" });
bus.listen("user.created", (payload) => console.log(payload));
bus.listen("user.*", (payload) => console.log(payload)); // wildcard
bus.listenOnce("user.created", handler);
bus.unlisten("user.created", handler);Async handlers
Handlers can return Promise. emit returns Promise<void> when any handler is async (waits for all).
Exports
| Entry | Content |
|-------|---------|
| @justwant/event | defineEvent, createEventBus (typed), createPrimitiveEventBus |
| @justwant/event/primitive | createPrimitiveEventBus (primitive) |
Contributing
Contributions are welcome. Please open an issue or pull request on the monorepo.
License
MIT © elydelva
