Documentation
Node.js SDK

Introduction

Welcome to the Commt Node.js SDK – the backbone of secure chat functionalities for your Node.js backend applications!

The Commt Node.js SDK is specifically designed for server-side applications, providing essential backend functionality for chat systems. Unlike frontend SDKs, this package focuses on secure message handling, room management, and seamless integration with your existing Node.js infrastructure.

What is Commt Node.js SDK?

The @commt/node-sdk is a TypeScript-first backend SDK that serves as the bridge between your Node.js application and the Commt chat platform. It provides essential server-side functionality including:

  • Message Decryption: Handle encrypted messages sent from client applications
  • Room Management: Create and manage chat rooms programmatically
  • Secure Backend Integration: Seamlessly integrate with your existing authentication and database systems
  • Webhook Support: Process real-time chat events in your backend

Key Benefits

  • 🔐 Security First: Built-in AES encryption with end-to-end encryption support
  • 🚀 Developer Friendly: Written in TypeScript with comprehensive type definitions
  • ⚡ Lightweight: Minimal dependencies for optimal performance
  • 🔧 Flexible: Easy integration with any Node.js framework (Express, Fastify, Koa, etc.)
  • 📦 Production Ready: Battle-tested in production environments

Perfect For

  • Backend Developers building chat APIs and webhooks
  • CTOs and Tech Leads implementing secure communication systems
  • Full-stack Teams requiring server-side chat functionality
  • Enterprise Applications needing scalable chat infrastructure

This SDK works seamlessly with Commt's frontend SDKs (React Native and React) to provide a complete chat solution for your application ecosystem.


Installation

Getting started with the Commt Node.js SDK is straightforward. Choose your preferred package manager and follow the installation steps below.

Package Manager Installation

Using NPM

npm install @commt/node-sdk

Using Yarn

yarn add @commt/node-sdk

Using pnpm

pnpm add @commt/node-sdk

Verification

After installation, you can verify the SDK is properly installed by checking the package version:

npm list @commt/node-sdk

TypeScript Support

The Commt Node.js SDK is written in TypeScript and provides full type definitions out of the box. No additional @types packages are required.

Prerequisites

Before using the Commt Node.js SDK, ensure you have:

  • Node.js: Version 14.0 or higher
  • Active Commt Project: Get your API credentials from the Commt Dashboard (opens in a new tab)
  • Project Configuration: Your apiKey, projectId, and secret key ready

Next Steps

Once installed, you can proceed to the Configuration section to set up your Commt client and start integrating chat functionality into your Node.js application.

Package Information


Configuration

The Commt Node.js SDK uses a simple initialization pattern that allows you to configure the client once and access it globally throughout your application.

Basic Configuration

Initialize the Commt SDK in your main application file (e.g., index.js, app.js, or server.js):

import { Commt } from "@commt/node-sdk";
 
// Initialize Commt with your project credentials
Commt.init({
  apiKey: "your-api-key",
  projectId: "your-project-id", 
  secret: "your-secret-key", // Must be 16, 24, or 32 bytes
});
 
// Create a global instance for easy access
global.commt = Commt.with();

Configuration Options

ParameterTypeRequiredDescription
apiKeystringYour project API key from Commt Dashboard
projectIdstringYour unique project identifier
secretstringEncryption secret key (16, 24, or 32 bytes)
APIUrlstringCustom API endpoint (defaults to Commt's service)

Getting Your Credentials

  1. Sign up for a Commt account at dashboard.commt.co (opens in a new tab)
  2. Create a new project or select an existing one
  3. Copy your credentials from the project settings:
    • API Key
    • Project ID
    • Secret Key

Environment Variables (Recommended)

For production applications, store your credentials securely using environment variables:

import { Commt } from "@commt/node-sdk";
 
Commt.init({
  apiKey: process.env.COMMT_API_KEY,
  projectId: process.env.COMMT_PROJECT_ID,
  secret: process.env.COMMT_SECRET_KEY,
});
 
global.commt = Commt.with();

Create a .env file in your project root:

COMMT_API_KEY=your-api-key
COMMT_PROJECT_ID=your-project-id
COMMT_SECRET_KEY=your-secret-key

Global Access Pattern

Once initialized, you can access the Commt instance from anywhere in your application:

// In any route or controller file
app.post('/save-message', async (req, res) => {
  // Access the global commt instance
  const decryptedMessage = global.commt.decrypt(req.body);
  // ... handle the message
});

Custom API Endpoint

If you're using a self-hosted Commt instance, you can specify a custom API URL:

Commt.init({
  apiKey: "your-api-key",
  projectId: "your-project-id",
  secret: "your-secret-key",
  APIUrl: "https://your-custom-commt-instance.com"
});

Secret Key Requirements

The secret key is used for AES encryption and must meet specific byte requirements:

  • 16 bytes: AES-128 encryption
  • 24 bytes: AES-192 encryption
  • 32 bytes: AES-256 encryption (recommended)

Example of a 32-byte secret key:

"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

Initialization Best Practices

  1. Initialize Early: Call Commt.init() before setting up your routes or middleware
  2. Single Initialization: Only initialize once per application lifecycle
  3. Environment-Specific: Use different credentials for development, staging, and production
  4. Error Handling: Always handle initialization errors gracefully
try {
  Commt.init({
    apiKey: process.env.COMMT_API_KEY,
    projectId: process.env.COMMT_PROJECT_ID,
    secret: process.env.COMMT_SECRET_KEY,
  });
  
  global.commt = Commt.with();
  console.log('Commt SDK initialized successfully');
} catch (error) {
  console.error('Failed to initialize Commt SDK:', error);
  process.exit(1);
}

API Methods

The Commt Node.js SDK provides essential methods for handling chat functionality on the server side. Below are the core methods available in the SDK.

Core Methods Overview

MethodPurposeReturns
init()Initialize the Commt SDKvoid
with()Get SDK instanceCommt
decrypt()Decrypt incoming messagesstring
createRoom()Create a new chat roomstring

Static Methods

Commt.init(config)

Initializes the Commt SDK with your project configuration.

Parameters:

interface IInit {
  apiKey: string;      // Your project API key
  projectId: string;   // Your project ID  
  secret: string;      // Encryption secret (16, 24, or 32 bytes)
  APIUrl?: string;     // Optional custom API endpoint
}

Example:

import { Commt } from "@commt/node-sdk";
 
Commt.init({
  apiKey: "your-api-key",
  projectId: "your-project-id",
  secret: "your-32-byte-secret-key-here",
});

Commt.with()

Returns the initialized Commt instance for use throughout your application.

Returns: Commt - The configured Commt instance

Example:

const commt = Commt.with();
// Now you can use commt.decrypt(), commt.createRoom(), etc.

Instance Methods

decrypt(props)

Decrypts encrypted messages received from client applications.

Parameters:

interface IAESDecrypt {
  iv: string;      // Initialization vector
  cipher: string;  // Encrypted message
}

Returns: string - Decrypted message content (usually JSON)

Example:

app.post('/save-message', async (req, res) => {
  const { message: cipher, iv } = req.body;
  
  // Decrypt the message
  const decryptedData = commt.decrypt({ cipher, iv });
  const messageData = JSON.parse(decryptedData);
  
  console.log(messageData);
  // Output: { roomId: "123", message: { text: "Hello!", senderId: "user1", ... } }
});

createRoom(participants)

Creates a new chat room and returns a unique room identifier.

Parameters:

  • participants: string[] - Array of participant chat authentication IDs

Returns: string - Generated chatRoomAuthId for the new room

Example:

app.post('/create-room', async (req, res) => {
  const { participants } = req.body; // Array of chatAuthIds
  
  // Create room in Commt system
  const chatRoomAuthId = commt.createRoom(participants);
  
  // Save to your database
  await RoomModel.create({
    roomId: generateRoomId(), // Your internal room ID
    chatRoomAuthId,          // Commt's room identifier
    participants: participants,
    createdAt: new Date()
  });
  
  res.json({ success: true, chatRoomAuthId });
});

Method Usage Patterns

Message Processing Workflow

// 1. Receive encrypted message from client
app.post('/webhook/message', async (req, res) => {
  try {
    // 2. Decrypt the message
    const { message: cipher, iv } = req.body;
    const decryptedData = commt.decrypt({ cipher, iv });
    const result = JSON.parse(decryptedData);
    
    // 3. Extract message details
    const { roomId, message } = result;
    
    // 4. Save to your database
    await MessageModel.create({
      roomId,
      type: message.type,
      senderId: message.senderId,
      text: message.text,
      createdAt: message.createdAt,
    });
    
    // 5. Return success response
    res.status(200).json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Room Creation Workflow

app.post('/rooms', async (req, res) => {
  try {
    const { participants, roomName, roomType } = req.body;
    
    // 1. Create room in Commt system
    const chatRoomAuthId = commt.createRoom(participants.map(p => p.chatAuthId));
    
    // 2. Store room in your database
    const room = await RoomModel.create({
      name: roomName,
      type: roomType,
      chatRoomAuthId,
      participants: participants.map(p => p.id),
      createdBy: req.user.id
    });
    
    res.json({ room, chatRoomAuthId });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Error Handling

Always wrap SDK method calls in try-catch blocks for robust error handling:

try {
  const decryptedMessage = commt.decrypt({ cipher, iv });
  // Process message...
} catch (error) {
  console.error('Decryption failed:', error);
  res.status(400).json({ error: 'Invalid message format' });
}

TypeScript Support

All methods include full TypeScript definitions for better development experience:

import { Commt, IDGenerator } from "@commt/node-sdk";
 
// TypeScript will provide autocompletion and type checking
const commt = Commt.with();
const roomId: string = commt.createRoom(["user1", "user2"]);

Utilities

The Commt Node.js SDK includes helpful utility functions to enhance your development experience.

IDGenerator

A utility function for generating unique identifiers, commonly used for creating room IDs, message IDs, or other unique identifiers in your chat application.

Import

import { IDGenerator } from "@commt/node-sdk";

Usage

// Generate a long ID (default)
const longId = IDGenerator({ longId: true });
// Example output: "a1b2c3-d4e5f6-g7h8i9j0k1l2m3n4o5p6"
 
// Generate a short ID
const shortId = IDGenerator({ longId: false });
// Example output: "a1b2c3d4e5"
 
// Generate with custom length (only for long IDs)
const customId = IDGenerator({ longId: true, idStrLen: 40 });
// Example output: "a1b2c3-d4e5f6-g7h8i9j0k1l2m3n4o5p6q7r8"

Parameters

ParameterTypeDefaultDescription
longIdbooleantrueGenerate long or short format ID
idStrLennumber32Length of the generated ID (long format only)

Examples

Room ID Generation

import { IDGenerator } from "@commt/node-sdk";
 
app.post('/create-room', async (req, res) => {
  // Generate unique room ID for your database
  const roomId = IDGenerator({ longId: false });
  
  const room = await RoomModel.create({
    roomId,
    name: req.body.roomName,
    // ... other room data
  });
  
  res.json({ room });
});

Message ID Generation

app.post('/save-message', async (req, res) => {
  // Generate unique message ID
  const messageId = IDGenerator({ longId: true, idStrLen: 24 });
  
  const message = await MessageModel.create({
    id: messageId,
    text: req.body.text,
    senderId: req.body.senderId,
    // ... other message data
  });
  
  res.json({ message });
});

User Session ID

app.post('/login', async (req, res) => {
  // Generate session ID
  const sessionId = IDGenerator({ longId: true });
  
  await SessionModel.create({
    id: sessionId,
    userId: user.id,
    expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
  });
  
  res.json({ sessionId, user });
});

ID Format Specifications

Long Format

  • Includes hyphens for readability
  • Starts with a letter (base 36)
  • Includes timestamp component
  • Configurable length (minimum 32 characters)
  • Example: "k-m-g7h8i9j0k1l2m3n4o5p6q7r8s9"

Short Format

  • No hyphens, compact format
  • Fixed length based on algorithm
  • Faster generation
  • Example: "k4m2n7p9"

Best Practices

  1. Use Short IDs for frequently generated identifiers (messages, events)
  2. Use Long IDs for important entities (rooms, users, sessions)
  3. Consistent Length for database indexing performance
  4. Store as Strings in your database for compatibility
// Good: Consistent ID strategy
const roomId = IDGenerator({ longId: true, idStrLen: 32 });
const messageId = IDGenerator({ longId: false });
 
// Database schema consideration
const roomSchema = {
  id: { type: String, length: 32 }, // Long format
  messageIds: [{ type: String, length: 10 }] // Short format
};

Integration with Database Models

MongoDB Example

const RoomSchema = new mongoose.Schema({
  _id: {
    type: String,
    default: () => IDGenerator({ longId: true, idStrLen: 24 })
  },
  chatRoomAuthId: String,
  participants: [String],
  createdAt: { type: Date, default: Date.now }
});

PostgreSQL Example

CREATE TABLE rooms (
  id VARCHAR(32) PRIMARY KEY DEFAULT generate_room_id(),
  chat_room_auth_id VARCHAR(20),
  participants TEXT[],
  created_at TIMESTAMP DEFAULT NOW()
);
// Custom function for PostgreSQL
export const generateRoomId = () => IDGenerator({ longId: true, idStrLen: 32 });

Performance Considerations

  • Short IDs: ~100,000 generations per second
  • Long IDs: ~50,000 generations per second
  • Memory Usage: Minimal (< 1KB per 1000 IDs)
  • Uniqueness: Cryptographically secure randomness

The IDGenerator is optimized for high-throughput applications and provides sufficient entropy to avoid collisions in distributed systems.


Quick Start

Get up and running with the Commt Node.js SDK in just a few minutes. This guide will walk you through the essential steps to integrate chat functionality into your Node.js application.

Step 1: Installation

Install the Commt Node.js SDK using your preferred package manager:

npm install @commt/node-sdk

Step 2: Get Your Credentials

  1. Visit the Commt Dashboard (opens in a new tab)
  2. Create a new project or select an existing one
  3. Copy your project credentials:
    • API Key
    • Project ID
    • Secret Key (must be 16, 24, or 32 bytes)

Step 3: Initialize the SDK

Create your main application file and initialize Commt:

index.js

import express from 'express';
import { Commt } from '@commt/node-sdk';
 
const app = express();
 
// Initialize Commt SDK
Commt.init({
  apiKey: "your-api-key",
  projectId: "your-project-id",
  secret: "your-32-byte-secret-key-here"
});
 
// Create global instance
global.commt = Commt.with();
 
app.use(express.json());
 
console.log('Commt SDK initialized successfully!');

Step 4: Handle Incoming Messages

Create an endpoint to receive and decrypt messages from client applications to save into your own Database:

app.post('/webhook/message', async (req, res) => {
  try {
    // Extract encrypted data from request
    const { message: cipher, iv } = req.body;
    
    // Decrypt using Commt SDK
    const decryptedData = global.commt.decrypt({ cipher, iv });
    const messageData = JSON.parse(decryptedData);
    
    console.log('Received message:', messageData);
    // messageData contains: { roomId, message: { text, senderId, createdAt, type } }
    
    // Save to your database
    await saveMessageToDatabase(messageData);
    
    res.status(200).json({ success: true });
  } catch (error) {
    console.error('Message processing failed:', error);
    res.status(500).json({ error: 'Failed to process message' });
  }
});

Step 5: Create Chat Rooms

Add an endpoint to create new room:

app.post('/rooms', async (req, res) => {
  try {
    const { participants } = req.body;
    // participants: ["chatAuthId1", "chatAuthId2", ...]
    
    // Create room in Commt system
    const chatRoomAuthId = global.commt.createRoom(participants);
    
    // Save room to your database
    const room = await createRoomInDatabase({
      chatRoomAuthId,
      participants,
      createdAt: new Date()
    });
    
    res.json({ 
      success: true, 
      roomId: room.id,
      chatRoomAuthId 
    });
  } catch (error) {
    console.error('Room creation failed:', error);
    res.status(500).json({ error: 'Failed to create room' });
  }
});

Step 6: Start Your Server

const PORT = process.env.PORT || 3000;
 
app.listen(PORT, () => {
  console.log(`🚀 Chat server running on port ${PORT}`);
  console.log(`📨 Webhook endpoint: http://localhost:${PORT}/webhook/message`);
  console.log(`🏠 Room creation: http://localhost:${PORT}/rooms`);
});

Complete Quick Start Example

Here's the full working example:

quick-start.js

import express from 'express';
import { Commt, IDGenerator } from '@commt/node-sdk';
 
const app = express();
app.use(express.json());
 
// Initialize Commt
Commt.init({
  apiKey: "your-api-key",
  projectId: "your-project-id", 
  secret: "your-32-byte-secret-key-here"
});
 
global.commt = Commt.with();
 
// In-memory storage for demo (use a real database in production)
const messages = [];
const rooms = [];
 
// Message webhook endpoint
app.post('/webhook/message', async (req, res) => {
  try {
    const { message: cipher, iv } = req.body;
    const decryptedData = global.commt.decrypt({ cipher, iv });
    const messageData = JSON.parse(decryptedData);
    
    // Store message
    messages.push({
      id: IDGenerator({ longId: false }),
      ...messageData,
      receivedAt: new Date()
    });
    
    console.log(`💬 New message in room ${messageData.roomId}: "${messageData.message.text}"`);
    
    res.status(200).json({ success: true });
  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({ error: error.message });
  }
});
 
// Create room endpoint
app.post('/rooms', (req, res) => {
  try {
    const { participants, name } = req.body;
    const chatRoomAuthId = global.commt.createRoom(participants);
    
    const room = {
      id: IDGenerator({ longId: false }),
      chatRoomAuthId,
      name: name || 'New Room',
      participants,
      createdAt: new Date()
    };
    
    rooms.push(room);
    
    console.log(`🏠 Created room: ${room.name} (${chatRoomAuthId})`);
    
    res.json({ success: true, room });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
 
// Get messages for a room
app.get('/rooms/:roomId/messages', (req, res) => {
  const roomMessages = messages.filter(m => m.roomId === req.params.roomId);
  res.json({ messages: roomMessages });
});
 
// Get all rooms
app.get('/rooms', (req, res) => {
  res.json({ rooms });
});
 
// Health check
app.get('/health', (req, res) => {
  res.json({ 
    status: 'OK', 
    commt: 'initialized',
    timestamp: new Date().toISOString() 
  });
});
 
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`
🚀 Commt Chat Server Started!
📡 Server: http://localhost:${PORT}
📨 Message Webhook: POST /webhook/message
🏠 Create Room: POST /rooms
📋 Health Check: GET /health
 
Ready to receive chat messages!
  `);
});

Testing Your Setup

1. Start the server:
node quick-start.js
2. Test room creation:
curl -X POST http://localhost:3000/rooms \
  -H "Content-Type: application/json" \
  -d '{"participants": ["user1", "user2"], "name": "Test Room"}'
3. Check health:
curl http://localhost:3000/health

Next Steps

  1. Database Integration: Replace in-memory storage with MongoDB, PostgreSQL, or your preferred database
  2. Authentication: Add user authentication and authorization
  3. Frontend Integration: Connect with Commt's React or React Native SDKs
  4. Production Setup: Add logging, monitoring, and error handling
  5. Advanced Features: Implement file uploads, typing indicators, and read receipts

Common Issues & Solutions

Issue: "Secret key must be 16, 24, or 32 bytes"

// ✅ Correct: 32-byte secret key
secret: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
 
// ❌ Wrong: Too short
secret: "mypassword"

Issue: Decryption fails

  • Verify your secret key matches the one used in client applications
  • Ensure the cipher and iv are correctly extracted from request body

Issue: Room creation returns error

  • Check that participants array contains valid chat authentication IDs
  • Verify your API key has room creation permissions

You're now ready to build powerful chat applications with the Commt Node.js SDK!


Security

The Commt Node.js SDK is designed with security as a top priority. Follow these best practices to ensure your chat application remains secure and protected.

Credential Management

Environment Variables

Always store sensitive credentials in environment variables, never in your source code:

// ✅ Good: Using environment variables
Commt.init({
  apiKey: process.env.COMMT_API_KEY,
  projectId: process.env.COMMT_PROJECT_ID,
  secret: process.env.COMMT_SECRET_KEY,
});
 
// ❌ Bad: Hardcoded credentials
Commt.init({
  apiKey: "ak_123456789",
  projectId: "proj_987654321",
  secret: "my-secret-key",
});

Secret Key Requirements

Your encryption secret key must meet specific security standards:

  • Length: Exactly 16, 24, or 32 bytes
  • Randomness: Use cryptographically secure random generation
  • Uniqueness: Each environment should have a unique secret
  • Rotation: Regularly rotate secrets in production
// Generate a secure 32-byte secret key
import crypto from 'crypto';
 
const generateSecretKey = () => {
  return crypto.randomBytes(32).toString('hex').substring(0, 32);
};
 
// Example: "a7b9c2d4e6f8g1h3i5j7k9l2m4n6o8p0"

Message Encryption

AES Encryption

Commt uses AES-CBC encryption for all message content:

  • Algorithm: AES-CBC (Cipher Block Chaining)
  • Key Sizes: 128, 192, or 256 bits
  • IV (Initialization Vector): Unique per message
  • Padding: PKCS#7

End-to-End Encryption

For maximum security, enable E2E encryption in your project settings:

// The SDK automatically handles E2E when enabled
const decryptedMessage = commt.decrypt({ cipher, iv });
// Message is automatically decrypted using your secret key

Input Validation

Always validate and sanitize input data before processing:

import Joi from 'joi';
 
const messageSchema = Joi.object({
  message: Joi.string().required(),
  iv: Joi.string().hex().length(32).required()
});
 
app.post('/webhook/message', async (req, res) => {
  try {
    // Validate input
    const { error, value } = messageSchema.validate(req.body);
    if (error) {
      return res.status(400).json({ error: 'Invalid input format' });
    }
    
    // Process validated data
    const decryptedData = commt.decrypt(value);
    // ... continue processing
  } catch (error) {
    res.status(500).json({ error: 'Processing failed' });
  }
});

Error Handling

Secure Error Messages

Avoid exposing sensitive information in error messages:

app.post('/webhook/message', async (req, res) => {
  try {
    const decryptedData = commt.decrypt(req.body);
    // ... process message
  } catch (error) {
    // ✅ Good: Generic error message to client
    console.error('Decryption error:', error); // Log detailed error
    res.status(400).json({ error: 'Invalid message format' });
    
    // ❌ Bad: Exposing internal details
    // res.status(500).json({ error: error.message });
  }
});

Production Checklist

Security Audit Checklist

  • All credentials stored in environment variables
  • Secret keys meet length requirements (32 bytes recommended)
  • HTTPS enabled for all endpoints
  • Rate limiting implemented
  • Input validation on all endpoints
  • Error handling doesn't expose sensitive data
  • Security logging implemented
  • CORS properly configured
  • Database connections secured
  • API authentication implemented
  • Regular security updates scheduled

Following these security best practices will help ensure your Commt-powered chat application remains secure and trustworthy for your users.


Complete Example

This comprehensive example demonstrates how to build a complete chat backend API using the Commt Node.js SDK with Express.js.

Project Structure

chat-backend/
├── src/
│   ├── controllers/
│   │   ├── messageController.js
│   │   ├── roomController.js
│   │   └── userController.js
│   ├── models/
│   │   ├── Message.js
│   │   ├── Room.js
│   │   └── User.js
│   ├── routes/
│   │   ├── messages.js
│   │   ├── rooms.js
│   │   └── users.js
│   ├── middleware/
│   │   └── auth.js
│   └── app.js
├── .env
└── package.json

Application Setup

package.json

{
  "name": "chat-backend",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node src/app.js",
    "dev": "nodemon src/app.js"
  },
  "dependencies": {
    "@commt/node-sdk": "^latest",
    "express": "^4.18.2",
    "mongoose": "^7.5.0",
    "cors": "^2.8.5",
    "dotenv": "^16.3.1"
  }
}

Environment Configuration

.env

# Commt Configuration
COMMT_API_KEY=your-api-key-here
COMMT_PROJECT_ID=your-project-id-here
COMMT_SECRET_KEY=your-32-byte-secret-key-here

# Database
MONGODB_URI=mongodb://localhost:27017/chat-app

# Server
PORT=3000

Main Application

src/app.js

import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import mongoose from 'mongoose';
import { Commt } from '@commt/node-sdk';
 
// Import routes
import messageRoutes from './routes/messages.js';
import roomRoutes from './routes/rooms.js';
import userRoutes from './routes/users.js';
 
dotenv.config();
 
const app = express();
const PORT = process.env.PORT || 3000;
 
// Initialize Commt SDK
try {
  Commt.init({
    apiKey: process.env.COMMT_API_KEY,
    projectId: process.env.COMMT_PROJECT_ID,
    secret: process.env.COMMT_SECRET_KEY,
  });
  
  global.commt = Commt.with();
  console.log('✅ Commt SDK initialized successfully');
} catch (error) {
  console.error('❌ Failed to initialize Commt SDK:', error);
  process.exit(1);
}
 
// Middleware
app.use(cors());
app.use(express.json());
 
// Database connection
mongoose.connect(process.env.MONGODB_URI)
  .then(() => console.log('✅ Connected to MongoDB'))
  .catch(err => console.error('❌ MongoDB connection error:', err));
 
// Routes
app.use('/api/messages', messageRoutes);
app.use('/api/rooms', roomRoutes);
app.use('/api/users', userRoutes);
 
// Health check
app.get('/health', (req, res) => {
  res.json({ status: 'OK', timestamp: new Date().toISOString() });
});
 
app.listen(PORT, () => {
  console.log(`🚀 Server running on port ${PORT}`);
});

Data Models

Message Model

src/models/Message.js

import mongoose from 'mongoose';
 
const messageSchema = new mongoose.Schema({
  roomId: { type: String, required: true, index: true },
  senderId: { type: String, required: true },
  text: { type: String, required: true },
  type: { type: String, default: 'text' },
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date, default: Date.now }
});
 
messageSchema.index({ roomId: 1, createdAt: -1 });
 
export default mongoose.model('Message', messageSchema);

Room Model

src/models/Room.js

import mongoose from 'mongoose';
import { IDGenerator } from '@commt/node-sdk';
 
const roomSchema = new mongoose.Schema({
  roomId: { 
    type: String, 
    default: () => IDGenerator({ longId: false }),
    unique: true 
  },
  chatRoomAuthId: { type: String, required: true, unique: true },
  name: String,
  participants: [{ type: String, required: true }],
  createdBy: String,
  isGroup: { type: Boolean, default: false },
  avatar: String,
  createdAt: { type: Date, default: Date.now }
});
 
export default mongoose.model('Room', roomSchema);

User Model

src/models/User.js

import mongoose from 'mongoose';
 
const userSchema = new mongoose.Schema({
  userId: { type: String, required: true, unique: true },
  chatAuthId: { type: String, required: true, unique: true },
  name: { type: String, required: true },
  email: String,
  avatar: String,
  isOnline: { type: Boolean, default: false },
  lastSeen: { type: Date, default: Date.now }
});
 
export default mongoose.model('User', userSchema);

API Controllers

Message Controller

src/controllers/messageController.js

import Message from '../models/Message.js';
 
export const saveMessage = async (req, res) => {
  try {
    const { message: cipher, iv } = req.body;
    
    // Decrypt message using Commt SDK
    const decryptedData = global.commt.decrypt({ cipher, iv });
    const result = JSON.parse(decryptedData);
    
    const { roomId, message } = result;
    
    // Save message to database
    const newMessage = await Message.create({
      roomId,
      senderId: message.senderId,
      text: message.text,
      type: message.type || 'text',
      createdAt: message.createdAt || new Date()
    });
    
    res.status(200).json({ 
      success: true, 
      messageId: newMessage._id 
    });
  } catch (error) {
    console.error('Save message error:', error);
    res.status(500).json({ 
      error: 'Failed to save message',
      details: error.message 
    });
  }
};
 
export const getMessages = async (req, res) => {
  try {
    const { roomId } = req.params;
    const { page = 1, limit = 50 } = req.query;
    
    const messages = await Message.find({ roomId })
      .sort({ createdAt: -1 })
      .limit(limit * 1)
      .skip((page - 1) * limit)
      .exec();
    
    res.json({
      messages: messages.reverse(),
      hasNext: messages.length === parseInt(limit)
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

Room Controller

src/controllers/roomController.js

import Room from '../models/Room.js';
 
export const createRoom = async (req, res) => {
  try {
    const { participants, name, isGroup = false } = req.body;
    
    // Create room in Commt system
    const chatAuthIds = participants.map(p => p.chatAuthId);
    const chatRoomAuthId = global.commt.createRoom(chatAuthIds);
    
    // Save room to database
    const room = await Room.create({
      chatRoomAuthId,
      name,
      participants: participants.map(p => p.userId),
      isGroup,
      createdBy: req.user?.userId
    });
    
    res.status(201).json({
      success: true,
      room: {
        roomId: room.roomId,
        chatRoomAuthId: room.chatRoomAuthId,
        name: room.name,
        participants: room.participants,
        isGroup: room.isGroup
      }
    });
  } catch (error) {
    console.error('Create room error:', error);
    res.status(500).json({ 
      error: 'Failed to create room',
      details: error.message 
    });
  }
};
 
export const getRooms = async (req, res) => {
  try {
    const { userId } = req.params;
    
    const rooms = await Room.find({
      participants: userId
    }).sort({ createdAt: -1 });
    
    res.json({ rooms });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

API Routes

Message Routes

src/routes/messages.js

import express from 'express';
import { saveMessage, getMessages } from '../controllers/messageController.js';
 
const router = express.Router();
 
// POST /api/messages/save - Save encrypted message from webhook
router.post('/save', saveMessage);
 
// GET /api/messages/:roomId - Get messages for a room
router.get('/:roomId', getMessages);
 
export default router;

Room Routes

src/routes/rooms.js

import express from 'express';
import { createRoom, getRooms } from '../controllers/roomController.js';
 
const router = express.Router();
 
// POST /api/rooms - Create new room
router.post('/', createRoom);
 
// GET /api/rooms/:userId - Get user's rooms
router.get('/:userId', getRooms);
 
export default router;

Usage Examples

Creating a Room

curl -X POST http://localhost:3000/api/rooms \
  -H "Content-Type: application/json" \
  -d '{
    "participants": [
      {"userId": "user1", "chatAuthId": "auth1"},
      {"userId": "user2", "chatAuthId": "auth2"}
    ],
    "name": "Project Discussion",
    "isGroup": true
  }'

Webhook Endpoint for Messages

curl -X POST http://localhost:3000/api/messages/save \
  -H "Content-Type: application/json" \
  -d '{
    "message": "encrypted-cipher-text",
    "iv": "initialization-vector"
  }'

Retrieving Messages

curl http://localhost:3000/api/messages/room123?page=1&limit=20

Production Considerations

  1. Error Logging: Implement comprehensive logging with Winston or similar
  2. Rate Limiting: Add rate limiting middleware for API protection
  3. Authentication: Implement JWT or session-based authentication
  4. Validation: Add input validation with Joi or express-validator
  5. Database Indexing: Optimize database queries with proper indexing
  6. Monitoring: Set up health checks and performance monitoring

This example provides a solid foundation for building production-ready chat applications with the Commt Node.js SDK.


Troubleshooting

This guide helps you resolve common issues when working with the Commt Node.js SDK. Find solutions to frequently encountered problems and learn how to debug effectively.

Common Issues

Installation Issues

Symptoms:

npm ERR! 404 Not Found - GET https://registry.npmjs.org/@commt/node-sdk

Solutions:

  1. Verify the package name is correct: @commt/node-sdk
  2. Check your npm registry configuration:
    npm config get registry
  3. Try clearing npm cache:
    npm cache clean --force

Issue: TypeScript compilation errors

Symptoms:

error TS2307: Cannot find module '@commt/node-sdk'

Solutions:

  1. Install the package properly: npm install @commt/node-sdk
  2. Restart your TypeScript server
  3. Check your tsconfig.json for correct module resolution

Initialization Issues

Issue: "Secret key must be 16, 24 or 32 bytes"

Symptoms:

Error: Secret key must be 16, 24 or 32 bytes

Solutions:

// ❌ Wrong: Incorrect byte length
secret: "mypassword" // Only 10 bytes
 
// ✅ Correct: 32-byte secret key
secret: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" // Exactly 32 bytes

Generate a proper secret key:

import crypto from 'crypto';
 
// Generate 32-byte secret
const secret = crypto.randomBytes(32).toString('hex').substring(0, 32);
console.log('Generated secret:', secret);

Issue: "API key is invalid"

Symptoms:

Error: API key is invalid or expired

Solutions:

  1. Verify your API key from the Commt Dashboard (opens in a new tab)
  2. Check if the API key has the correct permissions
  3. Ensure you're using the correct project ID
  4. Verify the API key format (should start with specific prefix)

Decryption Issues

Issue: Decryption fails with "Invalid cipher format"

Symptoms:

Error: Invalid cipher format or corrupted data

Common Causes & Solutions:

  1. Mismatched secret keys:

    // Ensure the same secret is used in both client and server
    // Client (React/RN): secret: "your-32-byte-secret"
    // Server (Node.js): secret: "your-32-byte-secret"
  2. Incorrect IV format:

    // ✅ Correct: IV should be hex string
    const { cipher, iv } = req.body;
    commt.decrypt({ cipher, iv });
     
    // ❌ Wrong: IV in wrong format
    const iv = Buffer.from(req.body.iv).toString('hex');
  3. Corrupted request data:

    // Validate input before decryption
    if (!cipher || !iv || typeof cipher !== 'string' || typeof iv !== 'string') {
      throw new Error('Invalid request format');
    }

Issue: "Cannot parse decrypted JSON"

Symptoms:

Error: Unexpected token in JSON at position 0

Solutions:

try {
  const decryptedData = commt.decrypt({ cipher, iv });
  
  // Add validation before parsing
  if (!decryptedData || typeof decryptedData !== 'string') {
    throw new Error('Decryption returned invalid data');
  }
  
  const messageData = JSON.parse(decryptedData);
} catch (parseError) {
  console.error('JSON parse error:', parseError);
  console.log('Raw decrypted data:', decryptedData);
}

Room Creation Issues

Issue: Room creation returns undefined

Symptoms:

const chatRoomAuthId = commt.createRoom(participants);
console.log(chatRoomAuthId); // undefined

Solutions:

  1. Check participants format:

    // ✅ Correct: Array of chat auth IDs
    const participants = ["chatAuth1", "chatAuth2"];
     
    // ❌ Wrong: Objects or other formats
    const participants = [
      { id: "user1", chatAuthId: "chatAuth1" }
    ];
  2. Verify initialization:

    // Ensure SDK is properly initialized
    if (!global.commt) {
      throw new Error('Commt SDK not initialized');
    }
  3. Check API connectivity:

    // Add error handling for network issues
    try {
      const chatRoomAuthId = commt.createRoom(participants);
      if (!chatRoomAuthId) {
        throw new Error('Room creation failed - no ID returned');
      }
    } catch (error) {
      console.error('Room creation error:', error);
    }

Network and API Issues

Issue: 401 Unauthorized errors

Symptoms:

Error: Request failed with status code 401

Solutions:

  1. Verify API credentials:

    console.log('API Key:', process.env.COMMT_API_KEY?.substring(0, 10) + '...');
    console.log('Project ID:', process.env.COMMT_PROJECT_ID);
  2. Check key permissions in dashboard

  3. Regenerate API key if compromised

Getting Help

Check Documentation

Contact Support

Community Resources

Before Reporting Issues

Include this information:

  1. Environment: Node.js version, OS, package version
  2. Configuration: Sanitized config (hide credentials)
  3. Error logs: Complete error messages and stack traces
  4. Reproduction steps: Minimal code that reproduces the issue
  5. Expected vs actual behavior: Clear description of the problem

This troubleshooting guide should help you resolve most common issues with the Commt Node.js SDK.


© 2025 Commt. All rights reserved.
Welcome to Commt, I am here to guide you!
Chat with Commt AI Bot
commt-chatbot-ai-avatar

Hi, welcome!

I am Commt's AI user, which is a future feature that developers work on, to provide for the clients to re-train and integrate into Commt SDKs.

How can I help you? 😇

01:14 PM