feat: migrate to instance configuration api - #3784
Merged
Merged
Conversation
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.
🎯 Goal
Migrate the SDK onto
client.config, the instance-configuration API added in stream-chat-js#1831.Two things follow from it:
channel.serverConfig?.read_eventsanswers only the server's half, so UI gated on it offers features the client has already disabled.client.configcan express are removed rather than kept as a second way in.🛠 Implementation details
Resolved config replaces raw server flags
useMarkReadgetConfig()?.read_eventschannel.config.readEvents.enabledChannelMessagePreviewDeliveryStatususeStateStoreThreadMessagePreviewDeliveryStatususeStateStoreChannelpoll gategetConfig()?.pollsmessageComposer.config.polls.enabledChannelcommandsgetConfig()?.commands?.lengthchannel.config.availableCommandsAutoCompleteInputgetConfig()?.max_message_lengthcomposer.config.text.maxLengthOnSend(server-capped)usePaginatedChannelspaginator.config.x = ypaginator.updateConfig({ x })paginator.configisReadonlynow — direct assignment is a compile error, and nested writes throw because defaults are deep-frozen.Props removed
<Channel doMarkReadRequest>client.config.set({ channel: { requestHandlers: { markReadRequest } } })<Channel doUpdateMessageRequest>…{ requestHandlers: { updateMessageRequest } }doFileUploadRequestclient.config.set({ messageComposer: { attachments: { doUploadRequest } } })<Channel stateUpdateThrottleInterval>…{ channel: { messagePaginator: { stateThrottleMs } } }<Channel newMessageStateUpdateThrottleInterval>The two throttle props had one reference each in the whole SDK — their own type declaration. Nothing read them. Deleted rather than left inert.
doSendMessageRequeststays (for now). The SDK occupiesrequestHandlers.sendMessageRequestunconditionally to runuploadPendingAttachmentsinside the send pipeline (after the optimistic ingest, before the POST), so it has to wrap an integrator handler rather than be replaced by it.TODOinuseChannelRequestHandlers— it can be deleted once async uploads move to the LLC, or if the LLC exposes anext-shaped handler slot. Since we'll be moving the async uploads feature to the LLC most likely I decided it was best to wait for this and then we can probably get rid of the hook for good.Removing
doFileUploadRequestalso fixed a latent bug: the image-compression branch inChannel.tsxskipped compression only when the prop was set, so adoUploadRequestregistered throughclient.configstill got compressed. It now reads resolved config.useChannelRequestHandlers: two correctness fixesRe-apply on re-derivation.
Channel.initializeConfigreplacesrequestHandlersfrom the declarative tree, and runs on every change tochannel,messagePaginatorormessageOperations(the latter two arealsoWatch). Our write goes throughconfigState.partialNext, which is not one of those layers — so anyclient.config.set()on those keys dropped our send handler, and with it the attachment-upload step, silently. AconfigState.subscribere-apply guards it; the handler's identity is the guard, so there is no write loop.Stopped deleting slots we don't own. The hook used to
deletemarkReadRequest/updateMessageRequestbefore re-registering. Once a handler arrives declaratively the LLC resolves it ontoconfigState, and thatdeleteremoved it — the LLC then fell back toctx.defaults.*, an unmocked request that hangs rather than errors. Now onlysendMessageRequest/retrySendMessageRequestare touched.Other
channel.configStateis a prototype getter now, so{ ...channel }no longer carries it. Guarded in the hook.initiateClientWithChannelswritesclient.channelServerConfigsStoreinstead ofjest.spyOn(channel, 'getConfig')—serverConfigis a getter, and going through the store also drives the channel's own derivation, sochannel.configis correct too.mock-builders/event/utils.ts—toChannelResponse().Channelwas structurally assignable toPartial<ChannelResponse>by accident; it isn't now thatchannel.configmeans something different.draftsmoved toclient.config.set()at the client-creation site; the setup function keeps only middleware and usesconfig.setSetupFunctioninstead of the deprecatedsetMessageComposerSetupFunction. DroppedlinkPreviews: { enabled: true }— that is the v10 default.ai-docs/ai-migration-v9-to-v10.md: new§13.1covering the whole API (registration site, request handlers, setup functions, resolved-vs-raw table, caveats), plus 9 quick-reference rows and corrections to§5,§13,§16.1,§17.3.§16.1was telling people to re-setmessagePaginator.pageSizeafter mount, which is an imperative patch that gets dropped on the next derivation.Behaviour changes without a compile error
linkPreviews.enableddefaults totrue(LLC change). Wasfalse, andLinkPreviewsManager.enabledused to ANDurl_enrichmentitself; that gate moved into resolved config. Link previews now appear wherever enrichment is enabled server-side.attachmentManager.isUploadEnabledis nowconfig.enabled && hasAvailableUploadSlots && (!usesStreamStorage || hasUploadPermission), with the channel type'suploadsflag ANDed intoconfig.enabled. A customdoUploadRequestno longer waives theupload-filecapability — integrators uploading outside Stream needattachments: { customCdn: true }.pollCreationEnabledwasfalseuntil the channel query landed (raw flag,undefined-> falsy). It is nowtrueoptimistically and narrows tofalseif the server says no, becausepolls.enableddefaults totruemeaning "no opinion, let the server decide".🎨 UI Changes
No visual changes. Three behavioural ones are listed above — link previews appearing by default is the visible one.
🧪 Testing
☑️ Checklist
developbranch — targetsV10