@ermis-network/ermis-chat-sdk 1.0.3 → 1.0.4
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 +122 -2
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.full-bundle.min.js +2 -2
- package/dist/index.browser.full-bundle.min.js.map +1 -1
- package/dist/index.browser.mjs +122 -2
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +122 -2
- 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 +122 -2
- 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/dist/index.mjs
CHANGED
|
@@ -354,15 +354,25 @@ var createForwardMessagePayload = (message, targetCid, activeCid) => {
|
|
|
354
354
|
// src/channel_state.ts
|
|
355
355
|
var ChannelState = class {
|
|
356
356
|
_channel;
|
|
357
|
+
/** The current count of users actively watching (having an open WebSocket) this channel. */
|
|
357
358
|
watcher_count;
|
|
359
|
+
/** A dictionary of active typing events gracefully keyed by the user's ID. */
|
|
358
360
|
typing;
|
|
361
|
+
/** A dictionary of read states mapped per user's ID detailing the last viewed message. */
|
|
359
362
|
read;
|
|
363
|
+
/** The locally cached array of pinned messages across the channel. */
|
|
360
364
|
pinnedMessages;
|
|
365
|
+
/** A directory of users actively watching the channel, keyed by User ID. */
|
|
361
366
|
watchers;
|
|
367
|
+
/** A comprehensive directory mapping user IDs to their member status in the channel. */
|
|
362
368
|
members;
|
|
369
|
+
/** The count of messages not yet read by the currently authenticated user. */
|
|
363
370
|
unreadCount;
|
|
371
|
+
/** Information detailing the authenticated user's own membership relation to this channel. */
|
|
364
372
|
membership;
|
|
373
|
+
/** Timestamp indicating when the very last message was created in this chat. */
|
|
365
374
|
last_message_at;
|
|
375
|
+
/** Designates if the local channel state is entirely synchronized with the backend history. */
|
|
366
376
|
isUpToDate;
|
|
367
377
|
messageSets = [];
|
|
368
378
|
topics = [];
|
|
@@ -394,6 +404,15 @@ var ChannelState = class {
|
|
|
394
404
|
const index = this.messageSets.findIndex((s) => s.isLatest);
|
|
395
405
|
this.messageSets[index].messages = messages;
|
|
396
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* Pushes a new message directly into the sorted array of the local tracking state.
|
|
409
|
+
* Useful to achieve optimistic UI updates locally.
|
|
410
|
+
*
|
|
411
|
+
* @param newMessage - The message context payload to insert.
|
|
412
|
+
* @param timestampChanged - Specifies if the underlying `created_at` timestamp mutated.
|
|
413
|
+
* @param addIfDoesNotExist - Append it strictly if its ID doesn't already exist.
|
|
414
|
+
* @param messageSetToAddToIfDoesNotExist - Specifies which message set scope to manipulate.
|
|
415
|
+
*/
|
|
397
416
|
addMessageSorted(newMessage, timestampChanged = false, addIfDoesNotExist = true, messageSetToAddToIfDoesNotExist = "latest") {
|
|
398
417
|
return this.addMessagesSorted(
|
|
399
418
|
[newMessage],
|
|
@@ -581,6 +600,12 @@ var ChannelState = class {
|
|
|
581
600
|
const result = msgArray.filter((message) => !(!!message.id && !!msg.id && message.id === msg.id));
|
|
582
601
|
return { removed: result.length < msgArray.length, result };
|
|
583
602
|
};
|
|
603
|
+
/**
|
|
604
|
+
* Refreshes internal user references cascading across all presently active messages.
|
|
605
|
+
* Invoked instantly whenever an underlying user's profile metadata updates (e.g. name or avatar changes).
|
|
606
|
+
*
|
|
607
|
+
* @param user - The newly formatted and populated User details object.
|
|
608
|
+
*/
|
|
584
609
|
updateUserMessages = (user) => {
|
|
585
610
|
const _updateUserMessages = (messages, user2) => {
|
|
586
611
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -852,6 +877,15 @@ var Channel = class {
|
|
|
852
877
|
lastTypingEvent;
|
|
853
878
|
isTyping;
|
|
854
879
|
disconnected;
|
|
880
|
+
/**
|
|
881
|
+
* Initializes a new Channel class instance.
|
|
882
|
+
* Normally you should not call this directly; use `client.channel(type, id)` instead.
|
|
883
|
+
*
|
|
884
|
+
* @param client - The shared ErmisChat client instance initializing this channel.
|
|
885
|
+
* @param type - The type of channel (`messaging`, `team`, `livestream`, etc.).
|
|
886
|
+
* @param id - The unique ID of the channel.
|
|
887
|
+
* @param data - Initial arbitrary metadata stored within this channel.
|
|
888
|
+
*/
|
|
855
889
|
constructor(client, type, id, data) {
|
|
856
890
|
const validTypeRe = /^[\w_-]+$/;
|
|
857
891
|
const validIDRe = /^[\w!:_-]+$/;
|
|
@@ -878,6 +912,13 @@ var Channel = class {
|
|
|
878
912
|
getClient() {
|
|
879
913
|
return this._client;
|
|
880
914
|
}
|
|
915
|
+
/**
|
|
916
|
+
* Sends a message to this channel.
|
|
917
|
+
* By default, it pushes the message eagerly (optimistically) to the local UI state before the server replies.
|
|
918
|
+
*
|
|
919
|
+
* @param message - The constructed text/attachment object payload representing the message.
|
|
920
|
+
* @returns A Promise resolving to the exact API response encompassing message details.
|
|
921
|
+
*/
|
|
881
922
|
async sendMessage(message) {
|
|
882
923
|
if (!message.id) {
|
|
883
924
|
message = { ...message, id: randomId() };
|
|
@@ -1107,6 +1148,11 @@ var Channel = class {
|
|
|
1107
1148
|
const url = this.getClient().baseURL + `/invites/${this.type}/${this.id}/skip`;
|
|
1108
1149
|
return this.getClient().post(url);
|
|
1109
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Directly invites or adds registered users into this channel.
|
|
1153
|
+
*
|
|
1154
|
+
* @param members - Array of user IDs explicitly selected to be added.
|
|
1155
|
+
*/
|
|
1110
1156
|
async addMembers(members) {
|
|
1111
1157
|
return await this._update({ add_members: members });
|
|
1112
1158
|
}
|
|
@@ -1172,6 +1218,11 @@ var Channel = class {
|
|
|
1172
1218
|
})
|
|
1173
1219
|
};
|
|
1174
1220
|
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Expels specified currently participating users out of the channel.
|
|
1223
|
+
*
|
|
1224
|
+
* @param members - Array of user IDs to strictly remove from this chat.
|
|
1225
|
+
*/
|
|
1175
1226
|
async removeMembers(members) {
|
|
1176
1227
|
return await this._update({ remove_members: members });
|
|
1177
1228
|
}
|
|
@@ -1251,6 +1302,10 @@ var Channel = class {
|
|
|
1251
1302
|
messageSlice.sort((a, b) => b.created_at.getTime() - a.created_at.getTime());
|
|
1252
1303
|
return messageSlice[0];
|
|
1253
1304
|
}
|
|
1305
|
+
/**
|
|
1306
|
+
* Emits a mark-read event, updating the backend that the authenticated user has viewed up to the latest known message.
|
|
1307
|
+
* @returns Successful acknowledgement from the server.
|
|
1308
|
+
*/
|
|
1254
1309
|
async markRead() {
|
|
1255
1310
|
return await this.getClient().post(this._channelURL() + "/read");
|
|
1256
1311
|
}
|
|
@@ -1264,6 +1319,13 @@ var Channel = class {
|
|
|
1264
1319
|
}
|
|
1265
1320
|
this.state.clean();
|
|
1266
1321
|
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Subscribes to realtime events (WebSocket) for this channel, grabs the latest available metadata,
|
|
1324
|
+
* loads the most recent messages, and initializes the local state.
|
|
1325
|
+
*
|
|
1326
|
+
* @param options - Pagination limits like `{ watch: true, presence: true, state: true }`.
|
|
1327
|
+
* @returns The synchronized comprehensive channel state.
|
|
1328
|
+
*/
|
|
1267
1329
|
async watch(options) {
|
|
1268
1330
|
await this.getClient().wsPromise;
|
|
1269
1331
|
const combined = { ...options };
|
|
@@ -2701,32 +2763,55 @@ function isString(x) {
|
|
|
2701
2763
|
var ErmisChat = class _ErmisChat {
|
|
2702
2764
|
static _instance;
|
|
2703
2765
|
// type is undefined|ErmisChat, unknown is due to TS limitations with statics
|
|
2766
|
+
/** A map of active channels currently tracked by the client, keyed by Channel ID. */
|
|
2704
2767
|
activeChannels;
|
|
2768
|
+
/** The internal configured Axios instance used for REST API requests. */
|
|
2705
2769
|
axiosInstance;
|
|
2770
|
+
/** The primary base URL for REST API communication. */
|
|
2706
2771
|
baseURL;
|
|
2772
|
+
/** The specific base URL for standard user-focused REST calls. */
|
|
2707
2773
|
userBaseURL;
|
|
2774
|
+
/** True when the SDK is executed inside a browser environment. */
|
|
2708
2775
|
browser;
|
|
2709
2776
|
cleaningIntervalRef;
|
|
2710
2777
|
clientID;
|
|
2711
2778
|
apiKey;
|
|
2712
2779
|
projectId;
|
|
2780
|
+
/** Internal mapped registry of event listeners. */
|
|
2713
2781
|
listeners;
|
|
2714
2782
|
logger;
|
|
2783
|
+
/** Whether the client should automatically fetch missing messages upon unexpected disconnects. */
|
|
2715
2784
|
recoverStateOnReconnect;
|
|
2785
|
+
/** True when the SDK is executed in a NodeJS environment constraint. */
|
|
2716
2786
|
node;
|
|
2787
|
+
/** Custom options passed during client initialization. */
|
|
2717
2788
|
options;
|
|
2718
2789
|
setUserPromise;
|
|
2790
|
+
/** Centralized global state orchestrating user and client metadata. */
|
|
2719
2791
|
state;
|
|
2720
2792
|
tokenManager;
|
|
2793
|
+
/** The globally authenticated current user object. */
|
|
2721
2794
|
user;
|
|
2722
2795
|
userAgent;
|
|
2796
|
+
/** The unique ID of the current authenticated user. */
|
|
2723
2797
|
userID;
|
|
2798
|
+
/** The configured WebSocket endpoint base URL for realtime subscriptions. */
|
|
2724
2799
|
wsBaseURL;
|
|
2800
|
+
/** The active WebSocket connection controller. */
|
|
2725
2801
|
wsConnection;
|
|
2726
2802
|
wsPromise;
|
|
2803
|
+
/** Tracks consecutive REST API failures for exponential backoff purposes. */
|
|
2727
2804
|
consecutiveFailures;
|
|
2728
2805
|
defaultWSTimeout;
|
|
2729
2806
|
eventSource = null;
|
|
2807
|
+
/**
|
|
2808
|
+
* Initializes a new Ermis Chat Client instance.
|
|
2809
|
+
*
|
|
2810
|
+
* @param apiKey - Your public Ermis Network API Key.
|
|
2811
|
+
* @param projectId - Your specific Project UUID pointing to the app config.
|
|
2812
|
+
* @param baseURL - The API base endpoint assigned to your project.
|
|
2813
|
+
* @param options - Additional connection rules and configuration options.
|
|
2814
|
+
*/
|
|
2730
2815
|
constructor(apiKey, projectId, baseURL, options) {
|
|
2731
2816
|
this.apiKey = apiKey;
|
|
2732
2817
|
this.projectId = projectId;
|
|
@@ -2760,6 +2845,16 @@ var ErmisChat = class _ErmisChat {
|
|
|
2760
2845
|
this.logger = isFunction(inputOptions.logger) ? inputOptions.logger : () => null;
|
|
2761
2846
|
this.recoverStateOnReconnect = this.options.recoverStateOnReconnect;
|
|
2762
2847
|
}
|
|
2848
|
+
/**
|
|
2849
|
+
* Retrieves the globally registered Singleton instance of the ErmisChat client.
|
|
2850
|
+
* If the instance lacks existence, it initializes a new one.
|
|
2851
|
+
*
|
|
2852
|
+
* @param key - Your public Ermis Network API Key.
|
|
2853
|
+
* @param projectId - Your specific Project UUID.
|
|
2854
|
+
* @param baseURL - The API base endpoint.
|
|
2855
|
+
* @param options - Connection options.
|
|
2856
|
+
* @returns The shared ErmisChat client instance.
|
|
2857
|
+
*/
|
|
2763
2858
|
static getInstance(key, projectId, baseURL, options) {
|
|
2764
2859
|
if (!_ErmisChat._instance) {
|
|
2765
2860
|
_ErmisChat._instance = new _ErmisChat(key, projectId, baseURL, options);
|
|
@@ -2807,6 +2902,15 @@ var ErmisChat = class _ErmisChat {
|
|
|
2807
2902
|
}
|
|
2808
2903
|
return await response.json();
|
|
2809
2904
|
}
|
|
2905
|
+
/**
|
|
2906
|
+
* Connects a user to the Ermis network and establishes the WebSocket connection.
|
|
2907
|
+
* This is the primary method to authenticate your client application.
|
|
2908
|
+
*
|
|
2909
|
+
* @param user - The User object containing `id`, `name`, and optional `avatar`.
|
|
2910
|
+
* @param userTokenOrProvider - The JWT token or an async token provider function.
|
|
2911
|
+
* @param extenal_auth - Set to `true` to use your custom backend external authentication flow.
|
|
2912
|
+
* @returns A promise resolving to the API connection response once authenticated.
|
|
2913
|
+
*/
|
|
2810
2914
|
connectUser = async (user, userTokenOrProvider, extenal_auth) => {
|
|
2811
2915
|
this.logger("info", "client:connectUser() - started", {
|
|
2812
2916
|
tags: ["connection", "client"]
|
|
@@ -2889,6 +2993,12 @@ var ErmisChat = class _ErmisChat {
|
|
|
2889
2993
|
return this.wsPromise;
|
|
2890
2994
|
};
|
|
2891
2995
|
_setupConnection = this.openConnection;
|
|
2996
|
+
/**
|
|
2997
|
+
* Gracefully disconnects the current user, terminates the WebSocket connection,
|
|
2998
|
+
* cleans up listeners, and resets the client's internal references.
|
|
2999
|
+
*
|
|
3000
|
+
* @param timeout - Optional timeout in milliseconds before forcing the disconnect.
|
|
3001
|
+
*/
|
|
2892
3002
|
disconnectUser = async (timeout) => {
|
|
2893
3003
|
this.logger("info", "client:disconnect() - Disconnecting the client", {
|
|
2894
3004
|
tags: ["connection", "client"]
|
|
@@ -3454,6 +3564,16 @@ var ErmisChat = class _ErmisChat {
|
|
|
3454
3564
|
this.state.updateUser(response);
|
|
3455
3565
|
return response;
|
|
3456
3566
|
}
|
|
3567
|
+
/**
|
|
3568
|
+
* Queries the API for a list of channels based on provided search filters and sort conditions.
|
|
3569
|
+
* Also hydrates these channels into the local SDK state memory.
|
|
3570
|
+
*
|
|
3571
|
+
* @param filterConditions - Specific criteria to filter channels (e.g. `{ type: 'messaging', members: { $in: ['user1'] } }`).
|
|
3572
|
+
* @param sort - The sorting hierarchy applied to the channel results.
|
|
3573
|
+
* @param options - Pagination and message limit parameters.
|
|
3574
|
+
* @param stateOptions - Defines whether to skip state initialization or offline usage.
|
|
3575
|
+
* @returns An array of hydrated and locally manageable `Channel` objects.
|
|
3576
|
+
*/
|
|
3457
3577
|
async queryChannels(filterConditions, sort = [], options = {}, stateOptions = {}) {
|
|
3458
3578
|
await this.wsPromise;
|
|
3459
3579
|
let project_id = this.projectId;
|
|
@@ -3605,7 +3725,7 @@ var ErmisChat = class _ErmisChat {
|
|
|
3605
3725
|
return pinExpires;
|
|
3606
3726
|
}
|
|
3607
3727
|
getUserAgent() {
|
|
3608
|
-
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.
|
|
3728
|
+
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.4"}`;
|
|
3609
3729
|
}
|
|
3610
3730
|
setUserAgent(userAgent) {
|
|
3611
3731
|
this.userAgent = userAgent;
|
|
@@ -6964,7 +7084,7 @@ var ErmisAuthProvider = class {
|
|
|
6964
7084
|
return data;
|
|
6965
7085
|
}
|
|
6966
7086
|
getUserAgent() {
|
|
6967
|
-
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.
|
|
7087
|
+
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.4"}`;
|
|
6968
7088
|
}
|
|
6969
7089
|
setUserAgent(userAgent) {
|
|
6970
7090
|
this.userAgent = userAgent;
|