Migrate ccs-chat-client 2.x to 3.0.0
Upgrade your backend from ccs-chat-client 2.x to 3.0.0. Version 3.0.0 follows the conventions of the Identity Server client: request and response objects use the Chat API’s own snake_case field names, and the granular scopes are the ones the Identity Server defines on the Chat API.
Prerequisites
Section titled “Prerequisites”- A backend on
ccs-chat-client2.x. See the changelog for the release. - Access to your backend client in the Identity Server admin UI, to grant the new scope names.
What changed
Section titled “What changed”Constructor options are unchanged and stay camelCase (issuerUrl, clientId, chatApiUrl, tenantId, applicationId).
| 2.x | 3.0.0 |
|---|---|
conversations.create({ type, memberUserIds, actorUserId }) |
conversations.create({ type, member_user_ids, actor_user_id }) |
conversations.addMember(id, { userId, displayName, email }) |
conversations.addMember(id, { user_id, display_name, email }) |
messages.send(id, { body, actorUserId, messageType, replyToMessageId, mentionedUserIds, attachments: [{ fileId, mimeType, … }] }) |
messages.send(id, { body, actor_user_id, message_type, reply_to_message_id, mentioned_user_ids, attachments: [{ file_id, mime_type, … }] }) |
Conversation (id, memberCount, …) |
ChatConversation (conversation_id, member_count, …), the API response unchanged |
ChatMessage (id, senderUserId, …) |
ChatMessage (message_id, sender_user_id, …) |
Member, UserRef |
ChatMember, ChatUserRef. users.lookup returns ChatUserProfile[]. |
Page { items, nextCursor } |
Page { items, next_cursor } |
Scopes chat:conversation:create, chat:conversation:read |
chat:conversations.manage, chat:conversations.read, plus chat:groups.manage, chat:channels.manage, chat:messages.send, chat:users.lookup |
scope?: string |
scope?: ChatMachineScope | ChatMachineScope[] | string |
| Not available | conversations.archive(id) and conversations.reactivate(id). A backend client may change the status of a DIRECT conversation. |
| Not available | ChatRateLimitedError (429) with retryAfterSeconds |
-
Upgrade the package. Install
@central-code-station/ccs-chat-client3.0.0 or later. -
Grant the new scope names. In the Identity Server admin UI, open your backend client’s Resource Permissions for the Chat API and grant
chat:sync, or the granular scopes you need. See Grant Chat scopes. If you setscopein the constructor, change it to the new names. -
Rename request fields. The compiler lists every place. For example:
// 2.xawait chat.conversations.create({ type: 'DIRECT', memberUserIds: [a, b], actorUserId: a });// 3.0.0await chat.conversations.create({ type: 'DIRECT', member_user_ids: [a, b], actor_user_id: a }); -
Rename the fields you read.
conversation.idbecomesconversation.conversation_id,message.idbecomesmessage.message_id,page.nextCursorbecomespage.next_cursor, and so on. Rename any of your own types that importConversation,MemberorUserRef. -
Use the new methods. Replace a hand-written
update(id, { status: 'ARCHIVED' })witharchive(id), and handleChatRateLimitedErrorfor 429.
To find leftovers, search your code for the 2.x names: memberUserIds, actorUserId, userId, displayName, messageType, replyToMessageId, mentionedUserIds, fileId, mimeType and nextCursor.
The same calls on 3.0.0:
import { chat } from './guide-chat-client';
export async function afterMigration(): Promise<void> { const conversation = await chat.conversations.create({ type: 'GROUP', name: 'Morning squad', member_user_ids: ['coach-ana', 'client-john'], actor_user_id: 'coach-ana', }); await chat.conversations.addMember(conversation.conversation_id, { user_id: 'client-sarah', display_name: 'Sarah Client' });
const message = await chat.messages.send(conversation.conversation_id, { body: 'Welcome!', actor_user_id: 'coach-ana', message_type: 'TEXT', mentioned_user_ids: ['client-john'], }); console.log(message.message_id, message.sender_user_id);
const page = await chat.messages.list(conversation.conversation_id, { limit: 50 }); console.log(page.items.length, page.next_cursor); // was nextCursor}Verify
Section titled “Verify”The project compiles with no errors. Then create a conversation and send a message in a test tenant. Both calls succeed, and conversation_id and message_id are present on the results. A token request with the new scope names returns a token whose scope lists them.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause and fix |
|---|---|
| TypeScript: “Object literal may only specify known properties” | A camelCase field is left. Rename it. |
400 invalid_request |
Your code sent a camelCase field the API does not accept. Check the request body. |
undefined where you read .id or .nextCursor |
The response fields are snake_case now. |
Token request fails with invalid_scope |
The client is not granted the new scope names. Grant them, or reduce scope. |
403 insufficient_scope |
The scopes in your token do not carry the permission the call needs. |