@ermis-network/ermis-chat-sdk 1.0.3 → 1.0.5
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/index.browser.cjs +123 -4
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.full-bundle.min.js +7 -7
- package/dist/index.browser.full-bundle.min.js.map +1 -1
- package/dist/index.browser.mjs +123 -3
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +123 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +173 -0
- package/dist/index.d.ts +173 -0
- package/dist/index.mjs +123 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/channel.ts +42 -0
- package/src/channel_state.ts +27 -0
- package/src/client.ts +104 -0
- package/src/wasm/ermis_call_node_wasm.js +1 -1
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -37,6 +37,11 @@ import {
|
|
|
37
37
|
EditMessage,
|
|
38
38
|
ForwardMessage,
|
|
39
39
|
} from './types';
|
|
40
|
+
/**
|
|
41
|
+
* Represents a Channel in the Ermis Network.
|
|
42
|
+
* Channels handle chat sessions, livestream messages, teams, or video calls.
|
|
43
|
+
* This class abstracts and exposes all API operations you can perform on a specific channel instance.
|
|
44
|
+
*/
|
|
40
45
|
export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
|
|
41
46
|
_client: ErmisChat<ErmisChatGenerics>;
|
|
42
47
|
type: string;
|
|
@@ -53,6 +58,15 @@ export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGener
|
|
|
53
58
|
isTyping: boolean;
|
|
54
59
|
disconnected: boolean;
|
|
55
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Initializes a new Channel class instance.
|
|
63
|
+
* Normally you should not call this directly; use `client.channel(type, id)` instead.
|
|
64
|
+
*
|
|
65
|
+
* @param client - The shared ErmisChat client instance initializing this channel.
|
|
66
|
+
* @param type - The type of channel (`messaging`, `team`, `livestream`, etc.).
|
|
67
|
+
* @param id - The unique ID of the channel.
|
|
68
|
+
* @param data - Initial arbitrary metadata stored within this channel.
|
|
69
|
+
*/
|
|
56
70
|
constructor(
|
|
57
71
|
client: ErmisChat<ErmisChatGenerics>,
|
|
58
72
|
type: string,
|
|
@@ -88,6 +102,13 @@ export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGener
|
|
|
88
102
|
return this._client;
|
|
89
103
|
}
|
|
90
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Sends a message to this channel.
|
|
107
|
+
* By default, it pushes the message eagerly (optimistically) to the local UI state before the server replies.
|
|
108
|
+
*
|
|
109
|
+
* @param message - The constructed text/attachment object payload representing the message.
|
|
110
|
+
* @returns A Promise resolving to the exact API response encompassing message details.
|
|
111
|
+
*/
|
|
91
112
|
async sendMessage(message: Message<ErmisChatGenerics>) {
|
|
92
113
|
// 1. Generate ID upfront
|
|
93
114
|
if (!message.id) {
|
|
@@ -391,6 +412,11 @@ export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGener
|
|
|
391
412
|
return this.getClient().post<APIResponse>(url);
|
|
392
413
|
}
|
|
393
414
|
|
|
415
|
+
/**
|
|
416
|
+
* Directly invites or adds registered users into this channel.
|
|
417
|
+
*
|
|
418
|
+
* @param members - Array of user IDs explicitly selected to be added.
|
|
419
|
+
*/
|
|
394
420
|
async addMembers(members: string[]) {
|
|
395
421
|
return await this._update({ add_members: members });
|
|
396
422
|
}
|
|
@@ -469,6 +495,11 @@ export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGener
|
|
|
469
495
|
};
|
|
470
496
|
}
|
|
471
497
|
|
|
498
|
+
/**
|
|
499
|
+
* Expels specified currently participating users out of the channel.
|
|
500
|
+
*
|
|
501
|
+
* @param members - Array of user IDs to strictly remove from this chat.
|
|
502
|
+
*/
|
|
472
503
|
async removeMembers(members: string[]) {
|
|
473
504
|
return await this._update({ remove_members: members });
|
|
474
505
|
}
|
|
@@ -569,6 +600,10 @@ export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGener
|
|
|
569
600
|
return messageSlice[0];
|
|
570
601
|
}
|
|
571
602
|
|
|
603
|
+
/**
|
|
604
|
+
* Emits a mark-read event, updating the backend that the authenticated user has viewed up to the latest known message.
|
|
605
|
+
* @returns Successful acknowledgement from the server.
|
|
606
|
+
*/
|
|
572
607
|
async markRead() {
|
|
573
608
|
return await this.getClient().post(this._channelURL() + '/read');
|
|
574
609
|
}
|
|
@@ -585,6 +620,13 @@ export class Channel<ErmisChatGenerics extends ExtendableGenerics = DefaultGener
|
|
|
585
620
|
this.state.clean();
|
|
586
621
|
}
|
|
587
622
|
|
|
623
|
+
/**
|
|
624
|
+
* Subscribes to realtime events (WebSocket) for this channel, grabs the latest available metadata,
|
|
625
|
+
* loads the most recent messages, and initializes the local state.
|
|
626
|
+
*
|
|
627
|
+
* @param options - Pagination limits like `{ watch: true, presence: true, state: true }`.
|
|
628
|
+
* @returns The synchronized comprehensive channel state.
|
|
629
|
+
*/
|
|
588
630
|
async watch(options?: ChannelQueryOptions) {
|
|
589
631
|
// Make sure we wait for the connect promise if there is a pending one
|
|
590
632
|
await this.getClient().wsPromise;
|
package/src/channel_state.ts
CHANGED
|
@@ -26,18 +26,30 @@ type ChannelReadStatus<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* ChannelState - A container class for the channel state.
|
|
29
|
+
* This class synchronously binds to a `Channel` and holds the single source of truth for
|
|
30
|
+
* messages, read status, watchers, and typing indicators locally on the client.
|
|
29
31
|
*/
|
|
30
32
|
export class ChannelState<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
|
|
31
33
|
_channel: Channel<ErmisChatGenerics>;
|
|
34
|
+
/** The current count of users actively watching (having an open WebSocket) this channel. */
|
|
32
35
|
watcher_count: number;
|
|
36
|
+
/** A dictionary of active typing events gracefully keyed by the user's ID. */
|
|
33
37
|
typing: Record<string, Event<ErmisChatGenerics>>;
|
|
38
|
+
/** A dictionary of read states mapped per user's ID detailing the last viewed message. */
|
|
34
39
|
read: ChannelReadStatus<ErmisChatGenerics>;
|
|
40
|
+
/** The locally cached array of pinned messages across the channel. */
|
|
35
41
|
pinnedMessages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>;
|
|
42
|
+
/** A directory of users actively watching the channel, keyed by User ID. */
|
|
36
43
|
watchers: Record<string, UserResponse<ErmisChatGenerics>>;
|
|
44
|
+
/** A comprehensive directory mapping user IDs to their member status in the channel. */
|
|
37
45
|
members: Record<string, ChannelMemberResponse<ErmisChatGenerics>>;
|
|
46
|
+
/** The count of messages not yet read by the currently authenticated user. */
|
|
38
47
|
unreadCount: number;
|
|
48
|
+
/** Information detailing the authenticated user's own membership relation to this channel. */
|
|
39
49
|
membership: ChannelMembership<ErmisChatGenerics>;
|
|
50
|
+
/** Timestamp indicating when the very last message was created in this chat. */
|
|
40
51
|
last_message_at: Date | null;
|
|
52
|
+
/** Designates if the local channel state is entirely synchronized with the backend history. */
|
|
41
53
|
isUpToDate: boolean;
|
|
42
54
|
messageSets: {
|
|
43
55
|
isCurrent: boolean;
|
|
@@ -78,6 +90,15 @@ export class ChannelState<ErmisChatGenerics extends ExtendableGenerics = Default
|
|
|
78
90
|
this.messageSets[index].messages = messages;
|
|
79
91
|
}
|
|
80
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Pushes a new message directly into the sorted array of the local tracking state.
|
|
95
|
+
* Useful to achieve optimistic UI updates locally.
|
|
96
|
+
*
|
|
97
|
+
* @param newMessage - The message context payload to insert.
|
|
98
|
+
* @param timestampChanged - Specifies if the underlying `created_at` timestamp mutated.
|
|
99
|
+
* @param addIfDoesNotExist - Append it strictly if its ID doesn't already exist.
|
|
100
|
+
* @param messageSetToAddToIfDoesNotExist - Specifies which message set scope to manipulate.
|
|
101
|
+
*/
|
|
81
102
|
addMessageSorted(
|
|
82
103
|
newMessage: MessageResponse<ErmisChatGenerics>,
|
|
83
104
|
timestampChanged = false,
|
|
@@ -356,6 +377,12 @@ export class ChannelState<ErmisChatGenerics extends ExtendableGenerics = Default
|
|
|
356
377
|
return { removed: result.length < msgArray.length, result };
|
|
357
378
|
};
|
|
358
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Refreshes internal user references cascading across all presently active messages.
|
|
382
|
+
* Invoked instantly whenever an underlying user's profile metadata updates (e.g. name or avatar changes).
|
|
383
|
+
*
|
|
384
|
+
* @param user - The newly formatted and populated User details object.
|
|
385
|
+
*/
|
|
359
386
|
updateUserMessages = (user: UserResponse<ErmisChatGenerics>) => {
|
|
360
387
|
const _updateUserMessages = (
|
|
361
388
|
messages: Array<ReturnType<ChannelState<ErmisChatGenerics>['formatMessage']>>,
|
package/src/client.ts
CHANGED
|
@@ -53,39 +53,69 @@ import {
|
|
|
53
53
|
function isString(x: unknown): x is string {
|
|
54
54
|
return typeof x === 'string' || x instanceof String;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* The ErmisChat Client represents the connection securely established between your application
|
|
58
|
+
* and the Ermis core servers. It acts as the primary access point for real-time messaging,
|
|
59
|
+
* presence updates, call management, and channel querying.
|
|
60
|
+
*
|
|
61
|
+
* It is highly recommended to instantiate this class as a Singleton via `ErmisChat.getInstance()`.
|
|
62
|
+
*/
|
|
56
63
|
export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics> {
|
|
57
64
|
private static _instance?: unknown | ErmisChat; // type is undefined|ErmisChat, unknown is due to TS limitations with statics
|
|
58
65
|
|
|
66
|
+
/** A map of active channels currently tracked by the client, keyed by Channel ID. */
|
|
59
67
|
activeChannels: {
|
|
60
68
|
[key: string]: Channel<ErmisChatGenerics>;
|
|
61
69
|
};
|
|
70
|
+
/** The internal configured Axios instance used for REST API requests. */
|
|
62
71
|
axiosInstance: AxiosInstance;
|
|
72
|
+
/** The primary base URL for REST API communication. */
|
|
63
73
|
baseURL?: string;
|
|
74
|
+
/** The specific base URL for standard user-focused REST calls. */
|
|
64
75
|
userBaseURL?: string;
|
|
76
|
+
/** True when the SDK is executed inside a browser environment. */
|
|
65
77
|
browser: boolean;
|
|
66
78
|
cleaningIntervalRef?: NodeJS.Timeout;
|
|
67
79
|
clientID?: string;
|
|
68
80
|
apiKey: string;
|
|
69
81
|
projectId: string;
|
|
82
|
+
/** Internal mapped registry of event listeners. */
|
|
70
83
|
listeners: Record<string, Array<(event: Event<ErmisChatGenerics>) => void>>;
|
|
71
84
|
logger: Logger;
|
|
85
|
+
/** Whether the client should automatically fetch missing messages upon unexpected disconnects. */
|
|
72
86
|
recoverStateOnReconnect?: boolean;
|
|
87
|
+
/** True when the SDK is executed in a NodeJS environment constraint. */
|
|
73
88
|
node: boolean;
|
|
89
|
+
/** Custom options passed during client initialization. */
|
|
74
90
|
options: ErmisChatOptions;
|
|
75
91
|
setUserPromise: ConnectAPIResponse<ErmisChatGenerics> | null;
|
|
92
|
+
/** Centralized global state orchestrating user and client metadata. */
|
|
76
93
|
state: ClientState<ErmisChatGenerics>;
|
|
77
94
|
tokenManager: TokenManager<ErmisChatGenerics>;
|
|
95
|
+
/** The globally authenticated current user object. */
|
|
78
96
|
user?: UserResponse<ErmisChatGenerics>;
|
|
79
97
|
userAgent?: string;
|
|
98
|
+
/** The unique ID of the current authenticated user. */
|
|
80
99
|
userID?: string;
|
|
100
|
+
/** The configured WebSocket endpoint base URL for realtime subscriptions. */
|
|
81
101
|
wsBaseURL?: string;
|
|
102
|
+
/** The active WebSocket connection controller. */
|
|
82
103
|
wsConnection: StableWSConnection<ErmisChatGenerics> | null;
|
|
83
104
|
wsPromise: ConnectAPIResponse<ErmisChatGenerics> | null;
|
|
105
|
+
/** Tracks consecutive REST API failures for exponential backoff purposes. */
|
|
84
106
|
consecutiveFailures: number;
|
|
85
107
|
defaultWSTimeout: number;
|
|
86
108
|
|
|
87
109
|
private eventSource: EventSourcePolyfill | null = null;
|
|
88
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Initializes a new Ermis Chat Client instance.
|
|
113
|
+
*
|
|
114
|
+
* @param apiKey - Your public Ermis Network API Key.
|
|
115
|
+
* @param projectId - Your specific Project UUID pointing to the app config.
|
|
116
|
+
* @param baseURL - The API base endpoint assigned to your project.
|
|
117
|
+
* @param options - Additional connection rules and configuration options.
|
|
118
|
+
*/
|
|
89
119
|
constructor(apiKey: string, projectId: string, baseURL: string, options?: ErmisChatOptions) {
|
|
90
120
|
this.apiKey = apiKey;
|
|
91
121
|
this.projectId = projectId;
|
|
@@ -132,6 +162,16 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
132
162
|
this.recoverStateOnReconnect = this.options.recoverStateOnReconnect;
|
|
133
163
|
}
|
|
134
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Retrieves the globally registered Singleton instance of the ErmisChat client.
|
|
167
|
+
* If the instance lacks existence, it initializes a new one.
|
|
168
|
+
*
|
|
169
|
+
* @param key - Your public Ermis Network API Key.
|
|
170
|
+
* @param projectId - Your specific Project UUID.
|
|
171
|
+
* @param baseURL - The API base endpoint.
|
|
172
|
+
* @param options - Connection options.
|
|
173
|
+
* @returns The shared ErmisChat client instance.
|
|
174
|
+
*/
|
|
135
175
|
public static getInstance<ErmisChatGenerics extends ExtendableGenerics = DefaultGenerics>(
|
|
136
176
|
key: string,
|
|
137
177
|
projectId: string,
|
|
@@ -190,6 +230,15 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
190
230
|
return await response.json();
|
|
191
231
|
}
|
|
192
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Connects a user to the Ermis network and establishes the WebSocket connection.
|
|
235
|
+
* This is the primary method to authenticate your client application.
|
|
236
|
+
*
|
|
237
|
+
* @param user - The User object containing `id`, `name`, and optional `avatar`.
|
|
238
|
+
* @param userTokenOrProvider - The JWT token or an async token provider function.
|
|
239
|
+
* @param extenal_auth - Set to `true` to use your custom backend external authentication flow.
|
|
240
|
+
* @returns A promise resolving to the API connection response once authenticated.
|
|
241
|
+
*/
|
|
193
242
|
connectUser = async (
|
|
194
243
|
user: UserResponse<ErmisChatGenerics>,
|
|
195
244
|
userTokenOrProvider: string | null,
|
|
@@ -305,6 +354,12 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
305
354
|
|
|
306
355
|
_setupConnection = this.openConnection;
|
|
307
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Gracefully disconnects the current user, terminates the WebSocket connection,
|
|
359
|
+
* cleans up listeners, and resets the client's internal references.
|
|
360
|
+
*
|
|
361
|
+
* @param timeout - Optional timeout in milliseconds before forcing the disconnect.
|
|
362
|
+
*/
|
|
308
363
|
disconnectUser = async (timeout?: number) => {
|
|
309
364
|
this.logger('info', 'client:disconnect() - Disconnecting the client', {
|
|
310
365
|
tags: ['connection', 'client'],
|
|
@@ -332,7 +387,21 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
332
387
|
|
|
333
388
|
disconnect = this.disconnectUser;
|
|
334
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Attaches an event listener to the client connection.
|
|
392
|
+
* Listeners can be scoped to specific event types (e.g. `message.new`) or listen to `all` events.
|
|
393
|
+
*
|
|
394
|
+
* @param callback - The handler invoked when the event is emitted.
|
|
395
|
+
* @returns An object containing an `unsubscribe` method to detach the listener.
|
|
396
|
+
*/
|
|
335
397
|
on(callback: EventHandler<ErmisChatGenerics>): { unsubscribe: () => void };
|
|
398
|
+
/**
|
|
399
|
+
* Attaches an event listener filtered by a specific event type.
|
|
400
|
+
*
|
|
401
|
+
* @param eventType - The specific event name to listen for (e.g., `'notification.message_new'`).
|
|
402
|
+
* @param callback - The handler invoked when the event is emitted.
|
|
403
|
+
* @returns An object containing an `unsubscribe` method to detach the listener.
|
|
404
|
+
*/
|
|
336
405
|
on(eventType: string, callback: EventHandler<ErmisChatGenerics>): { unsubscribe: () => void };
|
|
337
406
|
on(
|
|
338
407
|
callbackOrString: EventHandler<ErmisChatGenerics> | string,
|
|
@@ -357,7 +426,16 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
357
426
|
};
|
|
358
427
|
}
|
|
359
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Detaches a previously registered general event listener.
|
|
431
|
+
* @param callback - The original handler reference to remove.
|
|
432
|
+
*/
|
|
360
433
|
off(callback: EventHandler<ErmisChatGenerics>): void;
|
|
434
|
+
/**
|
|
435
|
+
* Detaches a previously registered event listener scoped to a specific event type.
|
|
436
|
+
* @param eventType - The specific event name.
|
|
437
|
+
* @param callback - The original handler reference to remove.
|
|
438
|
+
*/
|
|
361
439
|
off(eventType: string, callback: EventHandler<ErmisChatGenerics>): void;
|
|
362
440
|
off(callbackOrString: EventHandler<ErmisChatGenerics> | string, callbackOrNothing?: EventHandler<ErmisChatGenerics>) {
|
|
363
441
|
const key = callbackOrNothing ? (callbackOrString as string) : 'all';
|
|
@@ -1035,6 +1113,16 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
1035
1113
|
return response;
|
|
1036
1114
|
}
|
|
1037
1115
|
|
|
1116
|
+
/**
|
|
1117
|
+
* Queries the API for a list of channels based on provided search filters and sort conditions.
|
|
1118
|
+
* Also hydrates these channels into the local SDK state memory.
|
|
1119
|
+
*
|
|
1120
|
+
* @param filterConditions - Specific criteria to filter channels (e.g. `{ type: 'messaging', members: { $in: ['user1'] } }`).
|
|
1121
|
+
* @param sort - The sorting hierarchy applied to the channel results.
|
|
1122
|
+
* @param options - Pagination and message limit parameters.
|
|
1123
|
+
* @param stateOptions - Defines whether to skip state initialization or offline usage.
|
|
1124
|
+
* @returns An array of hydrated and locally manageable `Channel` objects.
|
|
1125
|
+
*/
|
|
1038
1126
|
async queryChannels(
|
|
1039
1127
|
filterConditions: ChannelFilters,
|
|
1040
1128
|
sort: ChannelSort = [],
|
|
@@ -1192,7 +1280,23 @@ export class ErmisChat<ErmisChatGenerics extends ExtendableGenerics = DefaultGen
|
|
|
1192
1280
|
return await this.post<APIResponse>(this.baseURL + `/channels/${channelType}/${channelId}/unpin`);
|
|
1193
1281
|
}
|
|
1194
1282
|
|
|
1283
|
+
/**
|
|
1284
|
+
* Creates or instantiates an interactive `Channel` object locally based on type and custom data.
|
|
1285
|
+
* This does NOT immediately ping the API unless `channel.watch()` or `channel.create()` is subsequently called.
|
|
1286
|
+
*
|
|
1287
|
+
* @param type - The strict channel type descriptor (e.g., `'messaging'`, `'team'`, `'livestream'`).
|
|
1288
|
+
* @param custom - Initial metadata or specific members to include in the channel.
|
|
1289
|
+
* @returns A newly instantiated `Channel` object.
|
|
1290
|
+
*/
|
|
1195
1291
|
channel(type: string, custom?: ChannelData<ErmisChatGenerics>): Channel<ErmisChatGenerics>;
|
|
1292
|
+
/**
|
|
1293
|
+
* Creates or instantiates an interactive `Channel` object locally using a specific ID.
|
|
1294
|
+
*
|
|
1295
|
+
* @param type - The strict channel type descriptor.
|
|
1296
|
+
* @param id - The unique identifer (UUID / slug) for the channel.
|
|
1297
|
+
* @param custom - Initial metadata or specific members to include in the channel.
|
|
1298
|
+
* @returns A newly instantiated `Channel` object.
|
|
1299
|
+
*/
|
|
1196
1300
|
channel(type: string, id: string, custom?: ChannelData<ErmisChatGenerics>): Channel<ErmisChatGenerics>;
|
|
1197
1301
|
channel(
|
|
1198
1302
|
channelType: string,
|
|
@@ -1481,7 +1481,7 @@ async function __wbg_init(module_or_path) {
|
|
|
1481
1481
|
}
|
|
1482
1482
|
|
|
1483
1483
|
if (typeof module_or_path === 'undefined') {
|
|
1484
|
-
module_or_path =
|
|
1484
|
+
module_or_path = '/ermis_call_node_wasm_bg.wasm';
|
|
1485
1485
|
}
|
|
1486
1486
|
const imports = __wbg_get_imports();
|
|
1487
1487
|
|