Typed event
const events = new EventPubSub();
events.on('invoice.paid', ({ id }) => {
console.log(`Paid: ${id}`);
});
events.emit('invoice.paid', { id: 42 });Examples
Each example isolates one practical behavior. Combine them only where the application boundary calls for it.
A bundler resolves the bare import normally. For a non-bundled app, serve the installed files over HTTP(S) and put this map before the first module script:
<script type="importmap">
{"imports":{"event-pubsub":"./node_modules/event-pubsub/index.js","strong-type":"./node_modules/strong-type/index.js"}}
</script>
<script type="module">import EventPubSub from 'event-pubsub';</script>If the app uses a strict CSP, authorize the inline import-map and module scripts with an allowed nonce or hash.
const events = new EventPubSub();
events.on('invoice.paid', ({ id }) => {
console.log(`Paid: ${id}`);
});
events.emit('invoice.paid', { id: 42 });events.once('app.ready', (context) => {
hydrate(context);
});
events.emit('app.ready', context);
events.emit('app.ready', context); // no second callevents.on('*', (type, ...payload) => {
audit.write({ type, payload });
});
events.emit('user.created', user);function render(state) {
view.update(state);
}
events.on('state.changed', render);
events.off('state.changed', render);Extending
class Counter extends EventPubSub {
value = 0;
increment() {
this.value += 1;
return this.emit('change', this.value);
}
}
const counter = new Counter();
counter.on('change', console.log).increment();Separate lifecycle boundaries reduce accidental coupling and make reset() meaningful. Multiple instances are fully isolated.