Common Patterns
PostboyGenericMessage is suited for situations where a single event must trigger reactions in multiple parts of the system without tight coupling.
Below are three recurring patterns, each with framework‑agnostic TypeScript examples.
1. Domain events
Use generic messages to announce that something meaningful happened in the business domain.
Services publish events; multiple subscribers react independently.
Message
import {PostboyGenericMessage} from '@artstesh/postboy';
export class OrderPlacedEvent extends PostboyGenericMessage {
static readonly ID = 'order.placed';
constructor(public readonly orderId: string, public readonly customerId: string) {
super();
}
}
Registration (once during bootstrap)
import {ConnectMessage} from '@artstesh/postboy';
import {Subject} from 'rxjs';
import {OrderPlacedEvent} from './order-placed.event';
postboy.exec(new ConnectMessage(OrderPlacedEvent, new Subject<OrderPlacedEvent>()));
Publishing (inside order service)
function placeOrder(orderId: string, customerId: string): void {
// ... business logic
postboy.fire(new OrderPlacedEvent(orderId, customerId));
}
Subscriber 1: inventory service
postboy.sub(OrderPlacedEvent).subscribe((msg) => {
console.log(`Reserving stock for order ${msg.orderId}`);
});
Subscriber 2: notification service
postboy.sub(OrderPlacedEvent).subscribe((msg) => {
sendPushNotification(msg.customerId, 'Order confirmed!');
});
2. UI notifications (toasts, banners)
A single bus channel for all transient user‑facing messages avoids scattered showToast() calls.
Message
export class ToastNotificationEvent extends PostboyGenericMessage {
static readonly ID = 'ui.toast';
constructor(public readonly text: string, public readonly severity: 'info' | 'error') {
super();
}
}
Registration
postboy.exec(new ConnectMessage(ToastNotificationEvent, new Subject<ToastNotificationEvent>()));
Toast service (the only place that renders toasts)
postboy.sub(ToastNotificationEvent).subscribe((msg) => {
renderToast(msg.text, msg.severity);
});
Anywhere in the app
postboy.fire(new ToastNotificationEvent('Item added to cart', 'info'));
postboy.fire(new ToastNotificationEvent('Failed to load settings', 'error'));
3. State synchronisation across components
When multiple UI pieces must reflect the same state (e.g. operator availability), a generic message acts as a state synchronisation signal.
Each component holds its own copy of the state and updates it upon receiving the event.
Message
export class OperatorStatusChangedEvent extends PostboyGenericMessage {
static readonly ID = 'operator.status';
constructor(public readonly status: 'online' | 'away') {
super();
}
}
Registration
postboy.exec(new ConnectMessage(OperatorStatusChangedEvent, new Subject<OperatorStatusChangedEvent>()));
Publishing (status switch component)
function onOperatorToggle(newStatus: 'online' | 'away'): void {
postboy.fire(new OperatorStatusChangedEvent(newStatus));
}
Header subscriber
postboy.sub(OperatorStatusChangedEvent).subscribe((msg) => {
updateHeaderBadge(msg.status);
});
Profile panel subscriber
postboy.sub(OperatorStatusChangedEvent).subscribe((msg) => {
setProfileBorderColor(msg.status);
});
Session logger subscriber
postboy.sub(OperatorStatusChangedEvent).subscribe((msg) => {
logActivity(`Operator went ${msg.status} at ${Date.now()}`);
});
Key points
Domain events: decouple business actions from their side effects.
UI notifications: a single place to render toasts, banners, etc.; any part of the app can trigger them.
State synchronisation: broadcast state changes so that every UI fragment stays consistent without shared services or @Input chains.
All patterns rely on the same fire/sub mechanism — no additional infrastructure is required.
03 мая 2026