feat(api): flatten client method chains to reduce call hops#634
Conversation
Promote grouped sub-client methods onto their parent clients so common calls drop from 3 hops to 2, keeping the existing chained accessors as deprecated aliases (additive and backward compatible). - users: getToken, getAadTokens, getTokenStatus, signOut, exchangeToken (users.token.* deprecated) - conversations: createActivity/updateActivity/replyToActivity/ deleteActivity/getActivityMembers + targeted variants, plus getMembers/getMemberById/getPagedMembers/deleteMember (conversations.activities(id).* and members(id).* deprecated) - reactions: moved onto conversations as addReaction/deleteReaction; client.reactions deprecated - bots: whole BotClient deprecated (no longer used) Keep the deprecated sub-client instances private (protected _token/_bots/_reactions) exposed via deprecated public accessors, so the new flattened code never consumes a deprecated member. Migrate internal apps callers to the flattened API and add tests for both the flattened methods and the deprecated aliases. Co-authored-by: Copilot <[email protected]>
heyitsaamir
left a comment
There was a problem hiding this comment.
Liking this direction!
- Make ConversationClient sub-client holders + settings private (_http/_activities/_members/_reactions/_apiClientSettings) - Deprecate legacy sub-client methods (ReactionClient, ConversationActivityClient, ConversationMemberClient) pointing to the flattened conversations.* methods - Drop the flattened deleteMember alias; member deletion stays available via the deprecated members(id).delete accessor Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR flattens several chained API client method paths into 2-hop calls (e.g., conversations.createActivity(...), users.getToken(...)) while retaining the previous chained accessors as deprecated aliases, and migrates @microsoft/teams.apps internal callers/tests to the flattened API.
Changes:
- Add flattened methods to
UserClientandConversationClient, keeping old grouped accessors as@deprecated. - Move reaction verbs into
ConversationClient(addReaction/deleteReaction) and deprecateclient.reactions+ReactionClientmethods. - Update
@microsoft/teams.appscall sites and tests to use flattened methods.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/apps/src/utils/function-context.ts | Switch member lookup to flattened conversations.getMemberById(...). |
| packages/apps/src/utils/function-context.spec.ts | Update mocks/assertions for flattened member lookup. |
| packages/apps/src/http/http-stream.ts | Use flattened conversations.createActivity/updateActivity(...) calls. |
| packages/apps/src/http/http-stream.spec.ts | Update stream tests for new flattened activity call signatures. |
| packages/apps/src/contexts/activity.ts | Replace users.token.* usage with flattened users.getToken/signOut(...). |
| packages/apps/src/contexts/activity.test.ts | Update mocks/assertions for flattened user token methods. |
| packages/apps/src/app.process.ts | Update token fetch helper to use users.getToken(...). |
| packages/apps/src/app.oauth.ts | Update OAuth flows to use users.getToken/exchangeToken(...). |
| packages/apps/src/activity-sender.ts | Flatten activity create/update targeted/non-targeted calls. |
| packages/api/src/clients/user/index.ts | Add flattened token methods on UserClient and deprecate users.token accessor. |
| packages/api/src/clients/user/index.spec.ts | Add tests for flattened UserClient methods and deprecated accessor coverage. |
| packages/api/src/clients/reaction/reaction.ts | Deprecate ReactionClient.add/delete in favor of conversations.addReaction/deleteReaction. |
| packages/api/src/clients/reaction/reaction.spec.ts | Add coverage for deprecated client.reactions accessor behavior. |
| packages/api/src/clients/index.ts | Deprecate bots and reactions accessors; switch to private backing fields. |
| packages/api/src/clients/conversation/member.ts | Deprecate member sub-client methods in favor of flattened conversation methods. |
| packages/api/src/clients/conversation/index.ts | Add flattened activity/member/reaction methods; keep grouped accessors as deprecated. |
| packages/api/src/clients/conversation/index.spec.ts | Add tests for flattened conversation methods plus deprecated chained aliases. |
| packages/api/src/clients/conversation/activity.ts | Deprecate activity sub-client methods in favor of flattened conversation methods. |
| packages/api/src/clients/bot/sign-in.spec.ts | Add coverage for deprecated client.bots.signIn accessor path. |
| packages/api/src/clients/bot/index.ts | Mark BotClient as deprecated. |
| packages/api/src/activities/message/message-reaction.ts | Update deprecation guidance to point at api.conversations.addReaction/deleteReaction. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
packages/apps/src/http/http-stream.spec.ts:223
- This mock still assumes the old
createActivity(activity)signature, butHttpStreamnow callscreateActivity(conversationId, activity). Updating the mock to accept(conversationId, activity)ensures the returned object (and any future assertions) reflect the real call contract.
client.conversations.createActivity.mockImplementation(async (_activity: any) => {
callCount++;
if (callCount === 1) {
return { _activity, id: 'activity-1' };
}
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Move the deprecation from the sub-client implementation methods (ConversationActivityClient, ConversationMemberClient, ReactionClient) onto the chained accessors consumers actually use (conversations.activities(id).*, conversations.members(id).*, client.reactions). Keeps the migration hint on every real call path while ensuring the flattened conversations.* methods no longer delegate into @deprecated members. Co-authored-by: Copilot <[email protected]>
…ream test mock signature - Mark the dual-use sub-client methods (ConversationActivityClient, ConversationMemberClient, ReactionClient) with a TODO noting they will be deprecated alongside their ConversationClient accessors, instead of @deprecated JSDoc (which struck through the flattened delegating calls). - Align the http-stream spec's createActivity mock with the flattened 2-arg signature (conversationId, activity) so it no longer binds the conversation id to the activity param. Co-authored-by: Copilot <[email protected]>
The main merge (#634, flatten client method chains) replaced the chained client.conversations.activities().create/.update API with flattened client.conversations.createActivity/updateActivity. Six stream tests still mocked the old chain, failing with 'client.conversations.activities is not a function'. Update the mocks to the flattened methods and their new signatures (conversationId is now the first argument). Co-authored-by: Copilot <[email protected]>
Port of the TODO markers from microsoft/teams.ts#634. Annotate the underlying ConversationActivityClient, ConversationMemberClient and ReactionClient methods with "TODO: Will be deprecated alongside accessor in ConversationClient", matching the TS change now that the flattened ConversationClient methods are the preferred entry points. Co-authored-by: Copilot <[email protected]>
Port of microsoft/teams.ts#634. Promotes grouped sub-client methods onto their parent clients so common calls drop from 3 hops to 2. Additive and backward compatible: the existing chained accessors remain as deprecated aliases. --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
## Release v2.0.14
Prepares the stable **2.0.14** release by merging `main` into `release`
and setting `version.json` to the stable version (removing the
`-preview.{height}` suffix).
- Previous release: `2.0.13` (published 2026-06-15)
- Only functional diff vs `main` is `version.json`:
`2.0.14-preview.{height}` → `2.0.14`
## What's in this release
### 🚀 Features
* Flatten client method chains to reduce call hops by @lilyydu in
#634
* Support resetting response streams and streaming error handling by
@lilyydu in #635
* Add `extendedMarkdown` text format value by @singhk97 in
#615
### 🐛 Fixes
* Set `replyToId` for all streaming activities by @lilyydu in
#646
* Use `artifactName` for pipelineArtifact inputs in publish pipeline by
@corinagum in #625
### ♻️ Refactors
* Move `apps` from file-based mixins to real classes by @heyitsaamir in
#633
* Split up Outbound and Inbound Activities by @heyitsaamir in
#639
* Remove `ExperimentalTeamsQuotedReplies` markers by @corinagum in
#621
### 🧪 Tests
* Add integration tests for Teams TypeScript SDK by @corinagum in
#622
### 📚 Docs & Examples
* Migrate examples to the flattened conversation API by @lilyydu in
#637
* Note npm CFS proxy for Microsoft-managed devices by @corinagum in
#638
* Update integration test runbook link to ADO wiki by @corinagum in
#624
### 🔧 Chores & Dependencies
* Bump version to 2.0.14-preview and fix pipeline release job by
@corinagum in #620
* Bump hono from 4.12.21 to 4.12.25 by @dependabot in
#623
* Bump react-router from 7.15.0 to 7.15.1 by @dependabot in
#619
* Bump vite from 6.4.2 to 6.4.3 by @dependabot in
#617
**Full Changelog**:
v2.0.13...prep-release/2.0.14
### After merge
1. Trigger the [release
pipeline](https://dev.azure.com/DomoreexpGithub/Github_Pipelines/_build?definitionId=52&_a=summary)
on `release` with **Public** publish type
2. Bump `main` → `2.0.15-preview.{height}`
3. Create the `v2.0.14` git tag + GitHub Release
Co-authored-by: Copilot <[email protected]>
Summary
Reduces the number of chained member accesses ("hops") needed to call the API by promoting grouped sub-client methods onto their parent clients. Common calls drop from 3 hops to 2. The change is additive and backward compatible — the existing chained accessors remain as
@deprecatedaliases until officially removed.Flattening
users.token.{get,getAad,getStatus,signOut,exchange}users.{getToken,getAadTokens,getTokenStatus,signOut,exchangeToken}conversations.activities(id).{create,update,reply,delete,members,createTargeted,updateTargeted,deleteTargeted}conversations.{createActivity,updateActivity,replyToActivity,deleteActivity,getActivityMembers,createTargetedActivity,updateTargetedActivity,deleteTargetedActivity}conversations.members(id).{get,getById,getPaged,delete}conversations.{getMembers,getMemberById,getPagedMembers}client.reactions.{add,delete}conversations.{addReaction,deleteReaction}teams.*andmeetings.*were already 2 hops — unchanged.Other changes
client.botsaccessor are marked@deprecated(not flattened).conversations.addReaction(conversationId, activityId, type));client.reactionskept as a deprecated alias.protected _token/_bots/_reactions) and exposed via deprecated public accessors, so the flattened code andClient.set httpnever touch a deprecated member.@microsoft/teams.appsnow uses the flattened API.Tests
UserClientandConversationClient.Verification
@microsoft/teams.api: 20 suites / 194 tests ✓, lint ✓@microsoft/teams.apps: 19 suites / 284 tests ✓Notes