Skip to content

chat-client: curate public models - hide generated schemas & conversation concept, document public API#894

Open
vicancy wants to merge 6 commits into
Azure:mainfrom
vicancy:chat-client-curate-public-models
Open

chat-client: curate public models - hide generated schemas & conversation concept, document public API#894
vicancy wants to merge 6 commits into
Azure:mainfrom
vicancy:chat-client-curate-public-models

Conversation

@vicancy

@vicancy vicancy commented Jun 9, 2026

Copy link
Copy Markdown
Member

What

Follow-up to #892 that finishes curating the chat client's public API surface.

  • Hide generated OpenAPI internals. Public types now live in a hand-written src/models.ts; index.ts no longer exports the generated components/Schemas aggregates (these dragged ~50 internal schema types plus never-typed members into the public API). The generated API report shrinks by ~280 lines.
  • Hide the conversation concept. RoomInfo.defaultConversationId and UserProfile.conversationIds are removed from the public surface. Internal code still uses them via aliased wire types (WireRoomInfo, WireUserProfile, WireRoomInfoWithMembers).
  • Drift guard. src/modelGuards.ts is a type-only compile-time check that fails the build if a field the public models expose diverges from the generated wire schema, while still allowing intentional omission of internal-only fields (one-directional: wire must satisfy the model).
  • Document the public API. Added TSDoc to every previously-undocumented public member (the ChatClient/ChatError classes, connection, getUserProfile, sendToRoom, getRoomDetail, userId, the event-argument fields, and the on/off/static start overloads). The API report now has zero (undocumented) markers.

Verification

  • npm run build, tsc --noEmit, npm run extract-api (no ae-forgotten-export, 0 undocumented members) ✅
  • Lifecycle unit tests 8/8
  • Drift guard proven non-vacuous (a probe change failed the build, then reverted)

No runtime behavior change — this is a type-surface and documentation refactor.

vicancy and others added 6 commits June 9, 2026 16:19
…tion concept, document public API

Stops the auto-generated OpenAPI aggregates from leaking into the public
API and hides the internal "conversation" concept, then documents every
remaining public member. The generated API report shrinks by ~280 lines.

- Add src/models.ts: hand-curated, standalone public domain types
  (MessageInfo, RoomInfo, RoomInfoWithMembers, UserProfile). index.ts no
  longer re-exports the generated `components`/`Schemas` aggregates and
  has zero reference to generatedTypes.
- Add src/modelGuards.ts: a type-only, compile-time guard that fails the
  build if a field the public models expose drifts from the generated
  wire schema. One-directional (wire must satisfy the model) so
  internal-only fields can be intentionally omitted.
- Hide the conversation concept from the public surface: drop
  RoomInfo.defaultConversationId and UserProfile.conversationIds. Internal
  code keeps them via aliased wire types (WireRoomInfo, WireUserProfile,
  WireRoomInfoWithMembers); public signatures use the curated models.
  Login room hydration keeps its explicit `withMembers: false`.
- Document all previously-undocumented public APIs: the ChatClient and
  ChatError classes, `connection`, `getUserProfile`, `sendToRoom`,
  `getRoomDetail`, `userId`, the event-argument fields, and the
  on/off/static-start overloads.

Verified: build, tsc --noEmit, api-extractor (no ae-forgotten-export, no
undocumented members), and the lifecycle unit tests (8/8) all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…omInfoWithMembers -> RoomDetail

getRoomDetail() previously always returned RoomInfoWithMembers even though
`members` is only populated when called with `withMembers: true`, so the
type guaranteed a field that was usually absent. Split it into overloads
so the return type reflects the argument:

  getRoomDetail(id, { withMembers: true }) -> RoomDetail   (members populated)
  getRoomDetail(id)                          -> RoomInfo     (lightweight)

Also:
- Rename the public type RoomInfoWithMembers -> RoomDetail (future-proof:
  reserved to carry further room detail such as conversations). The
  generated wire schema name is unchanged; internal code keeps using the
  WireRoomInfoWithMembers alias.
- Rename GetRoomOptions -> GetRoomDetailOptions for method/type consistency.
- Fix the misleading "extra round-trip" note (withMembers is a
  response-shaping flag on a single call) in the options doc and README.

Verified: build, tsc --noEmit, api-extractor (no ae-forgotten-export, 0
undocumented), and the lifecycle unit tests (8/8) all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
….members optional

Drop the separate RoomInfo-returning overload of getRoomDetail in favor of
a single signature that always returns RoomDetail, and make
RoomDetail.members optional so the type stays honest whether or not members
were requested. The `withMembers` option is retained and now simply
controls whether `members` is populated (left undefined otherwise).

Verified: build, tsc --noEmit, integration test type-check, api-extractor
(0 undocumented), and the lifecycle unit tests (8/8) all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…p WebPubSubClientOptions

Encapsulate the transport so consumers no longer deal with WebPubSubClient
or its options:

- The public constructor now takes a client-access URL or
  WebPubSubClientCredential (constructor(credential: string |
  WebPubSubClientCredential)) and builds the connection internally. The
  WebPubSubClient-injecting constructor is retained only as an @internal
  test seam.
- The WebPubSubClient instance is now a private `_connection` field
  (previously the public `connection` property).
- ChatClient.start collapses to a single start(credential, options?)
  signature; the WebPubSubClientOptions and pre-built-WebPubSubClient forms
  are removed.
- testUtils and the quickstart example now construct via a credential;
  README updated (construction, static methods, properties, and the
  connection-lifecycle section).

Verified: build, tsc --noEmit, api-extractor (no ae-forgotten-export, 0
undocumented), and the lifecycle unit tests (8/8) all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ential) overloads

Per API review, narrow the public construction surface:

- One public constructor: constructor(credential: WebPubSubClientCredential).
  WebPubSubClient no longer appears anywhere in the public API. The
  WebPubSubClient-injecting form remains only as a hidden implementation
  signature (test seam), distinguished at runtime via isWebPubSubClient.
- Two static start overloads: start(clientAccessUrl: string, options?) and
  start(credential: WebPubSubClientCredential, options?). A string URL is
  wrapped into a credential internally so both funnel through the single
  constructor.
- Update the lifecycle test injection cast and the README accordingly.

Verified: build, tsc --noEmit, api-extractor (no ae-forgotten-export, 0
undocumented), and the lifecycle unit tests (8/8) all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@xingsy97 xingsy97 force-pushed the chat-client-curate-public-models branch from 3b905e3 to 07f9496 Compare June 10, 2026 02:49

@xingsy97 xingsy97 left a comment

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.

added one commit. @vicancy please take a look.

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.

2 participants