Skip to content

feat: integrate OpenAPI generated clients#1760

Open
arnautov-anton wants to merge 26 commits into
release-v10from
feat/integrate-open-api-generated-client
Open

feat: integrate OpenAPI generated clients#1760
arnautov-anton wants to merge 26 commits into
release-v10from
feat/integrate-open-api-generated-client

Conversation

@arnautov-anton

Copy link
Copy Markdown
Contributor

No description provided.

@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch 3 times, most recently from 1d2959a to 3a85fb8 Compare June 8, 2026 15:32
@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch 3 times, most recently from 77a2d78 to 6d7cbe8 Compare June 15, 2026 09:42
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Size Change: -5.04 kB (-1.23%)

Total Size: 403 kB

📦 View Changed
Filename Size Change
dist/cjs/index.browser.js 134 kB -1.66 kB (-1.22%)
dist/cjs/index.node.js 136 kB -1.68 kB (-1.22%)
dist/esm/index.mjs 133 kB -1.69 kB (-1.25%)

compressed-size-action

@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch 3 times, most recently from 637babe to e7de829 Compare June 23, 2026 13:25
@arnautov-anton arnautov-anton changed the title feat: integrate open api generated client feat: integrate OpenAPI generated client Jun 29, 2026
if (
isFileReference(fileLike) &&
fileLike.duration &&
localAttachment.type === 'voiceRecording'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

From my personal testing, duration and waveform_data appeared only on attachments of type voiceRecording the rest seem to not have been using these properties so I clarified it here to make TS happy.

@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch from f077f72 to ffdd92c Compare July 3, 2026 10:46
Comment thread src/gen/models/index.ts
Comment on lines +7496 to +7500
export interface QueryBannedUsersPayload {
/**
* Filter conditions to apply to the query
*/
filter_conditions: Filters<{

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Filters are now part of the generated files.

Comment thread src/gen/models/index.ts
/**
* Custom data for this object
*/
custom: CustomReactionData;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

custom fields are populated with a different, JS-based script. I wasn's sure how to integrate this within the OAPI generator - I'm open to suggestions though.

Comment thread src/logger.ts
export { LogLevelEnum } from '@stream-io/logger';
export type { ConfigureLoggersOptions, LogLevel, Sink } from '@stream-io/logger';

export const chatLoggerSystem = scopedLogger.createLoggerSystem<ChatLoggerScope>();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The project now uses our logging system, no more this.logger.

Comment thread src/poll.ts
Comment on lines +49 to +53
export type PollState = Omit<PollResponse_old, 'own_votes' | 'id'> & {
lastActivityAt: Date; // todo: would be ideal to get this from the BE
maxVotedOptionIds: OptionId[];
ownVotesByOptionId: Record<OptionId, PollVote>;
ownAnswer?: PollAnswer; // each user can have only one answer
ownVotesByOptionId: Record<OptionId, PollVoteResponseData>;
ownAnswer?: PollVoteResponseData; // each user can have only one answer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@MartinCupela - I've tried porting poll-related types to the generated ones, but there were some inconsitencies and that's why PollResponse_old has been kept. We should make sure to drop it before official v10 release though.

Comment thread src/utils.ts
Comment on lines -134 to -151
export function normalizeQuerySort<T extends Record<string, AscDesc | undefined>>(
sort: T | T[],
) {
const sortFields: Array<{ direction: AscDesc; field: keyof T }> = [];
const sortArr = Array.isArray(sort) ? sort : [sort];
for (const item of sortArr) {
const entries = Object.entries(item) as [keyof T, AscDesc][];
if (entries.length > 1) {
console.warn(
"client._buildSort() - multiple fields in a single sort object detected. Object's field order is not guaranteed",
);
}
for (const [field, direction] of entries) {
sortFields.push({ field, direction });
}
}
return sortFields;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sort normalization has been dropped, we no longer accept the object version or even short array version:

{ pinned_at: -1, archived_at: 1 }
// or
[{ pinned_at: -1 }, { archived_at: 1 }]

The new version should look like this:

[{ field: "pinned_at", direction: -1 }, { field: "archived_at", direction: 1 }]

This version also allows to pass type property which allows casting of a value to the specified type before sorting.

Comment thread src/types.ts

export type SearchMessageSort = SearchMessageSortBase | Array<SearchMessageSortBase>;
export type ChannelSort = SortParamRequest[];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

All of these are the same and are fixed types without key suggestion - we should revisit this and generate this in a similar manner we generate filters.

Comment thread src/channel_state.ts
Comment on lines 208 to 275
@@ -228,48 +229,49 @@ export class ChannelState {
// If message is already formatted we can skip the tasks below
// This will be true for messages that are already present at the state -> this happens when we perform merging of message sets
// This will be also true for message previews used by some SDKs
const isMessageFormatted = messagesToAdd[i].created_at instanceof Date;
const isMessageFormatted =
typeof (messagesToAdd[i] as LocalMessage).status === 'string';
let message: ReturnType<ChannelState['formatMessage']>;
if (isMessageFormatted) {
message = messagesToAdd[i] as ReturnType<ChannelState['formatMessage']>;
} else {
message = this.formatMessage(messagesToAdd[i]);
}

if (message.user && this._channel?.cid) {
/**
* Store the reference to user for this channel, so that when we have to
* handle updates to user, we can use the reference map, to determine which
* channels need to be updated with updated user object.
*/
this._channel
.getClient()
.state.updateUserReference(message.user, this._channel.cid);
}
if (message.user && this._channel?.cid) {
/**
* Store the reference to user for this channel, so that when we have to
* handle updates to user, we can use the reference map, to determine which
* channels need to be updated with updated user object.
*/
this._channel
.getClient()
.state.updateUserReference(message.user, this._channel.cid);
}

if (
initializing &&
message.id &&
this.threads[message.id] &&
!this._channel.getClient().preventThreadCleanup
) {
// If we are initializing the state of channel (e.g., in case of connection recovery),
// then in that case we remove thread related to this message from threads object.
// This way we can ensure that we don't have any stale data in thread object
// and consumer can refetch the replies.
delete this.threads[message.id];
}
if (
initializing &&
message.id &&
this.threads[message.id] &&
!this._channel.getClient().preventThreadCleanup
) {
// If we are initializing the state of channel (e.g., in case of connection recovery),
// then in that case we remove thread related to this message from threads object.
// This way we can ensure that we don't have any stale data in thread object
// and consumer can refetch the replies.
delete this.threads[message.id];
}

const shouldSkipLastMessageAtUpdate =
this._channel.getConfig()?.skip_last_msg_update_for_system_msgs &&
message.type === 'system';
const shouldSkipLastMessageAtUpdate =
this._channel.getConfig()?.skip_last_msg_update_for_system_msgs &&
message.type === 'system';

if (
!shouldSkipLastMessageAtUpdate &&
(!this.last_message_at ||
message.created_at.getTime() > this.last_message_at.getTime())
) {
this.last_message_at = new Date(message.created_at.getTime());
}
if (
!shouldSkipLastMessageAtUpdate &&
(!this.last_message_at ||
message.created_at.getTime() > this.last_message_at.getTime())
) {
this.last_message_at = new Date(message.created_at.getTime());
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the biggest change I can think of - first, notice the bracked placement after message = this.formatMessage(messagesToAdd[i]); and second message has been considered a LocalMessage if it had created_at converted to a Date instance. Newly - message is considered local if it has been given status field which is not being delivered as part of the response. Some of the SDK code relies on this field to be present in the messages received through the WS events - I'm not sure how that worked previously, I'll mark it in the stream-chat-react for further discussion.

@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch from 807044b to 073d00d Compare July 9, 2026 08:47
@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch from 9b8598c to 6386793 Compare July 9, 2026 09:19
@arnautov-anton arnautov-anton marked this pull request as ready for review July 9, 2026 09:20
@arnautov-anton arnautov-anton reopened this Jul 9, 2026
@arnautov-anton arnautov-anton changed the base branch from master to release-v10 July 9, 2026 09:23
@arnautov-anton arnautov-anton changed the title feat: integrate OpenAPI generated client feat: integrate OpenAPI generated clients Jul 9, 2026
@arnautov-anton arnautov-anton force-pushed the feat/integrate-open-api-generated-client branch from e3be54c to f970219 Compare July 9, 2026 10:40
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.

1 participant