Skip to content

refactor: Migrate from @rocket.chat/sdk to @rocket.chat/ddp-client#1308

Draft
Aryan-Verma-999 wants to merge 6 commits into
RocketChat:developfrom
Aryan-Verma-999:api-modernisation-ddp-client
Draft

refactor: Migrate from @rocket.chat/sdk to @rocket.chat/ddp-client#1308
Aryan-Verma-999 wants to merge 6 commits into
RocketChat:developfrom
Aryan-Verma-999:api-modernisation-ddp-client

Conversation

@Aryan-Verma-999
Copy link
Copy Markdown
Contributor

@Aryan-Verma-999 Aryan-Verma-999 commented May 24, 2026

Migrate from @rocket.chat/sdk to @rocket.chat/ddp-client

Acceptance Criteria fulfillment

  • Replaced the legacy and deprecated @rocket.chat/sdk with the new official @rocket.chat/ddp-client package.
  • Refactored EmbeddedChatApi.ts to initialize DDPSDK.create(host) and establish standard DDP WebSocket sessions.
  • Migrated all REST calls from raw SDK wrappers to the modernized, type-safe sdk.rest.get and sdk.rest.post helper methods.
  • Normalised all API endpoints to clean paths
  • Implemented _syncRestCredentials() to synchronize session tokens via sdk.rest.setCredentials on mount and re-authentications.
  • Eliminated legacy DDP method .call(...) invocations, replacing them with modern, standard REST endpoints.
  • Resolves consoleStructured data cloning crashes (DOMException) on caught responses by preventing direct raw Response logs.

Known Issue (Working on it): Attachment uploads and previews are successfully sent/uploaded, but their browser media previews yield 403 Forbidden because raw GET asset requests to /file-upload/... do not carry WebSocket auth headers. I am actively working on a secure solution in a separate, dedicated PR.

Fixes # (issue)

Video/Screenshots

PR Test Details

Note: The PR will be ready for live testing at https://rocketchat.github.io/EmbeddedChat/pulls/pr-1308 after approval. Contributors are requested to replace <pr_number> with the actual PR number.

@Spiral-Memory Spiral-Memory marked this pull request as draft May 24, 2026 08:26
@@ -0,0 +1,17 @@
diff --git a/lib/index.mjs b/lib/index.mjs
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the patch file.

Comment thread package.json
Comment thread packages/api/src/EmbeddedChatApi.ts Outdated
"X-User-Id": userId,
},
method: "POST",
await this._syncRestCredentials();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to sync again ?

Comment thread packages/api/src/EmbeddedChatApi.ts Outdated
},
method: "POST",
await this._syncRestCredentials();
return await this.sdk.rest.post("/v1/users.update", {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you already defined restRequest, why use sdk.rest.post here ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See other similar problems, and make sure to use DRY

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, fixing all the _syncRestCredentials() + sdk.rest.get/post() occurrences now to go through _restRequest()

Comment thread packages/api/src/EmbeddedChatApi.ts Outdated
);
return await response.json();
} catch (err) {
await this._syncRestCredentials();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we syncing everytime, can't we define it as global state and unless something related to user changes, we shouldn't sync everytime. If i am misunderstanding something , let me know

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are doing it pre-request rather than caching because the auth token can be refreshed mid-session(token rotation). this is the same pattern rc's own sdk clients use. plus it just reads auth.getCurrentUser() (local async store lookup) and calls setCredentials()

Copy link
Copy Markdown
Collaborator

@Spiral-Memory Spiral-Memory May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we try caching approach and only run a pre-request if the cache fails? I might be mistaken, so feel free to verify if this is feasible.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(local async store lookup) -> if this is local async store lookup, how is it always updated, who updates it mid session ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(local async store lookup) -> if this is local async store lookup, how is it always updated, who updates it mid session ?

this.currentUser is an in-memory object on the RocketChatAuth class instance, not localStorage. It gets updated whenever:

  • loginWithPassword / loginWithResumeToken / loginWithOAuthServiceToken resolves → calls setUser() → updates this.currentUser
  • The 59-minute auto-refresh fires inside getCurrentUser() itself → calls loginWithResumeToken → updates this.currentUser

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we try caching approach and only run a pre-request if the cache fails? I might be mistaken, so feel free to verify if this is feasible.

we can do this, working to implement this

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If your sync function simply wraps the rc auth class instance that automatically refreshes when user data changes and otherwise serves from cache, then we are covered. Since the setCredentials function doesn't trigger an actual API call, there's no need to build a separate caching mechanism if the rc class is already managing it.

Comment thread packages/api/src/EmbeddedChatApi.ts Outdated
} catch (err) {
console.log(err);
await this._syncRestCredentials();
return await this.sdk.rest.get("/v1/chat.getThreadMessages", { tmid });
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment use restRequest

Comment thread packages/api/src/EmbeddedChatApi.ts Outdated
return await messages.json();
} catch (err) {
console.log(err);
await this._syncRestCredentials();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why need to sync again

Comment thread packages/api/src/EmbeddedChatApi.ts Outdated
},
method: "POST",
await this._syncRestCredentials();
return await this.sdk.rest.post("/v1/chat.sendMessage", {
Copy link
Copy Markdown
Collaborator

@Spiral-Memory Spiral-Memory May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, its repeated across many code blocks

Comment thread packages/auth/src/RocketChatAuth.ts Outdated
);
this.setUser(response.data);
this.notifyAuthListeners();
// Note: setUser → save() already calls notifyAuthListeners().
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, please remove comments

Comment thread packages/react/src/hooks/useRCAuth.js Outdated
setUserAvatarUrl(res.me.avatarUrl);
setAuthenticatedUserUsername(res.me.username);
setIsUserAuthenticated(true);
// Do NOT call setIsUserAuthenticated(true) here.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove comments

setAuthenticatedUserId(me._id);
setAuthenticatedName(me.name);
setAuthenticatedUserRoles(me.roles);
// currentUser shape differs by login method:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove comments

@Spiral-Memory
Copy link
Copy Markdown
Collaborator

Spiral-Memory commented May 30, 2026

Hello @Aryan-Verma-999, please resolve the comments and mark the PR as ready once everything has been thoroughly tested. Also, include videos demonstrating the working system for all major cases affected by this change. Thanks.

@Aryan-Verma-999 Aryan-Verma-999 force-pushed the api-modernisation-ddp-client branch from 6745d99 to 7a7f674 Compare May 30, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants