@ermis-network/ermis-chat-sdk 1.0.9 → 2.0.1

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.
Files changed (54) hide show
  1. package/README.md +330 -0
  2. package/bin/init-call.js +9 -0
  3. package/dist/encryption/index.browser.cjs +13045 -0
  4. package/dist/encryption/index.browser.cjs.map +1 -0
  5. package/dist/encryption/index.browser.mjs +12959 -0
  6. package/dist/encryption/index.browser.mjs.map +1 -0
  7. package/dist/encryption/index.cjs +13045 -0
  8. package/dist/encryption/index.cjs.map +1 -0
  9. package/dist/encryption/index.d.mts +3 -0
  10. package/dist/encryption/index.d.ts +3 -0
  11. package/dist/encryption/index.mjs +12959 -0
  12. package/dist/encryption/index.mjs.map +1 -0
  13. package/dist/index-CcvHIY5q.d.mts +4988 -0
  14. package/dist/index-CcvHIY5q.d.ts +4988 -0
  15. package/dist/index.browser.cjs +20399 -6823
  16. package/dist/index.browser.cjs.map +1 -1
  17. package/dist/index.browser.full-bundle.min.js +20 -18
  18. package/dist/index.browser.full-bundle.min.js.map +1 -1
  19. package/dist/index.browser.mjs +20315 -6790
  20. package/dist/index.browser.mjs.map +1 -1
  21. package/dist/index.cjs +20400 -6824
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.mts +167 -1356
  24. package/dist/index.d.ts +167 -1356
  25. package/dist/index.mjs +20312 -6787
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/wasm_worker.worker.mjs +1600 -0
  28. package/dist/wasm_worker.worker.mjs.map +1 -0
  29. package/package.json +22 -7
  30. package/public/e2ee-media-stream-worker.js +627 -0
  31. package/public/ermis_call_node_wasm_bg.wasm +0 -0
  32. package/public/openmls_wasm_bg.wasm +0 -0
  33. package/src/attachment_utils.ts +0 -148
  34. package/src/auth.ts +0 -352
  35. package/src/channel.ts +0 -1806
  36. package/src/channel_state.ts +0 -607
  37. package/src/client.ts +0 -1617
  38. package/src/client_state.ts +0 -55
  39. package/src/connection.ts +0 -587
  40. package/src/ermis_call_node.ts +0 -978
  41. package/src/errors.ts +0 -60
  42. package/src/events.ts +0 -46
  43. package/src/hevc_decoder_config.ts +0 -305
  44. package/src/index.ts +0 -16
  45. package/src/media_stream_receiver.ts +0 -525
  46. package/src/media_stream_sender.ts +0 -400
  47. package/src/shims/empty.ts +0 -1
  48. package/src/signal_message.ts +0 -146
  49. package/src/system_message.ts +0 -117
  50. package/src/token_manager.ts +0 -48
  51. package/src/types.ts +0 -581
  52. package/src/utils.ts +0 -534
  53. package/src/wasm/ermis_call_node_wasm.d.ts +0 -154
  54. package/src/wasm/ermis_call_node_wasm.js +0 -1498
package/dist/index.d.ts CHANGED
@@ -1,1354 +1,69 @@
1
- import { AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios';
2
- import WebSocket from 'isomorphic-ws';
1
+ import { I as INodeCall, a as IMediaReceiverEvents, E as ExtendableGenerics, D as DefaultGenerics, b as ErmisChat, M as Metadata, U as UserCallInfo, C as CallEventData, c as ErmisChatOptions, L as Logger, A as APIErrorResponse, d as ErrorFromResponse, e as UserResponse, F as FormatMessageResponse, f as ForwardMessage, g as MessageResponse } from './index-CcvHIY5q.js';
2
+ export { h as APIResponse, i as ArchiveAckRecord, j as ArchiveAckStatus, k as ArchiveBlobRecord, l as ArchiveKeyWrapRecord, m as ArchiveMaterializationStatus, n as ArchiveScope, o as AscDesc, p as Attachment, q as AttachmentResponse, r as AudioConfig, B as BatchAddMembersToTopicsRequest, s as BatchAddMembersTopicBundle, t as BatchExternalJoinTopicBundle, u as BatchExternalJoinTopicsRequest, v as BatchTopicResponse, w as BatchTopicResult, x as BootstrapKnownE2eeChannelsOptions, y as BootstrapKnownE2eeChannelsResult, z as BrowserEncryptionStorage, G as CallAction, H as CallEventType, J as CallStatus, K as Channel, N as ChannelAPIResponse, O as ChannelData, P as ChannelFilters, Q as ChannelMemberResponse, R as ChannelMembership, S as ChannelQueryOptions, T as ChannelRepairState, V as ChannelRepairStatus, W as ChannelResponse, X as ChannelSort, Y as ChannelState, Z as ChannelStateOptions, _ as ChannelSyncResult, $ as CiphertextCursor, a0 as CiphertextQueryResponse, a1 as ClientState, a2 as CommitEvictionRequest, a3 as CommitEvictionResponse, a4 as CompleteE2eeAttachmentRequest, a5 as CompleteE2eeAttachmentResponse, a6 as ConnectAPIResponse, a7 as ConnectionOpen, a8 as Contact, a9 as ContactResponse, aa as ContactResult, ab as CreateTopicData, ac as DecryptResult, ad as DeleteE2eeAttachmentResponse, ae as DeviceKeyPackage, af as DownloadE2eeAttachmentGrantResponse, ag as E2EEAddMembersOptions, ah as E2EERemoveMembersOptions, ai as E2EE_ATTACHMENT_FRAME_SIZE, aj as E2EE_ATTACHMENT_MULTIPART_UPLOAD_DEFAULT_CONCURRENCY, ak as E2EE_ATTACHMENT_MULTIPART_UPLOAD_MAX_CONCURRENCY, al as E2EE_ATTACHMENT_MULTIPART_UPLOAD_URL_EXPIRY_SAFETY_MARGIN_MS, am as E2EE_ATTACHMENT_PREVIEW_JPEG_QUALITY, an as E2EE_ATTACHMENT_PREVIEW_MAX_SIDE, ao as E2EE_ATTACHMENT_VIDEO_PREVIEW_TIMEOUT_MS, ap as E2EE_MEDIA_STREAM_BASE_SESSION_CACHE_LIMIT, aq as E2EE_MEDIA_STREAM_FULL_REPLAY_CACHE_LIMIT, ar as E2EE_MEDIA_STREAM_GLOBAL_CACHE_LIMIT, as as E2EE_MEDIA_STREAM_PREFETCH_FRAMES, at as E2EE_MEDIA_STREAM_PREFETCH_THRESHOLD_FRAMES, au as E2EE_MEDIA_STREAM_SEQUENTIAL_PREFETCH_HITS, av as E2eeAttachmentAssetKind, aw as E2eeAttachmentCryptoProvider, ax as E2eeAttachmentHash, ay as E2eeAttachmentManifest, az as E2eeAttachmentManifestAsset, aA as E2eeAttachmentPreviewResult, aB as E2eeAttachmentTransferPhase, aC as E2eeAttachmentTransferProgress, aD as E2eeAttachmentUploadMode, aE as E2eeBootstrapProgress, aF as E2eeBootstrapStatus, aG as E2eeClient, aH as E2eeMediaFrameBatchPlan, aI as E2eeMediaFrameBatchPlanInput, aJ as E2eeMediaMp4ProbeResult, aK as E2eeMediaPlaybackStrategy, aL as E2eeMediaStreamHandle, aM as E2eeMediaStreamSessionOptions, aN as E2eeMediaStreamWorkerOptions, aO as E2eeMessageAadParams, aP as E2eePayload, aQ as E2eeRecoveryPolicy, aR as E2eeStoredMessage, aS as E2eeSyncEvent, aT as E2eeSyncState, aU as E2eeSyncStatus, aV as EVENT_MAP, aW as EditMessage, aX as EditTopicData, aY as EnableE2eeRequest, aZ as EncryptAssetOptions, a_ as EncryptMultipartAssetOptions, a$ as EncryptedAsset, b0 as EncryptedAssetMetadata, b1 as EncryptedChannelRepairMode, b2 as EncryptedChannelRepairResult, aG as EncryptionApiClient, b3 as EncryptionManager, b4 as EncryptionManagerOptions, b5 as EncryptionOperationResponse, b6 as EncryptionStorageAdapter, b7 as EncryptionSyncCheckpoint, b8 as EnsureE2eeChannelResult, b9 as EpochArchiveCheckpoint, ba as EpochIndexEntry, bb as Event, bc as EventCursor, bd as EventHandler, be as EventTypes, bf as ExternalJoinRequest, bg as FRAME_TYPE, bh as GetGroupInfoResponse, bi as GetKeyPackagesByCidResponse, bj as GetKeyPackagesResponse, bk as HistoricalCiphertext, z as IndexedDBEncryptionStorage, bl as InitE2eeAttachmentAssetResponse, bm as InitE2eeAttachmentMultipartPartResponse, bn as InitE2eeAttachmentMultipartResponse, bo as InitE2eeAttachmentRequest, bp as InitE2eeAttachmentResponse, bq as KeyPackageCountResponse, br as KeyRotationRequest, bs as ListArchiveAvailabilityResponse, bt as LiteralStringForUnion, bu as LogLevel, bv as LoggerOption, bw as MemberKeyPackages, bx as MemberSnapshotRecord, by as Message, bz as MessageBase, bA as MessageDisplayType, bB as MessageLabel, bC as MessageResponseBase, bD as MessageSetType, bE as MultipartEncryptedAssetPart, bF as MultipartEncryptedAssetUploadResult, bG as OpenMlsWasmModule, bH as PendingArchiveUpload, bI as PendingDeferredArchive, bJ as PendingE2eeSendRecord, bK as PendingE2eeSendStatus, bL as PendingE2eeSnapshot, bM as PollMessage, bN as ProtocolMessage, bO as ProtocolType, bP as PutPresignedObjectResult, bQ as QueryArchiveMaterialRequest, bR as QueryChannelAPIResponse, bS as QueryChannelsAPIResponse, bT as QueryE2eeAttachmentAssetProjection, bU as QueryE2eeAttachmentProjection, bV as QueryE2eeAttachmentsCursor, bW as QueryE2eeAttachmentsRequest, bX as QueryE2eeAttachmentsResponse, bY as QueryEpochArchivesRequest, bZ as QueryEpochArchivesResponse, b_ as QuerySponsoredArchiveRecipientsResponse, b$ as Reaction, c0 as ReactionAPIResponse, c1 as ReactionResponse, c2 as ReadResponse, c3 as RecoveryPublicKeyResponse, c4 as RecoveryStatus, c5 as RecoveryVaultResponse, c6 as RemovedChannelSyncData, c7 as RemovedChannelsSyncResult, c8 as RemovedSyncCursor, c9 as RepairIssue, ca as RepairIssueReason, cb as RepairIssueStatus, cc as RepairMessageResult, cd as RepairMode, ce as RepairResult, cf as RestorePermanentGapReason, cg as RestoreProgressRecord, ch as RestoreStatus, ci as RestoreTransientFailureReason, cj as RestoredMessage, ck as Role, cl as ScopeSyncEvent, cm as ScopeSyncResponse, cn as ScopeSyncResult, co as SendE2eeMessageRequest, cp as SendFileAPIResponse, cq as SendMessageAPIResponse, cr as Sha256, cs as SignalData, ct as SponsoredArchiveRecipient, cu as StableWSConnection, cv as TokenManager, cw as TransceiverState, cx as UR, cy as UnifiedSyncResponse, cz as UpdateChannelAPIResponse, cA as UpdateE2eeMessageRequest, cB as UploadEpochArchiveReason, cC as UploadEpochArchiveRequest, cD as UploadEpochArchiveResponse, cE as UploadGroupInfoRequest, cF as UploadKeyPackagesRequest, cG as UploadKeyPackagesResponse, cH as UploadRecoveryVaultRequest, cI as UploadRecoveryVaultResponse, cJ as UploadedE2eeAttachment, cK as UsersResponse, cL as VideoConfig, cM as VoiceRecordingMeta, cN as WaterfallResult, cO as base64ToBytes, cP as buildAttachmentManifest, cQ as buildAttachmentPayload, cR as buildE2eeMessageAadV1, cS as buildManifestAsset, cT as bytesEqual, cU as bytesToBase64, cV as canonicalAttachmentIds, cW as ciphertextSha256, cX as compareUuidRaw, cY as createE2eeAttachmentStreamUrl, cZ as decryptE2eeAsset, c_ as defaultE2eeAttachmentCryptoProvider, c$ as disposeAllE2eeAttachmentStreamSessions, d0 as disposeE2eeAttachmentStreamUrl, d1 as downloadEncryptedAsset, d2 as e2eeAttachmentMultipartUploadUrlExpiresAtMs, d3 as e2eeMediaFramePlainLength, d4 as e2eeMediaSessionCacheLimit, d5 as encryptAndUploadE2eeAssetMultipart, d6 as encryptE2eeAsset, d7 as ensureE2eeMediaStreamWorker, d8 as estimateE2eeEncryptedAssetSize, d9 as generateE2eeAttachmentPreview, da as getAttachmentCategory, db as hasE2eeAadMetadata, dc as isE2eeMediaMsePlaybackAllowed, dd as isE2eeMediaMsePlaybackEnabled, de as isHeicFile, df as isVideoFile, dg as loadOpenMlsWasm, dh as newUuid, di as normalizeFileName, dj as planE2eeMediaFrameBatch, dk as probeE2eeMediaMp4ForMse, dl as putPresignedObject, dm as putPresignedObjectWithResult, dn as resolveE2eeAttachmentMultipartUploadConcurrency, dp as sha256Hex, dq as uuidToRawBytes, dr as verifyEncryptedAssetHash, ds as webE2eeAttachmentCryptoProvider } from './index-CcvHIY5q.js';
3
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
4
+ import 'isomorphic-ws';
3
5
 
4
6
  /**
5
- * StableWSConnection - A WS connection that reconnects upon failure.
6
- * - the browser will sometimes report that you're online or offline
7
- * - the WS connection can break and fail (there is a 30s health check)
8
- * - sometimes your WS connection will seem to work while the user is in fact offline
9
- * - to speed up online/offline detection you can use the window.addEventListener('offline');
7
+ * WasmWorkerProxy Proxy class chạy trên Main Thread.
10
8
  *
11
- * There are 4 ways in which a connection can become unhealthy:
12
- * - websocket.onerror is called
13
- * - websocket.onclose is called
14
- * - the health check fails and no event is received for ~40 seconds
15
- * - the browser indicates the connection is now offline
9
+ * Implement interface INodeCall, nhưng mọi method call đều được forward
10
+ * tới Web Worker qua postMessage. Main Thread KHÔNG BAO GIỜ gọi WASM trực tiếp.
16
11
  *
17
- * There are 2 assumptions we make about the server:
18
- * - state can be recovered by querying the channel again
19
- * - if the servers fails to publish a message to the client, the WS connection is destroyed
12
+ * Data transfer dùng Transferable buffers (zero-copy).
20
13
  */
21
- declare class StableWSConnection<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
22
- client: ErmisChat<ErmisChatGenerics>;
23
- connectionOpen?: ConnectAPIResponse<ErmisChatGenerics>;
24
- consecutiveFailures: number;
25
- pingInterval: number;
26
- healthCheckTimeoutRef?: NodeJS.Timeout;
27
- isConnecting: boolean;
28
- isDisconnected: boolean;
29
- isHealthy: boolean;
30
- isResolved?: boolean;
31
- lastEvent: Date | null;
32
- connectionCheckTimeout: number;
33
- connectionCheckTimeoutRef?: NodeJS.Timeout;
34
- rejectPromise?: (reason?: Error & {
35
- code?: string | number;
36
- isWSFailure?: boolean;
37
- StatusCode?: string | number;
38
- }) => void;
39
- requestID: string | undefined;
40
- resolvePromise?: (value: ConnectionOpen<ErmisChatGenerics>) => void;
41
- totalFailures: number;
42
- ws?: WebSocket;
43
- wsID: number;
44
- constructor({ client }: {
45
- client: ErmisChat<ErmisChatGenerics>;
46
- });
47
- _log(msg: string, extra?: UR, level?: LogLevel): void;
48
- setClient(client: ErmisChat<ErmisChatGenerics>): void;
49
- connect(timeout?: number): Promise<void | ConnectionOpen<ErmisChatGenerics>>;
50
- /**
51
- * _waitForHealthy polls the promise connection to see if its resolved until it times out
52
- * the default 15s timeout allows between 2~3 tries
53
- * @param timeout duration(ms)
54
- */
55
- _waitForHealthy(timeout?: number): Promise<void | ConnectionOpen<ErmisChatGenerics>>;
56
- /**
57
- * Builds and returns the url for websocket.
58
- * @private
59
- * @returns url string
60
- */
61
- _buildUrl: () => string;
62
- /**
63
- * disconnect - Disconnect the connection and doesn't recover...
64
- *
65
- */
66
- disconnect(timeout?: number): Promise<void>;
67
- _connect(): Promise<ConnectionOpen<ErmisChatGenerics> | undefined>;
68
- /**
69
- * _reconnect - Retry the connection to WS endpoint
70
- *
71
- * @param {{ interval?: number; refreshToken?: boolean }} options Following options are available
72
- *
73
- * - `interval` {int} number of ms that function should wait before reconnecting
74
- * - `refreshToken` {boolean} reload/refresh user token be refreshed before attempting reconnection.
75
- */
76
- _reconnect(options?: {
77
- interval?: number;
78
- refreshToken?: boolean;
79
- }): Promise<void>;
80
- /**
81
- * onlineStatusChanged - this function is called when the browser connects or disconnects from the internet.
82
- *
83
- * @param {Event} event Event with type online or offline
84
- *
85
- */
86
- onlineStatusChanged: (event: Event) => void;
87
- onopen: (wsID: number) => void;
88
- onmessage: (wsID: number, event: WebSocket.MessageEvent) => void;
89
- onclose: (wsID: number, event: WebSocket.CloseEvent) => void;
90
- onerror: (wsID: number, event: WebSocket.ErrorEvent) => void;
91
- /**
92
- * _setHealth - Sets the connection to healthy or unhealthy.
93
- * Broadcasts an event in case the connection status changed.
94
- *
95
- * @param {boolean} healthy boolean indicating if the connection is healthy or not
96
- *
97
- */
98
- _setHealth: (healthy: boolean) => void;
99
- /**
100
- * _errorFromWSEvent - Creates an error object for the WS event
101
- *
102
- */
103
- _errorFromWSEvent: (event: WebSocket.CloseEvent | WebSocket.Data | WebSocket.ErrorEvent, isWSFailure?: boolean) => Error & {
104
- code?: string | number;
105
- isWSFailure?: boolean;
106
- StatusCode?: string | number;
107
- };
108
- /**
109
- * _destroyCurrentWSConnection - Removes the current WS connection
110
- *
111
- */
112
- _destroyCurrentWSConnection(): void;
113
- /**
114
- * _setupPromise - sets up the this.connectOpen promise
115
- */
116
- _setupConnectionPromise: () => void;
117
- /**
118
- * Schedules a next health check ping for websocket.
119
- */
120
- scheduleNextPing: () => void;
121
- /**
122
- * scheduleConnectionCheck - schedules a check for time difference between last received event and now.
123
- * If the difference is more than 35 seconds, it means our health check logic has failed and websocket needs
124
- * to be reconnected.
125
- */
126
- scheduleConnectionCheck: () => void;
127
- }
128
-
129
- declare const EVENT_MAP: {
130
- 'channel.created': boolean;
131
- 'channel.deleted': boolean;
132
- 'channel.truncate': boolean;
133
- 'channel.updated': boolean;
134
- 'channel.pinned': boolean;
135
- 'channel.unpinned': boolean;
136
- 'health.check': boolean;
137
- 'member.added': boolean;
138
- 'member.removed': boolean;
139
- 'member.updated': boolean;
140
- 'member.joined': boolean;
141
- 'member.promoted': boolean;
142
- 'member.demoted': boolean;
143
- 'member.banned': boolean;
144
- 'member.unbanned': boolean;
145
- 'member.blocked': boolean;
146
- 'member.unblocked': boolean;
147
- 'message.deleted': boolean;
148
- 'message.deleted_for_me': boolean;
149
- 'message.new': boolean;
150
- 'message.read': boolean;
151
- 'message.updated': boolean;
152
- 'message.pinned': boolean;
153
- 'message.unpinned': boolean;
154
- 'notification.channel_deleted': boolean;
155
- 'notification.invite_accepted': boolean;
156
- 'notification.invite_rejected': boolean;
157
- 'notification.invite_messaging_skipped': boolean;
158
- 'pollchoice.new': boolean;
159
- 'reaction.deleted': boolean;
160
- 'reaction.new': boolean;
161
- 'typing.start': boolean;
162
- 'typing.stop': boolean;
163
- 'user.watching.start': boolean;
164
- 'user.watching.stop': boolean;
165
- 'connection.changed': boolean;
166
- 'connection.recovered': boolean;
167
- 'capabilities.changed': boolean;
168
- 'channel.topic.disabled': boolean;
169
- 'channel.topic.enabled': boolean;
170
- 'channel.topic.created': boolean;
171
- 'channel.topic.closed': boolean;
172
- 'channel.topic.reopen': boolean;
173
- 'channel.topic.updated': boolean;
174
- };
175
-
176
- type Role = 'owner' | 'moder' | 'member' | 'pending' | 'skipped' | string;
177
- type UR = Record<string, unknown>;
178
- type DefaultGenerics = {
179
- attachmentType: UR;
180
- channelType: UR;
181
- commandType: LiteralStringForUnion;
182
- eventType: UR;
183
- messageType: UR;
184
- pollOptionType: UR;
185
- pollType: UR;
186
- reactionType: UR;
187
- userType: UR;
188
- };
189
- type ExtendableGenerics = {
190
- attachmentType: UR;
191
- channelType: UR;
192
- commandType: string;
193
- eventType: UR;
194
- messageType: UR;
195
- pollOptionType: UR;
196
- pollType: UR;
197
- reactionType: UR;
198
- userType: UR;
199
- };
200
- /**
201
- * Response Types
202
- */
203
- type APIResponse = {
204
- duration?: string;
205
- };
206
- type ChannelResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['channelType'] & {
207
- cid: string;
208
- id: string;
209
- type: string;
210
- created_at?: string;
211
- created_by?: UserResponse<ErmisChatGenerics> | null;
212
- deleted_at?: string;
213
- last_message_at?: string;
214
- member_count?: number;
215
- members: ChannelMemberResponse<ErmisChatGenerics>[];
216
- name?: string;
217
- own_capabilities?: string[];
218
- updated_at?: string;
219
- image?: string;
220
- description?: string;
221
- member_message_cooldown?: number;
222
- member_capabilities?: string[];
223
- is_pinned?: boolean;
224
- topics_enabled?: boolean;
225
- parent_cid?: string;
226
- is_closed_topic?: boolean;
227
- };
228
- type QueryChannelsAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
229
- channels: Omit<ChannelAPIResponse<ErmisChatGenerics>, keyof APIResponse>[];
230
- };
231
- type QueryChannelAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & ChannelAPIResponse<ErmisChatGenerics>;
232
- type ChannelAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
233
- channel: ChannelResponse<ErmisChatGenerics>;
234
- members: ChannelMemberResponse<ErmisChatGenerics>[];
235
- messages: MessageResponse<ErmisChatGenerics>[];
236
- pinned_messages: MessageResponse<ErmisChatGenerics>[];
237
- membership?: ChannelMembership<ErmisChatGenerics> | null;
238
- read?: ReadResponse<ErmisChatGenerics>[];
239
- topics?: QueryChannelAPIResponse<ErmisChatGenerics>[];
240
- watcher_count?: number;
241
- watchers?: UserResponse<ErmisChatGenerics>[];
242
- is_pinned?: boolean;
243
- };
244
- type ChannelMemberResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
245
- banned?: boolean;
246
- blocked?: boolean;
247
- channel_role?: Role;
248
- created_at?: string;
249
- updated_at?: string;
250
- user?: UserResponse<ErmisChatGenerics>;
251
- user_id?: string;
252
- };
253
- type ConnectAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = Promise<void | ConnectionOpen<ErmisChatGenerics>>;
254
- type FormatMessageResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = Omit<MessageResponse<{
255
- attachmentType: ErmisChatGenerics['attachmentType'];
256
- channelType: ErmisChatGenerics['channelType'];
257
- commandType: ErmisChatGenerics['commandType'];
258
- eventType: ErmisChatGenerics['eventType'];
259
- messageType: {};
260
- pollOptionType: ErmisChatGenerics['pollOptionType'];
261
- pollType: ErmisChatGenerics['pollType'];
262
- reactionType: ErmisChatGenerics['reactionType'];
263
- userType: ErmisChatGenerics['userType'];
264
- }>, 'created_at' | 'pinned_at' | 'updated_at' | 'status'> & ErmisChatGenerics['messageType'] & {
265
- created_at: Date;
266
- pinned_at: Date | null;
267
- status: string;
268
- updated_at: Date;
269
- };
270
- type MessageResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = MessageResponseBase<ErmisChatGenerics> & {
271
- quoted_message?: MessageResponseBase<ErmisChatGenerics>;
272
- };
273
- type MessageResponseBase<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = MessageBase<ErmisChatGenerics> & {
274
- type: MessageLabel;
275
- channel?: ChannelResponse<ErmisChatGenerics>;
276
- cid?: string;
277
- created_at?: string;
278
- deleted_at?: string;
279
- latest_reactions?: ReactionResponse<ErmisChatGenerics>[];
280
- mentioned_users?: string[];
281
- own_reactions?: ReactionResponse<ErmisChatGenerics>[] | null;
282
- pinned_at?: string | null;
283
- pinned_by?: UserResponse<ErmisChatGenerics> | null;
284
- reaction_counts?: {
285
- [key: string]: number;
286
- } | null;
287
- reaction_scores?: {
288
- [key: string]: number;
289
- } | null;
290
- reply_count?: number;
291
- status?: string;
292
- updated_at?: string;
293
- };
294
- type ReactionAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
295
- message: MessageResponse<ErmisChatGenerics>;
296
- reaction: ReactionResponse<ErmisChatGenerics>;
297
- };
298
- type ReactionResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = Reaction<ErmisChatGenerics> & {
299
- created_at: string;
300
- message_id: string;
301
- updated_at: string;
302
- };
303
- type ReadResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
304
- last_read: string;
305
- user: UserResponse<ErmisChatGenerics>;
306
- last_read_message_id?: string;
307
- unread_messages?: number;
308
- last_send?: string;
309
- };
310
- type SendFileAPIResponse = APIResponse & {
311
- file: string;
312
- thumb_url?: string;
313
- };
314
- type SendMessageAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
315
- message: MessageResponse<ErmisChatGenerics>;
316
- };
317
- type UpdateChannelAPIResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
318
- channel: ChannelResponse<ErmisChatGenerics>;
319
- members: ChannelMemberResponse<ErmisChatGenerics>[];
320
- message?: MessageResponse<ErmisChatGenerics>;
321
- };
322
- type UserResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['userType'] & {
323
- id: string;
324
- name?: string;
325
- avatar?: string;
326
- about_me?: string;
327
- project_id?: string;
328
- email?: string;
329
- phone?: string;
330
- };
331
- type Contact = {
332
- project_id: string;
333
- user_id: string;
334
- other_id: string;
335
- relation_status: string;
336
- created_at: string;
337
- updated_at: string;
338
- };
339
- type ContactResponse = APIResponse & {
340
- project_id_user_ids: {
341
- [key: string]: Contact[];
342
- };
343
- };
344
- type ContactResult<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
345
- contact_users: UserResponse<ErmisChatGenerics>[];
346
- block_users: UserResponse<ErmisChatGenerics>[];
347
- };
348
- type ChannelQueryOptions = {
349
- messages?: {
350
- limit?: number;
351
- id_lt?: string;
352
- id_gt?: string;
353
- id_around?: string;
354
- };
355
- };
356
- type ChannelStateOptions = {
357
- offlineMode?: boolean;
358
- skipInitialization?: string[];
359
- };
360
- type ErmisChatOptions = AxiosRequestConfig & {
361
- /**
362
- * Used to disable warnings that are triggered by using connectUser or connectAnonymousUser server-side.
363
- */
364
- allowServerSideConnect?: boolean;
365
- axiosRequestConfig?: AxiosRequestConfig;
366
- /**
367
- * Base url for User BE API (uss/v1). Defaults to baseURL + '/uss/v1' if not provided.
368
- */
369
- userBaseURL?: string;
370
- browser?: boolean;
371
- enableInsights?: boolean;
372
- /** experimental feature, please contact support if you want this feature enabled for you */
373
- logger?: Logger;
374
- /**
375
- * When network is recovered, we re-query the active channels on client. But in single query, you can recover
376
- * only 30 channels. So its not guaranteed that all the channels in activeChannels object have updated state.
377
- * Thus in UI sdks, state recovery is managed by components themselves, they don't rely on js client for this.
378
- *
379
- * `recoverStateOnReconnect` parameter can be used in such cases, to disable state recovery within js client.
380
- * When false, user/consumer of this client will need to make sure all the channels present on UI by
381
- * manually calling queryChannels endpoint.
382
- */
383
- recoverStateOnReconnect?: boolean;
384
- warmUp?: boolean;
385
- wsConnection?: StableWSConnection;
386
- };
387
- /**
388
- * Event Types
389
- */
390
- type Event$1<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['eventType'] & {
391
- type: EventTypes;
392
- channel?: ChannelResponse<ErmisChatGenerics>;
393
- channel_id?: string;
394
- channel_type?: string;
395
- cid?: string;
396
- created_at?: string;
397
- hard_delete?: boolean;
398
- last_read_at?: string;
399
- last_read_message_id?: string;
400
- me?: UserResponse<ErmisChatGenerics>;
401
- member?: ChannelMemberResponse<ErmisChatGenerics>;
402
- message?: MessageResponse<ErmisChatGenerics>;
403
- online?: boolean;
404
- parent_id?: string;
405
- parent_cid?: string;
406
- reaction?: ReactionResponse<ErmisChatGenerics>;
407
- received_at?: string | Date;
408
- unread_messages?: number;
409
- user?: UserResponse<ErmisChatGenerics>;
410
- user_id?: string;
411
- watcher_count?: number;
412
- };
413
- type EventHandler<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = (event: Event$1<ErmisChatGenerics>) => void;
414
- type EventTypes = 'all' | keyof typeof EVENT_MAP;
415
- /**
416
- * Filter Types
417
- */
418
- type AscDesc = 1 | -1;
419
- type ChannelFilters = {
420
- project_id?: string;
421
- type: ('messaging' | 'team' | 'topic')[];
422
- limit?: number;
423
- offset?: number;
424
- roles?: string[];
425
- other_roles?: string[];
426
- banned?: boolean;
427
- blocked?: boolean;
428
- include_pinned_messages?: boolean;
429
- parent_cid?: string;
430
- parent_id?: string;
431
- include_parent?: boolean;
432
- };
433
- type CreateTopicData = {
434
- name: string;
435
- image?: string;
436
- [key: string]: any;
437
- };
438
- type EditTopicData = {
439
- name?: string;
440
- image?: string;
441
- description?: string;
442
- };
443
- type ChannelSort = {
444
- field: string;
445
- direction: -1 | 1;
446
- }[];
447
- type Attachment<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['attachmentType'] & {
448
- id?: string;
449
- thumb_url?: string;
450
- content_disposition?: string;
451
- content_length?: number;
452
- content_type?: string;
453
- updated_at?: string;
454
- created_at?: string;
455
- message_id?: string;
456
- file_name?: string;
457
- url?: string;
458
- cid?: string;
459
- user_id?: string;
460
- asset_url?: string;
461
- author_icon?: string;
462
- author_link?: string;
463
- author_name?: string;
464
- color?: string;
465
- duration?: number;
466
- fallback?: string;
467
- file_size?: number | string;
468
- footer?: string;
469
- footer_icon?: string;
470
- image_url?: string;
471
- mime_type?: string;
472
- og_scrape_url?: string;
473
- original_height?: number;
474
- original_width?: number;
475
- pretext?: string;
476
- text?: string;
477
- title?: string;
478
- title_link?: string;
479
- type?: string;
480
- waveform_data?: Array<number>;
481
- link_url?: string;
482
- };
483
- type ChannelData<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['channelType'] & {
484
- members?: string[];
485
- name?: string;
486
- is_pinned?: boolean;
487
- };
488
- type ChannelMembership<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
489
- banned?: boolean;
490
- blocked?: boolean;
491
- channel_role?: Role;
492
- created_at?: string;
493
- updated_at?: string;
494
- user?: UserResponse<ErmisChatGenerics>;
495
- };
496
- type ConnectionOpen<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
497
- cid?: string;
498
- created_at?: string;
499
- me?: UserResponse<ErmisChatGenerics>;
500
- type?: string;
501
- };
502
- type LiteralStringForUnion = string & {};
503
- type LogLevel = 'info' | 'error' | 'warn';
504
- type Logger = (logLevel: LogLevel, message: string, extraData?: Record<string, unknown>) => void;
505
- type Message<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = Partial<MessageBase<ErmisChatGenerics>> & {
506
- id?: string;
507
- mentioned_all?: boolean;
508
- mentioned_users?: string[];
509
- cid?: string;
510
- forward_cid?: string;
511
- forward_message_id?: string;
512
- poll_type?: string;
513
- poll_choices?: string[];
514
- sticker_url?: string;
515
- };
516
- type EditMessage = {
517
- text: string;
518
- mentioned_all?: boolean;
519
- mentioned_users?: string[];
520
- };
521
- type ForwardMessage<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
522
- cid: string;
523
- forward_cid: string;
524
- forward_message_id: string;
525
- id?: string;
526
- text?: string;
527
- attachments?: Attachment<ErmisChatGenerics>[];
528
- sticker_url?: string;
529
- };
530
- type PollMessage = {
531
- id?: string;
532
- text: string;
533
- poll_type: string;
534
- poll_choices: string[];
535
- };
536
- type MessageBase<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['messageType'] & {
537
- id: string;
538
- attachments?: Attachment[];
539
- html?: string;
540
- mml?: string;
541
- parent_id?: string;
542
- pinned?: boolean;
543
- pinned_at?: string | null;
544
- quoted_message_id?: string;
545
- text?: string;
546
- user?: UserResponse | null;
547
- user_id?: string;
548
- };
549
- type MessageLabel = 'regular' | 'system' | 'signal' | 'poll' | 'sticker' | 'error';
550
- type Reaction<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = ErmisChatGenerics['reactionType'] & {
551
- type: string;
552
- message_id?: string;
553
- score?: number;
554
- user?: UserResponse | null;
555
- user_id?: string;
556
- };
557
- type MessageSetType = 'latest' | 'current' | 'new';
558
- type APIErrorResponse = {
559
- code: number;
560
- duration: string;
561
- message: string;
562
- more_info: string;
563
- StatusCode: number;
564
- };
565
- declare class ErrorFromResponse<T> extends Error {
566
- code?: number;
567
- response?: AxiosResponse<T>;
568
- status?: number;
569
- }
570
- type UsersResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
571
- data: Array<UserResponse<ErmisChatGenerics>>;
572
- count: number;
573
- total: number;
574
- page: number;
575
- page_count: number;
576
- };
577
- type AttachmentResponse<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
578
- attachments: Attachment<ErmisChatGenerics>[];
579
- };
580
- type SignalData = {
581
- cid?: string;
582
- is_video?: boolean;
583
- action?: string;
584
- signal?: Object;
585
- metadata?: Object;
586
- };
587
- declare enum CallAction {
588
- CREATE_CALL = "create-call",
589
- ACCEPT_CALL = "accept-call",
590
- SIGNAL_CALL = "signal-call",
591
- CONNECT_CALL = "connect-call",
592
- HEALTH_CALL = "health-call",
593
- END_CALL = "end-call",
594
- REJECT_CALL = "reject-call",
595
- MISS_CALL = "miss-call",
596
- UPGRADE_CALL = "upgrade-call"
597
- }
598
- declare enum CallStatus {
599
- RINGING = "ringing",
600
- ENDED = "ended",
601
- CONNECTED = "connected",
602
- ERROR = "error"
603
- }
604
- type CallEventType = 'incoming' | 'outgoing';
605
- type CallEventData = {
606
- type: CallEventType;
607
- callType: string;
608
- cid: string;
609
- callerInfo: UserCallInfo | undefined;
610
- receiverInfo: UserCallInfo | undefined;
611
- metadata?: Object;
612
- };
613
- type UserCallInfo = {
614
- id: string;
615
- name?: string;
616
- avatar?: string;
617
- };
618
- type Metadata = {
619
- address?: string;
620
- };
621
- type INodeCall = {
622
- connect: (address: string) => Promise<void>;
623
- acceptConnection: () => Promise<void>;
624
- sendControlFrame: (packet: Uint8Array) => Promise<void>;
625
- sendAudioFrame: (packet: Uint8Array) => Promise<void>;
626
- sendFrame: (packet: Uint8Array) => Promise<void>;
627
- beginWithGop: (packet: Uint8Array) => Promise<void>;
628
- asyncRecv: () => Promise<Uint8Array>;
629
- };
630
- type VideoConfig = {
631
- codec: string;
632
- codedWidth: number;
633
- codedHeight: number;
634
- frameRate?: number;
635
- orientation?: number;
636
- rotation?: number;
637
- description?: any;
638
- };
639
- type AudioConfig = {
640
- codec: string;
641
- sampleRate: number;
642
- numberOfChannels: number;
643
- description?: string;
644
- };
645
- type TransceiverState = {
646
- audio_enable: boolean;
647
- video_enable: boolean;
648
- };
649
- interface IMediaReceiverEvents {
650
- onConnected?: () => void;
651
- onTransceiverState?: (state: any) => void;
652
- onRequestConfig?: () => void;
653
- onRequestKeyFrame?: () => void;
654
- onEndCall?: () => void;
655
- }
656
- declare enum FRAME_TYPE {
657
- VIDEO_CONFIG = 0,
658
- AUDIO_CONFIG = 1,
659
- VIDEO_KEY = 2,
660
- VIDEO_DELTA = 3,
661
- AUDIO = 4,
662
- ORIENTATION = 5,
663
- CONNECTED = 6,
664
- TRANSCEIVER_STATE = 7,
665
- REQUEST_CONFIG = 8,
666
- REQUEST_KEY_FRAME = 9,
667
- END_CALL = 10
668
- }
669
-
670
- type ChannelReadStatus<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> = Record<string, {
671
- last_read: Date;
672
- unread_messages: number;
673
- user: UserResponse<ErmisChatGenerics>;
674
- last_read_message_id?: string;
675
- last_send?: string;
676
- }>;
677
- /**
678
- * ChannelState - A container class for the channel state.
679
- * This class synchronously binds to a `Channel` and holds the single source of truth for
680
- * messages, read status, watchers, and typing indicators locally on the client.
681
- */
682
- declare class ChannelState<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
683
- _channel: Channel<ErmisChatGenerics>;
684
- /** The current count of users actively watching (having an open WebSocket) this channel. */
685
- watcher_count: number;
686
- /** A dictionary of active typing events gracefully keyed by the user's ID. */
687
- typing: Record<string, Event$1<ErmisChatGenerics>>;
688
- /** A dictionary of read states mapped per user's ID detailing the last viewed message. */
689
- read: ChannelReadStatus<ErmisChatGenerics>;
690
- /** The locally cached array of pinned messages across the channel. */
691
- pinnedMessages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>;
692
- /** A directory of users actively watching the channel, keyed by User ID. */
693
- watchers: Record<string, UserResponse<ErmisChatGenerics>>;
694
- /** A comprehensive directory mapping user IDs to their member status in the channel. */
695
- members: Record<string, ChannelMemberResponse<ErmisChatGenerics>>;
696
- /** The count of messages not yet read by the currently authenticated user. */
697
- unreadCount: number;
698
- /** Information detailing the authenticated user's own membership relation to this channel. */
699
- membership: ChannelMembership<ErmisChatGenerics>;
700
- /** Timestamp indicating when the very last message was created in this chat. */
701
- last_message_at: Date | null;
702
- /** Designates if the local channel state is entirely synchronized with the backend history. */
703
- isUpToDate: boolean;
704
- messageSets: {
705
- isCurrent: boolean;
706
- isLatest: boolean;
707
- messages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>;
708
- }[];
709
- topics?: Channel<ErmisChatGenerics>[];
710
- constructor(channel: Channel<ErmisChatGenerics>);
711
- get messages(): Array<ReturnType<ChannelState<ErmisChatGenerics>["formatMessage"]>>;
712
- set messages(messages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>);
713
- get latestMessages(): Array<ReturnType<ChannelState<ErmisChatGenerics>["formatMessage"]>>;
714
- set latestMessages(messages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>);
715
- /**
716
- * Pushes a new message directly into the sorted array of the local tracking state.
717
- * Useful to achieve optimistic UI updates locally.
718
- *
719
- * @param newMessage - The message context payload to insert.
720
- * @param timestampChanged - Specifies if the underlying `created_at` timestamp mutated.
721
- * @param addIfDoesNotExist - Append it strictly if its ID doesn't already exist.
722
- * @param messageSetToAddToIfDoesNotExist - Specifies which message set scope to manipulate.
723
- */
724
- addMessageSorted(newMessage: MessageResponse<ErmisChatGenerics>, timestampChanged?: boolean, addIfDoesNotExist?: boolean, messageSetToAddToIfDoesNotExist?: MessageSetType): {
725
- messageSet: {
726
- isCurrent: boolean;
727
- isLatest: boolean;
728
- messages: Array<ReturnType<ChannelState<ErmisChatGenerics>["formatMessage"]>>;
729
- };
730
- };
731
- formatMessage(message: MessageResponse<ErmisChatGenerics>): FormatMessageResponse<ErmisChatGenerics>;
732
- addMessagesSorted(newMessages: MessageResponse<ErmisChatGenerics>[], timestampChanged?: boolean, initializing?: boolean, addIfDoesNotExist?: boolean, messageSetToAddToIfDoesNotExist?: MessageSetType): {
733
- messageSet: {
734
- isCurrent: boolean;
735
- isLatest: boolean;
736
- messages: Array<ReturnType<ChannelState<ErmisChatGenerics>["formatMessage"]>>;
737
- };
738
- };
739
- addPinnedMessages(pinnedMessages: MessageResponse<ErmisChatGenerics>[]): void;
740
- addPinnedMessage(pinnedMessage: MessageResponse<ErmisChatGenerics>): void;
741
- removePinnedMessage(message: MessageResponse<ErmisChatGenerics>): void;
742
- addReaction(reaction: ReactionResponse<ErmisChatGenerics>, message?: MessageResponse<ErmisChatGenerics>, enforce_unique?: boolean): MessageResponse<ErmisChatGenerics> | undefined;
743
- _addOwnReactionToMessage(ownReactions: ReactionResponse<ErmisChatGenerics>[] | null | undefined, reaction: ReactionResponse<ErmisChatGenerics>, enforce_unique?: boolean): ReactionResponse<ErmisChatGenerics>[];
744
- _removeOwnReactionFromMessage(ownReactions: ReactionResponse<ErmisChatGenerics>[] | null | undefined, reaction: ReactionResponse<ErmisChatGenerics>): ReactionResponse<ErmisChatGenerics>[] | null | undefined;
745
- removeReaction(reaction: ReactionResponse<ErmisChatGenerics>, message?: MessageResponse<ErmisChatGenerics>): MessageResponse<ErmisChatGenerics> | undefined;
746
- removeQuotedMessageReferences(message: MessageResponse<ErmisChatGenerics>): void;
747
- _updateMessage(message: {
748
- id?: string;
749
- parent_id?: string;
750
- pinned?: boolean;
751
- }, updateFunc: (msg: ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>) => ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>): void;
752
- setIsUpToDate: (isUpToDate: boolean) => void;
753
- /**
754
- * Update the status of a message by ID (used for optimistic UI).
755
- */
756
- updateMessageStatus(messageId: string, status: string): void;
757
- _addToMessageList(messages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>, message: ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>, timestampChanged?: boolean, sortBy?: 'pinned_at' | 'created_at', addIfDoesNotExist?: boolean): FormatMessageResponse<ErmisChatGenerics>[];
758
- removeMessage(messageToRemove: {
759
- id: string;
760
- messageSetIndex?: number;
761
- parent_id?: string;
762
- }): boolean;
763
- removeMessageFromArray: (msgArray: Array<ReturnType<ChannelState<ErmisChatGenerics>["formatMessage"]>>, msg: {
764
- id: string;
765
- parent_id?: string;
766
- }) => {
767
- removed: boolean;
768
- result: FormatMessageResponse<ErmisChatGenerics>[];
769
- };
770
- /**
771
- * Refreshes internal user references cascading across all presently active messages.
772
- * Invoked instantly whenever an underlying user's profile metadata updates (e.g. name or avatar changes).
773
- *
774
- * @param user - The newly formatted and populated User details object.
775
- */
776
- updateUserMessages: (user: UserResponse<ErmisChatGenerics>) => void;
777
- deleteUserMessages: (user: UserResponse<ErmisChatGenerics>, hardDelete?: boolean) => void;
778
- filterErrorMessages(): void;
779
- clean(): void;
780
- clearMessages(): void;
781
- initMessages(): void;
782
- loadMessageIntoState(messageId: string | 'latest', parentMessageId?: string, limit?: number): Promise<void>;
783
- findMessage(messageId: string, parentMessageId?: string): FormatMessageResponse<ErmisChatGenerics> | undefined;
784
- private switchToMessageSet;
785
- private areMessageSetsOverlap;
786
- private findMessageSetIndex;
787
- private findTargetMessageSet;
788
- }
789
-
790
- /**
791
- * Normalize a file name for upload:
792
- * - Remove Vietnamese diacritics
793
- * - Replace đ/Đ with d/D
794
- * - Replace spaces with underscores
795
- * - Preserve extension
796
- */
797
- declare function normalizeFileName(name: string): string;
798
- /**
799
- * Check if a MIME type or file extension is HEIC/HEIF.
800
- */
801
- declare function isHeicFile(file: File): boolean;
802
- /**
803
- * Categorize a file by MIME type.
804
- * HEIC/HEIF files are treated as 'file' (not 'image') since browsers can't render them.
805
- */
806
- declare function getAttachmentCategory(mimeType: string, fileName?: string): 'image' | 'video' | 'audio' | 'file';
807
- /**
808
- * Check if a file is a video type that supports thumbnail extraction.
809
- */
810
- declare function isVideoFile(file: File): boolean;
811
- /**
812
- * Metadata for voice recording attachments.
813
- */
814
- type VoiceRecordingMeta = {
815
- waveform_data: number[];
816
- duration: number;
817
- };
818
- /**
819
- * Build a normalized attachment payload from an uploaded file.
820
- *
821
- * @param file - Original file object
822
- * @param uploadedUrl - URL returned by the upload API
823
- * @param thumbUrl - Optional thumbnail URL (for video)
824
- * @param voiceMeta - Optional voice recording metadata
825
- */
826
- declare function buildAttachmentPayload(file: File, uploadedUrl: string, thumbUrl?: string, voiceMeta?: VoiceRecordingMeta): Attachment;
827
-
828
- /**
829
- * Represents a Channel in the Ermis Network.
830
- * Channels handle chat sessions, livestream messages, teams, or video calls.
831
- * This class abstracts and exposes all API operations you can perform on a specific channel instance.
832
- */
833
- declare class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
834
- _client: ErmisChat<ErmisChatGenerics>;
835
- type: string;
836
- id: string | undefined;
837
- data: ChannelData<ErmisChatGenerics> | ChannelResponse<ErmisChatGenerics> | undefined;
838
- _data: ChannelData<ErmisChatGenerics> | ChannelResponse<ErmisChatGenerics>;
839
- cid: string;
840
- listeners: {
841
- [key: string]: (string | EventHandler<ErmisChatGenerics>)[];
842
- };
843
- state: ChannelState<ErmisChatGenerics>;
844
- initialized: boolean;
845
- offlineMode: boolean;
846
- lastKeyStroke?: Date;
847
- lastTypingEvent: Date | null;
848
- isTyping: boolean;
849
- disconnected: boolean;
850
- /**
851
- * Initializes a new Channel class instance.
852
- * Normally you should not call this directly; use `client.channel(type, id)` instead.
853
- *
854
- * @param client - The shared ErmisChat client instance initializing this channel.
855
- * @param type - The type of channel (`messaging`, `team`, `livestream`, etc.).
856
- * @param id - The unique ID of the channel.
857
- * @param data - Initial arbitrary metadata stored within this channel.
858
- */
859
- constructor(client: ErmisChat<ErmisChatGenerics>, type: string, id: string | undefined, data: ChannelData<ErmisChatGenerics>);
860
- getClient(): ErmisChat<ErmisChatGenerics>;
861
- /**
862
- * Sends a message to this channel.
863
- * By default, it pushes the message eagerly (optimistically) to the local UI state before the server replies.
864
- *
865
- * @param message - The constructed text/attachment object payload representing the message.
866
- * @returns A Promise resolving to the exact API response encompassing message details.
867
- */
868
- sendMessage(message: Message<ErmisChatGenerics>): Promise<SendMessageAPIResponse<ErmisChatGenerics>>;
869
- retryMessage(messageId: string): Promise<SendMessageAPIResponse<ErmisChatGenerics>>;
870
- createPoll(pollMessage: PollMessage): Promise<SendMessageAPIResponse<ErmisChatGenerics>>;
871
- votePoll(messageID: string, pollChoice: string): Promise<APIResponse>;
872
- forwardMessage(message: ForwardMessage<ErmisChatGenerics>, channel: {
873
- type: string;
874
- channelID: string;
875
- }): Promise<SendMessageAPIResponse<ErmisChatGenerics>>;
876
- pinMessage(messageID: string): Promise<unknown>;
877
- unpinMessage(messageID: string): Promise<unknown>;
878
- pin(): Promise<APIResponse>;
879
- unpin(): Promise<APIResponse>;
880
- editMessage(oldMessageID: string, message: EditMessage): Promise<unknown>;
881
- sendFile(uri: string | NodeJS.ReadableStream | Buffer | File, name?: string, contentType?: string, user?: UserResponse<ErmisChatGenerics>): Promise<SendFileAPIResponse>;
882
- /**
883
- * Pre-process files (normalize names), upload them in parallel,
884
- * generate video thumbnails, and build attachment payloads.
885
- *
886
- * @param files - Array of File objects to upload
887
- * @param options - Optional voice recording metadata
888
- * @returns `attachments` ready for sendMessage, and `failedFiles` for error display
889
- */
890
- uploadAndPrepareAttachments(files: File[], options?: {
891
- /** Map from file index → voice recording metadata */
892
- voiceMetadata?: Map<number, VoiceRecordingMeta>;
893
- }): Promise<{
894
- attachments: Attachment[];
895
- failedFiles: Array<{
896
- file: File;
897
- error: Error;
898
- }>;
899
- }>;
900
- sendEvent(event: Event$1<ErmisChatGenerics>): Promise<unknown>;
901
- sendReaction(messageID: string, reactionType: string): Promise<ReactionAPIResponse<ErmisChatGenerics>>;
902
- deleteReaction(messageID: string, reactionType: string): Promise<ReactionAPIResponse<ErmisChatGenerics>>;
903
- update(channelData?: Partial<ChannelData<ErmisChatGenerics>> | Partial<ChannelResponse<ErmisChatGenerics>>, updateMessage?: Message<ErmisChatGenerics>): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
904
- delete(): Promise<unknown>;
905
- truncate(): Promise<unknown>;
906
- blockUser(): Promise<unknown>;
907
- unblockUser(): Promise<unknown>;
908
- acceptInvite(action: string): Promise<APIResponse>;
909
- rejectInvite(): Promise<APIResponse>;
910
- skipInvite(): Promise<APIResponse>;
911
- /**
912
- * Directly invites or adds registered users into this channel.
913
- *
914
- * @param members - Array of user IDs explicitly selected to be added.
915
- */
916
- addMembers(members: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
917
- addModerators(members: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
918
- banMembers(members: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
919
- unbanMembers(members: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
920
- updateCapabilities(capabilities: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
921
- /**
922
- * Set slow mode (message cooldown) for the channel.
923
- * Only applicable to team channels. Prevents members from sending
924
- * messages faster than the specified cooldown interval.
925
- *
926
- * @param cooldown - Cooldown duration in milliseconds.
927
- * Allowed values: 0 (off), 10000 (10s), 30000 (30s),
928
- * 60000 (1min), 300000 (5min), 900000 (15min), 3600000 (1h).
929
- */
930
- setSlowMode(cooldown: 0 | 10000 | 30000 | 60000 | 300000 | 900000 | 3600000): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
931
- queryAttachmentMessages(): Promise<AttachmentResponse<ErmisChatGenerics>>;
932
- searchMessage(search_term: string, offset: number): Promise<any>;
933
- /**
934
- * Expels specified currently participating users out of the channel.
935
- *
936
- * @param members - Array of user IDs to strictly remove from this chat.
937
- */
938
- removeMembers(members: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
939
- demoteModerators(members: string[]): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
940
- _update(payload: Object): Promise<UpdateChannelAPIResponse<ErmisChatGenerics>>;
941
- _processTopics(topicsFromApi: any, users: any[]): void;
942
- muteNotification(duration: number | null): Promise<AttachmentResponse<ErmisChatGenerics>>;
943
- unMuteNotification(): Promise<AttachmentResponse<ErmisChatGenerics>>;
944
- keystroke(parent_id?: string, options?: {
945
- user_id: string;
946
- }): Promise<void>;
947
- stopTyping(parent_id?: string, options?: {
948
- user_id: string;
949
- }): Promise<void>;
950
- _isTypingIndicatorsEnabled(): boolean;
951
- lastMessage(): FormatMessageResponse<ErmisChatGenerics>;
952
- /**
953
- * Emits a mark-read event, updating the backend that the authenticated user has viewed up to the latest known message.
954
- * @returns Successful acknowledgement from the server.
955
- */
956
- markRead(): Promise<unknown>;
957
- clean(): void;
958
- /**
959
- * Subscribes to realtime events (WebSocket) for this channel, grabs the latest available metadata,
960
- * loads the most recent messages, and initializes the local state.
961
- *
962
- * @param options - Pagination limits like `{ watch: true, presence: true, state: true }`.
963
- * @returns The synchronized comprehensive channel state.
964
- */
965
- watch(options?: ChannelQueryOptions): Promise<QueryChannelAPIResponse<ErmisChatGenerics>>;
966
- lastRead(): Date | null | undefined;
967
- _countMessageAsUnread(message: FormatMessageResponse<ErmisChatGenerics> | MessageResponse<ErmisChatGenerics>): boolean;
968
- countUnread(lastRead?: Date | null): number;
969
- getUnreadMemberCount(): {
970
- last_read: Date;
971
- unread_messages: number;
972
- user: UserResponse<ErmisChatGenerics>;
973
- last_read_message_id?: string;
974
- last_send?: string;
975
- }[];
976
- getCapabilitiesMember(): unknown;
977
- create: () => Promise<QueryChannelAPIResponse<ErmisChatGenerics>>;
978
- createTopic(data: CreateTopicData): Promise<QueryChannelAPIResponse<ErmisChatGenerics>>;
979
- query(options: ChannelQueryOptions, messageSetToAddToIfDoesNotExist?: MessageSetType): Promise<QueryChannelAPIResponse<ErmisChatGenerics>>;
980
- createDirectChannel(messageSetToAddToIfDoesNotExist?: MessageSetType): Promise<QueryChannelAPIResponse<ErmisChatGenerics>>;
981
- queryMessagesLessThanId(message_id: string, limit?: number): Promise<MessageResponse<ErmisChatGenerics>[]>;
982
- queryMessagesGreaterThanId(message_id: string, limit?: number): Promise<MessageResponse<ErmisChatGenerics>[]>;
983
- queryMessagesAroundId(message_id: string, limit?: number): Promise<MessageResponse<ErmisChatGenerics>[]>;
984
- deleteMessage(messageId: string): Promise<APIResponse & {
985
- message: MessageResponse<ErmisChatGenerics>;
986
- }>;
987
- deleteMessageForMe(messageId: string): Promise<APIResponse & {
988
- message: MessageResponse<ErmisChatGenerics>;
989
- }>;
990
- getThumbBlobVideo(file: File): Promise<Blob | null>;
991
- enableTopics(): Promise<unknown>;
992
- disableTopics(): Promise<unknown>;
993
- closeTopic(topicCID: string): Promise<unknown>;
994
- reopenTopic(topicCID: string): Promise<unknown>;
995
- editTopic(topicCID: string, data: EditTopicData): Promise<any>;
996
- on(eventType: EventTypes, callback: EventHandler<ErmisChatGenerics>): {
997
- unsubscribe: () => void;
998
- };
999
- on(callback: EventHandler<ErmisChatGenerics>): {
1000
- unsubscribe: () => void;
1001
- };
1002
- off(eventType: EventTypes, callback: EventHandler<ErmisChatGenerics>): void;
1003
- off(callback: EventHandler<ErmisChatGenerics>): void;
1004
- _handleChannelEvent(event: Event$1<ErmisChatGenerics>): Promise<void>;
1005
- _callChannelListeners: (event: Event$1<ErmisChatGenerics>) => void;
1006
- _channelURL: () => string;
1007
- _checkInitialized(): void;
1008
- _initializeState(state: ChannelAPIResponse<ErmisChatGenerics>, messageSetToAddToIfDoesNotExist?: MessageSetType, updateUserIds?: (id: string) => void): {
1009
- messageSet: {
1010
- isCurrent: boolean;
1011
- isLatest: boolean;
1012
- messages: FormatMessageResponse<ErmisChatGenerics>[];
1013
- };
1014
- };
1015
- _extendEventWithOwnReactions(event: Event$1<ErmisChatGenerics>): void;
1016
- _disconnect(): void;
1017
- }
1018
14
 
1019
- /**
1020
- * ClientState - A container class for the client state.
1021
- */
1022
- declare class ClientState<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
1023
- users: {
1024
- [key: string]: UserResponse<ErmisChatGenerics>;
1025
- };
1026
- userChannelReferences: {
1027
- [key: string]: {
1028
- [key: string]: boolean;
1029
- };
1030
- };
1031
- constructor();
1032
- updateUsers(users: UserResponse<ErmisChatGenerics>[]): void;
1033
- updateUser(user?: UserResponse<ErmisChatGenerics>): void;
1034
- updateUserReference(user: UserResponse<ErmisChatGenerics>, channelID: string): void;
1035
- deleteAllChannelReference(channelID: string): void;
1036
- }
1037
-
1038
- /**
1039
- * TokenManager
1040
- *
1041
- * Manages token storage and retrieval for the chat client.
1042
- */
1043
- declare class TokenManager<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
1044
- loadTokenPromise: Promise<string> | null;
1045
- token?: string;
1046
- user?: UserResponse<ErmisChatGenerics>;
1047
- constructor();
1048
- /**
1049
- * Set the static string token.
1050
- */
1051
- setTokenOrProvider: (tokenOrProvider: string | null, user: UserResponse<ErmisChatGenerics>) => Promise<void>;
1052
- /**
1053
- * Resets the token manager.
1054
- */
1055
- reset: () => void;
1056
- /**
1057
- * Resolves when token is ready.
1058
- */
1059
- tokenReady: () => Promise<string> | null;
1060
- /** Returns the current token */
1061
- getToken: () => string | undefined;
1062
- }
1063
-
1064
- /**
1065
- * The ErmisChat Client represents the connection securely established between your application
1066
- * and the Ermis core servers. It acts as the primary access point for real-time messaging,
1067
- * presence updates, call management, and channel querying.
1068
- *
1069
- * It is highly recommended to instantiate this class as a Singleton via `ErmisChat.getInstance()`.
1070
- */
1071
- declare class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
1072
- private static _instance?;
1073
- /** A map of active channels currently tracked by the client, keyed by Channel ID. */
1074
- activeChannels: {
1075
- [key: string]: Channel<ErmisChatGenerics>;
1076
- };
1077
- /** The internal configured Axios instance used for REST API requests. */
1078
- axiosInstance: AxiosInstance;
1079
- /** The primary base URL for REST API communication. */
1080
- baseURL?: string;
1081
- /** The specific base URL for standard user-focused REST calls. */
1082
- userBaseURL?: string;
1083
- /** True when the SDK is executed inside a browser environment. */
1084
- browser: boolean;
1085
- cleaningIntervalRef?: NodeJS.Timeout;
1086
- clientID?: string;
1087
- apiKey: string;
1088
- projectId: string;
1089
- /** Internal mapped registry of event listeners. */
1090
- listeners: Record<string, Array<(event: Event$1<ErmisChatGenerics>) => void>>;
1091
- logger: Logger;
1092
- /** Whether the client should automatically fetch missing messages upon unexpected disconnects. */
1093
- recoverStateOnReconnect?: boolean;
1094
- /** True when the SDK is executed in a NodeJS environment constraint. */
1095
- node: boolean;
1096
- /** Custom options passed during client initialization. */
1097
- options: ErmisChatOptions;
1098
- setUserPromise: ConnectAPIResponse<ErmisChatGenerics> | null;
1099
- /** Centralized global state orchestrating user and client metadata. */
1100
- state: ClientState<ErmisChatGenerics>;
1101
- tokenManager: TokenManager<ErmisChatGenerics>;
1102
- /** The globally authenticated current user object. */
1103
- user?: UserResponse<ErmisChatGenerics>;
1104
- userAgent?: string;
1105
- /** The unique ID of the current authenticated user. */
1106
- userID?: string;
1107
- /** The configured WebSocket endpoint base URL for realtime subscriptions. */
1108
- wsBaseURL?: string;
1109
- /** The active WebSocket connection controller. */
1110
- wsConnection: StableWSConnection<ErmisChatGenerics> | null;
1111
- wsPromise: ConnectAPIResponse<ErmisChatGenerics> | null;
1112
- /** Tracks consecutive REST API failures for exponential backoff purposes. */
1113
- consecutiveFailures: number;
1114
- defaultWSTimeout: number;
1115
- private eventSource;
1116
- /**
1117
- * Initializes a new Ermis Chat Client instance.
1118
- *
1119
- * @param apiKey - Your public Ermis Network API Key.
1120
- * @param projectId - Your specific Project UUID pointing to the app config.
1121
- * @param baseURL - The API base endpoint assigned to your project.
1122
- * @param options - Additional connection rules and configuration options.
1123
- */
1124
- constructor(apiKey: string, projectId: string, baseURL: string, options?: ErmisChatOptions);
1125
- /**
1126
- * Retrieves the globally registered Singleton instance of the ErmisChat client.
1127
- * If the instance lacks existence, it initializes a new one.
1128
- *
1129
- * @param key - Your public Ermis Network API Key.
1130
- * @param projectId - Your specific Project UUID.
1131
- * @param baseURL - The API base endpoint.
1132
- * @param options - Connection options.
1133
- * @returns The shared ErmisChat client instance.
1134
- */
1135
- static getInstance<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics>(key: string, projectId: string, baseURL: string, options?: ErmisChatOptions): ErmisChat<ErmisChatGenerics>;
1136
- refreshNewToken(refresh_token: string): Promise<APIResponse>;
1137
- getAuthType(): string;
1138
- setBaseURL(baseURL: string): void;
1139
- getExternalAuthToken(user: UserResponse<ErmisChatGenerics>, token: string | null): Promise<any>;
1140
- /**
1141
- * Connects a user to the Ermis network and establishes the WebSocket connection.
1142
- * This is the primary method to authenticate your client application.
1143
- *
1144
- * @param user - The User object containing `id`, `name`, and optional `avatar`.
1145
- * @param userTokenOrProvider - The JWT token or an async token provider function.
1146
- * @param extenal_auth - Set to `true` to use your custom backend external authentication flow.
1147
- * @returns A promise resolving to the API connection response once authenticated.
1148
- */
1149
- connectUser: (user: UserResponse<ErmisChatGenerics>, userTokenOrProvider: string | null, external_auth?: boolean) => Promise<void | ConnectionOpen<ErmisChatGenerics>>;
1150
- setUser: (user: UserResponse<ErmisChatGenerics>, userTokenOrProvider: string | null, external_auth?: boolean) => Promise<void | ConnectionOpen<ErmisChatGenerics>>;
1151
- _setToken: (user: UserResponse<ErmisChatGenerics>, userTokenOrProvider: string | null) => Promise<void>;
1152
- _setUser(user: UserResponse<ErmisChatGenerics>): void;
1153
- closeConnection: (timeout?: number) => Promise<void>;
1154
- openConnection: () => Promise<void | ConnectionOpen<ErmisChatGenerics>>;
1155
- _setupConnection: () => Promise<void | ConnectionOpen<ErmisChatGenerics>>;
1156
- /**
1157
- * Gracefully disconnects the current user, terminates the WebSocket connection,
1158
- * cleans up listeners, and resets the client's internal references.
1159
- *
1160
- * @param timeout - Optional timeout in milliseconds before forcing the disconnect.
1161
- */
1162
- disconnectUser: (timeout?: number) => Promise<void>;
1163
- disconnect: (timeout?: number) => Promise<void>;
1164
- /**
1165
- * Attaches an event listener to the client connection.
1166
- * Listeners can be scoped to specific event types (e.g. `message.new`) or listen to `all` events.
1167
- *
1168
- * @param callback - The handler invoked when the event is emitted.
1169
- * @returns An object containing an `unsubscribe` method to detach the listener.
1170
- */
1171
- on(callback: EventHandler<ErmisChatGenerics>): {
1172
- unsubscribe: () => void;
1173
- };
1174
- /**
1175
- * Attaches an event listener filtered by a specific event type.
1176
- *
1177
- * @param eventType - The specific event name to listen for (e.g., `'notification.message_new'`).
1178
- * @param callback - The handler invoked when the event is emitted.
1179
- * @returns An object containing an `unsubscribe` method to detach the listener.
1180
- */
1181
- on(eventType: string, callback: EventHandler<ErmisChatGenerics>): {
1182
- unsubscribe: () => void;
1183
- };
1184
- /**
1185
- * Detaches a previously registered general event listener.
1186
- * @param callback - The original handler reference to remove.
1187
- */
1188
- off(callback: EventHandler<ErmisChatGenerics>): void;
1189
- /**
1190
- * Detaches a previously registered event listener scoped to a specific event type.
1191
- * @param eventType - The specific event name.
1192
- * @param callback - The original handler reference to remove.
1193
- */
1194
- off(eventType: string, callback: EventHandler<ErmisChatGenerics>): void;
1195
- _logApiRequest(type: string, url: string, data: unknown, config: AxiosRequestConfig & {
1196
- config?: AxiosRequestConfig & {
1197
- maxBodyLength?: number;
1198
- };
1199
- }): void;
1200
- _logApiResponse<T>(type: string, url: string, response: AxiosResponse<T>): void;
1201
- _logApiError(type: string, url: string, error: unknown, options: unknown): void;
1202
- doAxiosRequest: <T>(type: string, url: string, data?: unknown, options?: AxiosRequestConfig & {
1203
- config?: AxiosRequestConfig & {
1204
- maxBodyLength?: number;
1205
- };
1206
- }) => Promise<T>;
1207
- get<T>(url: string, params?: AxiosRequestConfig['params']): Promise<T>;
1208
- put<T>(url: string, data?: unknown): Promise<T>;
1209
- post<T>(url: string, data?: unknown, params?: AxiosRequestConfig['params']): Promise<T>;
1210
- patch<T>(url: string, data?: unknown): Promise<T>;
1211
- delete<T>(url: string, params?: AxiosRequestConfig['params']): Promise<T>;
1212
- sendFile(url: string, uri: string | NodeJS.ReadableStream | Buffer | File, name?: string, contentType?: string, user?: UserResponse<ErmisChatGenerics>): Promise<SendFileAPIResponse>;
1213
- /**
1214
- * Downloads a media file as a Blob via the SDK's configured axiosInstance.
1215
- * This avoids CORS issues that arise when using `fetch()` directly from the browser,
1216
- * because axios is routed through the SDK's authenticated transport layer.
1217
- *
1218
- * @param url - The full URL of the media file to download.
1219
- * @returns A Blob of the file content.
1220
- */
1221
- downloadMedia(url: string): Promise<Blob>;
1222
- errorFromResponse(response: AxiosResponse<APIErrorResponse>): ErrorFromResponse<APIErrorResponse>;
1223
- handleResponse<T>(response: AxiosResponse<T>): T;
1224
- dispatchEvent: (event: Event$1<ErmisChatGenerics>) => void;
1225
- _afterDispatchEvent(event: Event$1<ErmisChatGenerics>): void;
1226
- private _handleChannelCreatedEvent;
1227
- handleEvent: (messageEvent: WebSocket.MessageEvent) => void;
1228
- _updateMemberWatcherReferences: (user: UserResponse<ErmisChatGenerics>) => void;
1229
- _updateUserReferences: (user: UserResponse<ErmisChatGenerics>) => void;
1230
- _updateUserMessageReferences: (user: UserResponse<ErmisChatGenerics>) => void;
1231
- _deleteUserMessageReference: (user: UserResponse<ErmisChatGenerics>, hardDelete?: boolean) => void;
1232
- _handleClientEvent(event: Event$1<ErmisChatGenerics>): (() => void)[];
1233
- _callClientListeners: (event: Event$1<ErmisChatGenerics>) => void;
1234
- recoverState: () => Promise<void>;
1235
- connect(): Promise<void | ConnectionOpen<ErmisChatGenerics>>;
1236
- connectToSSE(onCallBack?: (data: any) => void): Promise<void>;
1237
- disconnectFromSSE(): Promise<void>;
1238
- queryUsers(page_size?: string, page?: number): Promise<UsersResponse>;
1239
- queryUser(user_id: string): Promise<UserResponse<ErmisChatGenerics>>;
1240
- getBatchUsers(users: string[], page?: number, page_size?: number): Promise<UserResponse<DefaultGenerics>[]>;
1241
- searchUsers(page: number, page_size: number, name?: string): Promise<UsersResponse>;
1242
- queryContacts(): Promise<ContactResult>;
1243
- _updateProjectID(project_id: string): void;
1244
- /**
1245
- * Uploads a new avatar image for the current user.
1246
- * The user's avatar URL is automatically updated in both the client and the local state.
1247
- *
1248
- * @param file - The image file to upload.
1249
- * @returns The response containing the new avatar URL.
1250
- */
1251
- uploadAvatar(file: File): Promise<{
1252
- avatar: string;
1253
- }>;
1254
- updateProfile(updates: Partial<UserResponse<ErmisChatGenerics>>): Promise<UserResponse<ErmisChatGenerics>>;
1255
- /**
1256
- * Queries the API for a list of channels based on provided search filters and sort conditions.
1257
- * Also hydrates these channels into the local SDK state memory.
1258
- *
1259
- * @param filterConditions - Specific criteria to filter channels (e.g. `{ type: 'messaging', members: { $in: ['user1'] } }`).
1260
- * @param sort - The sorting hierarchy applied to the channel results.
1261
- * @param options - Pagination and message limit parameters.
1262
- * @param stateOptions - Defines whether to skip state initialization or offline usage.
1263
- * @returns An array of hydrated and locally manageable `Channel` objects.
1264
- */
1265
- queryChannels(filterConditions: ChannelFilters, sort?: ChannelSort, options?: {
1266
- message_limit?: number;
1267
- }, stateOptions?: ChannelStateOptions): Promise<Channel<ErmisChatGenerics>[]>;
1268
- hydrateChannels(channelsFromApi?: ChannelAPIResponse<ErmisChatGenerics>[], stateOptions?: ChannelStateOptions): {
1269
- channels: Channel<ErmisChatGenerics>[];
1270
- userIds: string[];
1271
- };
1272
- searchPublicChannel(search_term: string, offset?: number, limit?: number): Promise<APIResponse>;
1273
- pinChannel(channelType: string, channelId: string): Promise<APIResponse>;
1274
- unpinChannel(channelType: string, channelId: string): Promise<APIResponse>;
1275
- /**
1276
- * Creates or instantiates an interactive `Channel` object locally based on type and custom data.
1277
- * This does NOT immediately ping the API unless `channel.watch()` or `channel.create()` is subsequently called.
1278
- *
1279
- * @param type - The strict channel type descriptor (e.g., `'messaging'`, `'team'`, `'livestream'`).
1280
- * @param custom - Initial metadata or specific members to include in the channel.
1281
- * @returns A newly instantiated `Channel` object.
1282
- */
1283
- channel(type: string, custom?: ChannelData<ErmisChatGenerics>): Channel<ErmisChatGenerics>;
1284
- /**
1285
- * Creates or instantiates an interactive `Channel` object locally using a specific ID.
1286
- *
1287
- * @param type - The strict channel type descriptor.
1288
- * @param id - The unique identifer (UUID / slug) for the channel.
1289
- * @param custom - Initial metadata or specific members to include in the channel.
1290
- * @returns A newly instantiated `Channel` object.
1291
- */
1292
- channel(type: string, id: string, custom?: ChannelData<ErmisChatGenerics>): Channel<ErmisChatGenerics>;
1293
- getChannelById: (channelType: string, channelID: string | undefined, custom: ChannelData<ErmisChatGenerics>) => Channel<ErmisChatGenerics>;
1294
- getChannel: (channelType: string, custom: ChannelData<ErmisChatGenerics>) => Channel<ErmisChatGenerics>;
1295
- /**
1296
- * Creates a quick channel and immediately registers it on the server.
1297
- * Quick channels are public group channels that anyone can join without an invitation.
1298
- * The creator is added as the first member automatically.
1299
- *
1300
- * @param name - An optional display name for the channel.
1301
- * @returns A promise that resolves to the created `Channel` object.
1302
- */
1303
- createQuickChannel(name?: string): Promise<Channel<ErmisChatGenerics>>;
1304
- /**
1305
- * Joins a quick channel by its ID.
1306
- * Automatically checks whether the caller is already a member.
1307
- * If not, it joins the channel and synchronizes state.
1308
- *
1309
- * @param channelId - The ID of the quick channel to join.
1310
- * @returns A promise that resolves to the joined `Channel` object.
1311
- */
1312
- joinQuickChannel(channelId: string): Promise<Channel<ErmisChatGenerics>>;
1313
- _normalizeExpiration(timeoutOrExpirationDate?: null | number | string | Date): string | null;
1314
- getUserAgent(): string;
1315
- setUserAgent(userAgent: string): void;
1316
- _enrichAxiosOptions(options?: AxiosRequestConfig & {
1317
- config?: AxiosRequestConfig;
1318
- }): AxiosRequestConfig;
1319
- _getToken(): string | null | undefined;
1320
- _startCleaning(): void;
1321
- _buildWSPayload: (client_request_id?: string) => string;
1322
- }
1323
-
1324
- declare class ErmisCall {
1325
- free(): void;
1326
- [Symbol.dispose](): void;
1327
- constructor();
1328
- spawn(relay_urls: any, secret_key?: Uint8Array | null): Promise<void>;
1329
- getLocalEndpointAddr(): Promise<string>;
1330
- connect(addr: string): Promise<void>;
1331
- closeEndpoint(): Promise<void>;
1332
- closeConnection(): void;
1333
- acceptConnection(): Promise<void>;
1334
- sendControlFrame(data: Uint8Array): void;
1335
- sendAudioFrame(data: Uint8Array): void;
1336
- sendFrame(data: Uint8Array): void;
1337
- notifyNewGop(): void;
1338
- recv(): Uint8Array;
1339
- asyncRecv(): Promise<Uint8Array>;
1340
- beginWithGop(data: Uint8Array): void;
1341
- connectionType(): string | undefined;
1342
- roundTripTime(): number | undefined;
1343
- currentPacketLoss(): number | undefined;
1344
- networkChange(): void;
1345
- getStats(): any;
15
+ declare class WasmWorkerProxy implements INodeCall {
16
+ private worker;
17
+ private nextId;
18
+ private pendingCalls;
19
+ /** Queue cho asyncRecv — Worker gửi data về, Main Thread consume từng cái */
20
+ private recvResolveQueue;
21
+ private recvDataQueue;
22
+ private recvErrorQueue;
23
+ /** Static cache — persist across Worker instances */
24
+ private static cachedBlobUrl;
25
+ private static cachedWasmBytes;
26
+ constructor(workerUrl: string | URL);
27
+ /** Initialize WASM trong Worker — fetch bytes 1 lần, gửi cached bytes cho Worker */
28
+ init(wasmPath?: string): Promise<void>;
29
+ /** Spawn WASM node */
30
+ spawn(relayUrls: string[]): Promise<void>;
31
+ /** Lấy local endpoint address */
32
+ getLocalEndpointAddr(): Promise<string>;
33
+ connect(address: string): Promise<void>;
34
+ acceptConnection(): Promise<void>;
35
+ sendFrame(data: Uint8Array): Promise<void>;
36
+ beginWithGop(data: Uint8Array): Promise<void>;
37
+ sendAudioFrame(data: Uint8Array): Promise<void>;
38
+ sendControlFrame(data: Uint8Array): Promise<void>;
39
+ /**
40
+ * asyncRecv nhận data từ Worker recv loop.
41
+ *
42
+ * Worker chạy recv loop nội bộ, gửi data về qua postMessage.
43
+ * Method này trả về Promise resolve khi có data mới.
44
+ * KHÔNG BAO GIỜ block Main Thread — chỉ chờ postMessage event.
45
+ */
46
+ asyncRecv(): Promise<Uint8Array>;
47
+ /** Bắt đầu recv loop trong Worker */
48
+ startRecvLoop(): Promise<void>;
49
+ /** Dừng recv loop trong Worker */
50
+ stopRecvLoop(): Promise<void>;
51
+ closeEndpoint(): Promise<void>;
52
+ closeConnection(): void;
53
+ networkChange(): void;
54
+ getStats(): Promise<any>;
55
+ /** Terminate Worker gọi khi call kết thúc */
56
+ terminate(): Promise<void>;
57
+ private handleMessage;
58
+ /** Send RPC call to Worker and wait for response */
59
+ private call;
1346
60
  }
1347
61
 
1348
62
  declare class MediaStreamSender {
1349
63
  private videoEncoder;
1350
64
  private audioEncoder;
1351
65
  private videoReader;
66
+ private audioReader;
1352
67
  private localStream;
1353
68
  private videoConfig;
1354
69
  private audioConfig;
@@ -1357,7 +72,10 @@ declare class MediaStreamSender {
1357
72
  private hasVideo;
1358
73
  private hasAudio;
1359
74
  private forceKeyFrame;
75
+ private isSendingVideo;
76
+ private isSendingAudio;
1360
77
  private nodeCall;
78
+ private healthCallInterval;
1361
79
  constructor(nodeCall: INodeCall);
1362
80
  /**
1363
81
  * Bắt đầu xử lý MediaStream
@@ -1384,6 +102,8 @@ declare class MediaStreamSender {
1384
102
  private sendVideoConfig;
1385
103
  private sendAudioConfig;
1386
104
  sendConnected: () => Promise<void>;
105
+ private startHealthCallInterval;
106
+ private sendHealthCall;
1387
107
  private sendPacketOrQueue;
1388
108
  }
1389
109
 
@@ -1393,9 +113,12 @@ declare class MediaStreamReceiver {
1393
113
  private videoWriter;
1394
114
  private audioContext;
1395
115
  private mediaDestination;
116
+ private scheduledAudioNodes;
1396
117
  private isWaitingForKeyFrame;
1397
118
  private nextStartTime;
1398
119
  private lastVideoConfig;
120
+ private lastVideoConfigStr;
121
+ private lastAudioConfigStr;
1399
122
  private nodeCall;
1400
123
  private events;
1401
124
  private generatedStream;
@@ -1417,6 +140,7 @@ declare class MediaStreamReceiver {
1417
140
 
1418
141
  declare class ErmisCallNode<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
1419
142
  wasmPath: string;
143
+ workerPath: string;
1420
144
  relayUrl: string;
1421
145
  /** Reference to the Ermis Chat client instance */
1422
146
  _client: ErmisChat<ErmisChatGenerics>;
@@ -1426,12 +150,12 @@ declare class ErmisCallNode<ErmisChatGenerics extends ExtendableGenerics = Defau
1426
150
  cid?: string;
1427
151
  /** Type of call: 'audio' or 'video' */
1428
152
  callType?: string;
1429
- /** ID of the current user */
1430
- userID?: string | undefined;
153
+ /** ID of the current user — always reads live value from client */
154
+ get userID(): string | undefined;
1431
155
  /** Current status of the call */
1432
156
  callStatus?: string | undefined;
1433
157
  metadata?: Metadata;
1434
- callNode: ErmisCall | null;
158
+ callNode: WasmWorkerProxy | null;
1435
159
  /** Local media stream from user's camera/microphone */
1436
160
  localStream?: MediaStream | null;
1437
161
  /** Remote media stream from the other participant */
@@ -1493,7 +217,7 @@ declare class ErmisCallNode<ErmisChatGenerics extends ExtendableGenerics = Defau
1493
217
  private isDestroyed;
1494
218
  mediaSender: MediaStreamSender | null;
1495
219
  mediaReceiver: MediaStreamReceiver | null;
1496
- constructor(client: ErmisChat<ErmisChatGenerics>, sessionID: string, wasmPath: string, relayUrl: string);
220
+ constructor(client: ErmisChat<ErmisChatGenerics>, sessionID: string, wasmPath: string, relayUrl: string, workerPath?: string);
1497
221
  private loadWasm;
1498
222
  private initialize;
1499
223
  getLocalEndpointAddr(): Promise<string | null>;
@@ -1508,7 +232,7 @@ declare class ErmisCallNode<ErmisChatGenerics extends ExtendableGenerics = Defau
1508
232
  private setUserInfo;
1509
233
  private listenSocketEvents;
1510
234
  private cleanupCall;
1511
- private destroy;
235
+ destroy(): Promise<void>;
1512
236
  getDevices(): Promise<{
1513
237
  audioDevices: MediaDeviceInfo[];
1514
238
  videoDevices: MediaDeviceInfo[];
@@ -1521,6 +245,7 @@ declare class ErmisCallNode<ErmisChatGenerics extends ExtendableGenerics = Defau
1521
245
  audioDevice?: MediaDeviceInfo;
1522
246
  videoDevice?: MediaDeviceInfo;
1523
247
  };
248
+ prefillUserInfo(cid: string): void;
1524
249
  createCall(callType: string, cid: string): Promise<void>;
1525
250
  acceptCall(): Promise<void>;
1526
251
  endCall(): Promise<void>;
@@ -1643,6 +368,16 @@ declare class ErmisAuthProvider {
1643
368
  }>;
1644
369
  }
1645
370
 
371
+ declare class IndexedDBUserCache<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
372
+ private dbPromise;
373
+ private readonly dbName;
374
+ constructor(projectId: string, ownerUserId: string);
375
+ private openDB;
376
+ saveUsers(users: Array<UserResponse<ErmisChatGenerics>>): Promise<void>;
377
+ saveUser(user: UserResponse<ErmisChatGenerics>): Promise<void>;
378
+ loadUsers(): Promise<Array<UserResponse<ErmisChatGenerics>>>;
379
+ }
380
+
1646
381
  /**
1647
382
  * logChatPromiseExecution - utility function for logging the execution of a promise..
1648
383
  * use this when you want to run the promise and handle errors by logging a warning
@@ -1667,15 +402,70 @@ declare function formatMessage<ErmisChatGenerics extends ExtendableGenerics = De
1667
402
  declare const createForwardMessagePayload: <ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics>(message: FormatMessageResponse<ErmisChatGenerics>, targetCid: string, activeCid: string) => ForwardMessage<ErmisChatGenerics>;
1668
403
 
1669
404
  /**
1670
- * Parse a raw system message string into a human-readable English sentence.
405
+ * Translation templates for system messages.
406
+ * Placeholders: {{user}}, {{channel}}, {{type}}, {{duration}}, {{targetUser}}, {{admin}}
407
+ */
408
+ interface SystemMessageTranslations {
409
+ '1'?: string;
410
+ '2'?: string;
411
+ '3'?: string;
412
+ '4'?: string;
413
+ '5'?: string;
414
+ '6'?: string;
415
+ '7'?: string;
416
+ '8'?: string;
417
+ '9'?: string;
418
+ '10'?: string;
419
+ '11'?: string;
420
+ '12'?: string;
421
+ '13'?: string;
422
+ '14'?: string;
423
+ '15_on'?: string;
424
+ '15_off'?: string;
425
+ '16'?: string;
426
+ '17'?: string;
427
+ '18'?: string;
428
+ '19'?: string;
429
+ '20'?: string;
430
+ changeName?: string;
431
+ changeAvatar?: string;
432
+ changeDescription?: string;
433
+ removed?: string;
434
+ banned?: string;
435
+ unbanned?: string;
436
+ promoted?: string;
437
+ demoted?: string;
438
+ permissionsUpdated?: string;
439
+ joined?: string;
440
+ declined?: string;
441
+ left?: string;
442
+ clearedHistory?: string;
443
+ changeType?: string;
444
+ cooldownOn?: string;
445
+ cooldownOff?: string;
446
+ bannedWordsUpdated?: string;
447
+ added?: string;
448
+ adminTransfer?: string;
449
+ pinned?: string;
450
+ unpinned?: string;
451
+ public?: string;
452
+ private?: string;
453
+ userFallback?: string;
454
+ adminFallback?: string;
455
+ durationUnitMin?: string;
456
+ durationUnitSec?: string;
457
+ }
458
+ /**
459
+ * Parse a raw system message string into a human-readable sentence.
1671
460
  *
1672
461
  * The raw format is: `"<formatId> <userID> [<param1> <param2> ...]"`
1673
462
  *
1674
- * @param value - Raw system message string from the server
1675
- * @param userMap - Mapping of user IDs → display names
1676
- * @returns Parsed English text, or the original string if the format is unknown
463
+ * @param value - Raw system message string from the server
464
+ * @param userMap - Mapping of user IDs → display names
465
+ * @param translations - Optional translation templates
466
+ * @returns Parsed text, or the original string if the format is unknown
1677
467
  */
1678
- declare function parseSystemMessage(value: string, userMap: Record<string, string>): string;
468
+ declare function parseSystemMessage(value: string, userMap: Record<string, string>, translations?: SystemMessageTranslations): string;
1679
469
 
1680
470
  /**
1681
471
  * Call type constants for signal messages.
@@ -1695,16 +485,37 @@ interface SignalMessageResult {
1695
485
  color: string;
1696
486
  }
1697
487
  /**
1698
- * Parse a raw signal message string into a structured object
1699
- * containing text, duration, call type, and color.
488
+ * Translation templates for signal messages.
489
+ */
490
+ interface SignalMessageTranslations {
491
+ calling?: string;
492
+ incomingAudioCall?: string;
493
+ incomingVideoCall?: string;
494
+ outgoingAudioCall?: string;
495
+ outgoingVideoCall?: string;
496
+ missedAudioCall?: string;
497
+ missedVideoCall?: string;
498
+ cancelAudioCall?: string;
499
+ cancelVideoCall?: string;
500
+ rejectedAudioCallRecipient?: string;
501
+ rejectedAudioCallYou?: string;
502
+ rejectedVideoCallRecipient?: string;
503
+ rejectedVideoCallYou?: string;
504
+ busyRecipient?: string;
505
+ durationUnitMin?: string;
506
+ durationUnitSec?: string;
507
+ }
508
+ /**
509
+ * Parse a raw signal message string into a structured object.
1700
510
  *
1701
511
  * Signal messages represent call events. The raw format is:
1702
512
  * `"<formatId> <callerId> [<enderId> <duration>]"`
1703
513
  *
1704
- * @param value - Raw signal message string from the server
1705
- * @param myUserId - The current user's ID (from client.userID)
1706
- * @returns Parsed signal message object, or null if input is empty
514
+ * @param value - Raw signal message string from the server
515
+ * @param myUserId - The current user's ID
516
+ * @param translations - Optional translation templates
517
+ * @returns Parsed signal message object, or null if input is empty
1707
518
  */
1708
- declare function parseSignalMessage(value: string, myUserId: string): SignalMessageResult | null;
519
+ declare function parseSignalMessage(value: string, myUserId: string, translations?: SignalMessageTranslations): SignalMessageResult | null;
1709
520
 
1710
- export { type APIErrorResponse, type APIResponse, type AscDesc, type Attachment, type AttachmentResponse, type AudioConfig, CallAction, type CallEventData, type CallEventType, CallStatus, CallType, type CallTypeValue, Channel, type ChannelAPIResponse, type ChannelData, type ChannelFilters, type ChannelMemberResponse, type ChannelMembership, type ChannelQueryOptions, type ChannelResponse, type ChannelSort, ChannelState, type ChannelStateOptions, ClientState, type ConnectAPIResponse, type ConnectionOpen, type Contact, type ContactResponse, type ContactResult, type CreateTopicData, type DefaultGenerics, EVENT_MAP, type EditMessage, type EditTopicData, ErmisAuthProvider, ErmisCallNode, ErmisChat, type ErmisChatOptions, ErrorFromResponse, type Event$1 as Event, type EventHandler, type EventTypes, type ExtendableGenerics, FRAME_TYPE, type FormatMessageResponse, type ForwardMessage, type IMediaReceiverEvents, type INodeCall, type LiteralStringForUnion, type LogLevel, type Logger, type Message, type MessageBase, type MessageLabel, type MessageResponse, type MessageResponseBase, type MessageSetType, type Metadata, type PollMessage, type QueryChannelAPIResponse, type QueryChannelsAPIResponse, type Reaction, type ReactionAPIResponse, type ReactionResponse, type ReadResponse, type Role, type SendFileAPIResponse, type SendMessageAPIResponse, type SignalData, type SignalMessageResult, StableWSConnection, TokenManager, type TransceiverState, type UR, type UpdateChannelAPIResponse, type UserCallInfo, type UserResponse, type UsersResponse, type VideoConfig, type VoiceRecordingMeta, buildAttachmentPayload, chatCodes, createForwardMessagePayload, formatMessage, getAttachmentCategory, isHeicFile, isVideoFile, logChatPromiseExecution, normalizeFileName, parseSignalMessage, parseSystemMessage };
521
+ export { APIErrorResponse, CallEventData, CallType, type CallTypeValue, DefaultGenerics, ErmisAuthProvider, ErmisCallNode, ErmisChat, ErmisChatOptions, ErrorFromResponse, ExtendableGenerics, FormatMessageResponse, ForwardMessage, IMediaReceiverEvents, INodeCall, IndexedDBUserCache, Logger, MessageResponse, Metadata, type SignalMessageResult, type SignalMessageTranslations, type SystemMessageTranslations, UserCallInfo, UserResponse, chatCodes, createForwardMessagePayload, formatMessage, logChatPromiseExecution, parseSignalMessage, parseSystemMessage };