From 0bb04e12ae70272554570f5fbb16295b2d89aeff Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 07:53:46 +0100 Subject: [PATCH 01/27] test: fix scheduled test --- .github/workflows/scheduled_test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/scheduled_test.yml b/.github/workflows/scheduled_test.yml index 1dd239d761..628276e3de 100644 --- a/.github/workflows/scheduled_test.yml +++ b/.github/workflows/scheduled_test.yml @@ -14,6 +14,9 @@ jobs: - uses: ./.github/actions/setup-node + - name: Build project + run: yarn build + - name: Run test env: API_KEY: ${{ secrets.TS_TEST_API_KEY }} From 142eaf4ef24a7999326ab4558a162cbe9be6a371 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 08:53:18 +0100 Subject: [PATCH 02/27] test: fix scheduled test --- test/typescript/response-generators/channel-search.js | 4 +++- test/typescript/response-generators/channel-type.js | 4 +++- test/typescript/response-generators/channel.js | 4 +++- test/typescript/response-generators/client.js | 4 +++- test/typescript/response-generators/event.js | 4 +++- test/typescript/response-generators/message.js | 4 +++- test/typescript/response-generators/moderation.js | 4 +++- test/typescript/response-generators/reaction.js | 4 +++- test/typescript/response-generators/update-users.js | 4 +++- test/typescript/utils.js | 2 +- 10 files changed, 28 insertions(+), 10 deletions(-) diff --git a/test/typescript/response-generators/channel-search.js b/test/typescript/response-generators/channel-search.js index 3b6d1eb2b8..408fe1a69c 100644 --- a/test/typescript/response-generators/channel-search.js +++ b/test/typescript/response-generators/channel-search.js @@ -1,4 +1,6 @@ -const { v4: uuid4 } = require('uuid'); +// External uuid package not available, using test UUID for test data +const uuid4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); const johnID = `john-${uuid4()}`; diff --git a/test/typescript/response-generators/channel-type.js b/test/typescript/response-generators/channel-type.js index c383421e43..c2af5e912a 100644 --- a/test/typescript/response-generators/channel-type.js +++ b/test/typescript/response-generators/channel-type.js @@ -1,4 +1,6 @@ -const { generateUUIDv4: uuidv4 } = require('../../../src/utils'); +// generateUUIDv4 is not exported from the public API, using test UUID for test data +const uuidv4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); async function createChannelType() { diff --git a/test/typescript/response-generators/channel.js b/test/typescript/response-generators/channel.js index af7c364a1c..e56a64f97b 100644 --- a/test/typescript/response-generators/channel.js +++ b/test/typescript/response-generators/channel.js @@ -1,4 +1,6 @@ -const { generateUUIDv4: uuidv4 } = require('../../../src/utils'); +// generateUUIDv4 is not exported from the public API, using test UUID for test data +const uuidv4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); const fs = require('fs'); const url = require('url'); diff --git a/test/typescript/response-generators/client.js b/test/typescript/response-generators/client.js index 1a38dab6f3..3910bf422e 100644 --- a/test/typescript/response-generators/client.js +++ b/test/typescript/response-generators/client.js @@ -1,4 +1,6 @@ -const { generateUUIDv4: uuidv4 } = require('../../../src/utils'); +// generateUUIDv4 is not exported from the public API, using test UUID for test data +const uuidv4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); async function addDevice() { diff --git a/test/typescript/response-generators/event.js b/test/typescript/response-generators/event.js index 8546c1f9f7..67b3a2f96e 100644 --- a/test/typescript/response-generators/event.js +++ b/test/typescript/response-generators/event.js @@ -1,4 +1,6 @@ -const { generateUUIDv4: uuidv4 } = require('../../../src/utils'); +// generateUUIDv4 is not exported from the public API, using test UUID for test data +const uuidv4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); const johnID = `john-${uuidv4()}`; diff --git a/test/typescript/response-generators/message.js b/test/typescript/response-generators/message.js index d811d10476..1be1cbd7bf 100644 --- a/test/typescript/response-generators/message.js +++ b/test/typescript/response-generators/message.js @@ -1,4 +1,6 @@ -const { generateUUIDv4: uuidv4 } = require('../../../src/utils'); +// generateUUIDv4 is not exported from the public API, using test UUID for test data +const uuidv4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); const johnID = `john-${uuidv4()}`; diff --git a/test/typescript/response-generators/moderation.js b/test/typescript/response-generators/moderation.js index a0163e9892..91cd46590d 100644 --- a/test/typescript/response-generators/moderation.js +++ b/test/typescript/response-generators/moderation.js @@ -1,4 +1,6 @@ -const { generateUUIDv4: uuidv4 } = require('../../../src/utils'); +// generateUUIDv4 is not exported from the public API, using test UUID for test data +const uuidv4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); const { sleep } = require('../utils'); diff --git a/test/typescript/response-generators/reaction.js b/test/typescript/response-generators/reaction.js index 536e00f8fc..b138fd1ff9 100644 --- a/test/typescript/response-generators/reaction.js +++ b/test/typescript/response-generators/reaction.js @@ -1,4 +1,6 @@ -const { v4: uuid4 } = require('uuid'); +// External uuid package not available, using test UUID for test data +const uuid4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); const johnID = `john-${uuid4()}`; diff --git a/test/typescript/response-generators/update-users.js b/test/typescript/response-generators/update-users.js index 313bc0b7de..5ee55f2691 100644 --- a/test/typescript/response-generators/update-users.js +++ b/test/typescript/response-generators/update-users.js @@ -1,4 +1,6 @@ -const { v4: uuid4 } = require('uuid'); +// External uuid package not available, using test UUID for test data +const uuid4 = () => + 'test-' + Math.random().toString(36).substring(2, 15) + '-' + Date.now(); const utils = require('../utils'); async function deactivateUser() { diff --git a/test/typescript/utils.js b/test/typescript/utils.js index fee87fdf27..3025f7e929 100644 --- a/test/typescript/utils.js +++ b/test/typescript/utils.js @@ -1,4 +1,4 @@ -const { StreamChat } = require('../../dist'); +const { StreamChat } = require('../../dist/cjs/index.node.js'); require('dotenv').config({ path: `${process.cwd()}/test/typescript/.env` }); From ba6525d38adecb65cede829a38b260aea7bbddad Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 09:11:12 +0100 Subject: [PATCH 03/27] test: use server-side client to test channel filter tag change --- test/typescript/response-generators/channel.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/typescript/response-generators/channel.js b/test/typescript/response-generators/channel.js index e56a64f97b..885645acc2 100644 --- a/test/typescript/response-generators/channel.js +++ b/test/typescript/response-generators/channel.js @@ -30,15 +30,25 @@ async function addMembers() { } async function addFilterTags() { - const channel = await utils.createTestChannelForUser(uuidv4(), johnID); - await channel.watch(); + // Use server-side client for filter tag operations (required by backend) + const serverClient = utils.getServerTestClient(); + const channelId = uuidv4(); + await utils.createUsers([johnID]); + const channel = serverClient.channel('messaging', channelId, { members: [johnID] }); + await channel.create(); return await channel.addFilterTags(['tag1', 'tag2']); } async function removeFilterTags() { - const channel = await utils.createTestChannelForUser(uuidv4(), johnID); - await channel.watch(); + // Use server-side client for filter tag operations (required by backend) + const serverClient = utils.getServerTestClient(); + const channelId = uuidv4(); + await utils.createUsers([johnID]); + const channel = serverClient.channel('messaging', channelId, { members: [johnID] }); + await channel.create(); + // Add tags first, then remove them + await channel.addFilterTags(['tag1', 'tag2']); return await channel.removeFilterTags(['tag1']); } From 7df5354acc6884bc9d10ada4f9a1e8fbfc36c015 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 09:18:29 +0100 Subject: [PATCH 04/27] test: use server-side client to test channel filter tag change --- test/typescript/response-generators/channel.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/typescript/response-generators/channel.js b/test/typescript/response-generators/channel.js index 885645acc2..9296bf4e48 100644 --- a/test/typescript/response-generators/channel.js +++ b/test/typescript/response-generators/channel.js @@ -34,7 +34,10 @@ async function addFilterTags() { const serverClient = utils.getServerTestClient(); const channelId = uuidv4(); await utils.createUsers([johnID]); - const channel = serverClient.channel('messaging', channelId, { members: [johnID] }); + const channel = serverClient.channel('messaging', channelId, { + members: [johnID], + created_by_id: johnID, // Required for server-side auth + }); await channel.create(); return await channel.addFilterTags(['tag1', 'tag2']); @@ -45,7 +48,10 @@ async function removeFilterTags() { const serverClient = utils.getServerTestClient(); const channelId = uuidv4(); await utils.createUsers([johnID]); - const channel = serverClient.channel('messaging', channelId, { members: [johnID] }); + const channel = serverClient.channel('messaging', channelId, { + members: [johnID], + created_by_id: johnID, // Required for server-side auth + }); await channel.create(); // Add tags first, then remove them await channel.addFilterTags(['tag1', 'tag2']); From df7974e64bf3ba804d2493768b58bf8690de4d7d Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 10:15:22 +0100 Subject: [PATCH 05/27] test: fix blocklist test case --- test/typescript/response-generators/moderation.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/typescript/response-generators/moderation.js b/test/typescript/response-generators/moderation.js index 91cd46590d..6958c7184d 100644 --- a/test/typescript/response-generators/moderation.js +++ b/test/typescript/response-generators/moderation.js @@ -75,16 +75,16 @@ async function deleteBlockList() { await cleanupBlockList(client, name); await cleanupBlockList(client, name2); - try { - await client.createBlockList({ name, words: ['F*!k'] }); - await client.createBlockList({ name: name2, words: ['S!*t'] }); - } catch (err) { - // in case the blocklist already exists - // do nothing - } + // Create the blocklists - if creation fails, the test should fail + await client.createBlockList({ name, words: ['F*!k'] }); + await client.createBlockList({ name: name2, words: ['S!*t'] }); + // Delete the first blocklist and return its response const returnValue = await client.deleteBlockList(name); + + // Clean up the second blocklist await client.deleteBlockList(name2); + return returnValue; } From 30272c2b29b0fe855a6b3218e3005e61c264234f Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 11:44:23 +0100 Subject: [PATCH 06/27] test: update test generator for latest generic format --- test/typescript/index.js | 274 +++++++++++++++++------------------ test/typescript/unit-test.ts | 105 +++----------- 2 files changed, 158 insertions(+), 221 deletions(-) diff --git a/test/typescript/index.js b/test/typescript/index.js index fa6d4cfbdc..10940abb86 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -10,94 +10,94 @@ const executables = [ { f: rg.acceptInvite, imports: ['Channel', 'Unpacked'], - type: "Unpacked['acceptInvite']>>", + type: "Unpacked>", }, { f: rg.addDevice, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['addDevice']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.addMembers, imports: ['Channel', 'Unpacked'], - type: "Unpacked['addMembers']>>", + type: "Unpacked>", }, { f: rg.addFilterTags, imports: ['Channel', 'Unpacked'], - type: "Unpacked['addFilterTags']>>", + type: "Unpacked>", }, { f: rg.addModerators, imports: ['Channel', 'Unpacked'], - type: "Unpacked['addModerators']>>", + type: "Unpacked>", }, { f: rg.banUsers, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['banUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.channelSearch, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['search']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, // TODO: Fix the issue "WS failed with code 5 and reason - anon auth token must have user_id claim equal to '!anon'" // { // f: rg.connect, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - // type: "Unpacked['connect']>>", + // imports: ['StreamChat', 'Unpacked'], + // type: "Unpacked>", // }, // { // f: rg.connectAnonymousUser, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - // type: "Unpacked['connectAnonymousUser']>>", + // imports: ['StreamChat', 'Unpacked'], + // type: "Unpacked>", // }, { f: rg.connectUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['connectUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.create, imports: ['Channel', 'Unpacked'], - type: "Unpacked['create']>>", + type: "Unpacked>", }, { f: rg.createBlockList, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['createBlockList']>>", + type: "Unpacked>", }, // createChannelType has a limit. So only run this when needed. // { // f: rg.createChannelType, // imports: ['StreamChat', 'Unpacked'], - // type: "Unpacked['createChannelType']>>", + // type: "Unpacked>", // }, { f: rg.createCommand, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['createCommand']>>", + type: "Unpacked>", }, { f: rg.createPermission, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['createPermission']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.deactivateUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['deactivateUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.deleteBlockList, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['deleteBlockList']>>", + type: "Unpacked>", }, { f: rg.deleteChannel, imports: ['Channel', 'Unpacked'], - type: "Unpacked['delete']>>", + type: "Unpacked>", }, // TODO: Fix the error which results from deleteChannelType api call:Add commentMore actions // `deleteChannelType failed with error: { Error: StreamChat error code 16: DeleteChannelType failed with error: "bc0b09df-2cfd-4e80-93e7-1f0091e6a435 is not a defined channel type"` @@ -105,412 +105,412 @@ const executables = [ // { // f: rg.deleteChannelType, // imports: ['StreamChat', 'Unpacked'], - // type: "Unpacked['deleteChannelType']>>", + // type: "Unpacked>", { f: rg.deleteCommand, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['deleteCommand']>>", + type: "Unpacked>", }, { f: rg.deleteFile, imports: ['Channel', 'Unpacked'], - type: "Unpacked['deleteFile']>>", + type: "Unpacked>", }, { f: rg.deleteImage, imports: ['Channel', 'Unpacked'], - type: "Unpacked['deleteImage']>>", + type: "Unpacked>", }, { f: rg.deleteMessage, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['deleteMessage']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.deletePermission, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['deletePermission']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.deleteReaction, imports: ['Channel', 'Unpacked'], - type: "Unpacked['deleteReaction']>>", + type: "Unpacked>", }, { f: rg.deleteUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['deleteUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.demoteModerators, imports: ['Channel', 'Unpacked'], - type: "Unpacked['demoteModerators']>>", + type: "Unpacked>", }, // { // f: rg.disconnect, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - // type: "Unpacked['disconnect']>>", + // imports: ['StreamChat', 'Unpacked'], + // type: "Unpacked>", // }, { f: rg.exportUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['exportUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.flagMessage, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['flagMessage']>>", + type: "Unpacked>", }, { f: rg.flagUser, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['flagUser']>>", + type: "Unpacked>", }, { f: rg.getAppSettings, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['getAppSettings']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.getBlockList, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['getBlockList']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.getChannelType, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['getChannelType']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.getCommand, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['getCommand']>>", + type: "Unpacked>", }, { f: rg.getConfig, imports: ['Channel', 'Unpacked'], - type: "Unpacked['getConfig']>>", + type: "Unpacked>", }, { f: rg.getDevices, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['getDevices']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.getMessage, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['getMessage']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.getMessagesById, imports: ['Channel', 'Unpacked'], - type: "Unpacked['getMessagesById']>>", + type: "Unpacked>", }, { f: rg.getMessageWithReply, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['getMessage']>>", + type: "Unpacked>", }, { f: rg.getPermission, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['getPermission']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.getReactions, imports: ['Channel', 'Unpacked'], - type: "Unpacked['getReactions']>>", + type: "Unpacked>", }, { f: rg.getReplies, imports: ['Channel', 'Unpacked'], - type: "Unpacked['getReplies']>>", + type: "Unpacked>", }, { f: rg.hide, imports: ['Channel', 'Unpacked'], - type: "Unpacked['hide']>>", + type: "Unpacked>", }, { f: rg.inviteMembers, imports: ['Channel', 'Unpacked'], - type: "Unpacked['inviteMembers']>>", + type: "Unpacked>", }, { f: rg.keystroke, imports: ['Channel', 'Unpacked'], - type: "Unpacked['keystroke']>>", + type: "Unpacked>", }, { f: rg.lastMessage, imports: ['Channel', 'FormatMessageResponse', 'Unpacked'], - type: "Omit, 'created_at' | 'updated_at'> & { created_at?: string; updated_at?: string } | undefined", + type: "Omit & { created_at?: string; updated_at?: string } | undefined", }, { f: rg.listBlockLists, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['listBlockLists']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.listChannelTypes, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['listChannelTypes']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.listCommands, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['listCommands']>>", + type: "Unpacked>", }, { f: rg.listPermissions, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['listPermissions']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.markAllRead, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['markAllRead']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.markRead, imports: ['Channel', 'Unpacked'], - type: "Unpacked['markRead']>>", + type: "Unpacked>", }, { f: rg.mute, imports: ['Channel', 'Unpacked'], - type: "Unpacked['mute']>>", + type: "Unpacked>", }, { f: rg.muteStatus, imports: ['Channel', 'Unpacked'], - type: "Unpacked['muteStatus']>>", + type: "Unpacked>", }, { f: rg.muteUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['muteUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.partialUpdateUser, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['partialUpdateUser']>>", + type: "Unpacked>", }, { f: rg.partialUpdateUsers, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['partialUpdateUsers']>>", + type: "Unpacked>", }, { f: rg.query, imports: ['Channel', 'Unpacked'], - type: "Unpacked['query']>>", + type: "Unpacked>", }, // TODO: Add this back in when queryBannedUsers is deployed to all shards for testing // { // f: rg.queryBannedUsers, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], + // imports: ['StreamChat', 'Unpacked'], // type: - // "Unpacked['queryBannedUsers']>>", + // "Unpacked>", // }, { f: rg.queryMembers, imports: ['Channel', 'Unpacked'], - type: "Unpacked['queryMembers']>>", + type: "Unpacked>", }, { f: rg.queryUsers, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['queryUsers']>>", + type: "Unpacked>", }, { f: rg.reactivateUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['reactivateUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.rejectInvite, imports: ['Channel', 'Unpacked'], - type: "Unpacked['rejectInvite']>>", + type: "Unpacked>", }, { f: rg.removeMembers, imports: ['Channel', 'Unpacked'], - type: "Unpacked['removeMembers']>>", + type: "Unpacked>", }, { f: rg.removeFilterTags, imports: ['Channel', 'Unpacked'], - type: "Unpacked['removeFilterTags']>>", + type: "Unpacked>", }, { f: rg.removeShadowBan, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['removeShadowBan']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.sendAction, imports: ['Channel', 'Unpacked'], - type: "Unpacked['sendAction']>>", + type: "Unpacked>", }, { f: rg.sendFile, imports: ['Channel', 'Unpacked'], - type: "Unpacked['sendFile']>>", + type: "Unpacked>", }, { f: rg.sendImage, imports: ['Channel', 'Unpacked'], - type: "Unpacked['sendImage']>>", + type: "Unpacked>", }, { f: rg.sendMessage, imports: ['Channel', 'Unpacked'], - type: "Unpacked['sendMessage']>>", + type: "Unpacked>", }, { f: rg.sendMessageReadEvent, imports: ['Channel', 'Unpacked'], - type: "Unpacked['sendEvent']>>", + type: "Unpacked>", }, { f: rg.sendReaction, imports: ['Channel', 'Unpacked'], - type: "Unpacked['sendReaction']>>", + type: "Unpacked>", }, { f: rg.setGuestUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['setGuestUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.shadowBan, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['shadowBan']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.show, imports: ['Channel', 'Unpacked'], - type: "Unpacked['show']>>", + type: "Unpacked>", }, { f: rg.stopTyping, imports: ['Channel', 'Unpacked'], - type: "Unpacked['stopTyping']>>", + type: "Unpacked>", }, { f: rg.stopWatching, imports: ['Channel', 'Unpacked'], - type: "Unpacked['stopWatching']>>", + type: "Unpacked>", }, { f: rg.sync, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['sync']>>", + type: "Unpacked>", }, { f: rg.syncTeam, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['sync']>>", + type: "Unpacked>", }, // Need translation on the account to run this test // { // f: rg.translateMessage, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], + // imports: ['StreamChat', 'Unpacked'], // type: - // "Unpacked['translateMessage']>>", + // "Unpacked>", // }, { f: rg.truncateChannel, imports: ['Channel', 'Unpacked'], - type: "Unpacked['truncate']>>", + type: "Unpacked>", }, { f: rg.unbanUsers, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['unbanUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.unmute, imports: ['Channel', 'Unpacked'], - type: "Unpacked['unmute']>>", + type: "Unpacked>", }, { f: rg.unmuteUser, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['unmuteUser']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.updateAppSettings, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['updateAppSettings']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.updateBlockList, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['updateBlockList']>>", + type: "Unpacked>", }, { f: rg.updateChannel, imports: ['Channel', 'Unpacked'], - type: "Unpacked['update']>>", + type: "Unpacked>", }, { f: rg.updateChannelFromOriginal, imports: ['Channel', 'Unpacked'], - type: "Unpacked['update']>>", + type: "Unpacked>", }, { f: rg.updateChannelType, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['updateChannelType']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.updateCommand, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['updateCommand']>>", + type: "Unpacked>", }, { f: rg.updateMessage, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['updateMessage']>>", + type: "Unpacked>", }, { f: rg.updatePermission, - imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - type: "Unpacked['updatePermission']>>", + imports: ['StreamChat', 'Unpacked'], + type: "Unpacked>", }, { f: rg.upsertUsers, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['upsertUsers']>>", + type: "Unpacked>", }, { f: rg.upsertUser, imports: ['StreamChat', 'Unpacked'], - type: "Unpacked['upsertUser']>>", + type: "Unpacked>", }, { f: rg.watch, imports: ['Channel', 'Unpacked'], - type: "Unpacked['watch']>>", + type: "Unpacked>", }, // Currently roles do not return // { // f: rg.createRole, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - // type: "Unpacked['createRole']>>", + // imports: ['StreamChat', 'Unpacked'], + // type: "Unpacked>", // }, // { // f: rg.deleteRole, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - // type: "Unpacked['deleteRole']>>", + // imports: ['StreamChat', 'Unpacked'], + // type: "Unpacked>", // }, // { // f: rg.listRoles, - // imports: ['StreamChat', 'DefaultGenerics', 'Unpacked'], - // type: "Unpacked['listRoles']>>", + // imports: ['StreamChat', 'Unpacked'], + // type: "Unpacked>", // }, ]; diff --git a/test/typescript/unit-test.ts b/test/typescript/unit-test.ts index 308b837fb7..7b9852521c 100644 --- a/test/typescript/unit-test.ts +++ b/test/typescript/unit-test.ts @@ -58,81 +58,21 @@ type StreamTypes = { let voidReturn: void | { unsubscribe: () => void }; let voidPromise: Promise; -const client: StreamChat = new StreamChat(apiKey, undefined, { +const client: StreamChat = new StreamChat(apiKey, undefined, { timeout: 3000, logger: (logLevel: string, msg: string, extraData?: Record) => {}, }); -const clientWithoutSecret: StreamChat<{ - attachmentType: {}; - channelType: ChannelType; - commandType: string & {}; - eventType: {}; - messageType: {}; - reactionType: {}; - userType: UserType; - pollType: {}; - pollOptionType: {}; -}> = new StreamChat<{ - attachmentType: {}; - channelType: ChannelType; - commandType: string & {}; - eventType: {}; - messageType: {}; - reactionType: {}; - userType: UserType; - pollType: {}; - pollOptionType: {}; -}>(apiKey, { +const clientWithoutSecret: StreamChat = new StreamChat(apiKey, { timeout: 3000, - logger: (logLevel: string, msg: string, extraData?: Record) => {}, }); +const singletonClient = StreamChat.getInstance(apiKey); -const singletonClient = StreamChat.getInstance(apiKey); +const singletonClient1: StreamChat = StreamChat.getInstance(apiKey); -const singletonClient1: StreamChat<{ - attachmentType: {}; - channelType: ChannelType; - commandType: string & {}; - eventType: {}; - messageType: {}; - reactionType: {}; - userType: UserType; - pollType: {}; - pollOptionType: {}; -}> = StreamChat.getInstance<{ - attachmentType: {}; - channelType: ChannelType; - commandType: string & {}; - eventType: {}; - messageType: {}; - reactionType: {}; - userType: UserType; - pollType: {}; - pollOptionType: {}; -}>(apiKey); - -const singletonClient2: StreamChat<{ - attachmentType: {}; - channelType: ChannelType; - commandType: string & {}; - eventType: {}; - messageType: {}; - reactionType: {}; - userType: UserType; - pollType: {}; - pollOptionType: {}; -}> = StreamChat.getInstance<{ - attachmentType: {}; - channelType: ChannelType; - commandType: string & {}; - eventType: {}; - messageType: {}; - reactionType: {}; - userType: UserType; - pollType: {}; - pollOptionType: {}; -}>(apiKey, '', {}); +const singletonClient2: StreamChat = StreamChat.getInstance(apiKey, { + timeout: 3000, +}); const devToken: string = client.devToken('joshua'); const token: string = client.createToken('james', 3600); @@ -143,7 +83,7 @@ const settingsPromise: Promise = client.updateAppSettings({}); const appPromise: Promise = client.getAppSettings(); voidPromise = client.disconnectUser(); -const updateRequest: PartialUserUpdate = { +const updateRequest: PartialUserUpdate = { id: 'vishal', set: { name: 'Awesome', @@ -152,14 +92,14 @@ const updateRequest: PartialUserUpdate = { }; const updateUser: Promise<{ - users: { [key: string]: UserResponse }; + users: { [key: string]: UserResponse }; }> = client.partialUpdateUser(updateRequest); const updateUsers: Promise<{ - users: { [key: string]: UserResponse }; + users: { [key: string]: UserResponse }; }> = client.partialUpdateUsers([updateRequest]); const updateUsersWithSingletonClient: Promise<{ - users: { [key: string]: UserResponse }; + users: { [key: string]: UserResponse }; }> = singletonClient.partialUpdateUsers([updateRequest]); const eventHandler = (event: Event) => {}; @@ -168,7 +108,7 @@ voidReturn = client.off(eventHandler); voidReturn = client.on('message.new', eventHandler); voidReturn = client.off('message.new', eventHandler); -let userReturn: ConnectAPIResponse; +let userReturn: ConnectAPIResponse; userReturn = client.connectUser({ id: 'john', phone: 2 }, devToken); userReturn = client.connectUser({ id: 'john', phone: 2 }, async () => 'token'); userReturn = client.setUser({ id: 'john', phone: 2 }, devToken); @@ -195,7 +135,7 @@ const file: Promise = client.sendFile( ); const type: EventTypes = 'user.updated'; -const event: Event = { +const event: Event = { type, cid: 'channelid', message: { @@ -224,26 +164,23 @@ const event: Event = { voidReturn = client.dispatchEvent(event); voidPromise = client.recoverState(); -const channels: Promise[]> = client.queryChannels({}, {}, {}); +const channels: Promise = client.queryChannels({}, {}, {}); channels.then((response) => { const type: string = response[0].type; const cid: string = response[0].cid; }); -const channel: Channel = client.channel('messaging', 'channelName', { +const channel: Channel = client.channel('messaging', 'channelName', { color: 'green', }); -const channelState: ChannelState = channel.state; -const chUser1: ChannelMemberResponse = channelState.members.someUser12433222; -const chUser2: ChannelMemberResponse = - channelState.members.someUser124332221; +const channelState: ChannelState = channel.state; +const chUser1: ChannelMemberResponse = channelState.members.someUser12433222; +const chUser2: ChannelMemberResponse = channelState.members.someUser124332221; -const chUser3: UserResponse = channelState.read.someUserId.user; -const typing: Event = channelState.typing['someUserId']; +const chUser3: UserResponse = channelState.read.someUserId.user; +const typing: Event = channelState.typing['someUserId']; -const acceptInvite: Promise> = channel.acceptInvite( - {}, -); +const acceptInvite: Promise = channel.acceptInvite({}); voidReturn = channel.on(eventHandler); voidReturn = channel.off(eventHandler); From 06fa5052416032caf998f8bcec44a0d3f157f351 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 12:02:15 +0100 Subject: [PATCH 07/27] test: fix flaky queryUsers case --- test/typescript/response-generators/client.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/typescript/response-generators/client.js b/test/typescript/response-generators/client.js index 3910bf422e..cddc8f3d12 100644 --- a/test/typescript/response-generators/client.js +++ b/test/typescript/response-generators/client.js @@ -115,9 +115,14 @@ async function markAllRead() { async function queryUsers() { const user1 = uuidv4(); const user2 = uuidv4(); - await utils.createUsers([user1, user2], { nickname: user2 }); + const nickname = `test-nickname-${Date.now()}`; + + // Create users with different properties + await utils.createUsers([user1], {}); // user1 without nickname + await utils.createUsers([user2], { nickname: nickname }); // user2 with nickname + const client = await utils.getTestClientForUser(user1); - return await client.queryUsers({ nickname: { $eq: user2 } }); + return await client.queryUsers({ nickname: { $eq: nickname } }); } async function queryBannedUsers() { From 9ad340b54c1e0c521510f87fcc43bdcc3bf0841f Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 13:02:35 +0100 Subject: [PATCH 08/27] test: fix typing --- test/typescript/unit-test.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/typescript/unit-test.ts b/test/typescript/unit-test.ts index 7b9852521c..61f11e118d 100644 --- a/test/typescript/unit-test.ts +++ b/test/typescript/unit-test.ts @@ -20,8 +20,22 @@ import { UpdateChannelAPIResponse, PartialUserUpdate, PermissionObject, + PolicyRequest, ConnectAPIResponse, } from '../../dist/types'; + +// Module augmentation to add custom properties for testing +declare module '../../dist/types' { + interface CustomUserData { + example?: number; + phone?: number; + name?: string; + } + interface CustomChannelData { + color?: string; + name?: string; + } +} const apiKey = 'apiKey'; type UserType = { @@ -108,7 +122,7 @@ voidReturn = client.off(eventHandler); voidReturn = client.on('message.new', eventHandler); voidReturn = client.off('message.new', eventHandler); -let userReturn: ConnectAPIResponse; +let userReturn: ConnectAPIResponse | undefined; userReturn = client.connectUser({ id: 'john', phone: 2 }, devToken); userReturn = client.connectUser({ id: 'john', phone: 2 }, async () => 'token'); userReturn = client.setUser({ id: 'john', phone: 2 }, devToken); @@ -227,7 +241,7 @@ const permissions = [ ]; client.updateChannelType('messaging', { permissions }).then((response) => { - const permissions: PermissionObject[] = response.permissions || []; + const permissions: PolicyRequest[] = response.permissions || []; const permissionName: string = permissions[0].name || ''; const permissionRoles: string[] = permissions[0].roles || []; }); From fabd377c075fe54f7133773ffd60ebb2ae6b715b Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 13:43:51 +0100 Subject: [PATCH 09/27] test: fix typing --- src/types.ts | 14 +++++++------- test/typescript/index.js | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/types.ts b/src/types.ts index ec597d8d32..9617c890ee 100644 --- a/src/types.ts +++ b/src/types.ts @@ -490,8 +490,8 @@ export type LocalMessageBase = Omit< }; export type LocalMessage = LocalMessageBase & { - error?: ErrorFromResponse; - quoted_message?: LocalMessageBase; + error?: ErrorFromResponse | null; + quoted_message?: LocalMessageBase | null; }; /** @@ -910,7 +910,7 @@ export type UserResponse = CustomUserData & { role?: string; shadow_banned?: boolean; teams?: string[]; - teams_role?: TeamsRole; + teams_role?: TeamsRole | null; updated_at?: string; username?: string; avg_response_time?: number; @@ -1066,9 +1066,8 @@ export type DeactivateUsersOptions = { export type NewMemberPayload = CustomMemberData & Pick; -export type Thresholds = Record< - 'explicit' | 'spam' | 'toxic', - Partial<{ block: number; flag: number }> +export type Thresholds = Partial< + Record<'explicit' | 'spam' | 'toxic', Partial<{ block: number; flag: number }>> >; export type BlockListOptions = { @@ -2049,7 +2048,7 @@ export type UserFilters = QueryFilters< } >; -export type InviteStatus = 'pending' | 'accepted' | 'rejected'; +export type InviteStatus = 'pending' | 'accepted' | 'rejected' | 'member'; // https://getstream.io/chat/docs/react/channel_member/#update-channel-members export type MemberFilters = QueryFilters< @@ -2373,6 +2372,7 @@ export type BlockList = { team?: string; type?: string; validate?: boolean; + is_leet_check_enabled?: boolean; }; export type ChannelConfig = ChannelConfigFields & diff --git a/test/typescript/index.js b/test/typescript/index.js index 10940abb86..724634f77b 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -530,8 +530,44 @@ const run = async () => { imports = uniqueTypes.join(', '); imports = `import { ${imports} } from '../..';`; + + // Module augmentation to add custom properties used in tests + const moduleAugmentation = ` +// Module augmentation to add custom properties for testing +declare module '../..' { + interface CustomUserData { + testString?: string; + instrument?: string; + song?: string; + gender?: string; + unique?: string; + work?: string; + status?: string; + image?: string; + devices?: unknown[]; + invisible?: boolean; + } + interface CustomChannelData { + description?: string; + image?: string; + } + interface CustomCommandData { + testCreateCommand?: unknown; + testCreateCommand_set?: unknown; + testDeleteCommand?: unknown; + testDeleteCommand_set?: unknown; + testGetCommand?: unknown; + testGetCommand_set?: unknown; + testListCommand?: unknown; + testListCommand_set?: unknown; + testUpdateCommand?: unknown; + testUpdateCommand_set?: unknown; + testUpdateCommand_set_two?: unknown; + } +}`; + tsFileName = `${__dirname}/data.ts`; - fs.writeFile(tsFileName, `${imports} \n\n`, function (err) { + fs.writeFile(tsFileName, `${imports} \n${moduleAugmentation}\n\n`, function (err) { if (err) { return console.log(err); } From adc1f9a1b70c2b780d0a89189a1361367efa737c Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 14:27:41 +0100 Subject: [PATCH 10/27] test: fix typing --- package.json | 4 +++- src/types.ts | 5 +++++ test/typescript/index.js | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e4398aea9c..1ee33627b5 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,9 @@ "eslint-fix": "yarn run eslint --fix", "test": "yarn test-unit", "testwatch": "NODE_ENV=test nodemon ./node_modules/.bin/mocha --timeout 20000 --require test-entry.js test/test.js", - "test-types": "node test/typescript/index.js && tsc --esModuleInterop true --noEmit true --strictNullChecks true --noImplicitAny true --strict true test/typescript/*.ts", + "test-types": "yarn run-test-types && yarn run-types-gen", + "run-test-types": "node test/typescript/index.js", + "run-types-gen": "tsc --esModuleInterop true --noEmit true --strictNullChecks true --noImplicitAny true --strict true test/typescript/*.ts", "test-unit": "vitest", "test-coverage": "vitest run --coverage", "fix-staged": "lint-staged --config .lintstagedrc.fix.json --concurrent 1", diff --git a/src/types.ts b/src/types.ts index 9617c890ee..8c08d1cf11 100644 --- a/src/types.ts +++ b/src/types.ts @@ -71,6 +71,7 @@ export type Unpacked = T extends (infer U)[] export type APIResponse = { duration: string; + blocklist?: BlockListResponse; }; export type TranslateResponse = { @@ -1034,6 +1035,7 @@ export type CreateChannelOptions = { reminders?: boolean; replies?: boolean; search?: boolean; + shared_locations?: boolean; skip_last_msg_update_for_system_msgs?: boolean; typing_events?: boolean; uploads?: boolean; @@ -1184,6 +1186,7 @@ export type UpdateChannelTypeResponse = { partition_size?: number; partition_ttl?: string; count_messages?: boolean; + user_message_reminders?: boolean; }; export type GetChannelTypeResponse = { @@ -1222,6 +1225,7 @@ export type GetChannelTypeResponse = { partition_size?: number; partition_ttl?: string; count_messages?: boolean; + user_message_reminders?: boolean; }; export type UpdateChannelOptions = Partial<{ @@ -2373,6 +2377,7 @@ export type BlockList = { type?: string; validate?: boolean; is_leet_check_enabled?: boolean; + is_plural_check_enabled?: boolean; }; export type ChannelConfig = ChannelConfigFields & diff --git a/test/typescript/index.js b/test/typescript/index.js index 724634f77b..92488a4a98 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -546,10 +546,13 @@ declare module '../..' { image?: string; devices?: unknown[]; invisible?: boolean; + last_engaged_at?: string; + mutes?: unknown[]; } interface CustomChannelData { description?: string; image?: string; + smallTitle?: string; } interface CustomCommandData { testCreateCommand?: unknown; From 92b69e3bea7b24cfaa392c988079aaf22b40c8f8 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 14:36:20 +0100 Subject: [PATCH 11/27] test: fix typing --- src/types.ts | 4 ++++ src/utils.ts | 1 + test/typescript/index.js | 1 + 3 files changed, 6 insertions(+) diff --git a/src/types.ts b/src/types.ts index 8c08d1cf11..c60ff13fc4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -789,6 +789,7 @@ export type OwnUserBase = { privacy_settings?: PrivacySettings; push_preferences?: PushPreference; roles?: string[]; + total_unread_count_by_team?: Record; }; export type OwnUserResponse = UserResponse & OwnUserBase; @@ -1041,6 +1042,7 @@ export type CreateChannelOptions = { uploads?: boolean; url_enrichment?: boolean; user_message_reminders?: boolean; + count_messages?: boolean; }; export type CreateCommandOptions = { @@ -1173,6 +1175,7 @@ export type UpdateChannelTypeResponse = { reminders: boolean; replies: boolean; search: boolean; + shared_locations: boolean; skip_last_msg_update_for_system_msgs: boolean; typing_events: boolean; updated_at: string; @@ -1212,6 +1215,7 @@ export type GetChannelTypeResponse = { reminders: boolean; replies: boolean; search: boolean; + shared_locations: boolean; skip_last_msg_update_for_system_msgs: boolean; typing_events: boolean; updated_at: string; diff --git a/src/utils.ts b/src/utils.ts index ef255ccb72..433be71286 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -104,6 +104,7 @@ export function isOwnUserBaseProperty(property: string) { privacy_settings: true, roles: true, push_preferences: true, + total_unread_count_by_team: true, }; return ownUserBaseProperties[property as keyof OwnUserBase]; diff --git a/test/typescript/index.js b/test/typescript/index.js index 92488a4a98..64d48a7b41 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -548,6 +548,7 @@ declare module '../..' { invisible?: boolean; last_engaged_at?: string; mutes?: unknown[]; + channel_mutes?: unknown[]; } interface CustomChannelData { description?: string; From ef5713159b4b138335fc7d88d0158bc2a038dec0 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 14:42:42 +0100 Subject: [PATCH 12/27] test: fix typing --- src/types.ts | 4 +++- test/typescript/index.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index c60ff13fc4..d9198b34c5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -789,7 +789,7 @@ export type OwnUserBase = { privacy_settings?: PrivacySettings; push_preferences?: PushPreference; roles?: string[]; - total_unread_count_by_team?: Record; + total_unread_count_by_team?: Record | null; }; export type OwnUserResponse = UserResponse & OwnUserBase; @@ -1186,6 +1186,7 @@ export type UpdateChannelTypeResponse = { blocklist?: string; blocklist_behavior?: BlocklistBehavior; blocklists?: BlockListOptions[]; + message_retention?: string; partition_size?: number; partition_ttl?: string; count_messages?: boolean; @@ -1226,6 +1227,7 @@ export type GetChannelTypeResponse = { blocklist?: string; blocklist_behavior?: BlocklistBehavior; blocklists?: BlockListOptions[]; + message_retention?: string; partition_size?: number; partition_ttl?: string; count_messages?: boolean; diff --git a/test/typescript/index.js b/test/typescript/index.js index 64d48a7b41..9c443c919c 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -549,6 +549,7 @@ declare module '../..' { last_engaged_at?: string; mutes?: unknown[]; channel_mutes?: unknown[]; + unread_count?: number; } interface CustomChannelData { description?: string; From f8c7a27d6ee11d0fc97854681ba5151415eee181 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 14:49:00 +0100 Subject: [PATCH 13/27] test: fix typing --- test/typescript/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/typescript/index.js b/test/typescript/index.js index 9c443c919c..d898b5f9b3 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -550,11 +550,13 @@ declare module '../..' { mutes?: unknown[]; channel_mutes?: unknown[]; unread_count?: number; + total_unread_count?: number; } interface CustomChannelData { description?: string; image?: string; smallTitle?: string; + shared_locations?: boolean; } interface CustomCommandData { testCreateCommand?: unknown; From 26c0aa946840d394daa5aa85bc763b3a6b7e4311 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 14:54:01 +0100 Subject: [PATCH 14/27] test: fix typing --- src/types.ts | 3 +++ test/typescript/index.js | 1 + 2 files changed, 4 insertions(+) diff --git a/src/types.ts b/src/types.ts index d9198b34c5..771126b726 100644 --- a/src/types.ts +++ b/src/types.ts @@ -109,6 +109,9 @@ export type AppSettingsAPIResponse = APIResponse & { read_events?: boolean; replies?: boolean; search?: boolean; + shared_locations?: boolean; + skip_last_msg_update_for_system_msgs?: boolean; + count_messages?: boolean; typing_events?: boolean; updated_at?: string; uploads?: boolean; diff --git a/test/typescript/index.js b/test/typescript/index.js index d898b5f9b3..8bcf6fab83 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -551,6 +551,7 @@ declare module '../..' { channel_mutes?: unknown[]; unread_count?: number; total_unread_count?: number; + unread_channels?: number; } interface CustomChannelData { description?: string; From 5c376a537ebd39a3c50936d49d441a9f46cf573c Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 15:02:35 +0100 Subject: [PATCH 15/27] test: fix typing --- src/types.ts | 1 + test/typescript/index.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/types.ts b/src/types.ts index 771126b726..e3cae82df1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,6 +81,7 @@ export type TranslateResponse = { export type AppSettingsAPIResponse = APIResponse & { app?: { + id?: string; // TODO // eslint-disable-next-line @typescript-eslint/no-explicit-any call_types: any; diff --git a/test/typescript/index.js b/test/typescript/index.js index 8bcf6fab83..c42d1f8934 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -552,6 +552,7 @@ declare module '../..' { unread_count?: number; total_unread_count?: number; unread_channels?: number; + unread_threads?: number; } interface CustomChannelData { description?: string; From 1354d2fedb18e0360084d0fe9ca5c44e97b58f26 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 15:24:21 +0100 Subject: [PATCH 16/27] test: fix typing --- src/types.ts | 3 ++- test/typescript/index.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index e3cae82df1..aab496f6ee 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,7 +81,7 @@ export type TranslateResponse = { export type AppSettingsAPIResponse = APIResponse & { app?: { - id?: string; + id?: string | number; // TODO // eslint-disable-next-line @typescript-eslint/no-explicit-any call_types: any; @@ -894,6 +894,7 @@ export type UsersAPIResponse = APIResponse & { export type UpdateUsersAPIResponse = APIResponse & { users: { [key: string]: UserResponse }; + membership_deletion_task_id?: string; }; export type UserResponse = CustomUserData & { diff --git a/test/typescript/index.js b/test/typescript/index.js index c42d1f8934..9ece4aa061 100644 --- a/test/typescript/index.js +++ b/test/typescript/index.js @@ -553,6 +553,7 @@ declare module '../..' { total_unread_count?: number; unread_channels?: number; unread_threads?: number; + nickname?: string; } interface CustomChannelData { description?: string; From aa40203a213857275844e432a772fd9ade6aea08 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 15:31:11 +0100 Subject: [PATCH 17/27] test: fix typing --- src/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types.ts b/src/types.ts index aab496f6ee..e7f0e5a72b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -151,6 +151,7 @@ export type AppSettingsAPIResponse = APIResponse & { name?: string; organization?: string; permission_version?: string; + placement?: string; policies?: Record; poll_enabled?: boolean; push_notifications?: { @@ -890,6 +891,7 @@ export type UpdateMessageAPIResponse = APIResponse & { export type UsersAPIResponse = APIResponse & { users: Array; + membership_deletion_task_id?: string; }; export type UpdateUsersAPIResponse = APIResponse & { From 38263de3696a07287930a89c05e0166342370753 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 16:07:02 +0100 Subject: [PATCH 18/27] test: fix typing --- src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.ts b/src/types.ts index e7f0e5a72b..18bcb66481 100644 --- a/src/types.ts +++ b/src/types.ts @@ -147,6 +147,7 @@ export type AppSettingsAPIResponse = APIResponse & { grants?: Record; image_moderation_enabled?: boolean; image_upload_config?: FileUploadConfig; + moderation_webhook_url?: string; multi_tenant_enabled?: boolean; name?: string; organization?: string; From f4b9932d8899dcdcb09654855fc4518335eb160a Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 16:24:18 +0100 Subject: [PATCH 19/27] test: fix typing --- src/client.ts | 15 +++++---------- src/types.ts | 1 + 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/client.ts b/src/client.ts index c2cbe87036..6ca932f27b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -226,6 +226,7 @@ import type { UserOptions, UserResponse, UserSort, + UpdateUsersAPIResponse, VoteSort, } from './types'; import { ErrorFromResponse } from './types'; @@ -2396,11 +2397,9 @@ export class StreamChat { userMap[userObject.id] = userObject; } - return await this.post< - APIResponse & { - users: { [key: string]: UserResponse }; - } - >(this.baseURL + '/users', { users: userMap }); + return await this.post(this.baseURL + '/users', { + users: userMap, + }); } /** @@ -2448,11 +2447,7 @@ export class StreamChat { } } - return await this.patch< - APIResponse & { - users: { [key: string]: UserResponse }; - } - >(this.baseURL + '/users', { users }); + return await this.patch(this.baseURL + '/users', { users }); } async deleteUser( diff --git a/src/types.ts b/src/types.ts index 18bcb66481..92fb100028 100644 --- a/src/types.ts +++ b/src/types.ts @@ -82,6 +82,7 @@ export type TranslateResponse = { export type AppSettingsAPIResponse = APIResponse & { app?: { id?: string | number; + allow_multi_user_devices?: boolean; // TODO // eslint-disable-next-line @typescript-eslint/no-explicit-any call_types: any; From ddfa687d6b40624c0e227addafb34fda0051409e Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 17:47:29 +0100 Subject: [PATCH 20/27] test: fix typing --- src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.ts b/src/types.ts index 92fb100028..61fcd3a7e5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -148,6 +148,7 @@ export type AppSettingsAPIResponse = APIResponse & { grants?: Record; image_moderation_enabled?: boolean; image_upload_config?: FileUploadConfig; + moderation_enabled?: boolean; moderation_webhook_url?: string; multi_tenant_enabled?: boolean; name?: string; From 8e869ea02b2c09c2d7a1f4da8ff92da57126e0dd Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Thu, 20 Nov 2025 18:25:45 +0100 Subject: [PATCH 21/27] test: fix typing --- src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.ts b/src/types.ts index 61fcd3a7e5..6e65053b94 100644 --- a/src/types.ts +++ b/src/types.ts @@ -149,6 +149,7 @@ export type AppSettingsAPIResponse = APIResponse & { image_moderation_enabled?: boolean; image_upload_config?: FileUploadConfig; moderation_enabled?: boolean; + moderation_multitenant_blocklist_enabled?: boolean; moderation_webhook_url?: string; multi_tenant_enabled?: boolean; name?: string; From 8b783b786cd423d740256f04c407009e89b786b1 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Fri, 21 Nov 2025 04:13:59 +0100 Subject: [PATCH 22/27] test: fix typing --- src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.ts b/src/types.ts index 6e65053b94..86ef9146fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -146,6 +146,7 @@ export type AppSettingsAPIResponse = APIResponse & { type: string; }>; grants?: Record; + guest_user_creation_disabled?: boolean; image_moderation_enabled?: boolean; image_upload_config?: FileUploadConfig; moderation_enabled?: boolean; From b4b5c2d3fd565b5dcf69febad579ce30b5e1a4e1 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Fri, 21 Nov 2025 04:28:02 +0100 Subject: [PATCH 23/27] test: fix typing --- src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.ts b/src/types.ts index 86ef9146fd..26e14f1b93 100644 --- a/src/types.ts +++ b/src/types.ts @@ -149,6 +149,7 @@ export type AppSettingsAPIResponse = APIResponse & { guest_user_creation_disabled?: boolean; image_moderation_enabled?: boolean; image_upload_config?: FileUploadConfig; + moderation_dashboard_preferences?: Record; moderation_enabled?: boolean; moderation_multitenant_blocklist_enabled?: boolean; moderation_webhook_url?: string; From 4b7af80e9a3261affe55d40a69eb39ecc134b87e Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Fri, 21 Nov 2025 04:38:01 +0100 Subject: [PATCH 24/27] test: fix typing --- src/client.ts | 2 +- src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 6ca932f27b..fac0de1614 100644 --- a/src/client.ts +++ b/src/client.ts @@ -220,13 +220,13 @@ import type { UpdatePollOptionAPIResponse, UpdateReminderOptions, UpdateSegmentData, + UpdateUsersAPIResponse, UpsertPushPreferencesResponse, UserCustomEvent, UserFilters, UserOptions, UserResponse, UserSort, - UpdateUsersAPIResponse, VoteSort, } from './types'; import { ErrorFromResponse } from './types'; diff --git a/src/types.ts b/src/types.ts index 26e14f1b93..bb76efb6bb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -149,7 +149,7 @@ export type AppSettingsAPIResponse = APIResponse & { guest_user_creation_disabled?: boolean; image_moderation_enabled?: boolean; image_upload_config?: FileUploadConfig; - moderation_dashboard_preferences?: Record; + moderation_dashboard_preferences?: Record | null; moderation_enabled?: boolean; moderation_multitenant_blocklist_enabled?: boolean; moderation_webhook_url?: string; From a993ec6440b2ceda574f898cfc3f5b23413626b4 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Fri, 21 Nov 2025 05:54:15 +0100 Subject: [PATCH 25/27] test: fix typing --- src/types.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/types.ts b/src/types.ts index bb76efb6bb..e22c5ec6c6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -148,9 +148,14 @@ export type AppSettingsAPIResponse = APIResponse & { grants?: Record; guest_user_creation_disabled?: boolean; image_moderation_enabled?: boolean; + image_moderation_labels?: string[]; image_upload_config?: FileUploadConfig; + allowed_flag_reasons?: string[]; + max_aggregated_activities_length?: number; + moderation_bulk_submit_action_enabled?: boolean; moderation_dashboard_preferences?: Record | null; moderation_enabled?: boolean; + moderation_llm_configurability_enabled?: boolean; moderation_multitenant_blocklist_enabled?: boolean; moderation_webhook_url?: string; multi_tenant_enabled?: boolean; @@ -179,6 +184,8 @@ export type AppSettingsAPIResponse = APIResponse & { sqs_url?: string; suspended?: boolean; suspended_explanation?: string; + use_hook_v2?: boolean; + user_response_time_enabled?: boolean; user_search_disallowed_roles?: string[] | null; video_provider?: string; webhook_events?: Array; From a43e4560d413dc43cb02fcc774cdf73adae977a5 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Fri, 21 Nov 2025 10:35:55 +0100 Subject: [PATCH 26/27] test: remove annotation null --- src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types.ts b/src/types.ts index e22c5ec6c6..5257b99b74 100644 --- a/src/types.ts +++ b/src/types.ts @@ -509,8 +509,8 @@ export type LocalMessageBase = Omit< }; export type LocalMessage = LocalMessageBase & { - error?: ErrorFromResponse | null; - quoted_message?: LocalMessageBase | null; + error?: ErrorFromResponse; + quoted_message?: LocalMessageBase; }; /** From 89043f673e9157133b23a0c912064916696d06d8 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Mon, 24 Nov 2025 09:31:24 +0100 Subject: [PATCH 27/27] chore: doc for placement field --- src/types.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/types.ts b/src/types.ts index 5257b99b74..6e2495aaa3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -162,6 +162,11 @@ export type AppSettingsAPIResponse = APIResponse & { name?: string; organization?: string; permission_version?: string; + /** + * The placement of the app in the form of `${region}.${shard}`. + * Examples: "us-east.c1", "dublin.c3", "singapore.c2" + * Note: The backend may add/remove regions or shards occasionally. + */ placement?: string; policies?: Record; poll_enabled?: boolean;