Skip to content

refactor(apps): Move from file-based mixins to real classes#633

Merged
heyitsaamir merged 2 commits into
mainfrom
heyitsaamir-super-adventure
Jun 30, 2026
Merged

refactor(apps): Move from file-based mixins to real classes#633
heyitsaamir merged 2 commits into
mainfrom
heyitsaamir-super-adventure

Conversation

@heyitsaamir

@heyitsaamir heyitsaamir commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Internal refactor of @microsoft/teams.apps that converts this: App-bound free functions into dedicated collaborator classes and "smart" context objects, mirroring the structure of the Python SDK (teams.py). No intended change to end-user behavior — this is structural cleanup.

Why the previous approach was bad

The old design implemented a lot of App's behavior as standalone free functions in app.routing.ts / app.embed.ts that were bound onto the class with this: App and assigned like on = on; message = message; func = func; tab = tab;. That had several problems:

  • No real encapsulation. Every one of these functions took the entire App as this, so they could reach into any field on App (the DI container, event manager, token manager, server, plugin array, etc.). Dependencies were implicit and untracked — you couldn't tell what a function actually needed without reading its whole body, and nothing stopped it from depending on more over time.
  • App was a god object. Plugin lifecycle/registration/injection, activity processing, oauth handling, and function/tab wiring were all smeared across App plus a grab-bag of free-function files, instead of living in cohesive units. This made the class hard to read and reason about, and changes in one concern risked touching unrelated ones.
  • Probably most importantly, it made things unnecessarily public so that they could be shared between files. So in interest of separating out logic in files, we polluted things in our public interface. Things like token-manager which should be implementation details were publicly leaked which made things like refactors extremely difficult.

Changes

  • PluginManager (app.plugins.ts) — owns the plugin registry, duplicate-name check, container double-registration, dependency/event injection, and onInit/onStart/onStop lifecycle. App delegates plugin()/getPlugin() to it. The plugins getter returns the live array so EventManager/ActivityProcessor observe plugins added after construction.
  • FunctionContext class (contexts/function.ts) — owns send() and conversation-id resolution, replacing the inline closures. getConversationIdResolver now takes api instead of app.
  • Inlined on/message/use/event/function/tab into App as proper methods; deleted app.routing.ts and app.embed.ts.
  • app.oauth.ts — removed the as TokenExchangeInvokeResponse cast in favor of a typed const body.
  • Fully encapsulated App plugin state (removed the public plugins getter; getPlugin(name) remains the read path).

Verification

  • tsc clean, eslint clean
  • 284/284 apps tests pass

Reviewer note

tokenManager visibility was narrowed from public readonly to protected readonly

Convert App-bound free functions into dedicated collaborator classes and
smart context objects, mirroring the teams.py structure:

- Add PluginManager (app.plugins.ts) owning plugin registry, DI/event
  injection, and init/start/stop lifecycle
- Add FunctionContext class (contexts/function.ts) owning send() and
  conversation-id resolution; refactor getConversationIdResolver to take
  api instead of app
- Inline on/message/use/event/function/tab into App; delete app.routing.ts
  and app.embed.ts
- Remove the as TokenExchangeInvokeResponse cast in app.oauth.ts
- Fully encapsulate App plugin state (remove public plugins getter)

Co-authored-by: Copilot <[email protected]>
@heyitsaamir heyitsaamir changed the title refactor(apps): extract collaborators and smart contexts refactor(apps): Move from file-based mixins to real classes Jun 29, 2026
@heyitsaamir
heyitsaamir marked this pull request as ready for review June 30, 2026 21:54
Copilot AI review requested due to automatic review settings June 30, 2026 21:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors @microsoft/teams.apps internals away from this: App-bound free functions into dedicated collaborator classes (PluginManager, EventManager, ActivityProcessor, OauthHandlers) and a “smart” FunctionContext, aiming to improve encapsulation and reduce App surface area without changing end-user behavior.

Changes:

  • Introduces collaborator classes for plugins/events/activity processing/oauth and rewires App to delegate to them.
  • Adds FunctionContext class and updates conversation-id resolution helper to accept ApiClient directly.
  • Removes legacy mixin-style files (app.routing.ts, app.embed.ts) and updates/expands tests accordingly.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/apps/src/utils/function-context.ts Refactors resolver helper to take ApiClient instead of App.
packages/apps/src/utils/function-context.spec.ts Updates tests to pass app.api into resolver helper.
packages/apps/src/contexts/function.ts Introduces FunctionContext class implementing function send/conversation resolution.
packages/apps/src/app.ts Inlines routing/tab/function APIs as real methods; wires new collaborators; narrows tokenManager visibility.
packages/apps/src/app.routing.ts Deleted legacy routing mixin free functions.
packages/apps/src/app.process.ts Replaces $process free function with ActivityProcessor class.
packages/apps/src/app.process.spec.ts Adds coverage for lifecycle events emitted during processing.
packages/apps/src/app.plugins.ts Replaces plugin helpers/mixins with PluginManager class and handler hooks.
packages/apps/src/app.oauth.ts Replaces oauth mixins with OauthHandlers collaborator; removes cast via typed body.
packages/apps/src/app.events.ts Replaces event mixins with EventManager collaborator.
packages/apps/src/app.embed.ts Deleted legacy embed/function/tab mixin free functions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/apps/src/utils/function-context.ts
Comment thread packages/apps/src/app.plugins.ts
@heyitsaamir
heyitsaamir added this pull request to the merge queue Jun 30, 2026
Merged via the queue into main with commit 239b4ff Jun 30, 2026
7 checks passed
@heyitsaamir
heyitsaamir deleted the heyitsaamir-super-adventure branch June 30, 2026 23:43
heyitsaamir added a commit that referenced this pull request Jul 10, 2026
Resolve conflicts from main's class refactor (PR #633):
- Add flattened methods to ConversationClient (createActivity, updateActivity, getMemberById)
- Add flattened methods to UserClient (getToken, exchangeToken, etc.)
- Keep our agentic auth additions (AuthProvider, RequestOptions, cloud)

Co-authored-by: Copilot App <[email protected]>
@lilyydu lilyydu mentioned this pull request Jul 16, 2026
lilyydu added a commit that referenced this pull request Jul 16, 2026
## 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants