Custom events
Platform providers can emit events beyond messages — typing indicators, read receipts, delivery status, whatever the provider chooses to surface. Spectrum exposes each event as a flat async iterable on the app instance:platform field so you know the source.
Lazy streams
Event streams are created lazily on first access. Accessingapp.typing once kicks off the underlying listener; subsequent iterations share the same source.
Per-platform access
The same events are available on a narrowed platform instance, scoped to that platform only:app when you want a merged feed across platforms; use the narrowed form when you only care about one.
Fusor custom events
Fusor-backed providers can emit non-message events (presence, read receipts, delivery status) into typed event streams usingfusorEvent. Inside a Fusor messages handler, yield a fusorEvent(name, data) alongside regular messages to push events into app.<name> streams:
app.presence (merged across providers) or narrowedInstance.presence (scoped to the emitting provider). The event name and data shape are fully typed based on the provider’s event declarations.
Lifecycle
Graceful shutdown
lifecycle.destroyClient hook (if one is defined), and flushes any pending telemetry data when telemetry is enabled. It’s idempotent — calling stop() twice is safe.
Signal handling
Spectrum registersSIGINT and SIGTERM handlers on startup. When a signal fires:
stop()is invoked with a 3-second timeout.- If cleanup completes in time, the process exits with code 0.
- If not, the process exits with code 1.
docker stop or hitting Ctrl-C in a terminal will drain cleanly.
When to call stop() manually
- You’re embedding Spectrum in a longer-running process and want to tear it down without exiting.
- You’re writing tests that create and dispose an app per case.
- You want deterministic cleanup before re-initializing with a different provider set.