A simple and efficient client for subscribing to various Donation Alerts events.
Using npm
:
npm i @donation-alerts/events @donation-alerts/api
Using yarn
:
yarn add @donation-alerts/events @donation-alerts/api
Using pnpm
:
pnpm add @donation-alerts/events @donation-alerts/api
There are two primary clients to listen to events:
UserEventsClient
for each user added.Before subscribing to events, you need an instance of ApiClient. Refer to the ApiClient documentation for setup details.
To create an instance of UserEventsClient
, provide a UserEventsClientConfig object to its constructor.
import { ApiClient } from '@donation-alerts/api';
import { UserEventsClient } from '@donation-alerts/events';
const userId = 123456789;
const apiClient = new ApiClient({
//...
});
const userEventsClient = new UserEventsClient({
user: userId,
apiClient: apiClient,
});
After creating a UserEventsClient
instance, you can now listen to events of your choice.
import {
DonationAlertsDonationEvent,
DonationAlertsGoalUpdateEvent,
DonationAlertsPollUpdateEvent,
} from '@donation-alerts/events';
// Listening to donations
const donationsListener = userEventsClient.onDonation((evt: DonationAlertsDonationEvent) => {
console.log('New donation received:', evt);
});
// Listening to goal updates
const goalUpdatesListener = userEventsClient.onGoalUpdate((evt: DonationAlertsGoalUpdateEvent) => {
console.log('Goal updated:', evt);
});
// Listening to poll updates
const pollUpdatesListener = userEventsClient.onPollUpdate((evt: DonationAlertsPollUpdateEvent) => {
console.log('Poll updated:', evt);
});
Each of the methods above returns an EventsListener instance.
For detailed information on event data structures, refer to the documentation pages of the respective event classes:
If you no longer require a listener, you can remove it in one of two ways.
Using the EventsListener
instance:
await donationsListener.remove();
Using the removeEventsListener
method of the UserEventsClient
:
await userEventsClient.removeEventsListener(donationsListener);
The user being listened to must be added to the AuthProvider provided to the ApiClient, and their access token must include the necessary scopes for subscribing to private channels.
The client automatically manages its connection to the Donation Alerts Centrifugo server. A connection is established when you create the first listener, and it is automatically closed once all listeners are removed.
You can also manually manage the connection state by using connect, disconnect, or reconnect methods of the UserEventsClient
instance.
disconnect - Closes the connection to the server. After calling disconnect
, the client will not attempt to reconnect automatically.
The method accepts an optional removeListeners
argument (boolean).
If removeListeners
is set to true
, all event listeners will be permanently removed.
If omitted or set to false
(default), the client retains the listeners and is able to restore them during the next connection attempt.
// Disconnect and remove all listeners.
await userEventsClient.disconnect(true);
connect - Establishes a connection to the Donation Alerts Centrifugo server. If listeners were retained during a previous disconnection, this method can restore them automatically.
The method accepts an optional restoreExistingListeners
argument (boolean).
When restoreExistingListeners
is true
(default), previously stored listeners are restored automatically.
Pass false
to skip restoring listeners.
// Reconnect and restore all listeners.
await userEventsClient.connect(true);
reconnect - This method performs both disconnect
and connect
operations in sequence.
The method accepts an optional removeListeners
argument (boolean):
When removeListeners
is false
(default), the client restores all listeners after reconnection.
If true
, all listeners are removed during the disconnection step.
The client uses a persistent connection and automatically handles unplanned disconnections (e.g., network issues). Reconnection attempts follow an exponential backoff strategy: The first reconnection attempt happens immediately. The maximum interval between attempts is capped at 30 seconds.
// Reconnect and restore listeners.
await userEventsClient.reconnect();
// Reconnect and remove all listeners.
await userEventsClient.reconnect(true);
You can monitor the connection status by subscribing to onConnect and onDisconnect callbacks.
onConnect: Triggered whenever a connection to the server is established.
userEventsClient.onConnect(() => {
console.log('Connection established!');
});
onDisconnect: Triggered whenever the client disconnects from the server. The callback provides two arguments:
reason
: A string describing the reason for the disconnection.reconnect
: A boolean indicating whether the client will attempt to reconnect automatically.userEventsClient.onDisconnect((reason: string, reconnect: boolean) => {
console.log(`Disconnected: ${reason}`);
console.log(`Will attempt to reconnect: ${reconnect}`);
});
These callbacks allow fine-grained control over the connection state. Use them as needed to handle both planned and unexpected disconnection events.
When you need to listen to events for multiple users, use the EventsClient. This client simplifies managing events across different users. To create an EventsClient
instance, provide an ApiClient
through the EventsClientConfig.
import { ApiClient } from '@donation-alerts/api';
import { EventsClient } from '@donation-alerts/events';
const apiClient = new ApiClient({
// Provide your ApiClient configuration here
});
const eventsClient = new EventsClient({
apiClient: apiClient,
});
Once you have an EventsClient
instance, you must add users to it in order to start listening to their events.
addUser - Registers a user in the EventsClient
. If the user is already registered, an error will be thrown.
import { UserEventsClient } from '@donation-alerts/events';
const userId = 123456789;
const userEventsClient = eventsClient.addUser(userId);
Returns a UserEventsClient instance for the user.
hasUser - Checks whether a specific user is already added to the client.
const userId = 123456789;
const hasUser = eventsClient.hasUser(userId);
Returns boolean
.
removeUser - Unsubscribes the client from this user's channels and closes the connection before removing the user from the client. This method does nothing if the user is not registered.
const userId = 123456789;
eventsClient.removeUser(userId);
getUserClient - Retrieves the UserEventsClient instance for a specific user.
const userId = 123456789;
const userEventsClient = eventsClient.getUserClient(userId);
Creating listeners for events in EventsClient
is similar to UserEventsClient
, with the additional requirement of specifying a user ID.
import {
DonationAlertsDonationEvent,
DonationAlertsGoalUpdateEvent,
DonationAlertsPollUpdateEvent,
} from '@donation-alerts/events';
const userId = 123456789;
// Listening to donations for a user
const donationsListener = eventsClient.onDonation(userId, (evt: DonationAlertsDonationEvent) => {
console.log(`Donation event for user ${userId}: `, evt);
});
// Listening to goal updates for a user
const goalUpdatesListener = eventsClient.onGoalUpdate(userId, (evt: DonationAlertsGoalUpdateEvent) => {
console.log(`Goal update event for user ${userId}: `, evt);
});
// Listening to poll updates for a user
const pollUpdatesListener = eventsClient.onPollUpdate(userId, (evt: DonationAlertsPollUpdateEvent) => {
console.log(`Poll update event for user ${userId}: `, evt);
});
These methods return an EventsListener
instance. You can remove these listeners by using the remove
method:
await donationsListener.remove();
If you remove all listeners for a specific user, the connection for that user will be closed. However, the UserEventsClient
instance for the user will not be removed from the EventsClient
. This means you can restore the connection at a later time.
EventsClient
also allows you to listen to connection events:
The EventsClient
also supports listening to user-specific connection states. This can be helpful for managing user-specific workflows.
// Listening for connection establishment
eventsClient.onConnect((userId: number) => {
console.log(`User ${userId} successfully connected.`);
});
// Listening for disconnections
eventsClient.onDisconnect((userId: number, reason: string, reconnect: boolean) => {
console.log(`User ${userId} disconnected. Reason: ${reason}. Will reconnect: ${reconnect}`);
});
Each data instance (event) returned by the library is immutable and exposes its data through getters, ensuring that properties cannot be reassigned. For convenience, every data instance implements a toJSON()
method, which serializes the instance into a plain JavaScript object representation of the data.
This method is automatically invoked when the instance is passed to JSON.stringify()
. In Node.js, it is also used when the instance is logged via console.log()
, utilizing the util.inspect
mechanism.
If you wish to explore the structure of the data instance, it is always preferable to refer to the official documentation rather than relying on logging. A data instance may include additional utility methods that are not serialized by toJSON()
. The documentation also provides detailed descriptions of all available properties and methods.
Also, each data instance retains the original event data received from the Donation Alerts Centrifugo API. This raw data is hidden and immutable but can be accessed via the getRawData
function provided by the @donation-alerts/common
package:
import { getRawData } from '@donation-alerts/common';
const donationsListener = userEventsClient.onDonation((evt: DonationAlertsDonationEvent) => {
console.log(evt);
});
At the time of writing, the output resembles the following structure:
interface DonationEventRawData {
id: number;
name: 'Donations';
username: string;
message: string;
message_type: string;
payin_system: { title: string } | null;
amount: number;
currency: string;
is_shown: 0 | 1;
amount_in_user_currency: number;
recipient_name: string;
recipient: {
user_id: number;
code: string;
name: string;
avatar: string;
};
created_at: string;
shown_at: string | null;
reason: string;
}
As you may notice, the raw response includes some fields that are neither directly exposed by the library nor mentioned in Donation Alerts' official documentation.
For best practices, avoid depending on undocumented fields, as their structure or availability may change over time.
For more detailed information, refer to the documentation.