@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.browser.cjs
CHANGED
|
@@ -416,15 +416,25 @@ var createForwardMessagePayload = (message, targetCid, activeCid) => {
|
|
|
416
416
|
// src/channel_state.ts
|
|
417
417
|
var ChannelState = class {
|
|
418
418
|
_channel;
|
|
419
|
+
/** The current count of users actively watching (having an open WebSocket) this channel. */
|
|
419
420
|
watcher_count;
|
|
421
|
+
/** A dictionary of active typing events gracefully keyed by the user's ID. */
|
|
420
422
|
typing;
|
|
423
|
+
/** A dictionary of read states mapped per user's ID detailing the last viewed message. */
|
|
421
424
|
read;
|
|
425
|
+
/** The locally cached array of pinned messages across the channel. */
|
|
422
426
|
pinnedMessages;
|
|
427
|
+
/** A directory of users actively watching the channel, keyed by User ID. */
|
|
423
428
|
watchers;
|
|
429
|
+
/** A comprehensive directory mapping user IDs to their member status in the channel. */
|
|
424
430
|
members;
|
|
431
|
+
/** The count of messages not yet read by the currently authenticated user. */
|
|
425
432
|
unreadCount;
|
|
433
|
+
/** Information detailing the authenticated user's own membership relation to this channel. */
|
|
426
434
|
membership;
|
|
435
|
+
/** Timestamp indicating when the very last message was created in this chat. */
|
|
427
436
|
last_message_at;
|
|
437
|
+
/** Designates if the local channel state is entirely synchronized with the backend history. */
|
|
428
438
|
isUpToDate;
|
|
429
439
|
messageSets = [];
|
|
430
440
|
topics = [];
|
|
@@ -456,6 +466,15 @@ var ChannelState = class {
|
|
|
456
466
|
const index = this.messageSets.findIndex((s) => s.isLatest);
|
|
457
467
|
this.messageSets[index].messages = messages;
|
|
458
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* Pushes a new message directly into the sorted array of the local tracking state.
|
|
471
|
+
* Useful to achieve optimistic UI updates locally.
|
|
472
|
+
*
|
|
473
|
+
* @param newMessage - The message context payload to insert.
|
|
474
|
+
* @param timestampChanged - Specifies if the underlying `created_at` timestamp mutated.
|
|
475
|
+
* @param addIfDoesNotExist - Append it strictly if its ID doesn't already exist.
|
|
476
|
+
* @param messageSetToAddToIfDoesNotExist - Specifies which message set scope to manipulate.
|
|
477
|
+
*/
|
|
459
478
|
addMessageSorted(newMessage, timestampChanged = false, addIfDoesNotExist = true, messageSetToAddToIfDoesNotExist = "latest") {
|
|
460
479
|
return this.addMessagesSorted(
|
|
461
480
|
[newMessage],
|
|
@@ -643,6 +662,12 @@ var ChannelState = class {
|
|
|
643
662
|
const result = msgArray.filter((message) => !(!!message.id && !!msg.id && message.id === msg.id));
|
|
644
663
|
return { removed: result.length < msgArray.length, result };
|
|
645
664
|
};
|
|
665
|
+
/**
|
|
666
|
+
* Refreshes internal user references cascading across all presently active messages.
|
|
667
|
+
* Invoked instantly whenever an underlying user's profile metadata updates (e.g. name or avatar changes).
|
|
668
|
+
*
|
|
669
|
+
* @param user - The newly formatted and populated User details object.
|
|
670
|
+
*/
|
|
646
671
|
updateUserMessages = (user) => {
|
|
647
672
|
const _updateUserMessages = (messages, user2) => {
|
|
648
673
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -914,6 +939,15 @@ var Channel = class {
|
|
|
914
939
|
lastTypingEvent;
|
|
915
940
|
isTyping;
|
|
916
941
|
disconnected;
|
|
942
|
+
/**
|
|
943
|
+
* Initializes a new Channel class instance.
|
|
944
|
+
* Normally you should not call this directly; use `client.channel(type, id)` instead.
|
|
945
|
+
*
|
|
946
|
+
* @param client - The shared ErmisChat client instance initializing this channel.
|
|
947
|
+
* @param type - The type of channel (`messaging`, `team`, `livestream`, etc.).
|
|
948
|
+
* @param id - The unique ID of the channel.
|
|
949
|
+
* @param data - Initial arbitrary metadata stored within this channel.
|
|
950
|
+
*/
|
|
917
951
|
constructor(client, type, id, data) {
|
|
918
952
|
const validTypeRe = /^[\w_-]+$/;
|
|
919
953
|
const validIDRe = /^[\w!:_-]+$/;
|
|
@@ -940,6 +974,13 @@ var Channel = class {
|
|
|
940
974
|
getClient() {
|
|
941
975
|
return this._client;
|
|
942
976
|
}
|
|
977
|
+
/**
|
|
978
|
+
* Sends a message to this channel.
|
|
979
|
+
* By default, it pushes the message eagerly (optimistically) to the local UI state before the server replies.
|
|
980
|
+
*
|
|
981
|
+
* @param message - The constructed text/attachment object payload representing the message.
|
|
982
|
+
* @returns A Promise resolving to the exact API response encompassing message details.
|
|
983
|
+
*/
|
|
943
984
|
async sendMessage(message) {
|
|
944
985
|
if (!message.id) {
|
|
945
986
|
message = { ...message, id: randomId() };
|
|
@@ -1169,6 +1210,11 @@ var Channel = class {
|
|
|
1169
1210
|
const url = this.getClient().baseURL + `/invites/${this.type}/${this.id}/skip`;
|
|
1170
1211
|
return this.getClient().post(url);
|
|
1171
1212
|
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Directly invites or adds registered users into this channel.
|
|
1215
|
+
*
|
|
1216
|
+
* @param members - Array of user IDs explicitly selected to be added.
|
|
1217
|
+
*/
|
|
1172
1218
|
async addMembers(members) {
|
|
1173
1219
|
return await this._update({ add_members: members });
|
|
1174
1220
|
}
|
|
@@ -1234,6 +1280,11 @@ var Channel = class {
|
|
|
1234
1280
|
})
|
|
1235
1281
|
};
|
|
1236
1282
|
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Expels specified currently participating users out of the channel.
|
|
1285
|
+
*
|
|
1286
|
+
* @param members - Array of user IDs to strictly remove from this chat.
|
|
1287
|
+
*/
|
|
1237
1288
|
async removeMembers(members) {
|
|
1238
1289
|
return await this._update({ remove_members: members });
|
|
1239
1290
|
}
|
|
@@ -1313,6 +1364,10 @@ var Channel = class {
|
|
|
1313
1364
|
messageSlice.sort((a, b) => b.created_at.getTime() - a.created_at.getTime());
|
|
1314
1365
|
return messageSlice[0];
|
|
1315
1366
|
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Emits a mark-read event, updating the backend that the authenticated user has viewed up to the latest known message.
|
|
1369
|
+
* @returns Successful acknowledgement from the server.
|
|
1370
|
+
*/
|
|
1316
1371
|
async markRead() {
|
|
1317
1372
|
return await this.getClient().post(this._channelURL() + "/read");
|
|
1318
1373
|
}
|
|
@@ -1326,6 +1381,13 @@ var Channel = class {
|
|
|
1326
1381
|
}
|
|
1327
1382
|
this.state.clean();
|
|
1328
1383
|
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Subscribes to realtime events (WebSocket) for this channel, grabs the latest available metadata,
|
|
1386
|
+
* loads the most recent messages, and initializes the local state.
|
|
1387
|
+
*
|
|
1388
|
+
* @param options - Pagination limits like `{ watch: true, presence: true, state: true }`.
|
|
1389
|
+
* @returns The synchronized comprehensive channel state.
|
|
1390
|
+
*/
|
|
1329
1391
|
async watch(options) {
|
|
1330
1392
|
await this.getClient().wsPromise;
|
|
1331
1393
|
const combined = { ...options };
|
|
@@ -2763,32 +2825,55 @@ function isString(x) {
|
|
|
2763
2825
|
var ErmisChat = class _ErmisChat {
|
|
2764
2826
|
static _instance;
|
|
2765
2827
|
// type is undefined|ErmisChat, unknown is due to TS limitations with statics
|
|
2828
|
+
/** A map of active channels currently tracked by the client, keyed by Channel ID. */
|
|
2766
2829
|
activeChannels;
|
|
2830
|
+
/** The internal configured Axios instance used for REST API requests. */
|
|
2767
2831
|
axiosInstance;
|
|
2832
|
+
/** The primary base URL for REST API communication. */
|
|
2768
2833
|
baseURL;
|
|
2834
|
+
/** The specific base URL for standard user-focused REST calls. */
|
|
2769
2835
|
userBaseURL;
|
|
2836
|
+
/** True when the SDK is executed inside a browser environment. */
|
|
2770
2837
|
browser;
|
|
2771
2838
|
cleaningIntervalRef;
|
|
2772
2839
|
clientID;
|
|
2773
2840
|
apiKey;
|
|
2774
2841
|
projectId;
|
|
2842
|
+
/** Internal mapped registry of event listeners. */
|
|
2775
2843
|
listeners;
|
|
2776
2844
|
logger;
|
|
2845
|
+
/** Whether the client should automatically fetch missing messages upon unexpected disconnects. */
|
|
2777
2846
|
recoverStateOnReconnect;
|
|
2847
|
+
/** True when the SDK is executed in a NodeJS environment constraint. */
|
|
2778
2848
|
node;
|
|
2849
|
+
/** Custom options passed during client initialization. */
|
|
2779
2850
|
options;
|
|
2780
2851
|
setUserPromise;
|
|
2852
|
+
/** Centralized global state orchestrating user and client metadata. */
|
|
2781
2853
|
state;
|
|
2782
2854
|
tokenManager;
|
|
2855
|
+
/** The globally authenticated current user object. */
|
|
2783
2856
|
user;
|
|
2784
2857
|
userAgent;
|
|
2858
|
+
/** The unique ID of the current authenticated user. */
|
|
2785
2859
|
userID;
|
|
2860
|
+
/** The configured WebSocket endpoint base URL for realtime subscriptions. */
|
|
2786
2861
|
wsBaseURL;
|
|
2862
|
+
/** The active WebSocket connection controller. */
|
|
2787
2863
|
wsConnection;
|
|
2788
2864
|
wsPromise;
|
|
2865
|
+
/** Tracks consecutive REST API failures for exponential backoff purposes. */
|
|
2789
2866
|
consecutiveFailures;
|
|
2790
2867
|
defaultWSTimeout;
|
|
2791
2868
|
eventSource = null;
|
|
2869
|
+
/**
|
|
2870
|
+
* Initializes a new Ermis Chat Client instance.
|
|
2871
|
+
*
|
|
2872
|
+
* @param apiKey - Your public Ermis Network API Key.
|
|
2873
|
+
* @param projectId - Your specific Project UUID pointing to the app config.
|
|
2874
|
+
* @param baseURL - The API base endpoint assigned to your project.
|
|
2875
|
+
* @param options - Additional connection rules and configuration options.
|
|
2876
|
+
*/
|
|
2792
2877
|
constructor(apiKey, projectId, baseURL, options) {
|
|
2793
2878
|
this.apiKey = apiKey;
|
|
2794
2879
|
this.projectId = projectId;
|
|
@@ -2822,6 +2907,16 @@ var ErmisChat = class _ErmisChat {
|
|
|
2822
2907
|
this.logger = isFunction(inputOptions.logger) ? inputOptions.logger : () => null;
|
|
2823
2908
|
this.recoverStateOnReconnect = this.options.recoverStateOnReconnect;
|
|
2824
2909
|
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Retrieves the globally registered Singleton instance of the ErmisChat client.
|
|
2912
|
+
* If the instance lacks existence, it initializes a new one.
|
|
2913
|
+
*
|
|
2914
|
+
* @param key - Your public Ermis Network API Key.
|
|
2915
|
+
* @param projectId - Your specific Project UUID.
|
|
2916
|
+
* @param baseURL - The API base endpoint.
|
|
2917
|
+
* @param options - Connection options.
|
|
2918
|
+
* @returns The shared ErmisChat client instance.
|
|
2919
|
+
*/
|
|
2825
2920
|
static getInstance(key, projectId, baseURL, options) {
|
|
2826
2921
|
if (!_ErmisChat._instance) {
|
|
2827
2922
|
_ErmisChat._instance = new _ErmisChat(key, projectId, baseURL, options);
|
|
@@ -2869,6 +2964,15 @@ var ErmisChat = class _ErmisChat {
|
|
|
2869
2964
|
}
|
|
2870
2965
|
return await response.json();
|
|
2871
2966
|
}
|
|
2967
|
+
/**
|
|
2968
|
+
* Connects a user to the Ermis network and establishes the WebSocket connection.
|
|
2969
|
+
* This is the primary method to authenticate your client application.
|
|
2970
|
+
*
|
|
2971
|
+
* @param user - The User object containing `id`, `name`, and optional `avatar`.
|
|
2972
|
+
* @param userTokenOrProvider - The JWT token or an async token provider function.
|
|
2973
|
+
* @param extenal_auth - Set to `true` to use your custom backend external authentication flow.
|
|
2974
|
+
* @returns A promise resolving to the API connection response once authenticated.
|
|
2975
|
+
*/
|
|
2872
2976
|
connectUser = async (user, userTokenOrProvider, extenal_auth) => {
|
|
2873
2977
|
this.logger("info", "client:connectUser() - started", {
|
|
2874
2978
|
tags: ["connection", "client"]
|
|
@@ -2951,6 +3055,12 @@ var ErmisChat = class _ErmisChat {
|
|
|
2951
3055
|
return this.wsPromise;
|
|
2952
3056
|
};
|
|
2953
3057
|
_setupConnection = this.openConnection;
|
|
3058
|
+
/**
|
|
3059
|
+
* Gracefully disconnects the current user, terminates the WebSocket connection,
|
|
3060
|
+
* cleans up listeners, and resets the client's internal references.
|
|
3061
|
+
*
|
|
3062
|
+
* @param timeout - Optional timeout in milliseconds before forcing the disconnect.
|
|
3063
|
+
*/
|
|
2954
3064
|
disconnectUser = async (timeout) => {
|
|
2955
3065
|
this.logger("info", "client:disconnect() - Disconnecting the client", {
|
|
2956
3066
|
tags: ["connection", "client"]
|
|
@@ -3516,6 +3626,16 @@ var ErmisChat = class _ErmisChat {
|
|
|
3516
3626
|
this.state.updateUser(response);
|
|
3517
3627
|
return response;
|
|
3518
3628
|
}
|
|
3629
|
+
/**
|
|
3630
|
+
* Queries the API for a list of channels based on provided search filters and sort conditions.
|
|
3631
|
+
* Also hydrates these channels into the local SDK state memory.
|
|
3632
|
+
*
|
|
3633
|
+
* @param filterConditions - Specific criteria to filter channels (e.g. `{ type: 'messaging', members: { $in: ['user1'] } }`).
|
|
3634
|
+
* @param sort - The sorting hierarchy applied to the channel results.
|
|
3635
|
+
* @param options - Pagination and message limit parameters.
|
|
3636
|
+
* @param stateOptions - Defines whether to skip state initialization or offline usage.
|
|
3637
|
+
* @returns An array of hydrated and locally manageable `Channel` objects.
|
|
3638
|
+
*/
|
|
3519
3639
|
async queryChannels(filterConditions, sort = [], options = {}, stateOptions = {}) {
|
|
3520
3640
|
await this.wsPromise;
|
|
3521
3641
|
let project_id = this.projectId;
|
|
@@ -3667,7 +3787,7 @@ var ErmisChat = class _ErmisChat {
|
|
|
3667
3787
|
return pinExpires;
|
|
3668
3788
|
}
|
|
3669
3789
|
getUserAgent() {
|
|
3670
|
-
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.
|
|
3790
|
+
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.4"}`;
|
|
3671
3791
|
}
|
|
3672
3792
|
setUserAgent(userAgent) {
|
|
3673
3793
|
this.userAgent = userAgent;
|
|
@@ -7026,7 +7146,7 @@ var ErmisAuthProvider = class {
|
|
|
7026
7146
|
return data;
|
|
7027
7147
|
}
|
|
7028
7148
|
getUserAgent() {
|
|
7029
|
-
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.
|
|
7149
|
+
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.4"}`;
|
|
7030
7150
|
}
|
|
7031
7151
|
setUserAgent(userAgent) {
|
|
7032
7152
|
this.userAgent = userAgent;
|