Skip to main content
Version: 0.14.0 (Latest)

๐Ÿ’ฌ Chat

Chat provides HTTP and WebSocket composition for channels, messages, attachments, templates, subscriptions, and per-channel read states through chatService.

Start hereโ€‹

Mount the service below /api. defService installs JSON parsing on the returned router. Cookie transport additionally needs cookie-parser before the mount, signed attachment and channel-icon operations need a fileStorageDriver, and the current service must receive a webSocketServer because it always composes the WebSocket route.

chatService selects getBearerTokenInfo unless authMode === 'cookie', when it selects getCookieTokenInfo. The typed store requires identities, chatChannels, subscriptions, chatMessages, and chatChannelReadStates; organizations and chatMessageTemplates are optional in the type but required at runtime by routes that query them.

import express from 'express';
import cookieParser from 'cookie-parser';
import { services } from '@nodeblocks/backend-sdk';

const app = express();
app.use(cookieParser()); // Only required for authMode: 'cookie'.
app.use('/api', services.chatService(
{ identities, chatChannels, organizations, subscriptions, chatMessages, chatMessageTemplates, chatChannelReadStates },
{
authSecrets: { authEncSecret: process.env.AUTH_ENC_SECRET!, authSignSecret: process.env.AUTH_SIGN_SECRET! },
authMode: 'bearer',
identity: { typeIds: { admin: 'admin-type-id', guest: 'guest-type-id', regular: 'regular-type-id' } },
organization: { roles: { admin: 'organization-admin-role-id', member: 'organization-member-role-id', owner: 'organization-owner-role-id' } },
},
{ fileStorageDriver, webSocketServer },
));
ConfigurationDefault / source behaviorEffect
authSecrets.authEncSecretRequired; passed to every composed feature through configurationRequired authentication secret material.
authSecrets.authSignSecretRequired; passed to every composed feature through configurationRequired authentication secret material.
authModeOmitted and 'bearer' select getBearerTokenInfo; 'cookie' selects getCookieTokenInfoSelects the protected-route access-token transport.
identity.typeIds.adminRead by administrator checks when suppliedEnables the admin branch of channel, subscription, and template access rules.
organization.roles.owner / adminRead by template routes when suppliedEnables organization-template authorization.
fileStorageDriverRequired for attachment upload/download URLs and channel icon upload URLsSupplies signed-file operations.
webSocketServerRequired when constructing the current full chatServiceRegisters streamChatMessagesRoute.

Common tasksโ€‹

TaskStart withContract
Manage channelsChannel featuresFeatures, routes
Send, list, edit, or stream messagesMessage featuresRoutes, schemas
Attach files or obtain upload URLsFile-storage-backed routesBlocks, routes
Manage templates, subscriptions, and read statesTemplate feature groupsFeatures

Chat exposes no public HTTP endpoint: every HTTP route begins with isAuthenticated(). The WebSocket stream is currently unguarded because its intended authentication and subscription validators are commented out; this is a source limitation, not a public-HTTP authentication workflow.

Bearer HTTP workflowโ€‹

export ACCESS_TOKEN='replace-with-an-access-token'
export CHANNEL_ID='replace-with-a-channel-id'

curl -X POST 'http://localhost:8080/api/channels' \
-H "authorization: Bearer $ACCESS_TOKEN" \
-H 'content-type: application/json' \
-d '{"name":"Support","description":"Customer support"}'

curl "http://localhost:8080/api/channels/$CHANNEL_ID/messages" \
-H "authorization: Bearer $ACCESS_TOKEN"

This is a host-application fragment: the token must identify an existing identity, and the second request needs an existing channel subscription. Channel creation returns 201 with the normalized channel in data; channel-message lookup returns 200 with normalized messages and pagination metadata. A missing/invalid token fails authentication, while a missing subscription fails authorization. Consult createChatChannelRoute, createChatChannelSchema, getChannelMessagesRoute, and getChannelMessagesSchema.

With authMode: 'cookie', register cookie-parser before Chat, obtain an access cookie through Authentication, and include that cookie in the request. The example returns 200 with normalized channels and pagination metadata when the token identity matches the requested scope; a missing/invalid cookie fails authentication. The same protected route rules applyโ€”only token extraction changes. See findChatChannelsRoute and findChatChannelsSchema.

export ACCESS_COOKIE='accessToken=replace-with-an-access-token'
curl 'http://localhost:8080/api/channels' \
-H "cookie: $ACCESS_COOKIE"

WebSocket workflowโ€‹

Pass webSocketServer to chatService before construction, then connect to streamChatMessagesRoute with the required channelId query value defined by streamChatMessagesSchema. The route uses protocol ws at /messages/listen and emits normalized inserted messages as JSON. A missing channel ID maps to 400, and stream construction failure maps to 500. Its intended isAuthenticated() and hasSubscription(...) validators are currently commented out in source, so configured Bearer/cookie extraction is not enforced for this endpoint.

Custom feature compositionโ€‹

Compose only the public feature exports needed by your host, then call defService with the same data-store/configuration context passed by chatService. Add fileStorageDriver and webSocketServer only when the selected features require them.

import { partial } from 'ramda';
import { features, primitives, utils } from '@nodeblocks/backend-sdk';

const channelFeature = primitives.compose(
features.createChannelFeature,
features.getChannelFeature,
);

const router = primitives.defService(partial(channelFeature, [{
authenticate: utils.getBearerTokenInfo,
configuration,
dataStores: { identities, chatChannels, subscriptions },
fileStorageDriver,
}]));

app.use('/api', router);

This HTTP-only custom composition does not include streamChatMessagesFeature, so it does not need a WebSocket server. Supply every collection and driver read by the selected features.

Reference mapโ€‹

PagePurpose
BlocksReusable persistence, normalization, signed-file, and stream operations.
FeaturesSchema-to-route composition.
HandlersHTTP pipeline operations and terminators.
RoutesExact HTTP and WebSocket endpoint contracts.
SchemasField-level request contracts.
ValidatorsShared access and existence guards.

See Authentication for token transport, file-storage for signed-file drivers, Organization for role configuration, and error handling for shared failures.