🛣️ Chat Routes
Chat routes provide pre-configured HTTP endpoints for chat management operations in Nodeblocks applications. These routes combine handlers, validators, and middleware to create complete API endpoints with proper authentication, authorization, and error handling.
🎯 Overview
Chat routes are designed to:
- Provide complete API endpoints for chat management operations
- Combine handlers with validators for secure operations
- Include authentication and authorization checks
- Support functional composition patterns
- Handle logging and error management automatically
📋 Route Structure
Each chat route follows a consistent pattern:
- HTTP Method: Defines the operation type (GET, POST, PATCH, DELETE)
- Path: Specifies the endpoint URL with parameters
- Handler: Composed function chain for business logic
- Validators: Authentication and authorization checks
🔧 Available Chat Routes
Channel Routes
createChatChannelRoute
Creates a new channel and returns the created resource.
Purpose: Handles channel creation with full resource retrieval
Route Details:
- Method:
POST - Path:
/channels - Authentication: Required (Bearer token)
Handlers: createChatChannel, getChatChannelById, createChatChannelTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'ownerId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createChatChannelRoute);
findChatChannelsRoute
Retrieves all channels with normalized list format.
Purpose: Lists channels with pagination
Route Details:
- Method:
GET - Path:
/channels - Authentication: Required (Bearer token)
Handlers: findChatChannels, normalizeChatChannelsListTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), isSelf(['params', 'requestQuery', 'ownerId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findChatChannelsRoute);
getChatChannelRoute
Retrieves a specific channel by ID.
Purpose: Fetches channel data
Route Details:
- Method:
GET - Path:
/channels/:channelId - Authentication: Required (Bearer token)
Handlers: getChatChannelById, normalizeChatChannelTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChatChannelRoute);
updateChatChannelRoute
Updates an existing channel and returns the updated resource.
Purpose: Modifies channel data with access control
Route Details:
- Method:
PATCH - Path:
/channels/:channelId - Authentication: Required (Bearer token)
Handlers: updateChatChannel, getChatChannelById, normalizeChatChannelTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateChatChannelRoute);
deleteChatChannelRoute
Deletes a channel by ID.
Purpose: Removes channel with access control
Route Details:
- Method:
DELETE - Path:
/channels/:channelId - Authentication: Required (Bearer token)
Handlers: deleteChatChannel, deleteChatChannelTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteChatChannelRoute);
getChannelMessagesRoute
Retrieves all chat messages for a specific channel via GET /channels/:channelId/messages.
Purpose: Fetches all messages belonging to a specific channel with pagination support
Route Details:
- Method:
GET - Path:
/channels/:channelId/messages - Authentication: Required (Bearer token)
Blocks: getChannelMessagesByChannelId
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators:
isAuthenticated- Ensures user is authenticatedchannelExists- Checks channel existence by channelIdhasSubscription- Checks user subscription to channel
Response (200 OK): Array of message objects
Error Responses:
401: User is not authenticated403: User is not subscribed to the channel404: Channel does not exist500: Database operation failed
Handler Process:
- Validates user authentication and channel subscription
- Retrieves all messages for the specified channel
- Applies pagination if query parameters provided
- Returns array of messages with 200 status
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChannelMessagesRoute);
// Client usage:
const response = await fetch('/api/channels/channel-123/messages', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const messages = await response.json();
console.log('Channel messages:', messages);
}
getChatChannelIconUploadUrlRoute
Generates signed upload URL for chat channel icon via GET /channels/:channelId/icon-upload-url.
Purpose: Provides pre-signed URL for uploading chat channel icon images with proper authentication and authorization.
Route Details:
- Method:
GET - Path:
/channels/:channelId/icon-upload-url - Authentication: Required (Bearer token)
Blocks: generateChatChannelIconUploadUrl
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']))
Response (200 OK):
{
"objectId": "string",
"url": "string"
}
Query Parameters:
contentType: string- MIME type of the file to be uploaded (e.g., 'image/png')contentLength: number- Size of the file in bytes (max 10MB)
Error Responses:
400 Bad Request: Invalid query parameters (file size too large, invalid content type)401 Unauthorized: Authentication failed403 Forbidden: User lacks admin privileges and doesn't own the channel500 Internal Server Error: File storage service error
Handler Process:
- Validates authentication and authorization (admin or channel owner)
- Validates query parameters (contentType, contentLength)
- Generates UUID objectId with file extension
- Creates signed upload URL using file storage driver
- Returns objectId and signed URL for upload
Authorization Notes:
- Requires authentication
- Accessible by admins or channel owners
- Uses
somevalidator to allow either admin access or channel ownership
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChatChannelIconUploadUrlRoute);
// Client usage:
const response = await fetch('/api/channels/channel-123/icon-upload-url?contentType=image/png&contentLength=1024000', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const { objectId, url } = await response.json();
// Use url to upload the file
// Store objectId for later reference
}
Subscription Routes
createChatSubscriptionRoute
Creates a new subscription and returns the created resource.
Purpose: Handles subscription creation with full resource retrieval
Route Details:
- Method:
POST - Path:
/subscriptions - Authentication: Required (Bearer token)
Handlers: createChatSubscription, getChatSubscriptionById, createChatSubscriptionTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'subscribedId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createChatSubscriptionRoute);
findChatSubscriptionsRoute
Retrieves all subscriptions with normalized list format.
Purpose: Lists subscriptions with pagination
Route Details:
- Method:
GET - Path:
/subscriptions - Authentication: Required (Bearer token)
Handlers: findChatSubscriptions, normalizeChatSubscriptionsListTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), ownsChannel(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'subscribedId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findChatSubscriptionsRoute);
getChatSubscriptionRoute
Retrieves a specific subscription by ID.
Purpose: Fetches subscription data
Route Details:
- Method:
GET - Path:
/subscriptions/:subscriptionId - Authentication: Required (Bearer token)
Handlers: getChatSubscriptionById, normalizeChatSubscriptionTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChatSubscriptionRoute);
deleteChatSubscriptionRoute
Deletes a subscription by ID.
Purpose: Removes subscription
Route Details:
- Method:
DELETE - Path:
/subscriptions/:subscriptionId - Authentication: Required (Bearer token)
Handlers: deleteChatSubscription, deleteChatSubscriptionTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteChatSubscriptionRoute);
Message Routes
createChatMessageRoute
Creates a new message and returns the created resource.
Purpose: Handles message creation with full resource retrieval
Route Details:
- Method:
POST - Path:
/messages - Authentication: Required (Bearer token)
Handlers: createChatMessage, getChatMessageById, createChatMessageTerminator
Validators: isAuthenticated, isSelf(['params', 'requestBody', 'senderId']), hasSubscription(['params', 'requestBody', 'channelId'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createChatMessageRoute);
findChatMessagesRoute
Retrieves all messages with normalized list format.
Purpose: Lists messages with pagination
Route Details:
- Method:
GET - Path:
/messages - Authentication: Required (Bearer token)
Handlers: findChatMessages, normalizeChatMessagesListTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'senderId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findChatMessagesRoute);
getChatMessageRoute
Retrieves a specific message by ID.
Purpose: Fetches message data
Route Details:
- Method:
GET - Path:
/messages/:messageId - Authentication: Required (Bearer token)
Handlers: getChatMessageById, normalizeChatMessageTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChatMessageRoute);
updateChatMessageRoute
Updates an existing message and returns the updated resource.
Purpose: Modifies message data with owner-only access control
Route Details:
- Method:
PATCH - Path:
/messages/:messageId - Authentication: Required (Bearer token)
Handlers: updateChatMessage, getChatMessageById, normalizeChatMessageTerminator
Validators: isAuthenticated, ownsMessage(['params', 'requestParams', 'messageId'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateChatMessageRoute);
deleteChatMessageRoute
Deletes a message by ID.
Purpose: Removes message with access control
Route Details:
- Method:
DELETE - Path:
/messages/:messageId - Authentication: Required (Bearer token)
Handlers: deleteChatMessage, deleteChatMessageTerminator
Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteChatMessageRoute);
getChatMessageAttachmentUploadUrlRoute
Generates file upload URL for chat message attachments via GET /messages/:messageId/attachment-upload-url.
Purpose: Provides secure, time-limited URLs for uploading attachments to chat messages
Route Details:
- Method:
GET - Path:
/messages/:messageId/attachment-upload-url - Authentication: Required (Bearer token)
Blocks: generateChatMessageAttachmentUploadUrl
Terminators: orThrow
Validators: isAuthenticated, ownsMessage
Query Parameters:
contentType: string(required) - MIME type of the file to upload (validated against safe types)contentLength: integer(required) - Size of the file in bytes (max 10MB)
Response: Object with objectId and signed upload URL
Response Structure:
{
objectId: string; // Unique identifier for the uploaded file
url: string; // Pre-signed URL for uploading the file
}
Error Responses:
400- Invalid content type or file size exceeds limit401- Not authenticated403- Not authorized to upload to this message500- FileStorageServiceError or ChatMessageBlockError
Handler Process:
- Validates authentication and message ownership
- Validates content type and size via schema
- Generates unique object ID
- Creates signed upload URL with proper file extension
- Returns objectId and URL to client
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChatMessageAttachmentUploadUrlRoute);
// Client-side request:
const messageId = 'message123';
const response = await fetch(
`/api/messages/${messageId}/attachment-upload-url?contentType=image/png&contentLength=1000000`,
{
headers: {
'Authorization': 'Bearer <token>'
}
}
);
const { objectId, url } = await response.json();
// Upload file to signed URL
await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'image/png'
},
body: fileData
});
// Store objectId with message for later retrieval
Security Features:
- Excludes dangerous MIME types (executables, scripts, archives)
- Enforces file size limits (10MB max)
- Requires message ownership validation
- Time-limited signed URLs
createChatMessageAttachmentRoute
Creates a new chat message attachment via POST /messages/:messageId/attachments.
Purpose: Adds a file attachment to an existing message with validation and automatic entity generation
Route Details:
- Method:
POST - Path:
/messages/:messageId/attachments - Authentication: Required (Bearer token)
Blocks: createChatMessageAttachment, getChatMessageAttachmentById
Terminators: orThrow
Validators: isAuthenticated, ownsMessage
Request Body:
{
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"type": "image/png"
}
Response: Created attachment with base entity fields (status 201)
Response Structure:
{
objectId: string; // UUID reference to uploaded file
type: string; // MIME type
id: string; // Generated attachment ID
createdAt: string; // ISO datetime
updatedAt: string; // ISO datetime
}
Error Responses:
400- Invalid request body (missing objectId or type)401- Not authenticated403- Not authorized to modify this message404- Message not found or attachment not found500- ChatMessageUnexpectedDBError or ChatMessageBlockError
Handler Process:
- Validates authentication and message ownership
- Validates objectId (UUID) and type via schema
- Creates attachment with base entity fields
- Pushes attachment to message's attachments array
- Retrieves and returns created attachment
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createChatMessageAttachmentRoute);
// Client-side request:
const response = await fetch(`/api/messages/${messageId}/attachments`, {
method: 'POST',
headers: {
'Authorization': 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
objectId: '550e8400-e29b-41d4-a716-446655440000',
type: 'image/png'
})
});
const attachment = await response.json();
// attachment has id, createdAt, updatedAt fields
Key Features:
- Automatic base entity field generation for attachments
- Message ownership validation
- Atomic MongoDB
$pushoperation - Returns complete attachment with generated fields
- Full error handling for all failure scenarios
deleteChatMessageAttachmentRoute
Deletes a chat message attachment via DELETE /messages/:messageId/attachments/:attachmentId.
Purpose: Removes a file attachment from an existing message and deletes it from storage
Route Details:
- Method:
DELETE - Path:
/messages/:messageId/attachments/:attachmentId - Authentication: Required (Bearer token)
Blocks: deleteChatMessageAttachment
Terminators: orThrow
Validators: isAuthenticated, some (checks checkIdentityType for admin OR ownsMessage)
Response: No content (status 204) on success
Error Responses:
401- Not authenticated403- Not authorized to modify this message (not admin or owner)404- Message not found or attachment not found500- ChatMessageUnexpectedDBError, ChatMessageBlockError, or FileStorageServiceError
Handler Process:
- Validates authentication and authorization (admin or message owner)
- Validates messageId and attachmentId via schema
- Removes attachment from message's attachments array using
$pull - Updates message
updatedAttimestamp - Deletes physical file from storage
- Returns 204 No Content on success
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteChatMessageAttachmentRoute);
// Client-side request:
const response = await fetch(`/api/messages/${messageId}/attachments/${attachmentId}`, {
method: 'DELETE',
headers: {
'Authorization': 'Bearer <token>'
}
});
// response.status === 204 on success
Key Features:
- Atomic MongoDB
$pulloperation - Returns document before update to retrieve attachment details
- Deletes physical file from storage using objectId and type
- Automatic message timestamp update
- Admin or owner authorization check
- Full error handling for all failure scenarios
streamChatMessagesRoute
Streams chat messages in real-time via WebSocket at /messages/listen.
Purpose: Enables real-time message streaming to clients using WebSocket and MongoDB change streams
Route Details:
- Method: WebSocket (implicit)
- Path:
/messages/listen - Protocol:
ws - Authentication: Currently disabled (TODO: enable when WebSocket IP address format is fixed)
Handlers: streamChatMessages, normalizeChatMessageStream
Validators: Currently commented out due to WebSocket IP address format issues:
isAuthenticated()- Will validate Bearer token authenticationhasSubscription(['params', 'requestQuery', 'channelId'])- Will verify user is subscribed to channel
Query Parameters:
channelId: string(required) - Channel ID to stream messages from
Response: Stream of normalized chat messages as they are created
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.streamChatMessagesRoute);
// Client-side WebSocket connection:
const ws = new WebSocket('ws://localhost:3000/api/messages/listen?channelId=channel123');
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('New message:', message);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('WebSocket connection closed');
};
WebSocket Flow:
- Client establishes WebSocket connection with
channelIdquery parameter - Server validates
channelIdpresence (schema validation) - Server creates MongoDB change stream for the specified channel
- Server normalizes each new message (removes
_idfield) - Server streams normalized messages to client in real-time
- Connection remains open until client disconnects or error occurs
Error Handling:
400: Missing or invalidchannelIdparameter500: Failed to create MongoDB change stream
Notes:
- Only streams new messages (insert operations)
- Messages are normalized before transmission (MongoDB
_idfield removed) - Authentication validators are currently disabled pending WebSocket IP format fix
Message Template Routes
createChatMessageTemplateRoute
Creates a new chat message template and returns the created resource.
Purpose: Handles message template creation with full resource retrieval
Route Details:
- Method:
POST - Path:
/message-templates - Authentication: Required (Bearer token)
Handlers: createChatMessageTemplate, getChatMessageTemplateById, orThrow
Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrgRole(['owner','admin'], ['params','requestBody','organizationId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createChatMessageTemplateRoute);
getChatMessageTemplateRoute
Retrieves a chat message template by ID.
Purpose: Fetches template data with organization access control
Route Details:
- Method:
GET - Path:
/message-templates/:messageTemplateId - Authentication: Required (Bearer token)
Handlers: getChatMessageTemplateById, orThrow
Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate(['owner','admin'], ['params','requestParams','messageTemplateId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getChatMessageTemplateRoute);
updateChatMessageTemplateRoute
Updates an existing chat message template via PATCH /message-templates/:messageTemplateId.
Purpose: Modifies existing message templates with organization access control and validation
Route Details:
- Method:
PATCH - Path:
/message-templates/:messageTemplateId - Authentication: Required (Bearer token)
Handlers: updateChatMessageTemplate, getChatMessageTemplateById, orThrow
Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate(['owner','admin'], ['params','requestParams','messageTemplateId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateChatMessageTemplateRoute);
deleteChatMessageTemplateRoute
Deletes a chat message template via DELETE /message-templates/:messageTemplateId.
Purpose: Removes existing message templates with organization access control and validation.
Route Details:
- Method:
DELETE - Path:
/message-templates/:messageTemplateId - Authentication: Required (Bearer token)
Handlers: deleteChatMessageTemplate, orThrow
Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate(['owner','admin'], ['params','requestParams','messageTemplateId']))
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteChatMessageTemplateRoute);
Response (204 No Content):
{}
Error Responses:
401: Unauthorized - Invalid or missing authentication token403: Forbidden - User lacks permission to delete this message template404: Not Found - Message template does not exist500: Internal Server Error - Database operation failed
Key Features:
- Authorization Control: Restricts access to template owners, organization admins, or system admins
- Safe Deletion: Validates template existence before deletion
- Atomic Operations: Uses MongoDB atomic delete operations
- Comprehensive Error Handling: Specific error responses for different failure scenarios
findChatMessageTemplatesRoute
Lists chat message templates via GET /message-templates.
Purpose: Retrieves paginated chat message templates with data normalization and admin-only access control
Route Details:
- Method:
GET - Path:
/message-templates - Authentication: Required (Bearer token)
- Authorization: Admin only (
checkIdentityType(['admin']))
Handlers: findChatMessageTemplates, normalizeDocuments, orThrow
Validators: isAuthenticated, checkIdentityType(['admin'])
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | ❌ | 1 | Page number for pagination |
limit | number | ❌ | 10 | Number of templates per page |
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findChatMessageTemplatesRoute);
Response (200 - Success):
{
"data": [
{
"id": "template-123",
"title": "Welcome Message",
"content": "Hello, welcome to our chat!",
"organizationId": "org-456",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"hasNext": false,
"hasPrev": false,
"limit": 10,
"page": 1,
"total": 1,
"totalPages": 1
}
}
}
Error Responses:
401: Unauthorized - Invalid or missing authentication token403: Forbidden - User is not an admin404: Not Found - No templates found (returns empty array)500: Internal Server Error - Database or normalization error
Key Features:
- Pagination Support: Full pagination with metadata
- Data Normalization: Automatic document normalization via
normalizeDocuments - Admin Access Control: Restricted to admin users only
- Flexible Filtering: Supports MongoDB-style query filters
- Comprehensive Error Handling: Specific error responses for different scenarios
findChatMessageTemplatesForOrganizationRoute
Retrieves chat message templates for a specific organization via GET /organizations/:organizationId/message-templates.
Purpose: Provides organization-scoped access to message templates with proper authorization controls and data normalization
Route Details:
- Method: GET
- Path:
/organizations/:organizationId/message-templates - Authentication: Required (Bearer token)
- Authorization: Organization role-based (
hasOrgRole(['owner', 'admin']))
Handlers: buildFilterToGetChatMessageTemplatesByOrganizationId, findChatMessageTemplates, normalizeDocuments, orThrow
Validators: isAuthenticated, hasOrgRole(['owner', 'admin'], ['params', 'requestParams', 'organizationId'])
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | ❌ | 1 | Page number for pagination |
limit | number | ❌ | 10 | Number of templates per page |
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findChatMessageTemplatesForOrganizationRoute);
Response (200 - Success):
{
"data": [
{
"id": "template-123",
"title": "Welcome Message",
"content": "Hello, welcome to our organization!",
"organizationId": "org-456",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"hasNext": false,
"hasPrev": false,
"limit": 10,
"page": 1,
"total": 1,
"totalPages": 1
}
}
}
Error Responses:
401: Unauthorized - Invalid or missing authentication token403: Forbidden - User lacks organization access or insufficient role permissions404: Not Found - Organization not found or no templates available500: Internal Server Error - Database or normalization error
Key Features:
- Organization Scoping: Templates are automatically filtered by organization ID
- Role-Based Authorization: Access restricted to organization owners and admins
- Pagination Support: Full pagination with metadata for large template collections
- Data Normalization: Automatic document normalization for clean API responses
- Secure Access Control: Multi-layer validation ensuring proper permissions
upsertChatChannelReadStateRoute
Upserts or creates a chat channel read state via PUT /channels/:channelId/read-state.
Purpose: Creates or updates a read state record to track which message a user has last read in a channel
Route Details:
- Method:
PUT - Path:
/channels/:channelId/read-state - Authentication: Required (Bearer token)
Blocks:
buildChatChannelReadStateQuery- Builds query for finding existing read statefindChatChannelReadStates- Finds existing read state recordsbuildLastReadMessageQuery- Builds query for finding last read messagefindChatMessages- Finds the last read messagebuildCreateChatChannelReadStatePayload- Builds payload for creationbuildUpdateChatChannelReadStatePayload- Builds payload for updatecreateChatChannelReadState- Creates new read stateupdateChatChannelReadState- Updates existing read state
Terminators: Built-in success/error mapping via orThrow with 204 status code
Validators:
isAuthenticated- Ensures user is authenticatedchannelExists- Checks channel existence by channelIdhasSubscription- Checks user subscription to channel
Request Body:
{
identityId: string; // required - user identity ID
lastReadMessageId: string; // required - last read message ID
}
Response (204 No Content): Empty response body on success
Error Responses:
401: User is not authenticated403: User is not subscribed to the channel or identityId doesn't match authenticated user404: Channel does not exist or last read message not found500: Database operation failed
Handler Process:
- Finds existing read state for the channel and identity
- Finds the last read message by ID
- If read state exists, updates it with new message information
- If read state doesn't exist, creates a new one
- Returns 204 No Content on success
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.upsertChatChannelReadStateRoute);
// Client usage:
const response = await fetch('/api/channels/channel-123/read-state', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
identityId: 'user-456',
lastReadMessageId: 'message-789'
})
});
if (response.status === 204) {
console.log('Read state upserted successfully');
}
🔗 Related Documentation
- Chat Domain Overview - Chat domain overview
- Chat Schemas - Chat validation schemas
- Chat Handlers - Chat business logic functions