ccs-chat-notifications-client
@central-code-station/ccs-chat-notifications-client brings the signed-in user’s live updates and web push to your web app. Its realtime part opens the realtime stream and emits events. Its /push part registers the browser for web push. It has no runtime dependencies.
It does not create conversations, send messages or manage members. Your backend does that with ccs-chat-client, and the user reads and writes with ccs-chat-user-client. Event payloads use the same snake_case shapes: the message of a message.created event is a ChatMessage.
Install
Section titled “Install”The package is private on GitHub Packages. Point the scope at it in your .npmrc, then install. See SDKs overview for how to get access.
@central-code-station:registry=https://npm.pkg.github.com//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_TOKEN}npm install @central-code-station/ccs-chat-notifications-clientGITHUB_PACKAGES_TOKEN is a GitHub token with read:packages that can read the organization’s packages. There are no required peer dependencies. @angular/core, @angular/common and rxjs (for /angular) and react (for /react) are optional: install what your app uses.
| Entry point | Use |
|---|---|
@central-code-station/ccs-chat-notifications-client |
Plain realtime client. |
.../angular |
Signals and Observables. |
.../react |
Hooks. |
.../push and .../push/react |
Web push. |
What you need first
Section titled “What you need first”Each user needs their own Chat token: audience chat-api, scope chat:access, issued to your application’s client. The token for your own API is rejected with 401. See Get the user’s Chat token. The token works only in your application’s context. Any other context answers 403 client_context_mismatch. The library does not sign users in. It only reads the token through getAccessToken when it connects.
chat:accessimport { ChatNotificationsClient } from '@central-code-station/ccs-chat-notifications-client';import { getChatAccessToken } from './fe-guide-chat-token';
const notifications = new ChatNotificationsClient({ chatApiUrl: 'https://chat.centralcodestation.com/api/v1', tenantId: 'fitness', applicationId: 'fitness-app', getAccessToken: getChatAccessToken, // sync or async, read again on every (re)connect // debug: true, // log the connection lifecycle while you develop});
const stopListening = notifications.on('message.created', ({ message }) => { console.log(`${message.sender?.display_name ?? message.sender_user_id}: ${message.body}`);});notifications.on('connectionStateChange', (state) => console.log('connection:', state));
notifications.connect();
// While a PUBLIC channel you are not a member of is open:export function viewChannel(conversationId: string): () => void { notifications.subscribeToConversation(conversationId); return () => notifications.unsubscribeFromConversation(conversationId);}
// On sign-out or unmount:export function stop(): void { stopListening(); notifications.disconnect();}| Member | Description |
|---|---|
connect() |
Opens the stream. Does nothing if the client is already started. |
disconnect() |
Closes the stream and stops retries. |
subscribeToConversation(id) |
Adds one conversation’s channel, for a PUBLIC channel you can read but are not a member of. A new call replaces the previous one. |
unsubscribeFromConversation(id) |
Removes it. |
on(event, handler) |
Subscribes to an event. Returns a function that unsubscribes. |
connectionState |
'disconnected', 'connecting', 'connected' or 'error'. |
Events
Section titled “Events”Handlers receive the payload as the Chat API publishes it, in snake_case, with tenant_id and application_id. See Realtime events for every payload and when it fires.
| Event | Payload type | Fires when |
|---|---|---|
message.created, message.updated |
MessageCreatedEvent |
A message is sent or edited. message is the full message. |
message.deleted |
MessageDeletedEvent |
A message is deleted. Render a tombstone. |
reaction.added, reaction.removed |
ReactionEvent |
A reaction changes. |
typing |
TypingEvent |
Another member types. Never stored. |
member.added, member.removed |
MemberAddedEvent, MemberRemovedEvent |
Membership changes. |
conversation.created, .updated, .deleted |
ConversationChangedEvent |
A conversation of yours changes. |
conversation.access_revoked |
ConversationEventBase |
The user lost access. Drop the conversation. |
presence.updated |
PresenceUpdatedEvent |
A fellow member goes online or offline. |
connectionStateChange |
ConnectionState |
The connection state changes. |
Connection model
Section titled “Connection model”connect()fetches a stream credential from the realtime token operation and opens it withEventSource. One connection carries the user’s personal events and their channels, up to 100 channels.- The credential lasts at most 10 minutes. The client reopens the stream
tokenRefreshBufferSeconds(30 by default) before it expires. - When the user creates or is added to a CHANNEL, the client reopens the stream so that channel’s events arrive. You call nothing.
- A short network drop is retried by the browser. A fatal failure, such as a rejected token, is retried with backoff of 1, 2, 4, 8, 16 and 30 seconds. After that the state stays
error. Calldisconnect()and thenconnect()to start again. - Reopening the stream is not seamless. Events published in between are not replayed, so reload after each return to
connected. See Live updates. - Errors never throw into your code. Set
debug: trueto log them.
Configuration reference
Section titled “Configuration reference”ChatNotificationsClientOptions:
| Field | Required | Description |
|---|---|---|
chatApiUrl |
yes | The Chat API base URL, such as https://chat.centralcodestation.com/api/v1. |
tenantId |
yes | The tenant to listen in. |
applicationId |
yes | The application to listen in. |
getAccessToken |
yes | Returns the user’s Chat token, sync or async. Read again on every (re)connect. |
fetch |
no | Override fetch for tests or runtimes without one. |
eventSourceFactory |
no | Create the stream connection yourself, for tests or a runtime that needs an EventSource polyfill. |
tokenRefreshBufferSeconds |
no | Seconds before expiry to reconnect with a fresh credential. Default 30. |
debug |
no | Log the connection lifecycle to the console with the prefix [ChatNotificationsClient]. Default false. |
To switch tenant or application, disconnect and create a new client.
Not covered
Section titled “Not covered”React Native is not covered. EventSource and the Push API are not universally available there. You can pass eventSourceFactory for realtime, which we have not tested. See Mobile and React Native.
Module formats
Section titled “Module formats”Every entry point ships ES modules and CommonJS with type declarations for each. import loads dist/esm, require() loads dist/cjs. It works with any bundler and with the node16, nodenext, bundler and legacy node module resolution. Load it one way per app: the two builds are separate copies, so instanceof checks do not cross them.
Reference and changelog
Section titled “Reference and changelog”- Generated API reference
- Changelog
- Upgrading from 0.x: Migrate ccs-chat-notifications-client 0 to 1