stream-chat 9.2.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.browser.cjs +64 -15
- package/dist/cjs/index.browser.cjs.map +3 -3
- package/dist/cjs/index.node.cjs +65 -15
- package/dist/cjs/index.node.cjs.map +3 -3
- package/dist/esm/index.js +64 -15
- package/dist/esm/index.js.map +3 -3
- package/dist/types/channel.d.ts +3 -5
- package/dist/types/client.d.ts +20 -3
- package/dist/types/offline-support/offline_support_api.d.ts +2 -4
- package/dist/types/offline-support/types.d.ts +14 -4
- package/dist/types/types.d.ts +24 -0
- package/package.json +1 -1
- package/src/channel.ts +5 -5
- package/src/client.ts +26 -7
- package/src/offline-support/offline_support_api.ts +12 -9
- package/src/offline-support/types.ts +28 -4
- package/src/types.ts +26 -0
- package/src/utils/mergeWith/mergeWithCore.ts +7 -1
package/dist/types/channel.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export declare class Channel {
|
|
|
139
139
|
sendReaction(messageID: string, reaction: Reaction, options?: {
|
|
140
140
|
enforce_unique?: boolean;
|
|
141
141
|
skip_push?: boolean;
|
|
142
|
-
}): Promise<ReactionAPIResponse
|
|
142
|
+
}): Promise<ReactionAPIResponse>;
|
|
143
143
|
/**
|
|
144
144
|
* sendReaction - Send a reaction about a message
|
|
145
145
|
*
|
|
@@ -152,10 +152,8 @@ export declare class Channel {
|
|
|
152
152
|
_sendReaction(messageID: string, reaction: Reaction, options?: {
|
|
153
153
|
enforce_unique?: boolean;
|
|
154
154
|
skip_push?: boolean;
|
|
155
|
-
}): Promise<ReactionAPIResponse
|
|
156
|
-
deleteReaction(messageID: string, reactionType: string, user_id?: string): Promise<
|
|
157
|
-
message: MessageResponse;
|
|
158
|
-
}) | undefined>;
|
|
155
|
+
}): Promise<ReactionAPIResponse>;
|
|
156
|
+
deleteReaction(messageID: string, reactionType: string, user_id?: string): Promise<ReactionAPIResponse>;
|
|
159
157
|
/**
|
|
160
158
|
* deleteReaction - Delete a reaction by user and type
|
|
161
159
|
*
|
package/dist/types/client.d.ts
CHANGED
|
@@ -227,7 +227,24 @@ export declare class StreamChat {
|
|
|
227
227
|
'data_template': 'data handlebars template',
|
|
228
228
|
'apn_template': 'apn notification handlebars template under v2'
|
|
229
229
|
},
|
|
230
|
-
'webhook_url': 'https://acme.com/my/awesome/webhook/'
|
|
230
|
+
'webhook_url': 'https://acme.com/my/awesome/webhook/',
|
|
231
|
+
'event_hooks': [
|
|
232
|
+
{
|
|
233
|
+
'hook_type': 'webhook',
|
|
234
|
+
'enabled': true,
|
|
235
|
+
'event_types': ['message.new'],
|
|
236
|
+
'webhook_url': 'https://acme.com/my/awesome/webhook/'
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
'hook_type': 'sqs',
|
|
240
|
+
'enabled': true,
|
|
241
|
+
'event_types': ['message.new'],
|
|
242
|
+
'sqs_url': 'https://sqs.us-east-1.amazonaws.com/1234567890/my-queue',
|
|
243
|
+
'sqs_auth_type': 'key',
|
|
244
|
+
'sqs_key': 'my-access-key',
|
|
245
|
+
'sqs_secret': 'my-secret-key'
|
|
246
|
+
}
|
|
247
|
+
]
|
|
231
248
|
}
|
|
232
249
|
*/
|
|
233
250
|
updateAppSettings(options: AppSettings): Promise<APIResponse>;
|
|
@@ -1103,9 +1120,9 @@ export declare class StreamChat {
|
|
|
1103
1120
|
partialUpdateMessage(id: string, partialMessageObject: PartialMessageUpdate, partialUserOrUserId?: string | {
|
|
1104
1121
|
id: string;
|
|
1105
1122
|
}, options?: UpdateMessageOptions): Promise<UpdateMessageAPIResponse>;
|
|
1106
|
-
deleteMessage(messageID: string, hardDelete?: boolean): Promise<
|
|
1123
|
+
deleteMessage(messageID: string, hardDelete?: boolean): Promise<APIResponse & {
|
|
1107
1124
|
message: MessageResponse;
|
|
1108
|
-
}
|
|
1125
|
+
}>;
|
|
1109
1126
|
_deleteMessage(messageID: string, hardDelete?: boolean): Promise<APIResponse & {
|
|
1110
1127
|
message: MessageResponse;
|
|
1111
1128
|
}>;
|
|
@@ -522,11 +522,9 @@ export declare abstract class AbstractOfflineDB implements OfflineDBApi {
|
|
|
522
522
|
* It will return the response from the execution if it succeeded.
|
|
523
523
|
* @param task - the pending task we want to execute
|
|
524
524
|
*/
|
|
525
|
-
queueTask: ({ task }: {
|
|
525
|
+
queueTask: <T>({ task }: {
|
|
526
526
|
task: PendingTask;
|
|
527
|
-
}) => Promise<
|
|
528
|
-
message: import("..").MessageResponse;
|
|
529
|
-
}) | undefined>;
|
|
527
|
+
}) => Promise<T>;
|
|
530
528
|
/**
|
|
531
529
|
* A utility method that determines if a failed task should be added to the
|
|
532
530
|
* queue based on its error.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AppSettingsAPIResponse, ChannelAPIResponse, ChannelFilters, ChannelMemberResponse, ChannelResponse, ChannelSort, LocalMessage,
|
|
1
|
+
import type { AppSettingsAPIResponse, ChannelAPIResponse, ChannelFilters, ChannelMemberResponse, ChannelResponse, ChannelSort, LocalMessage, MessageResponse, PollResponse, ReactionFilters, ReactionResponse, ReactionSort, ReadResponse } from '../types';
|
|
2
2
|
import type { Channel } from '../channel';
|
|
3
3
|
import type { StreamChat } from '../client';
|
|
4
4
|
export type PrepareBatchDBQueries = [string] | [string, Array<unknown> | Array<Array<unknown>>];
|
|
@@ -322,6 +322,16 @@ export type PendingTask = {
|
|
|
322
322
|
payload: Parameters<Channel['sendMessage']>;
|
|
323
323
|
type: PendingTaskTypes['sendMessage'];
|
|
324
324
|
});
|
|
325
|
-
export type
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
export type OfflineErrorType = 'connection:lost';
|
|
326
|
+
export declare class OfflineError extends Error {
|
|
327
|
+
type: OfflineErrorType;
|
|
328
|
+
name: string;
|
|
329
|
+
constructor(message: string, { type, }: {
|
|
330
|
+
type: OfflineError['type'];
|
|
331
|
+
});
|
|
332
|
+
toJSON(): {
|
|
333
|
+
message: string;
|
|
334
|
+
stack: string | undefined;
|
|
335
|
+
name: string;
|
|
336
|
+
};
|
|
337
|
+
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -90,6 +90,7 @@ export type AppSettingsAPIResponse = APIResponse & {
|
|
|
90
90
|
disable_auth_checks?: boolean;
|
|
91
91
|
disable_permissions_checks?: boolean;
|
|
92
92
|
enforce_unique_usernames?: 'no' | 'app' | 'team';
|
|
93
|
+
event_hooks?: Array<EventHook>;
|
|
93
94
|
file_upload_config?: FileUploadConfig;
|
|
94
95
|
geofences?: Array<{
|
|
95
96
|
country_codes: Array<string>;
|
|
@@ -1698,6 +1699,7 @@ export type AppSettings = {
|
|
|
1698
1699
|
disable_auth_checks?: boolean;
|
|
1699
1700
|
disable_permissions_checks?: boolean;
|
|
1700
1701
|
enforce_unique_usernames?: 'no' | 'app' | 'team';
|
|
1702
|
+
event_hooks?: Array<EventHook> | null;
|
|
1701
1703
|
file_upload_config?: FileUploadConfig;
|
|
1702
1704
|
firebase_config?: {
|
|
1703
1705
|
apn_template?: string;
|
|
@@ -2905,4 +2907,26 @@ export type ThreadFilters = QueryFilters<{
|
|
|
2905
2907
|
} & {
|
|
2906
2908
|
last_message_at?: RequireOnlyOne<Pick<QueryFilter<ThreadResponse['last_message_at']>, '$eq' | '$gt' | '$lt' | '$gte' | '$lte'>> | PrimitiveFilter<ThreadResponse['last_message_at']>;
|
|
2907
2909
|
}>;
|
|
2910
|
+
export type HookType = 'webhook' | 'sqs' | 'sns';
|
|
2911
|
+
export type EventHook = {
|
|
2912
|
+
id?: string;
|
|
2913
|
+
hook_type?: HookType;
|
|
2914
|
+
enabled?: boolean;
|
|
2915
|
+
event_types?: Array<string>;
|
|
2916
|
+
webhook_url?: string;
|
|
2917
|
+
sqs_queue_url?: string;
|
|
2918
|
+
sqs_region?: string;
|
|
2919
|
+
sqs_auth_type?: string;
|
|
2920
|
+
sqs_key?: string;
|
|
2921
|
+
sqs_secret?: string;
|
|
2922
|
+
sqs_role_arn?: string;
|
|
2923
|
+
sns_topic_arn?: string;
|
|
2924
|
+
sns_region?: string;
|
|
2925
|
+
sns_auth_type?: string;
|
|
2926
|
+
sns_key?: string;
|
|
2927
|
+
sns_secret?: string;
|
|
2928
|
+
sns_role_arn?: string;
|
|
2929
|
+
created_at?: string;
|
|
2930
|
+
updated_at?: string;
|
|
2931
|
+
};
|
|
2908
2932
|
export {};
|
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -207,7 +207,7 @@ export class Channel {
|
|
|
207
207
|
if (offlineDb) {
|
|
208
208
|
const messageId = message.id;
|
|
209
209
|
if (messageId) {
|
|
210
|
-
return
|
|
210
|
+
return await offlineDb.queueTask<SendMessageAPIResponse>({
|
|
211
211
|
task: {
|
|
212
212
|
channelId: this.id as string,
|
|
213
213
|
channelType: this.type,
|
|
@@ -215,7 +215,7 @@ export class Channel {
|
|
|
215
215
|
payload: [message, options],
|
|
216
216
|
type: 'send-message',
|
|
217
217
|
},
|
|
218
|
-
})
|
|
218
|
+
});
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
} catch (error) {
|
|
@@ -410,7 +410,7 @@ export class Channel {
|
|
|
410
410
|
messageID: string,
|
|
411
411
|
reaction: Reaction,
|
|
412
412
|
options?: { enforce_unique?: boolean; skip_push?: boolean },
|
|
413
|
-
)
|
|
413
|
+
) {
|
|
414
414
|
if (!messageID) {
|
|
415
415
|
throw Error(`Message id is missing`);
|
|
416
416
|
}
|
|
@@ -454,7 +454,7 @@ export class Channel {
|
|
|
454
454
|
messageID: string,
|
|
455
455
|
reaction: Reaction,
|
|
456
456
|
options?: { enforce_unique?: boolean; skip_push?: boolean },
|
|
457
|
-
)
|
|
457
|
+
) {
|
|
458
458
|
if (!messageID) {
|
|
459
459
|
throw Error(`Message id is missing`);
|
|
460
460
|
}
|
|
@@ -498,7 +498,7 @@ export class Channel {
|
|
|
498
498
|
});
|
|
499
499
|
}
|
|
500
500
|
|
|
501
|
-
return await offlineDb.queueTask({
|
|
501
|
+
return await offlineDb.queueTask<ReactionAPIResponse>({
|
|
502
502
|
task: {
|
|
503
503
|
channelId: this.id as string,
|
|
504
504
|
channelType: this.type,
|
package/src/client.ts
CHANGED
|
@@ -777,7 +777,24 @@ export class StreamChat {
|
|
|
777
777
|
'data_template': 'data handlebars template',
|
|
778
778
|
'apn_template': 'apn notification handlebars template under v2'
|
|
779
779
|
},
|
|
780
|
-
'webhook_url': 'https://acme.com/my/awesome/webhook/'
|
|
780
|
+
'webhook_url': 'https://acme.com/my/awesome/webhook/',
|
|
781
|
+
'event_hooks': [
|
|
782
|
+
{
|
|
783
|
+
'hook_type': 'webhook',
|
|
784
|
+
'enabled': true,
|
|
785
|
+
'event_types': ['message.new'],
|
|
786
|
+
'webhook_url': 'https://acme.com/my/awesome/webhook/'
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
'hook_type': 'sqs',
|
|
790
|
+
'enabled': true,
|
|
791
|
+
'event_types': ['message.new'],
|
|
792
|
+
'sqs_url': 'https://sqs.us-east-1.amazonaws.com/1234567890/my-queue',
|
|
793
|
+
'sqs_auth_type': 'key',
|
|
794
|
+
'sqs_key': 'my-access-key',
|
|
795
|
+
'sqs_secret': 'my-secret-key'
|
|
796
|
+
}
|
|
797
|
+
]
|
|
781
798
|
}
|
|
782
799
|
*/
|
|
783
800
|
async updateAppSettings(options: AppSettings) {
|
|
@@ -3019,13 +3036,15 @@ export class StreamChat {
|
|
|
3019
3036
|
} else {
|
|
3020
3037
|
await this.offlineDb.softDeleteMessage({ id: messageID });
|
|
3021
3038
|
}
|
|
3022
|
-
return await this.offlineDb.queueTask(
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3039
|
+
return await this.offlineDb.queueTask<APIResponse & { message: MessageResponse }>(
|
|
3040
|
+
{
|
|
3041
|
+
task: {
|
|
3042
|
+
messageId: messageID,
|
|
3043
|
+
payload: [messageID, hardDelete],
|
|
3044
|
+
type: 'delete-message',
|
|
3045
|
+
},
|
|
3027
3046
|
},
|
|
3028
|
-
|
|
3047
|
+
);
|
|
3029
3048
|
}
|
|
3030
3049
|
} catch (error) {
|
|
3031
3050
|
this.logger('error', `offlineDb:deleteMessage`, {
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
PendingTask,
|
|
7
7
|
PrepareBatchDBQueries,
|
|
8
8
|
} from './types';
|
|
9
|
+
import { OfflineError } from './types';
|
|
9
10
|
import type { StreamChat } from '../client';
|
|
10
11
|
import type { AxiosError } from 'axios';
|
|
11
12
|
import { OfflineDBSyncManager } from './offline_sync_manager';
|
|
@@ -986,22 +987,24 @@ export abstract class AbstractOfflineDB implements OfflineDBApi {
|
|
|
986
987
|
* It will return the response from the execution if it succeeded.
|
|
987
988
|
* @param task - the pending task we want to execute
|
|
988
989
|
*/
|
|
989
|
-
public queueTask = async ({ task }: { task: PendingTask }) => {
|
|
990
|
-
|
|
991
|
-
try {
|
|
990
|
+
public queueTask = async <T>({ task }: { task: PendingTask }): Promise<T> => {
|
|
991
|
+
const attemptTaskExecution = async () => {
|
|
992
992
|
if (!this.client.wsConnection?.isHealthy) {
|
|
993
|
-
|
|
994
|
-
|
|
993
|
+
throw new OfflineError(
|
|
994
|
+
'Cannot execute task because the connection has been lost.',
|
|
995
|
+
{ type: 'connection:lost' },
|
|
996
|
+
);
|
|
995
997
|
}
|
|
996
|
-
|
|
998
|
+
return (await this.executeTask({ task })) as T;
|
|
999
|
+
};
|
|
1000
|
+
try {
|
|
1001
|
+
return await attemptTaskExecution();
|
|
997
1002
|
} catch (e) {
|
|
998
1003
|
if (!this.shouldSkipQueueingTask(e as AxiosError<APIErrorResponse>)) {
|
|
999
1004
|
await this.addPendingTask(task);
|
|
1000
|
-
throw e;
|
|
1001
1005
|
}
|
|
1006
|
+
throw e;
|
|
1002
1007
|
}
|
|
1003
|
-
|
|
1004
|
-
return response;
|
|
1005
1008
|
};
|
|
1006
1009
|
|
|
1007
1010
|
/**
|
|
@@ -6,7 +6,6 @@ import type {
|
|
|
6
6
|
ChannelResponse,
|
|
7
7
|
ChannelSort,
|
|
8
8
|
LocalMessage,
|
|
9
|
-
Message,
|
|
10
9
|
MessageResponse,
|
|
11
10
|
PollResponse,
|
|
12
11
|
ReactionFilters,
|
|
@@ -398,6 +397,31 @@ export type PendingTask = {
|
|
|
398
397
|
}
|
|
399
398
|
);
|
|
400
399
|
|
|
401
|
-
export type
|
|
402
|
-
|
|
403
|
-
|
|
400
|
+
export type OfflineErrorType = 'connection:lost';
|
|
401
|
+
|
|
402
|
+
export class OfflineError extends Error {
|
|
403
|
+
public type: OfflineErrorType;
|
|
404
|
+
public name = 'OfflineError';
|
|
405
|
+
|
|
406
|
+
constructor(
|
|
407
|
+
message: string,
|
|
408
|
+
{
|
|
409
|
+
type,
|
|
410
|
+
}: {
|
|
411
|
+
type: OfflineError['type'];
|
|
412
|
+
},
|
|
413
|
+
) {
|
|
414
|
+
super(message);
|
|
415
|
+
this.type = type;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Vitest helper (serialized errors are too large to read)
|
|
419
|
+
// https://github.com/vitest-dev/vitest/blob/v3.1.3/packages/utils/src/error.ts#L60-L62
|
|
420
|
+
toJSON() {
|
|
421
|
+
return {
|
|
422
|
+
message: `${this.type} - ${this.message}`,
|
|
423
|
+
stack: this.stack,
|
|
424
|
+
name: this.name,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -129,6 +129,7 @@ export type AppSettingsAPIResponse = APIResponse & {
|
|
|
129
129
|
disable_auth_checks?: boolean;
|
|
130
130
|
disable_permissions_checks?: boolean;
|
|
131
131
|
enforce_unique_usernames?: 'no' | 'app' | 'team';
|
|
132
|
+
event_hooks?: Array<EventHook>;
|
|
132
133
|
file_upload_config?: FileUploadConfig;
|
|
133
134
|
geofences?: Array<{
|
|
134
135
|
country_codes: Array<string>;
|
|
@@ -2213,6 +2214,7 @@ export type AppSettings = {
|
|
|
2213
2214
|
disable_auth_checks?: boolean;
|
|
2214
2215
|
disable_permissions_checks?: boolean;
|
|
2215
2216
|
enforce_unique_usernames?: 'no' | 'app' | 'team';
|
|
2217
|
+
event_hooks?: Array<EventHook> | null;
|
|
2216
2218
|
// all possible file mime types are https://www.iana.org/assignments/media-types/media-types.xhtml
|
|
2217
2219
|
file_upload_config?: FileUploadConfig;
|
|
2218
2220
|
firebase_config?: {
|
|
@@ -4006,3 +4008,27 @@ export type ThreadFilters = QueryFilters<
|
|
|
4006
4008
|
| PrimitiveFilter<ThreadResponse['last_message_at']>;
|
|
4007
4009
|
}
|
|
4008
4010
|
>;
|
|
4011
|
+
|
|
4012
|
+
export type HookType = 'webhook' | 'sqs' | 'sns';
|
|
4013
|
+
|
|
4014
|
+
export type EventHook = {
|
|
4015
|
+
id?: string;
|
|
4016
|
+
hook_type?: HookType;
|
|
4017
|
+
enabled?: boolean;
|
|
4018
|
+
event_types?: Array<string>;
|
|
4019
|
+
webhook_url?: string;
|
|
4020
|
+
sqs_queue_url?: string;
|
|
4021
|
+
sqs_region?: string;
|
|
4022
|
+
sqs_auth_type?: string;
|
|
4023
|
+
sqs_key?: string;
|
|
4024
|
+
sqs_secret?: string;
|
|
4025
|
+
sqs_role_arn?: string;
|
|
4026
|
+
sns_topic_arn?: string;
|
|
4027
|
+
sns_region?: string;
|
|
4028
|
+
sns_auth_type?: string;
|
|
4029
|
+
sns_key?: string;
|
|
4030
|
+
sns_secret?: string;
|
|
4031
|
+
sns_role_arn?: string;
|
|
4032
|
+
created_at?: string;
|
|
4033
|
+
updated_at?: string;
|
|
4034
|
+
};
|
|
@@ -438,7 +438,13 @@ export function createMergeCore<T extends object>(options: { trackDiff?: boolean
|
|
|
438
438
|
return false;
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
-
function createNewTarget(targetValue: unknown, srcValue:
|
|
441
|
+
function createNewTarget(targetValue: unknown, srcValue: object): object {
|
|
442
|
+
if (targetValue === null || typeof targetValue === 'undefined') {
|
|
443
|
+
return srcValue;
|
|
444
|
+
}
|
|
445
|
+
if (!Array.isArray(targetValue) && typeof targetValue !== 'object') {
|
|
446
|
+
return srcValue;
|
|
447
|
+
}
|
|
442
448
|
if (targetValue && typeof targetValue === 'object') {
|
|
443
449
|
// Check if it's a class instance (not a plain object)
|
|
444
450
|
const isTargetClassInstance = isClassInstance(targetValue);
|