
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@notifyhub/client
Advanced tools
@notifyhub/client is the transport and state layer for recipient-facing NotifyHub integrations.
It handles:
It does not include privileged server APIs like send().
npm install @notifyhub/client
Use @notifyhub/client when you want:
Use @notifyhub/react instead when you want ready-made hooks, provider wiring, inbox UI, preference UI, and toasts.
@notifyhub/client expects a short-lived recipient session token.
Your app backend should mint that token using @notifyhub/node, then the browser should provide it through getSessionToken().
import {createNotifyHubClient} from '@notifyhub/client';
const client = createNotifyHubClient({
baseUrl: 'https://notifyhub.example.com',
getSessionToken: async () => {
const response = await fetch('/api/notifyhub/session', {
method: 'POST',
});
if (!response.ok) {
return null;
}
return (await response.json()) as {token: string; expiresAt: number | null};
},
});
import {createNotifyHubClient} from '@notifyhub/client';
const client = createNotifyHubClient({
baseUrl: 'https://notifyhub.example.com',
getSessionToken: async () => {
const response = await fetch('/api/notifyhub/session', {
method: 'POST',
});
if (!response.ok) {
return null;
}
return await response.json();
},
});
const unsubscribe = client.subscribe(() => {
const snapshot = client.getSnapshot();
console.log(snapshot.notifications, snapshot.unreadCount, snapshot.realtimeStatus);
});
await client.connect();
const notifications = await client.listNotifications({limit: 20});
const firstNotification = notifications.notifications[0];
if (firstNotification) {
await client.markAsRead(firstNotification.id);
}
unsubscribe();
client.disconnect();
| Export | Description |
|---|---|
new NotifyHubClient(config) | Creates a client instance directly |
createNotifyHubClient(config) | Factory helper |
NotifyHubClientConfig| Field | Type | Required | Description |
|---|---|---|---|
baseUrl | string | yes | Base URL for the NotifyHub public API |
getSessionToken | () => Promise<NotifyHubSession | null> | NotifyHubSession | null | yes | Returns the current recipient session token or null |
fetch | typeof fetch | no | Override for custom runtimes, testing, or instrumentation |
| Method | Returns | Description |
|---|---|---|
subscribe(listener) | () => void | Subscribes to local snapshot updates |
getSnapshot() | NotifyHubClientSnapshot | Returns the current in-memory client state |
connect() | Promise<void> | Hydrates state and starts the SSE loop |
disconnect() | void | Stops realtime and marks status as stopped |
refresh() | Promise<void> | Re-hydrates notifications, unread count, and preferences |
| Method | Returns | Description |
|---|---|---|
listNotifications(params?) | Promise<ListNotificationsResponse> | Lists notifications, optionally including archived items and a limit |
getUnreadCount() | Promise<UnreadCountResponse> | Fetches unread count |
markAsRead(notificationId) | Promise<MarkAsReadResponse> | Marks a single notification as read |
markAsUnread(notificationId) | Promise<MarkAsReadResponse> | Marks a single notification as unread |
markAllAsRead() | Promise<MarkAllAsReadResponse> | Marks all active notifications as read |
archive(notificationId) | Promise<ArchiveResponse> | Moves a notification into the archived collection |
unarchive(notificationId) | Promise<ArchiveResponse> | Restores an archived notification |
delete(notificationId) | Promise<DeleteResponse> | Deletes a notification |
| Method | Returns | Description |
|---|---|---|
getPreferences() | Promise<GetPreferencesResponse> | Fetches effective recipient preferences |
getTopics() | Promise<GetTopicsResponse> | Fetches available topics and category grouping |
updatePreferences(params) | Promise<UpdatePreferencesResponse> | Batch updates topic preferences |
setGlobalMute(muted) | Promise<SetGlobalMuteResponse> | Toggles recipient-wide mute |
subscribeToTopic(topicId) | Promise<SubscribeResponse> | Subscribes the recipient to a topic |
unsubscribeFromTopic(topicId) | Promise<SubscribeResponse> | Unsubscribes the recipient from a topic |
updateTopicPreference(topicId, params) | Promise<{success: boolean}> | Updates one topic's subscription, channel preferences, or frequency |
setTopicChannelPreference(topicId, channel, enabled) | Promise<SubscribeResponse> | Enables or disables one channel for one topic |
setGlobalChannelPreference(channel, enabled) | Promise<SetChannelPreferenceResponse> | Enables or disables a global default channel |
NotifyHubSessionNotifyHubClientConfigNotifyHubClientSnapshotNotifyHubRealtimeStatusAPIErrorNotificationNotificationActionNotificationTypeNotificationPriorityListNotificationsParamsListNotificationsResponseUnreadCountResponseMarkAsReadResponseMarkAllAsReadResponseArchiveResponseDeleteResponseTopicTopicPreferenceUserPreferencesChannelChannelPreferencesFrequencyGetPreferencesResponseGetTopicsResponseUpdatePreferenceParamsUpdatePreferencesParamsUpdatePreferencesResponseSetGlobalMuteResponseSetChannelPreferenceResponseSubscribeResponseconnect() is idempotent for a single client instance.Last-Event-ID and reconnects with backoff.401 response causes one token refresh attempt through getSessionToken().APIError when the backend responds with an error status.send() are intentionally not part of @notifyhub/client.From the monorepo root:
bun install
cd packages/client && bun run play
cd packages/client && bun run play:check-types
cd packages/client && bun run test
cd packages/client && bun run build
cd packages/client && bun run check-types
FAQs
Transport client for Notifyhub.
We found that @notifyhub/client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.