@antzsoft/chat-core 1.4.6 → 1.4.7
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/README.md +18 -4
- package/dist/chat.store-TA6G7PD6.js +7 -0
- package/dist/chunk-QHELYVNT.js +109 -0
- package/dist/chunk-QHELYVNT.js.map +1 -0
- package/dist/index.cjs +116 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +62 -5
- package/dist/index.js.map +1 -1
- package/docs/integration-guide.html +19 -5
- package/package.json +1 -1
- package/dist/chat.store-UVTDBPEC.js +0 -7
- package/dist/chunk-UIYJAOGL.js +0 -62
- package/dist/chunk-UIYJAOGL.js.map +0 -1
- /package/dist/{chat.store-UVTDBPEC.js.map → chat.store-TA6G7PD6.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -339,6 +339,7 @@ declare function getSocket(): Socket;
|
|
|
339
339
|
declare function tryGetSocket(): Socket | null;
|
|
340
340
|
declare function getSocketStatus(): SocketStatus;
|
|
341
341
|
declare function onSocketStatus(listener: StatusListener): () => void;
|
|
342
|
+
declare function registerTeardownHook(hook: () => void): () => void;
|
|
342
343
|
/** Drop all tracked rooms. Call on a genuine identity change (user/tenant
|
|
343
344
|
* switch) so the reconnect re-flush can't re-join the previous user's rooms.
|
|
344
345
|
* NOT called from disconnectSocket() — a token refresh is not an intent change. */
|
|
@@ -353,6 +354,9 @@ declare function reconnectSocket(token: string, userId?: string, tenantId?: stri
|
|
|
353
354
|
*/
|
|
354
355
|
declare function refreshSocketAuth(): boolean;
|
|
355
356
|
|
|
357
|
+
/** Clears the typing throttle state. Call on teardown/identity change so a new
|
|
358
|
+
* session cannot inherit the previous one's suppression window. */
|
|
359
|
+
declare function resetTypingThrottle(): void;
|
|
356
360
|
declare const socketEmit: {
|
|
357
361
|
joinRoom(conversationId: string): void;
|
|
358
362
|
leaveRoom(conversationId: string): void;
|
|
@@ -584,6 +588,10 @@ interface ChatState {
|
|
|
584
588
|
} | null) => void;
|
|
585
589
|
addTypingUser: (conversationId: string, user: TypingUser) => void;
|
|
586
590
|
removeTypingUser: (conversationId: string, userId: string) => void;
|
|
591
|
+
/** Drops every typing indicator and cancels their expiry timers. For teardown
|
|
592
|
+
* and identity change — a socket drop no longer needs it, since indicators
|
|
593
|
+
* expire on their own. */
|
|
594
|
+
clearTypingUsers: () => void;
|
|
587
595
|
setUserOnline: (userId: string) => void;
|
|
588
596
|
setUserOffline: (userId: string) => void;
|
|
589
597
|
setOnlineUsers: (userIds: string[]) => void;
|
|
@@ -848,4 +856,4 @@ declare class AntzChatClient {
|
|
|
848
856
|
uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
|
|
849
857
|
}
|
|
850
858
|
|
|
851
|
-
export { AntzChatAuthError, AntzChatClient, AntzChatConfig, AntzChatError, AntzChatNetworkError, AntzChatPermissionError, AntzChatServerError, AntzChatValidationError, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationSyncResponse, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CrossConversationSyncResponse, CursorPaginatedResponse, FileResponse, FileType, ForwardAckPayload, ForwardMessagePayload, type ForwardResult, HIGHLY_FORWARDED_DEPTH_THRESHOLD, type LastReadEntry, type ListMessagesParams, LoginCredentials, MAX_FORWARD_TARGETS, type MentionPart, type MentionSegment, Message, MessageReactionsResponse, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, type ParsedMention, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, type TransitIdentity, TransitRateLimitedError, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, buildMentionText, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, extractMentionIds, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isApiClientConfigured, isMentionAll, isTransitEnvelope, messagesApi, normalizeAxiosError, normalizeConversation, onSocketStatus, parseMentions, performHandshake, readRetryAfterMs, reconnectSocket, refreshSocketAuth, renderMentionParts, resetAuthStore, resetTrackedRooms, resolveSystemMessageText, setApiClientInstance, setAuthReadyPromise, setTransitSession, socketEmit, syncApi, tryGetSocket, useChatStore, usersApi };
|
|
859
|
+
export { AntzChatAuthError, AntzChatClient, AntzChatConfig, AntzChatError, AntzChatNetworkError, AntzChatPermissionError, AntzChatServerError, AntzChatValidationError, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationSyncResponse, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CrossConversationSyncResponse, CursorPaginatedResponse, FileResponse, FileType, ForwardAckPayload, ForwardMessagePayload, type ForwardResult, HIGHLY_FORWARDED_DEPTH_THRESHOLD, type LastReadEntry, type ListMessagesParams, LoginCredentials, MAX_FORWARD_TARGETS, type MentionPart, type MentionSegment, Message, MessageReactionsResponse, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, type ParsedMention, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, type TransitIdentity, TransitRateLimitedError, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, buildMentionText, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, extractMentionIds, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isApiClientConfigured, isMentionAll, isTransitEnvelope, messagesApi, normalizeAxiosError, normalizeConversation, onSocketStatus, parseMentions, performHandshake, readRetryAfterMs, reconnectSocket, refreshSocketAuth, registerTeardownHook, renderMentionParts, resetAuthStore, resetTrackedRooms, resetTypingThrottle, resolveSystemMessageText, setApiClientInstance, setAuthReadyPromise, setTransitSession, socketEmit, syncApi, tryGetSocket, useChatStore, usersApi };
|
package/dist/index.d.ts
CHANGED
|
@@ -339,6 +339,7 @@ declare function getSocket(): Socket;
|
|
|
339
339
|
declare function tryGetSocket(): Socket | null;
|
|
340
340
|
declare function getSocketStatus(): SocketStatus;
|
|
341
341
|
declare function onSocketStatus(listener: StatusListener): () => void;
|
|
342
|
+
declare function registerTeardownHook(hook: () => void): () => void;
|
|
342
343
|
/** Drop all tracked rooms. Call on a genuine identity change (user/tenant
|
|
343
344
|
* switch) so the reconnect re-flush can't re-join the previous user's rooms.
|
|
344
345
|
* NOT called from disconnectSocket() — a token refresh is not an intent change. */
|
|
@@ -353,6 +354,9 @@ declare function reconnectSocket(token: string, userId?: string, tenantId?: stri
|
|
|
353
354
|
*/
|
|
354
355
|
declare function refreshSocketAuth(): boolean;
|
|
355
356
|
|
|
357
|
+
/** Clears the typing throttle state. Call on teardown/identity change so a new
|
|
358
|
+
* session cannot inherit the previous one's suppression window. */
|
|
359
|
+
declare function resetTypingThrottle(): void;
|
|
356
360
|
declare const socketEmit: {
|
|
357
361
|
joinRoom(conversationId: string): void;
|
|
358
362
|
leaveRoom(conversationId: string): void;
|
|
@@ -584,6 +588,10 @@ interface ChatState {
|
|
|
584
588
|
} | null) => void;
|
|
585
589
|
addTypingUser: (conversationId: string, user: TypingUser) => void;
|
|
586
590
|
removeTypingUser: (conversationId: string, userId: string) => void;
|
|
591
|
+
/** Drops every typing indicator and cancels their expiry timers. For teardown
|
|
592
|
+
* and identity change — a socket drop no longer needs it, since indicators
|
|
593
|
+
* expire on their own. */
|
|
594
|
+
clearTypingUsers: () => void;
|
|
587
595
|
setUserOnline: (userId: string) => void;
|
|
588
596
|
setUserOffline: (userId: string) => void;
|
|
589
597
|
setOnlineUsers: (userIds: string[]) => void;
|
|
@@ -848,4 +856,4 @@ declare class AntzChatClient {
|
|
|
848
856
|
uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
|
|
849
857
|
}
|
|
850
858
|
|
|
851
|
-
export { AntzChatAuthError, AntzChatClient, AntzChatConfig, AntzChatError, AntzChatNetworkError, AntzChatPermissionError, AntzChatServerError, AntzChatValidationError, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationSyncResponse, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CrossConversationSyncResponse, CursorPaginatedResponse, FileResponse, FileType, ForwardAckPayload, ForwardMessagePayload, type ForwardResult, HIGHLY_FORWARDED_DEPTH_THRESHOLD, type LastReadEntry, type ListMessagesParams, LoginCredentials, MAX_FORWARD_TARGETS, type MentionPart, type MentionSegment, Message, MessageReactionsResponse, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, type ParsedMention, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, type TransitIdentity, TransitRateLimitedError, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, buildMentionText, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, extractMentionIds, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isApiClientConfigured, isMentionAll, isTransitEnvelope, messagesApi, normalizeAxiosError, normalizeConversation, onSocketStatus, parseMentions, performHandshake, readRetryAfterMs, reconnectSocket, refreshSocketAuth, renderMentionParts, resetAuthStore, resetTrackedRooms, resolveSystemMessageText, setApiClientInstance, setAuthReadyPromise, setTransitSession, socketEmit, syncApi, tryGetSocket, useChatStore, usersApi };
|
|
859
|
+
export { AntzChatAuthError, AntzChatClient, AntzChatConfig, AntzChatError, AntzChatNetworkError, AntzChatPermissionError, AntzChatServerError, AntzChatValidationError, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationSyncResponse, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CrossConversationSyncResponse, CursorPaginatedResponse, FileResponse, FileType, ForwardAckPayload, ForwardMessagePayload, type ForwardResult, HIGHLY_FORWARDED_DEPTH_THRESHOLD, type LastReadEntry, type ListMessagesParams, LoginCredentials, MAX_FORWARD_TARGETS, type MentionPart, type MentionSegment, Message, MessageReactionsResponse, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, type ParsedMention, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, type TransitIdentity, TransitRateLimitedError, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, buildMentionText, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, extractMentionIds, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isApiClientConfigured, isMentionAll, isTransitEnvelope, messagesApi, normalizeAxiosError, normalizeConversation, onSocketStatus, parseMentions, performHandshake, readRetryAfterMs, reconnectSocket, refreshSocketAuth, registerTeardownHook, renderMentionParts, resetAuthStore, resetTrackedRooms, resetTypingThrottle, resolveSystemMessageText, setApiClientInstance, setAuthReadyPromise, setTransitSession, socketEmit, syncApi, tryGetSocket, useChatStore, usersApi };
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./chunk-U637W5MD.js";
|
|
42
42
|
import {
|
|
43
43
|
useChatStore
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-QHELYVNT.js";
|
|
45
45
|
|
|
46
46
|
// src/config/types.ts
|
|
47
47
|
function resolveConfig(config) {
|
|
@@ -405,6 +405,19 @@ function secureOn(socket, event, handler) {
|
|
|
405
405
|
handler(raw);
|
|
406
406
|
});
|
|
407
407
|
}
|
|
408
|
+
var _teardownHooks = /* @__PURE__ */ new Set();
|
|
409
|
+
function registerTeardownHook(hook) {
|
|
410
|
+
_teardownHooks.add(hook);
|
|
411
|
+
return () => _teardownHooks.delete(hook);
|
|
412
|
+
}
|
|
413
|
+
function runTeardownHooks() {
|
|
414
|
+
_teardownHooks.forEach((hook) => {
|
|
415
|
+
try {
|
|
416
|
+
hook();
|
|
417
|
+
} catch {
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
408
421
|
var _joinedRooms = /* @__PURE__ */ new Set();
|
|
409
422
|
function trackRoomJoin(conversationId) {
|
|
410
423
|
_joinedRooms.add(conversationId);
|
|
@@ -548,13 +561,13 @@ async function _doConnect(config, getToken) {
|
|
|
548
561
|
});
|
|
549
562
|
}
|
|
550
563
|
secureOn(_socket, "read_receipt", (event) => {
|
|
551
|
-
import("./chat.store-
|
|
564
|
+
import("./chat.store-TA6G7PD6.js").then(({ useChatStore: useChatStore2 }) => {
|
|
552
565
|
const e = event;
|
|
553
566
|
useChatStore2.getState().setLastRead(e.conversationId, e.messageId, e.readAt);
|
|
554
567
|
});
|
|
555
568
|
});
|
|
556
569
|
secureOn(_socket, "user_online", (event) => {
|
|
557
|
-
import("./chat.store-
|
|
570
|
+
import("./chat.store-TA6G7PD6.js").then(({ useChatStore: useChatStore2 }) => {
|
|
558
571
|
const store = useChatStore2.getState();
|
|
559
572
|
const e = event;
|
|
560
573
|
store.setUserOnline(e.userId);
|
|
@@ -562,7 +575,7 @@ async function _doConnect(config, getToken) {
|
|
|
562
575
|
});
|
|
563
576
|
});
|
|
564
577
|
secureOn(_socket, "user_offline", (event) => {
|
|
565
|
-
import("./chat.store-
|
|
578
|
+
import("./chat.store-TA6G7PD6.js").then(({ useChatStore: useChatStore2 }) => {
|
|
566
579
|
const e = event;
|
|
567
580
|
const store = useChatStore2.getState();
|
|
568
581
|
store.setUserOffline(e.userId);
|
|
@@ -600,6 +613,10 @@ function disconnectSocket() {
|
|
|
600
613
|
}
|
|
601
614
|
clearTransitSession();
|
|
602
615
|
resetAlgoCache();
|
|
616
|
+
runTeardownHooks();
|
|
617
|
+
import("./chat.store-TA6G7PD6.js").then(({ useChatStore: useChatStore2 }) => {
|
|
618
|
+
useChatStore2.getState().clearTypingUsers();
|
|
619
|
+
});
|
|
603
620
|
_getToken = null;
|
|
604
621
|
_userId = void 0;
|
|
605
622
|
_tenantId = void 0;
|
|
@@ -651,6 +668,12 @@ var RECONNECT_WAIT_TIMEOUT = 15e3;
|
|
|
651
668
|
var QUEUE_MAX_SIZE = 100;
|
|
652
669
|
var QUEUE_ENTRY_TTL = 3e4;
|
|
653
670
|
var sendQueues = /* @__PURE__ */ new Map();
|
|
671
|
+
var TYPING_THROTTLE_MS = 3e3;
|
|
672
|
+
var _lastTypingSentAt = /* @__PURE__ */ new Map();
|
|
673
|
+
function resetTypingThrottle() {
|
|
674
|
+
_lastTypingSentAt.clear();
|
|
675
|
+
}
|
|
676
|
+
registerTeardownHook(resetTypingThrottle);
|
|
654
677
|
var sendQueueRunning = /* @__PURE__ */ new Map();
|
|
655
678
|
async function drainSendQueue(conversationId) {
|
|
656
679
|
if (sendQueueRunning.get(conversationId)) return;
|
|
@@ -781,8 +804,40 @@ var socketEmit = {
|
|
|
781
804
|
return withAck("unpin_message", { messageId });
|
|
782
805
|
},
|
|
783
806
|
// markRead and typing are best-effort — silently dropped if socket not ready
|
|
807
|
+
//
|
|
808
|
+
// Typing is additionally LEADING-THROTTLED here rather than in the UI layer,
|
|
809
|
+
// so every consumer (both UI SDKs and any host calling socketEmit directly)
|
|
810
|
+
// gets the same emit budget and none can bypass it.
|
|
811
|
+
//
|
|
812
|
+
// The composer calls this on EVERY keystroke. A 40-word message is ~200 calls
|
|
813
|
+
// of which exactly one carries information: "this person started typing".
|
|
814
|
+
// Each one previously cost a round trip plus real server work, making typing
|
|
815
|
+
// the single most expensive event in the system per unit of user value.
|
|
816
|
+
//
|
|
817
|
+
// Shape of the throttle:
|
|
818
|
+
// isTyping:true — passed through at most once per TYPING_THROTTLE_MS per
|
|
819
|
+
// conversation. A continuous typist emits ~20/min instead
|
|
820
|
+
// of ~200/min.
|
|
821
|
+
// isTyping:false — ALWAYS passed through, and resets the window. It is the
|
|
822
|
+
// edge that clears the indicator on every peer, it is
|
|
823
|
+
// already debounced by the composer, and dropping it is
|
|
824
|
+
// exactly the failure that leaves "is typing…" stuck.
|
|
825
|
+
//
|
|
826
|
+
// The server refreshes its typing key on each true edge (10s TTL) and
|
|
827
|
+
// receivers expire their own indicators after TYPING_EXPIRY_MS, both of which
|
|
828
|
+
// are comfortably longer than TYPING_THROTTLE_MS — so a throttled-away event
|
|
829
|
+
// never lets an indicator lapse mid-typing.
|
|
784
830
|
typing(conversationId, isTyping) {
|
|
785
|
-
|
|
831
|
+
if (!isTyping) {
|
|
832
|
+
_lastTypingSentAt.delete(conversationId);
|
|
833
|
+
fireAndForget("typing", { conversationId, isTyping: false });
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
const now = Date.now();
|
|
837
|
+
const last = _lastTypingSentAt.get(conversationId) ?? 0;
|
|
838
|
+
if (now - last < TYPING_THROTTLE_MS) return;
|
|
839
|
+
_lastTypingSentAt.set(conversationId, now);
|
|
840
|
+
fireAndForget("typing", { conversationId, isTyping: true });
|
|
786
841
|
},
|
|
787
842
|
markRead(conversationId, messageId) {
|
|
788
843
|
fireAndForget("mark_read", { conversationId, ...messageId ? { messageId } : {} });
|
|
@@ -1369,9 +1424,11 @@ export {
|
|
|
1369
1424
|
readRetryAfterMs,
|
|
1370
1425
|
reconnectSocket,
|
|
1371
1426
|
refreshSocketAuth,
|
|
1427
|
+
registerTeardownHook,
|
|
1372
1428
|
renderMentionParts,
|
|
1373
1429
|
resetAuthStore,
|
|
1374
1430
|
resetTrackedRooms,
|
|
1431
|
+
resetTypingThrottle,
|
|
1375
1432
|
resolveConfig,
|
|
1376
1433
|
resolveSystemMessageText,
|
|
1377
1434
|
setApiClientInstance,
|