From a026892f46c438597c955c6ab144c362004ba3a8 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 13 Aug 2026 13:06:35 -0500 Subject: [PATCH 1/6] chore: include applying custom types in generator script --- scripts/generate-client.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh index 960c504bf..420057e19 100755 --- a/scripts/generate-client.sh +++ b/scripts/generate-client.sh @@ -8,4 +8,6 @@ rm -rf $OUTPUT_DIR ( cd $CHAT_DIR ; make openapi ; make -C projects/chat-manager build; build/chat-manager openapi generate-client --language ts --spec releases/v2/chat-clientside-api.yaml --output $OUTPUT_DIR --opt typed_filters=true) +node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts + yarn lint-fix \ No newline at end of file From 746bd7a501eacece61184757489a18435c7cf814 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 13 Aug 2026 13:17:46 -0500 Subject: [PATCH 2/6] feat: regenerate from latest generator version --- src/gen/models/index.ts | 297 ++++++++++++++--------------- src/pagination/FilterBuilder.ts | 8 +- v9-to-v10-migration-guide-other.md | 47 +++++ 3 files changed, 190 insertions(+), 162 deletions(-) diff --git a/src/gen/models/index.ts b/src/gen/models/index.ts index c9c616c58..31dfeebbb 100644 --- a/src/gen/models/index.ts +++ b/src/gen/models/index.ts @@ -1,32 +1,22 @@ -import type { - CustomAttachmentData, - CustomChannelData, - CustomEventData, - CustomMemberData, - CustomMessageData, - CustomPollData, - CustomPollOptionData, - CustomReactionData, - CustomThreadData, - CustomUserData, -} from '../../custom_types'; +import type { CustomChannelData } from '../../custom_types'; export type Filters< FilterConditions extends Record, > = QueryFilters<{ - [Property in keyof FCHelper]: FCHelper[Property]['operators'] extends string - ? - | RequireOnlyOne<{ - [Operator in FCHelper[Property]['operators']]: - | (Operator extends '$in' | '$nin' - ? Array[Property]['type']> - : Operator extends '$exists' - ? boolean - : FCHelper[Property]['type']) - | null; - }> - | FCHelper[Property]['type'] - | null - : undefined; + [Property in keyof FCHelper]: + | RequireOnlyOne<{ + [Operator in FCHelper[Property]['operators']]: Operator extends + | '$in' + | '$nin' + ? Array[Property]['type']> + : Operator extends '$exists' + ? boolean + : Operator extends '$eq' | '$ne' + ? FCHelper[Property]['type'] | null + : FCHelper[Property]['type']; + }> + | ('$eq' extends FCHelper[Property]['operators'] + ? FCHelper[Property]['type'] | null + : never); }>; export type FCHelper< @@ -61,20 +51,11 @@ export type QueryFilters = { } & QueryLogicalOperators; export type QueryLogicalOperators = { - $and?: ArrayOneOrMore>; - $nor?: ArrayOneOrMore>; - $or?: ArrayTwoOrMore>; + $and?: Array>; + $nor?: Array>; + $or?: Array>; }; -export type ArrayOneOrMore = { - 0: T; -} & Array; - -export type ArrayTwoOrMore = { - 0: T; - 1: T; -} & Array; - export type RequireOnlyOne = Omit & { [K in Keys]-?: Required> & Partial, undefined>>; @@ -119,7 +100,7 @@ export interface AIIndicatorClearEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "ai_indicator.clear" in this case @@ -150,7 +131,7 @@ export interface AIIndicatorStopEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "ai_indicator.stop" in this case @@ -191,7 +172,7 @@ export interface AIIndicatorUpdateEvent { */ message_id: string; - custom: CustomEventData; + custom: Record; /** * The type of event: "ai_indicator.update" in this case @@ -436,7 +417,7 @@ export interface AppUpdatedEvent { app: AppEventResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "app.updated" in this case @@ -585,7 +566,7 @@ export interface AppealResponse { } export interface Attachment { - custom: CustomAttachmentData; + custom: Record; asset_url?: string; @@ -1308,7 +1289,7 @@ export interface ChannelCreatedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.created" in this case @@ -1357,7 +1338,7 @@ export interface ChannelDeletedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.deleted" in this case @@ -1404,7 +1385,7 @@ export interface ChannelFrozenEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.frozen" in this case @@ -1479,7 +1460,7 @@ export interface ChannelHiddenEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.hidden" in this case @@ -1557,7 +1538,7 @@ export interface ChannelInput { created_by?: UserRequest; - custom?: CustomChannelData; + custom?: Record; } export interface ChannelInputRequest { @@ -1579,7 +1560,7 @@ export interface ChannelInputRequest { created_by?: UserRequest; - custom?: CustomChannelData; + custom?: Record; } export interface ChannelKickedEvent { @@ -1588,7 +1569,7 @@ export interface ChannelKickedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.kicked" in this case @@ -1652,7 +1633,7 @@ export interface ChannelMemberRequest { */ channel_role?: string; - custom?: CustomMemberData; + custom?: Record; user?: UserResponse; } @@ -1685,7 +1666,7 @@ export interface ChannelMemberResponse { */ updated_at: Date; - custom: CustomMemberData; + custom: Record; archived_at?: Date; @@ -1881,7 +1862,7 @@ export interface ChannelResponse { /** * Custom data for this object */ - custom: CustomChannelData; + custom: Record; /** * Whether auto translation is enabled or not @@ -2081,7 +2062,7 @@ export interface ChannelTruncatedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.truncated" in this case @@ -2132,7 +2113,7 @@ export interface ChannelUnFrozenEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.unfrozen" in this case @@ -2165,7 +2146,7 @@ export interface ChannelUpdatedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.updated" in this case @@ -2218,7 +2199,7 @@ export interface ChannelVisibleEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "channel.visible" in this case @@ -2264,7 +2245,7 @@ export interface ChatDraftPayloadResponse { text: string; - custom: CustomMessageData; + custom: Record; html?: string; @@ -2340,7 +2321,7 @@ export interface ChatMessageResponse { restricted_visibility: Array; - custom: CustomMessageData; + custom: Record; reaction_counts: Record; @@ -2502,7 +2483,7 @@ export interface ChatReactionResponse { user_id: string; - custom: CustomReactionData; + custom: Record; user: UserResponse; } @@ -2747,7 +2728,7 @@ export interface ConnectUserDetailsRequest { name?: string; - custom?: CustomUserData; + custom?: Record; privacy_settings?: PrivacySettingsResponse; } @@ -2879,7 +2860,7 @@ export interface CreatePollOptionRequest { /** * Custom data for this object */ - custom?: CustomPollOptionData; + custom?: Record; } export interface CreatePollRequest { @@ -2924,7 +2905,7 @@ export interface CreatePollRequest { /** * Custom data for this object */ - custom?: CustomPollData; + custom?: Record; } export interface CreateQueueRequest { @@ -2991,7 +2972,7 @@ export interface CustomActionRequestPayload { export interface CustomEvent { created_at: Date; - custom: CustomEventData; + custom: Record; type: string; @@ -3306,7 +3287,7 @@ export interface DraftDeletedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "draft.deleted" in this case @@ -3339,7 +3320,7 @@ export interface DraftPayloadResponse { */ text: string; - custom: CustomMessageData; + custom: Record; /** * Contains HTML markup of the message @@ -3411,7 +3392,7 @@ export interface DraftUpdatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "draft.updated" in this case @@ -3521,7 +3502,7 @@ export interface EntityCreatorResponse { teams: Array; - custom: CustomUserData; + custom: Record; avg_response_time?: number; @@ -3570,7 +3551,7 @@ export interface EventRequest { parent_id?: string; - custom?: CustomEventData; + custom?: Record; } export interface EventResponse { @@ -4208,7 +4189,7 @@ export interface FullUserResponse { teams: Array; - custom: CustomUserData; + custom: Record; avg_response_time?: number; @@ -4321,7 +4302,7 @@ export interface GetMessageResponse { export interface GetOGResponse { duration: string; - custom: CustomAttachmentData; + custom: Record; /** * URL of detected video or audio @@ -4511,7 +4492,7 @@ export interface HealthCheckEvent { created_at: Date; - custom: CustomEventData; + custom: Record; type: string; @@ -4867,7 +4848,7 @@ export interface MarkUnreadRequest { export interface MaxStreakChangedEvent { created_at: Date; - custom: CustomEventData; + custom: Record; type: string; @@ -4882,7 +4863,7 @@ export interface MemberAddedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -4936,7 +4917,7 @@ export interface MemberRemovedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -4990,7 +4971,7 @@ export interface MemberUpdatedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -5097,7 +5078,7 @@ export interface MessageDeletedEvent { message_id: string; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -5154,7 +5135,7 @@ export interface MessageDeliveredEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "message.delivered" in this case @@ -5304,7 +5285,7 @@ export interface MessageNewEvent { */ watcher_count: number; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -5442,7 +5423,7 @@ export interface MessageReadEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "message.read" in this case @@ -5580,7 +5561,7 @@ export interface MessageRequest { */ restricted_visibility?: Array; - custom?: CustomMessageData; + custom?: Record; shared_location?: SharedLocation; } @@ -5678,7 +5659,7 @@ export interface MessageResponse { */ restricted_visibility: Array; - custom: CustomMessageData; + custom: Record; /** * An object containing number of reactions of each type. Key: reaction type (string), value: number of reactions (int) @@ -5795,7 +5776,7 @@ export interface MessageUndeletedEvent { message_id: string; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -5853,7 +5834,7 @@ export interface MessageUpdatedEvent { message_id: string; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -5996,7 +5977,7 @@ export interface MessageWithChannelResponse { channel: ChannelResponse; - custom: CustomMessageData; + custom: Record; /** * An object containing number of reactions of each type. Key: reaction type (string), value: number of reactions (int) @@ -6198,7 +6179,7 @@ export interface ModerationCustomActionEvent { created_at: Date; - custom: CustomEventData; + custom: Record; review_queue_item: ReviewQueueItemResponse; @@ -6259,7 +6240,7 @@ export interface ModerationFlaggedEvent { */ object_id: string; - custom: CustomEventData; + custom: Record; type: string; @@ -6269,7 +6250,7 @@ export interface ModerationFlaggedEvent { export interface ModerationMarkReviewedEvent { created_at: Date; - custom: CustomEventData; + custom: Record; item: ReviewQueueItemResponse; @@ -6458,7 +6439,7 @@ export interface NotificationAddedToChannelEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -6504,7 +6485,7 @@ export interface NotificationChannelDeletedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "notification.channel_deleted" in this case @@ -6566,7 +6547,7 @@ export interface NotificationChannelMutesUpdatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; me: OwnUserResponse; @@ -6586,7 +6567,7 @@ export interface NotificationChannelTruncatedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "notification.channel_truncated" in this case @@ -6654,7 +6635,7 @@ export interface NotificationInviteAcceptedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -6708,7 +6689,7 @@ export interface NotificationInviteRejectedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -6762,7 +6743,7 @@ export interface NotificationInvitedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -6829,7 +6810,7 @@ export interface NotificationMarkReadEvent { */ unread_count: number; - custom: CustomEventData; + custom: Record; /** * The type of event: "notification.mark_read" in this case @@ -6902,7 +6883,7 @@ export interface NotificationMarkUnreadEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "notification.mark_unread" in this case @@ -7003,7 +6984,7 @@ export interface NotificationMutesUpdatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; me: OwnUserResponse; @@ -7030,7 +7011,7 @@ export interface NotificationNewMessageEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -7091,7 +7072,7 @@ export interface NotificationRemovedFromChannelEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; member: ChannelMemberResponse; @@ -7157,7 +7138,7 @@ export interface NotificationThreadMessageNewEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -7257,7 +7238,7 @@ export interface OwnUserResponse { teams: Array; - custom: CustomUserData; + custom: Record; avg_response_time?: number; @@ -7311,7 +7292,7 @@ export interface PendingMessageEvent { */ method: string; - custom: CustomEventData; + custom: Record; /** * The type of event: "message.pending" in this case @@ -7348,7 +7329,7 @@ export interface PollClosedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; poll: PollResponseData; @@ -7378,7 +7359,7 @@ export interface PollDeletedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; poll: PollResponseData; @@ -7405,7 +7386,7 @@ export interface PollDeletedEvent { export interface PollOptionInput { text?: string; - custom?: CustomPollOptionData; + custom?: Record; } export interface PollOptionRequest { @@ -7413,7 +7394,7 @@ export interface PollOptionRequest { text?: string; - custom?: CustomPollOptionData; + custom?: Record; } export interface PollOptionResponse { @@ -7430,7 +7411,7 @@ export interface PollOptionResponseData { text: string; - custom: CustomPollOptionData; + custom: Record; } export interface PollResponse { @@ -7473,7 +7454,7 @@ export interface PollResponseData { own_votes: Array; - custom: CustomPollData; + custom: Record; latest_votes_by_option: Record>; @@ -7492,7 +7473,7 @@ export interface PollUpdatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; poll: PollResponseData; @@ -7522,7 +7503,7 @@ export interface PollVoteCastedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; poll: PollResponseData; @@ -7554,7 +7535,7 @@ export interface PollVoteChangedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; poll: PollResponseData; @@ -7586,7 +7567,7 @@ export interface PollVoteRemovedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; poll: PollResponseData; @@ -8132,7 +8113,7 @@ export interface QueryChannelsRequest { }; custom: { - type: CustomChannelData; + type: Record; operators: | '$autocomplete' | '$contains' @@ -8497,7 +8478,7 @@ export interface QueryMembersPayload { }; custom: { - type: CustomMemberData; + type: Record; operators: | '$autocomplete' | '$contains' @@ -8905,7 +8886,7 @@ export interface QueryPollsRequest { }; custom: { - type: CustomPollData; + type: Record; operators: | '$autocomplete' | '$contains' @@ -9606,7 +9587,7 @@ export interface QueryThreadsRequest { }; custom: { - type: CustomThreadData; + type: Record; operators: | '$autocomplete' | '$contains' @@ -9699,7 +9680,7 @@ export interface QueryUsersPayload { }; custom: { - type: CustomUserData; + type: Record; operators: | '$contains' | '$eq' @@ -9889,7 +9870,7 @@ export interface ReactionDeletedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "reaction.deleted" in this case @@ -9993,7 +9974,7 @@ export interface ReactionNewEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; /** * The type of event: "reaction.new" in this case @@ -10069,7 +10050,7 @@ export interface ReactionRequest { */ updated_at?: Date; - custom?: CustomReactionData; + custom?: Record; } export interface ReactionResponse { @@ -10106,7 +10087,7 @@ export interface ReactionResponse { /** * Custom data for this object */ - custom: CustomReactionData; + custom: Record; user: UserResponse; } @@ -10121,7 +10102,7 @@ export interface ReactionUpdatedEvent { channel: ChannelResponse; - custom: CustomEventData; + custom: Record; message: MessageResponse; @@ -10215,7 +10196,7 @@ export interface ReminderCreatedEvent { */ user_id: string; - custom: CustomEventData; + custom: Record; /** * The type of event: "reminder.created" in this case @@ -10253,7 +10234,7 @@ export interface ReminderDeletedEvent { */ user_id: string; - custom: CustomEventData; + custom: Record; /** * The type of event: "reminder.deleted" in this case @@ -10291,7 +10272,7 @@ export interface ReminderNotificationEvent { */ user_id: string; - custom: CustomEventData; + custom: Record; /** * The type of event: "notification.reminder_due" in this case @@ -10346,7 +10327,7 @@ export interface ReminderUpdatedEvent { */ user_id: string; - custom: CustomEventData; + custom: Record; /** * The type of event: "reminder.updated" in this case @@ -10749,7 +10730,7 @@ export interface SearchPayload { }; custom: { - type: CustomChannelData; + type: Record; operators: | '$autocomplete' | '$contains' @@ -11034,7 +11015,7 @@ export interface SearchPayload { }; custom: { - type: CustomMessageData; + type: Record; operators: '$eq' | '$gt' | '$gte' | '$in' | '$lt' | '$lte'; }; @@ -11216,7 +11197,7 @@ export interface SearchResultMessage { restricted_visibility: Array; - custom: CustomMessageData; + custom: Record; reaction_counts: Record; @@ -11681,7 +11662,7 @@ export interface ThreadParticipant { last_read_at: Date; - custom: CustomThreadData; + custom: Record; last_thread_message_at?: Date; @@ -11752,7 +11733,7 @@ export interface ThreadResponse { /** * Custom data for this object */ - custom: CustomThreadData; + custom: Record; /** * Deleted At @@ -11827,7 +11808,7 @@ export interface ThreadStateResponse { /** * Custom data for this object */ - custom: CustomThreadData; + custom: Record; /** * Deleted At @@ -11858,7 +11839,7 @@ export interface ThreadStateResponse { export interface ThreadUpdatedEvent { created_at: Date; - custom: CustomEventData; + custom: Record; type: string; @@ -11993,7 +11974,7 @@ export interface TypingStartEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "typing.start" in this case @@ -12031,7 +12012,7 @@ export interface TypingStopEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "typing.stop" in this case @@ -12401,7 +12382,7 @@ export interface UpdatePollOptionRequest { /** * Custom data for this object */ - custom?: CustomPollOptionData; + custom?: Record; } export interface UpdatePollPartialRequest { @@ -12471,7 +12452,7 @@ export interface UpdatePollRequest { /** * Custom data for this object */ - custom?: CustomPollData; + custom?: Record; } export interface UpdateQueueRequest { @@ -12791,7 +12772,7 @@ export interface UserBannedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -12869,7 +12850,7 @@ export interface UserDeactivatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -12919,7 +12900,7 @@ export interface UserDeletedEvent { */ mark_messages_deleted: boolean; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -12957,7 +12938,7 @@ export interface UserGroupCreatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "user_group.created" in this case @@ -12977,7 +12958,7 @@ export interface UserGroupDeletedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "user_group.deleted" in this case @@ -13014,7 +12995,7 @@ export interface UserGroupMemberAddedEvent { */ members: Array; - custom: CustomEventData; + custom: Record; /** * The type of event: "user_group.member_added" in this case @@ -13039,7 +13020,7 @@ export interface UserGroupMemberRemovedEvent { */ members: Array; - custom: CustomEventData; + custom: Record; /** * The type of event: "user_group.member_removed" in this case @@ -13077,7 +13058,7 @@ export interface UserGroupUpdatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; /** * The type of event: "user_group.updated" in this case @@ -13103,7 +13084,7 @@ export interface UserMessagesDeletedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -13164,7 +13145,7 @@ export interface UserMutedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -13189,7 +13170,7 @@ export interface UserPresenceChangedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -13207,7 +13188,7 @@ export interface UserReactivatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -13244,7 +13225,7 @@ export interface UserRequest { /** * Custom user data */ - custom?: CustomUserData; + custom?: Record; privacy_settings?: PrivacySettingsResponse; } @@ -13295,7 +13276,7 @@ export interface UserResponse { /** * Custom data for this object */ - custom: CustomUserData; + custom: Record; avg_response_time?: number; @@ -13348,7 +13329,7 @@ export interface UserResponseCommonFields { teams: Array; - custom: CustomUserData; + custom: Record; avg_response_time?: number; @@ -13386,7 +13367,7 @@ export interface UserResponsePrivacyFields { teams: Array; - custom: CustomUserData; + custom: Record; avg_response_time?: number; @@ -13425,7 +13406,7 @@ export interface UserUnbannedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -13476,7 +13457,7 @@ export interface UserUpdatedEvent { */ created_at: Date; - custom: CustomEventData; + custom: Record; user: UserResponsePrivacyFields; @@ -13499,7 +13480,7 @@ export interface UserWatchingStartEvent { */ watcher_count: number; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; @@ -13537,7 +13518,7 @@ export interface UserWatchingStopEvent { */ watcher_count: number; - custom: CustomEventData; + custom: Record; user: UserResponseCommonFields; diff --git a/src/pagination/FilterBuilder.ts b/src/pagination/FilterBuilder.ts index 53182a2c9..933caa61d 100644 --- a/src/pagination/FilterBuilder.ts +++ b/src/pagination/FilterBuilder.ts @@ -1,5 +1,5 @@ import { StateStore } from '../store'; -import type { ArrayOneOrMore, ArrayTwoOrMore, QueryFilter } from '../types'; +import type { QueryFilter } from '../types'; type ElementType = T extends (infer U)[] ? U : T; @@ -12,9 +12,9 @@ export type ExtendedQueryFilter = QueryFilter & { }; export type ExtendedQueryLogicalOperators = { - $and?: ArrayOneOrMore>; - $nor?: ArrayOneOrMore>; - $or?: ArrayTwoOrMore>; + $and?: Array>; + $nor?: Array>; + $or?: Array>; }; export type ExtendedQueryFilters = { diff --git a/v9-to-v10-migration-guide-other.md b/v9-to-v10-migration-guide-other.md index 8f96c88f6..70c429150 100644 --- a/v9-to-v10-migration-guide-other.md +++ b/v9-to-v10-migration-guide-other.md @@ -242,6 +242,53 @@ Beyond the three breaking effects above, the field sets shifted to match the API The legacy building blocks (`QueryFilter`, `PrimitiveFilter`, `QueryFilters`, `RequireOnlyOne`) remain exported for callers who compose their own filter types against `itemMatchesFilter` and the paginators. +### Removed — `ArrayOneOrMore` and `ArrayTwoOrMore` + +The two non-empty-array utilities are gone from `stream-chat`. In v9 they existed only to constrain the logical operators — `$and` / `$nor` required at least one element (`ArrayOneOrMore`), `$or` at least two (`ArrayTwoOrMore`): + +```ts +// v9 — src/types.ts +export type ArrayOneOrMore = { 0: T } & Array; +export type ArrayTwoOrMore = { 0: T; 1: T } & Array; +``` + +**Why they were dropped.** That encoding is only satisfied by a value whose length TypeScript knows statically, so any array _variable_ is rejected. It probably wasn't a common use-case for the logical operators, but the helpers were generically named, and cause issues when used in other places, for example: + +```ts +declare const ids: string[]; + +// TS2322: Property '0' is missing in type 'string[]' +const a: ChannelFilters = { members: { $in: ids } }; +// same +const b: ChannelFilters = { members: { $in: [...ids] } }; +// only literals and non-empty tuples pass +const c: ChannelFilters = { members: { $in: ['u1'] } }; +``` + +No non-empty encoding avoids this: TypeScript cannot prove a `T[]` has at least one element, so the guarantee costs a hard compile error on working code. An empty array stays a runtime 400 with a clear message, which is the cheaper failure. + +**What to do.** Use a plain `Array` (or `T[]`) wherever you referenced them: + +```ts +// v9 +import type { ArrayOneOrMore, ArrayTwoOrMore } from 'stream-chat'; + +type MyLogicalOperators = { + $and?: ArrayOneOrMore>; + $nor?: ArrayOneOrMore>; + $or?: ArrayTwoOrMore>; +}; + +// v10 +type MyLogicalOperators = { + $and?: Array>; + $nor?: Array>; + $or?: Array>; +}; +``` + +This mirrors what the SDK itself now does in `ExtendedQueryLogicalOperators` (`src/pagination/FilterBuilder.ts`). The change is widening, not narrowing: everything that compiled in v9 still compiles, and the array-variable cases above now compile too. The only thing you lose is the compile error on an empty (or single-element `$or`) array, which the API rejects at runtime anyway. + --- ## State shape changes From 2a2687cb5383c7db894f174e0972eb09dcba825a Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 13 Aug 2026 13:26:02 -0500 Subject: [PATCH 3/6] chore: fix script --- scripts/generate-client.sh | 7 +- src/gen/models/index.ts | 253 +++++++++++++++++++------------------ 2 files changed, 138 insertions(+), 122 deletions(-) diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh index 420057e19..70b796fa5 100755 --- a/scripts/generate-client.sh +++ b/scripts/generate-client.sh @@ -8,6 +8,11 @@ rm -rf $OUTPUT_DIR ( cd $CHAT_DIR ; make openapi ; make -C projects/chat-manager build; build/chat-manager openapi generate-client --language ts --spec releases/v2/chat-clientside-api.yaml --output $OUTPUT_DIR --opt typed_filters=true) -node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts +# apply-custom-data-types matches `export interface` / `}` anchored to column 0, +# but the generator emits them indented — format first so it can track which +# interface each `custom` field belongs to. +yarn exec prettier --write $OUTPUT_DIR + +node ./scripts/apply-custom-data-types.mts -i $OUTPUT_DIR/models/index.ts yarn lint-fix \ No newline at end of file diff --git a/src/gen/models/index.ts b/src/gen/models/index.ts index 31dfeebbb..faf51bbec 100644 --- a/src/gen/models/index.ts +++ b/src/gen/models/index.ts @@ -1,4 +1,15 @@ -import type { CustomChannelData } from '../../custom_types'; +import type { + CustomAttachmentData, + CustomChannelData, + CustomEventData, + CustomMemberData, + CustomMessageData, + CustomPollData, + CustomPollOptionData, + CustomReactionData, + CustomThreadData, + CustomUserData, +} from '../../custom_types'; export type Filters< FilterConditions extends Record, > = QueryFilters<{ @@ -100,7 +111,7 @@ export interface AIIndicatorClearEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "ai_indicator.clear" in this case @@ -131,7 +142,7 @@ export interface AIIndicatorStopEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "ai_indicator.stop" in this case @@ -172,7 +183,7 @@ export interface AIIndicatorUpdateEvent { */ message_id: string; - custom: Record; + custom: CustomEventData; /** * The type of event: "ai_indicator.update" in this case @@ -417,7 +428,7 @@ export interface AppUpdatedEvent { app: AppEventResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "app.updated" in this case @@ -566,7 +577,7 @@ export interface AppealResponse { } export interface Attachment { - custom: Record; + custom: CustomAttachmentData; asset_url?: string; @@ -1289,7 +1300,7 @@ export interface ChannelCreatedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.created" in this case @@ -1338,7 +1349,7 @@ export interface ChannelDeletedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.deleted" in this case @@ -1385,7 +1396,7 @@ export interface ChannelFrozenEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.frozen" in this case @@ -1460,7 +1471,7 @@ export interface ChannelHiddenEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.hidden" in this case @@ -1538,7 +1549,7 @@ export interface ChannelInput { created_by?: UserRequest; - custom?: Record; + custom?: CustomChannelData; } export interface ChannelInputRequest { @@ -1560,7 +1571,7 @@ export interface ChannelInputRequest { created_by?: UserRequest; - custom?: Record; + custom?: CustomChannelData; } export interface ChannelKickedEvent { @@ -1569,7 +1580,7 @@ export interface ChannelKickedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.kicked" in this case @@ -1633,7 +1644,7 @@ export interface ChannelMemberRequest { */ channel_role?: string; - custom?: Record; + custom?: CustomMemberData; user?: UserResponse; } @@ -1666,7 +1677,7 @@ export interface ChannelMemberResponse { */ updated_at: Date; - custom: Record; + custom: CustomMemberData; archived_at?: Date; @@ -1862,7 +1873,7 @@ export interface ChannelResponse { /** * Custom data for this object */ - custom: Record; + custom: CustomChannelData; /** * Whether auto translation is enabled or not @@ -2062,7 +2073,7 @@ export interface ChannelTruncatedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.truncated" in this case @@ -2113,7 +2124,7 @@ export interface ChannelUnFrozenEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.unfrozen" in this case @@ -2146,7 +2157,7 @@ export interface ChannelUpdatedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.updated" in this case @@ -2199,7 +2210,7 @@ export interface ChannelVisibleEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "channel.visible" in this case @@ -2245,7 +2256,7 @@ export interface ChatDraftPayloadResponse { text: string; - custom: Record; + custom: CustomMessageData; html?: string; @@ -2321,7 +2332,7 @@ export interface ChatMessageResponse { restricted_visibility: Array; - custom: Record; + custom: CustomMessageData; reaction_counts: Record; @@ -2483,7 +2494,7 @@ export interface ChatReactionResponse { user_id: string; - custom: Record; + custom: CustomReactionData; user: UserResponse; } @@ -2728,7 +2739,7 @@ export interface ConnectUserDetailsRequest { name?: string; - custom?: Record; + custom?: CustomUserData; privacy_settings?: PrivacySettingsResponse; } @@ -2860,7 +2871,7 @@ export interface CreatePollOptionRequest { /** * Custom data for this object */ - custom?: Record; + custom?: CustomPollOptionData; } export interface CreatePollRequest { @@ -2905,7 +2916,7 @@ export interface CreatePollRequest { /** * Custom data for this object */ - custom?: Record; + custom?: CustomPollData; } export interface CreateQueueRequest { @@ -2972,7 +2983,7 @@ export interface CustomActionRequestPayload { export interface CustomEvent { created_at: Date; - custom: Record; + custom: CustomEventData; type: string; @@ -3287,7 +3298,7 @@ export interface DraftDeletedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "draft.deleted" in this case @@ -3320,7 +3331,7 @@ export interface DraftPayloadResponse { */ text: string; - custom: Record; + custom: CustomMessageData; /** * Contains HTML markup of the message @@ -3392,7 +3403,7 @@ export interface DraftUpdatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "draft.updated" in this case @@ -3502,7 +3513,7 @@ export interface EntityCreatorResponse { teams: Array; - custom: Record; + custom: CustomUserData; avg_response_time?: number; @@ -3551,7 +3562,7 @@ export interface EventRequest { parent_id?: string; - custom?: Record; + custom?: CustomEventData; } export interface EventResponse { @@ -4189,7 +4200,7 @@ export interface FullUserResponse { teams: Array; - custom: Record; + custom: CustomUserData; avg_response_time?: number; @@ -4302,7 +4313,7 @@ export interface GetMessageResponse { export interface GetOGResponse { duration: string; - custom: Record; + custom: CustomAttachmentData; /** * URL of detected video or audio @@ -4492,7 +4503,7 @@ export interface HealthCheckEvent { created_at: Date; - custom: Record; + custom: CustomEventData; type: string; @@ -4848,7 +4859,7 @@ export interface MarkUnreadRequest { export interface MaxStreakChangedEvent { created_at: Date; - custom: Record; + custom: CustomEventData; type: string; @@ -4863,7 +4874,7 @@ export interface MemberAddedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -4917,7 +4928,7 @@ export interface MemberRemovedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -4971,7 +4982,7 @@ export interface MemberUpdatedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -5078,7 +5089,7 @@ export interface MessageDeletedEvent { message_id: string; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -5135,7 +5146,7 @@ export interface MessageDeliveredEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "message.delivered" in this case @@ -5285,7 +5296,7 @@ export interface MessageNewEvent { */ watcher_count: number; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -5423,7 +5434,7 @@ export interface MessageReadEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "message.read" in this case @@ -5561,7 +5572,7 @@ export interface MessageRequest { */ restricted_visibility?: Array; - custom?: Record; + custom?: CustomMessageData; shared_location?: SharedLocation; } @@ -5659,7 +5670,7 @@ export interface MessageResponse { */ restricted_visibility: Array; - custom: Record; + custom: CustomMessageData; /** * An object containing number of reactions of each type. Key: reaction type (string), value: number of reactions (int) @@ -5776,7 +5787,7 @@ export interface MessageUndeletedEvent { message_id: string; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -5834,7 +5845,7 @@ export interface MessageUpdatedEvent { message_id: string; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -5977,7 +5988,7 @@ export interface MessageWithChannelResponse { channel: ChannelResponse; - custom: Record; + custom: CustomMessageData; /** * An object containing number of reactions of each type. Key: reaction type (string), value: number of reactions (int) @@ -6179,7 +6190,7 @@ export interface ModerationCustomActionEvent { created_at: Date; - custom: Record; + custom: CustomEventData; review_queue_item: ReviewQueueItemResponse; @@ -6240,7 +6251,7 @@ export interface ModerationFlaggedEvent { */ object_id: string; - custom: Record; + custom: CustomEventData; type: string; @@ -6250,7 +6261,7 @@ export interface ModerationFlaggedEvent { export interface ModerationMarkReviewedEvent { created_at: Date; - custom: Record; + custom: CustomEventData; item: ReviewQueueItemResponse; @@ -6439,7 +6450,7 @@ export interface NotificationAddedToChannelEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -6485,7 +6496,7 @@ export interface NotificationChannelDeletedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "notification.channel_deleted" in this case @@ -6547,7 +6558,7 @@ export interface NotificationChannelMutesUpdatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; me: OwnUserResponse; @@ -6567,7 +6578,7 @@ export interface NotificationChannelTruncatedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "notification.channel_truncated" in this case @@ -6635,7 +6646,7 @@ export interface NotificationInviteAcceptedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -6689,7 +6700,7 @@ export interface NotificationInviteRejectedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -6743,7 +6754,7 @@ export interface NotificationInvitedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -6810,7 +6821,7 @@ export interface NotificationMarkReadEvent { */ unread_count: number; - custom: Record; + custom: CustomEventData; /** * The type of event: "notification.mark_read" in this case @@ -6883,7 +6894,7 @@ export interface NotificationMarkUnreadEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "notification.mark_unread" in this case @@ -6984,7 +6995,7 @@ export interface NotificationMutesUpdatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; me: OwnUserResponse; @@ -7011,7 +7022,7 @@ export interface NotificationNewMessageEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -7072,7 +7083,7 @@ export interface NotificationRemovedFromChannelEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; member: ChannelMemberResponse; @@ -7138,7 +7149,7 @@ export interface NotificationThreadMessageNewEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -7238,7 +7249,7 @@ export interface OwnUserResponse { teams: Array; - custom: Record; + custom: CustomUserData; avg_response_time?: number; @@ -7292,7 +7303,7 @@ export interface PendingMessageEvent { */ method: string; - custom: Record; + custom: CustomEventData; /** * The type of event: "message.pending" in this case @@ -7329,7 +7340,7 @@ export interface PollClosedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; poll: PollResponseData; @@ -7359,7 +7370,7 @@ export interface PollDeletedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; poll: PollResponseData; @@ -7386,7 +7397,7 @@ export interface PollDeletedEvent { export interface PollOptionInput { text?: string; - custom?: Record; + custom?: CustomPollOptionData; } export interface PollOptionRequest { @@ -7394,7 +7405,7 @@ export interface PollOptionRequest { text?: string; - custom?: Record; + custom?: CustomPollOptionData; } export interface PollOptionResponse { @@ -7411,7 +7422,7 @@ export interface PollOptionResponseData { text: string; - custom: Record; + custom: CustomPollOptionData; } export interface PollResponse { @@ -7454,7 +7465,7 @@ export interface PollResponseData { own_votes: Array; - custom: Record; + custom: CustomPollData; latest_votes_by_option: Record>; @@ -7473,7 +7484,7 @@ export interface PollUpdatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; poll: PollResponseData; @@ -7503,7 +7514,7 @@ export interface PollVoteCastedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; poll: PollResponseData; @@ -7535,7 +7546,7 @@ export interface PollVoteChangedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; poll: PollResponseData; @@ -7567,7 +7578,7 @@ export interface PollVoteRemovedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; poll: PollResponseData; @@ -8113,7 +8124,7 @@ export interface QueryChannelsRequest { }; custom: { - type: Record; + type: CustomChannelData; operators: | '$autocomplete' | '$contains' @@ -8478,7 +8489,7 @@ export interface QueryMembersPayload { }; custom: { - type: Record; + type: CustomMemberData; operators: | '$autocomplete' | '$contains' @@ -8886,7 +8897,7 @@ export interface QueryPollsRequest { }; custom: { - type: Record; + type: CustomPollData; operators: | '$autocomplete' | '$contains' @@ -9587,7 +9598,7 @@ export interface QueryThreadsRequest { }; custom: { - type: Record; + type: CustomThreadData; operators: | '$autocomplete' | '$contains' @@ -9680,7 +9691,7 @@ export interface QueryUsersPayload { }; custom: { - type: Record; + type: CustomUserData; operators: | '$contains' | '$eq' @@ -9870,7 +9881,7 @@ export interface ReactionDeletedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "reaction.deleted" in this case @@ -9974,7 +9985,7 @@ export interface ReactionNewEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; /** * The type of event: "reaction.new" in this case @@ -10050,7 +10061,7 @@ export interface ReactionRequest { */ updated_at?: Date; - custom?: Record; + custom?: CustomReactionData; } export interface ReactionResponse { @@ -10087,7 +10098,7 @@ export interface ReactionResponse { /** * Custom data for this object */ - custom: Record; + custom: CustomReactionData; user: UserResponse; } @@ -10102,7 +10113,7 @@ export interface ReactionUpdatedEvent { channel: ChannelResponse; - custom: Record; + custom: CustomEventData; message: MessageResponse; @@ -10196,7 +10207,7 @@ export interface ReminderCreatedEvent { */ user_id: string; - custom: Record; + custom: CustomEventData; /** * The type of event: "reminder.created" in this case @@ -10234,7 +10245,7 @@ export interface ReminderDeletedEvent { */ user_id: string; - custom: Record; + custom: CustomEventData; /** * The type of event: "reminder.deleted" in this case @@ -10272,7 +10283,7 @@ export interface ReminderNotificationEvent { */ user_id: string; - custom: Record; + custom: CustomEventData; /** * The type of event: "notification.reminder_due" in this case @@ -10327,7 +10338,7 @@ export interface ReminderUpdatedEvent { */ user_id: string; - custom: Record; + custom: CustomEventData; /** * The type of event: "reminder.updated" in this case @@ -10730,7 +10741,7 @@ export interface SearchPayload { }; custom: { - type: Record; + type: CustomChannelData; operators: | '$autocomplete' | '$contains' @@ -11015,7 +11026,7 @@ export interface SearchPayload { }; custom: { - type: Record; + type: CustomMessageData; operators: '$eq' | '$gt' | '$gte' | '$in' | '$lt' | '$lte'; }; @@ -11197,7 +11208,7 @@ export interface SearchResultMessage { restricted_visibility: Array; - custom: Record; + custom: CustomMessageData; reaction_counts: Record; @@ -11662,7 +11673,7 @@ export interface ThreadParticipant { last_read_at: Date; - custom: Record; + custom: CustomThreadData; last_thread_message_at?: Date; @@ -11733,7 +11744,7 @@ export interface ThreadResponse { /** * Custom data for this object */ - custom: Record; + custom: CustomThreadData; /** * Deleted At @@ -11808,7 +11819,7 @@ export interface ThreadStateResponse { /** * Custom data for this object */ - custom: Record; + custom: CustomThreadData; /** * Deleted At @@ -11839,7 +11850,7 @@ export interface ThreadStateResponse { export interface ThreadUpdatedEvent { created_at: Date; - custom: Record; + custom: CustomEventData; type: string; @@ -11974,7 +11985,7 @@ export interface TypingStartEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "typing.start" in this case @@ -12012,7 +12023,7 @@ export interface TypingStopEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "typing.stop" in this case @@ -12382,7 +12393,7 @@ export interface UpdatePollOptionRequest { /** * Custom data for this object */ - custom?: Record; + custom?: CustomPollOptionData; } export interface UpdatePollPartialRequest { @@ -12452,7 +12463,7 @@ export interface UpdatePollRequest { /** * Custom data for this object */ - custom?: Record; + custom?: CustomPollData; } export interface UpdateQueueRequest { @@ -12772,7 +12783,7 @@ export interface UserBannedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -12850,7 +12861,7 @@ export interface UserDeactivatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -12900,7 +12911,7 @@ export interface UserDeletedEvent { */ mark_messages_deleted: boolean; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -12938,7 +12949,7 @@ export interface UserGroupCreatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "user_group.created" in this case @@ -12958,7 +12969,7 @@ export interface UserGroupDeletedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "user_group.deleted" in this case @@ -12995,7 +13006,7 @@ export interface UserGroupMemberAddedEvent { */ members: Array; - custom: Record; + custom: CustomEventData; /** * The type of event: "user_group.member_added" in this case @@ -13020,7 +13031,7 @@ export interface UserGroupMemberRemovedEvent { */ members: Array; - custom: Record; + custom: CustomEventData; /** * The type of event: "user_group.member_removed" in this case @@ -13058,7 +13069,7 @@ export interface UserGroupUpdatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; /** * The type of event: "user_group.updated" in this case @@ -13084,7 +13095,7 @@ export interface UserMessagesDeletedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -13145,7 +13156,7 @@ export interface UserMutedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -13170,7 +13181,7 @@ export interface UserPresenceChangedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -13188,7 +13199,7 @@ export interface UserReactivatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -13225,7 +13236,7 @@ export interface UserRequest { /** * Custom user data */ - custom?: Record; + custom?: CustomUserData; privacy_settings?: PrivacySettingsResponse; } @@ -13276,7 +13287,7 @@ export interface UserResponse { /** * Custom data for this object */ - custom: Record; + custom: CustomUserData; avg_response_time?: number; @@ -13329,7 +13340,7 @@ export interface UserResponseCommonFields { teams: Array; - custom: Record; + custom: CustomUserData; avg_response_time?: number; @@ -13367,7 +13378,7 @@ export interface UserResponsePrivacyFields { teams: Array; - custom: Record; + custom: CustomUserData; avg_response_time?: number; @@ -13406,7 +13417,7 @@ export interface UserUnbannedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -13457,7 +13468,7 @@ export interface UserUpdatedEvent { */ created_at: Date; - custom: Record; + custom: CustomEventData; user: UserResponsePrivacyFields; @@ -13480,7 +13491,7 @@ export interface UserWatchingStartEvent { */ watcher_count: number; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; @@ -13518,7 +13529,7 @@ export interface UserWatchingStopEvent { */ watcher_count: number; - custom: Record; + custom: CustomEventData; user: UserResponseCommonFields; From b6cfbfd19574e839991d177b4c76d8d96a0f3943 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 13 Aug 2026 13:55:29 -0500 Subject: [PATCH 4/6] chore: temp skill to map custom types --- .../skills/check-custom-data-mapping/SKILL.md | 165 ++++++++++++++++++ scripts/generate-client.sh | 14 +- 2 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 .claude/skills/check-custom-data-mapping/SKILL.md diff --git a/.claude/skills/check-custom-data-mapping/SKILL.md b/.claude/skills/check-custom-data-mapping/SKILL.md new file mode 100644 index 000000000..9ceb375ba --- /dev/null +++ b/.claude/skills/check-custom-data-mapping/SKILL.md @@ -0,0 +1,165 @@ +--- +name: check-custom-data-mapping +description: Audit newly generated API models for `custom` fields that need a `Custom*Data` type and update the mapping in scripts/apply-custom-data-types.mts. Run after `yarn generate-client` (or any regeneration of src/gen) and before committing the regenerated models. +--- + +# Check custom-data mapping after model generation + +The OpenAPI generator emits `custom: Record` for every model that carries +custom data. `scripts/apply-custom-data-types.mts` is a codemod that rewrites those fields +to the module-augmentable `Custom*Data` interfaces from `src/custom_types.ts`, driven by two +hand-maintained maps inside the script: + +- `CUSTOM_DATA_MAPPING` — `interfaceName → CustomXData`, for `custom` fields in an interface body. +- `FILTER_CUSTOM_MAPPING` — `` `${interfaceName}.${filterField}` → CustomXData ``, for the + `custom: { type: Record; … }` entry inside a `Filters<{ … }>` block. + +When the spec adds a model, it lands in `src/gen/models/index.ts` with no map entry, so its +`custom` field silently stays `Record` and integrators lose their augmentation on +that shape. **This skill finds those and adds the entries.** + +`channel_custom` needs no map entry — the codemod always rewrites it to `CustomChannelData`. + +## Step 0 — the shortcut: is there anything to do at all? + +**Run this first. Most runs end here.** The regenerated models are still uncommitted at this +point, so the diff answers it directly — no baseline to maintain. + +```bash +# 1. did the generated models change at all? +git diff --quiet HEAD -- src/gen/models/index.ts && echo "UNCHANGED" + +# 2. models added by this regeneration that the codemod could not map: +comm -12 \ + <(git diff -U0 HEAD -- src/gen/models/index.ts \ + | sed -n 's/^+export interface \([A-Za-z0-9_]*\).*/\1/p' | sort -u) \ + <(node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts 2>&1 >/dev/null \ + | sed -n 's/^Skipped \([A-Za-z0-9_]*\)[. ].*/\1/p' | sort -u) +``` + +**`UNCHANGED`, or no output from the second command, means there is nothing to do.** Stop +immediately: report "no new models carrying custom data — mapping unchanged" and do nothing +else. Do not read the mapping, do not open the generated file, do not run lint or types. The +regeneration already ran them. + +Names that pre-date this regeneration are deliberately invisible here — they were audited when +they arrived and left unmapped on purpose. The diff is the filter; do not re-litigate them. + +Two edge cases worth one command each: + +- **An existing model gained a `custom` field** (rather than a whole new model appearing). It + will not show up as `+export interface`, so also check + `git diff -U0 HEAD -- src/gen/models/index.ts | grep -E '^\+\s*custom\??: Record;'`. + Extra hits beyond the new interfaces mean an old model started carrying custom data — find it + with `grep -n` around the added line and treat it like a new name. +- **The regeneration was already committed**, so the diff is empty. Diff against the commit + before it instead: `git diff -U0 HEAD~1 HEAD -- src/gen/models/index.ts`. + +If names come out of this step, those — and only those — are what the rest of the skill is +about. + +## Step 1 — see the full picture (only when Step 0 printed something) + +The codemod reports every unmapped occurrence on stderr: + +```bash +node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts 2>&1 >/dev/null +``` + +It prints one line per unmapped occurrence: + +``` +Skipped .custom — no mapping +Skipped . filter custom — no mapping +``` + +Two prerequisites, or the output is meaningless: + +- **The file must already be Prettier-formatted.** The codemod anchors `export interface` and + the closing `}` to column 0; raw generator output is indented, and against it every + interface-scoped rewrite is skipped silently. `scripts/generate-client.sh` formats before + invoking the codemod. If you are unsure, run + `yarn exec prettier --write src/gen/models/index.ts` first — that one file only, since + pre-formatting the API classes leaves stray blank lines once `eslint --fix` runs over them. +- The codemod **writes in place** and is idempotent — running it here is safe and is a step + you need anyway. + +## Step 2 — decide, per unmapped name + +Feeds, Moderation, and flag surfaces (`Feeds*`, `Moderation*`, `*FlagResponse`, `FlagRequest`, +`UpsertActionConfig*`, `ActionLogResponse`, `ChannelMetadata`) stay unmapped — their `custom` is +not part of the chat client's custom-data contract. Never add mapping entries for those. + +Standing open question, unrelated to any one regeneration: `ChannelMemberPartialResponse.custom` +looks like a genuine `CustomMemberData` candidate that was never mapped. If you are already +working in this area, raise it — do not map it silently as a side effect. + +The names Step 0 printed are new and each needs a decision. Map one when +the model describes an entity the SDK exposes custom data on; pick the type by what the model +*is*, not by its name suffix: + +| Entity | Type | Existing examples | +| --------------------- | ---------------------- | ---------------------------------------------------------- | +| Attachment / OG scrape | `CustomAttachmentData` | `Attachment`, `GetOGResponse` | +| Channel | `CustomChannelData` | `ChannelInput`, `ChannelResponse` | +| Channel member | `CustomMemberData` | `ChannelMemberRequest`, `ChannelMemberResponse` | +| Message / draft | `CustomMessageData` | `MessageRequest`, `DraftPayloadResponse` | +| Reaction | `CustomReactionData` | `ReactionRequest`, `ChatReactionResponse` | +| Thread | `CustomThreadData` | `ThreadResponse`, `ThreadParticipant` | +| User | `CustomUserData` | `UserRequest`, `OwnUserResponse`, `EntityCreatorResponse` | +| Poll | `CustomPollData` | `CreatePollRequest`, `PollResponseData` | +| Poll option | `CustomPollOptionData` | `PollOptionRequest`, `PollOptionResponseData` | +| WS event | `CustomEventData` | every `*Event` interface, plus `CustomEvent`/`EventRequest` | + +Rules of thumb: + +- **Every new `*Event` interface gets `CustomEventData`.** That block is exhaustive by + construction — a missing event is always a bug, never a decision. +- Request/response pairs for the same entity both get the same type + (`XRequest` and `XResponse` are mapped together). +- If a model genuinely needs a custom-data type that does not exist in `src/custom_types.ts`, + **stop and report it — do not invent one.** Adding a `Custom*Data` interface is a public API + change (it is module-augmented by integrators and re-exported from `src/index.ts`), so it + needs a human decision, not a codemod entry. +- When a new name is ambiguous, leave it unmapped and report it rather than guessing. An + unmapped field is a missing feature; a wrongly mapped one is a wrong public type. + +## Step 3 — update the mapping + +Edit `scripts/apply-custom-data-types.mts` only — never hand-edit `src/gen/models/index.ts`, +the codemod is its only writer. + +- `CUSTOM_DATA_MAPPING` is grouped by `// CustomXData` comment blocks, alphabetical within each + block. Insert into the right group in the right position. +- `FILTER_CUSTOM_MAPPING` is a flat, alphabetically sorted map keyed by + `'Interface.fieldName'`. Its keys are compound because one interface can carry several filter + blocks (`SearchPayload.filter_conditions` vs `SearchPayload.message_filter_conditions`). + +Names you decide **not** to map need no bookkeeping — the next regeneration's diff will not +list them again, because they will no longer be new. + +## Step 4 — apply and verify + +```bash +node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts +yarn lint-fix +yarn types +``` + +The codemod's summary line (`Rewrote N custom + N channel_custom + N filter custom fields`) +should account for every entry you added. `yarn types` must pass — a failure here usually means +the chosen `Custom*Data` type conflicts with how the model is consumed in `src/`. + +## Step 5 — report + +State plainly: + +1. **Added** — each new map entry, as `Interface → CustomXData`. +2. **Deferred** — new unmapped names you chose not to map, each with a one-line reason + (out-of-scope surface, ambiguous, or would need a new `Custom*Data` type). Anything needing a + new type in `src/custom_types.ts` goes here, called out as needing a human decision. +3. **Unchanged** — if Step 0 printed nothing, this is the whole report: one line, no mapping + touched, no commands run beyond Step 0. + +If you added entries, mention that `src/gen/models/index.ts` changed as a result and should be +committed alongside the script. diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh index 70b796fa5..d12b21655 100755 --- a/scripts/generate-client.sh +++ b/scripts/generate-client.sh @@ -11,8 +11,18 @@ rm -rf $OUTPUT_DIR # apply-custom-data-types matches `export interface` / `}` anchored to column 0, # but the generator emits them indented — format first so it can track which # interface each `custom` field belongs to. -yarn exec prettier --write $OUTPUT_DIR +yarn exec prettier --write $OUTPUT_DIR/models/index.ts node ./scripts/apply-custom-data-types.mts -i $OUTPUT_DIR/models/index.ts -yarn lint-fix \ No newline at end of file +yarn lint-fix + +# TODO: temp solution until we figure out how to treat custom data +# New models can carry a `custom` field with no entry in the codemod's mapping, in +# which case they stay `Record`. Let Claude audit the diff and add the +# missing entries; see .claude/skills/check-custom-data-mapping/SKILL.md. +if command -v claude >/dev/null 2>&1; then + claude -p "/check-custom-data-mapping" --permission-mode acceptEdits +else + echo "claude CLI not found — run 'claude -p \"/check-custom-data-mapping\"' before committing." >&2 +fi \ No newline at end of file From 89b2d5706a9461c5831385eb0cc3877c3ed1e958 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 13 Aug 2026 13:59:46 -0500 Subject: [PATCH 5/6] fix: add missing type for ChannelMemberPartialResponse --- .claude/skills/check-custom-data-mapping/SKILL.md | 14 ++++++++------ scripts/apply-custom-data-types.mts | 2 ++ src/gen/models/index.ts | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.claude/skills/check-custom-data-mapping/SKILL.md b/.claude/skills/check-custom-data-mapping/SKILL.md index 9ceb375ba..b7746848e 100644 --- a/.claude/skills/check-custom-data-mapping/SKILL.md +++ b/.claude/skills/check-custom-data-mapping/SKILL.md @@ -87,12 +87,14 @@ Two prerequisites, or the output is meaningless: ## Step 2 — decide, per unmapped name Feeds, Moderation, and flag surfaces (`Feeds*`, `Moderation*`, `*FlagResponse`, `FlagRequest`, -`UpsertActionConfig*`, `ActionLogResponse`, `ChannelMetadata`) stay unmapped — their `custom` is -not part of the chat client's custom-data contract. Never add mapping entries for those. - -Standing open question, unrelated to any one regeneration: `ChannelMemberPartialResponse.custom` -looks like a genuine `CustomMemberData` candidate that was never mapped. If you are already -working in this area, raise it — do not map it silently as a side effect. +`UpsertActionConfig*`, `ActionLogResponse`) stay unmapped — their `custom` is not part of the +chat client's custom-data contract. Never add mapping entries for those. + +Judge by the fields, not the name. `ChannelMetadata` reads like an internal shape but carries +`cid` / `member_count` / `last_message_at`, so its `custom` is channel custom data and it is +mapped; `ModerationCallResponse` carries call fields, so its `custom` would need a call-scoped +type that does not exist and it stays unmapped. When a name is unfamiliar, open the interface +and look at what sits next to `custom`. The names Step 0 printed are new and each needs a decision. Map one when the model describes an entity the SDK exposes custom data on; pick the type by what the model diff --git a/scripts/apply-custom-data-types.mts b/scripts/apply-custom-data-types.mts index 71c6491e9..011426827 100644 --- a/scripts/apply-custom-data-types.mts +++ b/scripts/apply-custom-data-types.mts @@ -28,9 +28,11 @@ const CUSTOM_DATA_MAPPING: Record = { // CustomChannelData ChannelInput: 'CustomChannelData', ChannelInputRequest: 'CustomChannelData', + ChannelMetadata: 'CustomChannelData', ChannelResponse: 'CustomChannelData', // CustomMemberData + ChannelMemberPartialResponse: 'CustomMemberData', ChannelMemberRequest: 'CustomMemberData', ChannelMemberResponse: 'CustomMemberData', diff --git a/src/gen/models/index.ts b/src/gen/models/index.ts index faf51bbec..58301885c 100644 --- a/src/gen/models/index.ts +++ b/src/gen/models/index.ts @@ -1633,7 +1633,7 @@ export interface ChannelMemberPartialResponse { /** * Channel-member custom fields projected via `member_custom_include` */ - custom?: Record; + custom?: CustomMemberData; } export interface ChannelMemberRequest { @@ -1747,7 +1747,7 @@ export interface ChannelMetadata { type: string; - custom: Record; + custom: CustomChannelData; last_message_at?: Date; From 79269dd0b714b00b1beaf253ce050d1c5aa61e6b Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 13 Aug 2026 14:04:23 -0500 Subject: [PATCH 6/6] fix: remove the skill, it is slow --- .../skills/check-custom-data-mapping/SKILL.md | 167 ------------------ scripts/generate-client.sh | 12 +- 2 files changed, 1 insertion(+), 178 deletions(-) delete mode 100644 .claude/skills/check-custom-data-mapping/SKILL.md diff --git a/.claude/skills/check-custom-data-mapping/SKILL.md b/.claude/skills/check-custom-data-mapping/SKILL.md deleted file mode 100644 index b7746848e..000000000 --- a/.claude/skills/check-custom-data-mapping/SKILL.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -name: check-custom-data-mapping -description: Audit newly generated API models for `custom` fields that need a `Custom*Data` type and update the mapping in scripts/apply-custom-data-types.mts. Run after `yarn generate-client` (or any regeneration of src/gen) and before committing the regenerated models. ---- - -# Check custom-data mapping after model generation - -The OpenAPI generator emits `custom: Record` for every model that carries -custom data. `scripts/apply-custom-data-types.mts` is a codemod that rewrites those fields -to the module-augmentable `Custom*Data` interfaces from `src/custom_types.ts`, driven by two -hand-maintained maps inside the script: - -- `CUSTOM_DATA_MAPPING` — `interfaceName → CustomXData`, for `custom` fields in an interface body. -- `FILTER_CUSTOM_MAPPING` — `` `${interfaceName}.${filterField}` → CustomXData ``, for the - `custom: { type: Record; … }` entry inside a `Filters<{ … }>` block. - -When the spec adds a model, it lands in `src/gen/models/index.ts` with no map entry, so its -`custom` field silently stays `Record` and integrators lose their augmentation on -that shape. **This skill finds those and adds the entries.** - -`channel_custom` needs no map entry — the codemod always rewrites it to `CustomChannelData`. - -## Step 0 — the shortcut: is there anything to do at all? - -**Run this first. Most runs end here.** The regenerated models are still uncommitted at this -point, so the diff answers it directly — no baseline to maintain. - -```bash -# 1. did the generated models change at all? -git diff --quiet HEAD -- src/gen/models/index.ts && echo "UNCHANGED" - -# 2. models added by this regeneration that the codemod could not map: -comm -12 \ - <(git diff -U0 HEAD -- src/gen/models/index.ts \ - | sed -n 's/^+export interface \([A-Za-z0-9_]*\).*/\1/p' | sort -u) \ - <(node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts 2>&1 >/dev/null \ - | sed -n 's/^Skipped \([A-Za-z0-9_]*\)[. ].*/\1/p' | sort -u) -``` - -**`UNCHANGED`, or no output from the second command, means there is nothing to do.** Stop -immediately: report "no new models carrying custom data — mapping unchanged" and do nothing -else. Do not read the mapping, do not open the generated file, do not run lint or types. The -regeneration already ran them. - -Names that pre-date this regeneration are deliberately invisible here — they were audited when -they arrived and left unmapped on purpose. The diff is the filter; do not re-litigate them. - -Two edge cases worth one command each: - -- **An existing model gained a `custom` field** (rather than a whole new model appearing). It - will not show up as `+export interface`, so also check - `git diff -U0 HEAD -- src/gen/models/index.ts | grep -E '^\+\s*custom\??: Record;'`. - Extra hits beyond the new interfaces mean an old model started carrying custom data — find it - with `grep -n` around the added line and treat it like a new name. -- **The regeneration was already committed**, so the diff is empty. Diff against the commit - before it instead: `git diff -U0 HEAD~1 HEAD -- src/gen/models/index.ts`. - -If names come out of this step, those — and only those — are what the rest of the skill is -about. - -## Step 1 — see the full picture (only when Step 0 printed something) - -The codemod reports every unmapped occurrence on stderr: - -```bash -node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts 2>&1 >/dev/null -``` - -It prints one line per unmapped occurrence: - -``` -Skipped .custom — no mapping -Skipped . filter custom — no mapping -``` - -Two prerequisites, or the output is meaningless: - -- **The file must already be Prettier-formatted.** The codemod anchors `export interface` and - the closing `}` to column 0; raw generator output is indented, and against it every - interface-scoped rewrite is skipped silently. `scripts/generate-client.sh` formats before - invoking the codemod. If you are unsure, run - `yarn exec prettier --write src/gen/models/index.ts` first — that one file only, since - pre-formatting the API classes leaves stray blank lines once `eslint --fix` runs over them. -- The codemod **writes in place** and is idempotent — running it here is safe and is a step - you need anyway. - -## Step 2 — decide, per unmapped name - -Feeds, Moderation, and flag surfaces (`Feeds*`, `Moderation*`, `*FlagResponse`, `FlagRequest`, -`UpsertActionConfig*`, `ActionLogResponse`) stay unmapped — their `custom` is not part of the -chat client's custom-data contract. Never add mapping entries for those. - -Judge by the fields, not the name. `ChannelMetadata` reads like an internal shape but carries -`cid` / `member_count` / `last_message_at`, so its `custom` is channel custom data and it is -mapped; `ModerationCallResponse` carries call fields, so its `custom` would need a call-scoped -type that does not exist and it stays unmapped. When a name is unfamiliar, open the interface -and look at what sits next to `custom`. - -The names Step 0 printed are new and each needs a decision. Map one when -the model describes an entity the SDK exposes custom data on; pick the type by what the model -*is*, not by its name suffix: - -| Entity | Type | Existing examples | -| --------------------- | ---------------------- | ---------------------------------------------------------- | -| Attachment / OG scrape | `CustomAttachmentData` | `Attachment`, `GetOGResponse` | -| Channel | `CustomChannelData` | `ChannelInput`, `ChannelResponse` | -| Channel member | `CustomMemberData` | `ChannelMemberRequest`, `ChannelMemberResponse` | -| Message / draft | `CustomMessageData` | `MessageRequest`, `DraftPayloadResponse` | -| Reaction | `CustomReactionData` | `ReactionRequest`, `ChatReactionResponse` | -| Thread | `CustomThreadData` | `ThreadResponse`, `ThreadParticipant` | -| User | `CustomUserData` | `UserRequest`, `OwnUserResponse`, `EntityCreatorResponse` | -| Poll | `CustomPollData` | `CreatePollRequest`, `PollResponseData` | -| Poll option | `CustomPollOptionData` | `PollOptionRequest`, `PollOptionResponseData` | -| WS event | `CustomEventData` | every `*Event` interface, plus `CustomEvent`/`EventRequest` | - -Rules of thumb: - -- **Every new `*Event` interface gets `CustomEventData`.** That block is exhaustive by - construction — a missing event is always a bug, never a decision. -- Request/response pairs for the same entity both get the same type - (`XRequest` and `XResponse` are mapped together). -- If a model genuinely needs a custom-data type that does not exist in `src/custom_types.ts`, - **stop and report it — do not invent one.** Adding a `Custom*Data` interface is a public API - change (it is module-augmented by integrators and re-exported from `src/index.ts`), so it - needs a human decision, not a codemod entry. -- When a new name is ambiguous, leave it unmapped and report it rather than guessing. An - unmapped field is a missing feature; a wrongly mapped one is a wrong public type. - -## Step 3 — update the mapping - -Edit `scripts/apply-custom-data-types.mts` only — never hand-edit `src/gen/models/index.ts`, -the codemod is its only writer. - -- `CUSTOM_DATA_MAPPING` is grouped by `// CustomXData` comment blocks, alphabetical within each - block. Insert into the right group in the right position. -- `FILTER_CUSTOM_MAPPING` is a flat, alphabetically sorted map keyed by - `'Interface.fieldName'`. Its keys are compound because one interface can carry several filter - blocks (`SearchPayload.filter_conditions` vs `SearchPayload.message_filter_conditions`). - -Names you decide **not** to map need no bookkeeping — the next regeneration's diff will not -list them again, because they will no longer be new. - -## Step 4 — apply and verify - -```bash -node ./scripts/apply-custom-data-types.mts -i ./src/gen/models/index.ts -yarn lint-fix -yarn types -``` - -The codemod's summary line (`Rewrote N custom + N channel_custom + N filter custom fields`) -should account for every entry you added. `yarn types` must pass — a failure here usually means -the chosen `Custom*Data` type conflicts with how the model is consumed in `src/`. - -## Step 5 — report - -State plainly: - -1. **Added** — each new map entry, as `Interface → CustomXData`. -2. **Deferred** — new unmapped names you chose not to map, each with a one-line reason - (out-of-scope surface, ambiguous, or would need a new `Custom*Data` type). Anything needing a - new type in `src/custom_types.ts` goes here, called out as needing a human decision. -3. **Unchanged** — if Step 0 printed nothing, this is the whole report: one line, no mapping - touched, no commands run beyond Step 0. - -If you added entries, mention that `src/gen/models/index.ts` changed as a result and should be -committed alongside the script. diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh index d12b21655..494a09b05 100755 --- a/scripts/generate-client.sh +++ b/scripts/generate-client.sh @@ -15,14 +15,4 @@ yarn exec prettier --write $OUTPUT_DIR/models/index.ts node ./scripts/apply-custom-data-types.mts -i $OUTPUT_DIR/models/index.ts -yarn lint-fix - -# TODO: temp solution until we figure out how to treat custom data -# New models can carry a `custom` field with no entry in the codemod's mapping, in -# which case they stay `Record`. Let Claude audit the diff and add the -# missing entries; see .claude/skills/check-custom-data-mapping/SKILL.md. -if command -v claude >/dev/null 2>&1; then - claude -p "/check-custom-data-mapping" --permission-mode acceptEdits -else - echo "claude CLI not found — run 'claude -p \"/check-custom-data-mapping\"' before committing." >&2 -fi \ No newline at end of file +yarn lint-fix \ No newline at end of file