feat!: openapi related clean up - #1870
Merged
Merged
Conversation
szuperaz
force-pushed
the
small-tasks-clean-up
branch
from
September 16, 2026 13:04
0f52f42 to
af03caf
Compare
This was referenced Sep 16, 2026
szuperaz
marked this pull request as ready for review
September 16, 2026 19:40
szuperaz
requested review from
MartinCupela,
isekovanic,
oliverlaz,
santhoshvai and
vishalnarkhede
as code owners
September 16, 2026 19:40
| /** | ||
| * Sets the instance of `StableWSConnection` on the chat client. Intended purely for testing and | ||
| * should not be used in production apps. | ||
| */ |
Contributor
There was a problem hiding this comment.
I think this is in conflict with this PR: #1859 where wsConnection property is kept.
Contributor
There was a problem hiding this comment.
Or is this just about not allowing to provide own StableWSConnection implementation?
Contributor
There was a problem hiding this comment.
I will adapt my PR to yours
isekovanic
requested changes
Sep 17, 2026
MartinCupela
added a commit
that referenced
this pull request
Sep 17, 2026
…ealthy Four changes that could not be separated cleanly, because they overlap in nearly every file they touch. **The connection id gets an owner.** `client.connectionIdManager` holds it, and `ApiClient` holds any request that watches a channel or subscribes to presence until one exists. That replaces the wait this branch had at two call sites, and it covers requests those never did: stop-watching and long polling carry no watch flag and are recognised by their declared `connection_id` parameter instead. A caller's abort signal reaches the wait. Ported from #1870 so the two branches implement it the same way, with one difference — invalidation hangs off the status funnel rather than one drop path, so the deliberate close and the two error paths are covered as well. **`isHealthy` comes back.** The socket's status is a different fact from the device's network, and calling both `isOnline` forced every reader of the pair to alias one of them. `isHealthy` was the name before this branch renamed it; it keeps that name and moves to a getter on `client.wsConnection`, which is not replaced per connect. The store's timestamps follow it to `lastHealthyAt` and `lastUnhealthyAt`, so each store now reads in one vocabulary and no field name is shared between them. **Recovery cannot re-enter.** A reload that moves the socket's status called straight back into the pass that triggered it, recursing until the stack gave out. A reconnect arriving mid-pass is now deferred to the end of that pass and run once, rather than dropped, which would strand it, or stacked, which would reload every active channel twice. **`connection.recovered` loses its discriminator.** One possible value forever, which every consumer had to narrow on, and an omitted field silently skipped the thread list reload. Also: the socket's parent is required rather than optional, since construction-time injection is the one path that needed it and #1870 removes that capability; `channel.watch()` takes an abort signal like `queryChannels`; and the repository documentation is updated throughout. BREAKING CHANGE: `client.wsConnection.state` carries `isHealthy`, `lastHealthyAt` and `lastUnhealthyAt` rather than `isOnline`, `lastOnlineAt` and `lastOfflineAt`, and no longer carries `connectionId` — read `client.connectionIdManager.connectionId`. `connection.recovered` carries no payload. `new StableWSConnection()` requires its `wsConnection` parent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
isekovanic
approved these changes
Sep 17, 2026
github-actions Bot
pushed a commit
that referenced
this pull request
Sep 18, 2026
## [10.0.0-rc.12](v10.0.0-rc.11...v10.0.0-rc.12) (2026-09-18) ### ⚠ BREAKING CHANGES * `connection.changed` is removed. Connectivity is published as two state stores and nothing else: `client.networkConnection.state` for the device and `client.wsConnection.state` for this client's socket. The event was silent on `closeConnection()` and two error paths, and held a drop for five seconds; the stores are written on every transition and publish immediately. * `client.wsConnection` is now a `WSConnection` wrapper rather than the `StableWSConnection` itself, and is never null. The live socket is `client.wsConnection.connection`, replaced on every connect; read `isHealthy`, `isConnecting`, `connect()` and `disconnect()` from the wrapper. `StableWSConnection` is constructed with `{ wsConnection }` instead of `{ client }`. * `client.defaultWSTimeout` is removed, along with the `WebSocketImpl` and `wsUrlParams` client options. They move to the socket's configuration as `connectTimeoutMs`, `webSocketImpl` and `urlParams`, set with `client.config.set({ client: { wsConnection: { … } } })`. Unlike the fields and options they replace, these survive a reconnect. * `ThreadManagerState.lastConnectionDropAt` is removed. Read `client.wsConnection.state.lastUnhealthyAt`, which is written on every status transition, including the `disconnect()` path the old event was silent about. * requests that watch a channel or subscribe to presence now wait for a WebSocket connection id instead of silently returning unwatched data. The gate is in `ApiClient._doRequest`, so it covers every endpoint carrying `watch` or `presence`, plus `stopWatchingChannel` and `longPoll`. With no socket open and none being established the request rejects with "No connection id is available"; an explicit `watch: false` is still honoured, and a caller's `AbortSignal` abandons the wait. Test fixtures that fake a connected user without a live socket will now throw. * a UI that renders a "connection lost" banner must hold the drop itself. The socket's store publishes drops the moment they happen, where the old event delayed them by five seconds. `client.wsConnection.config.offlineNotificationDisplayDelayMs` (5s) is the shared value to wait for; nothing in this package acts on it. * `connection.recovered` is no longer dispatched when the socket drops while a recovery is running, because every reload in it can have failed. Work keyed off that event will correctly stop running for recoveries that recovered nothing. * openapi related clean up (#1870) ### Bug Fixes * add missing app config fields to AppSettingsAPIResponse ([#1854](#1854)) ([18bc3cf](18bc3cf)) * do not reset channel unread count on thread read ([#1835](#1835)) ([79fbf54](79fbf54)) * hanging wsPromise after closeConnection ([#1868](#1868)) ([b4e7a89](b4e7a89)), closes [#1122](#1122) [#1863](#1863) * isolate event listener errors from the dispatch loop ([#1850](#1850)) ([dc56e57](dc56e57)) * reconnect past connection timeout ([#1874](#1874)) ([2004a83](2004a83)), closes [#1760](#1760) * send the read request regardless of read receipt privacy settings ([#1853](#1853)) ([59d8f31](59d8f31)) ### Features * **client:** support custom_set and custom_unset in batch channel update ([#1856](#1856)) ([d05c2f5](d05c2f5)) * establish network connection observer services ([#1859](#1859)) ([4c46949](4c46949)) * message pruning ([696f56f](696f56f)) * message pruning ([#1875](#1875)) ([d4d2c6c](d4d2c6c)) * **MessageComposer:** add composition middleware for pending attachment uploads ([#1845](#1845)) ([68e5d69](68e5d69)) * openapi related clean up ([#1870](#1870)) ([b3fa906](b3fa906))
|
🎉 This PR is included in version 10.0.0-rc.12 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Breaking changes
QueryFilter,PrimitiveFilter,ExtendedQueryFilter,ExtendedQueryFilters,ExtendedQueryLogicalOperatorsandUnpacked- generated filter types should be used insteaddisableCache,wsConnection,enableInsights,warmUpqueryChannelswithwatch: true, the client just sent the request withwatchset tofalse. This now throws an error.watch: truerequest the request was sent with the old connection id (then most likely rejected if we had no internet connection). These requests now will wait for the reconnect to complete and only send the request once the new connection id is ready.Detailed description below:
This PR contains various openapi-related clean up tasks. Some of them are technically breaking but shouldn't really impact SDK work or QA tests.
_checkInitializeddiscrepancyI always thought that
_checkInitialized(checking if channel data is fetched already) method is called before all channel API calls. But that's not really the case; it is called in a few places, mostly from this repo's initial commit, and then never applied to newer api calls. Since it doesn't seem to be used, I've consolidated the checks to the necessary places:_checkInitializedis called when we rely on data only available after a channel is initialized; it's onlymarkReadandmarkUnreadwhere we need to know if read events are enabled. (Although the TS compiler doesn't warn about this, becauseconfigController's data is typed as always available, I think in practice it has to be async data we only get once channel data is fetched)_ checkHasIdis introduced, which checks ifchannel.idis defined. The use case is that for a distinct channel, we only get the ID after the channel data is fetched. Sincechannel.idis optional, the TS compiler warns us about these places. Technically, the same is true forchannel.cidbut since this field isn't typed as optional, the compiler can't warn us here.disableCache- was only relevant to server-side SDKswsConnection- replaced byWebSocketImplenableInsights- not documented, no chat QA tests eitherwarmUp- not documented, no chat QA tests eitherawait this.wsPromisetoApiClientWe need to call
await this.wsPromisebefore an API call that setswatch/presence/etc flags totrue. With the generated API layer this would mean to manually wrap these API calls, and wait for the promise there. Since it's easy to miss a new method when regenerating from open api spec, the logic is moved toApiClientwhere it automatically works for new endpoints too. The same method is used in stream-feeds-js already: https://github.com/GetStream/stream-feeds-js/blob/main/packages/feeds-client/src/common/ApiClient.ts#L67Two behavior changes:
queryChannelswithwatch: true, the client just sent the request withwatchset tofalse. This now throws an error.watch: truerequest the request was sent with the old connection id (then most likely rejected if we had no internet connection). These requests now will wait for the reconnect to complete and only send the request once the new connection id is ready.This step was to remove any remaining reference to JS client aceepting API secret, these were mainly docs and unit tests. But it turns out the type tests were also working using the server-side capability of the JS client. Since type tests seem unnecessary with the generated API layer, I removed type tests altogether.
These were already unused in client.
Linear tickets: