@antzsoft/chat-core 1.2.5 → 1.2.6

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.d.cts CHANGED
@@ -123,6 +123,7 @@ declare const conversationsApi: {
123
123
  */
124
124
  uploadIcon(conversationId: string, fileId: string): Promise<Conversation>;
125
125
  removeIcon(conversationId: string): Promise<Conversation>;
126
+ clearChat(conversationId: string): Promise<void>;
126
127
  };
127
128
 
128
129
  /** Shared fields for every device registration. */
@@ -267,6 +268,7 @@ declare const socketEmit: {
267
268
  updateMessage(messageId: string, text: string): Promise<unknown>;
268
269
  deleteMessage(messageId: string): Promise<unknown>;
269
270
  deleteMessageForMe(messageId: string): Promise<unknown>;
271
+ clearChat(conversationId: string): Promise<unknown>;
270
272
  addReaction(messageId: string, emoji: string): Promise<unknown>;
271
273
  removeReaction(messageId: string, emoji: string): Promise<unknown>;
272
274
  pinMessage(messageId: string): Promise<unknown>;
@@ -453,6 +455,45 @@ interface ChatState {
453
455
  }
454
456
  declare const useChatStore: zustand.UseBoundStore<zustand.StoreApi<ChatState>>;
455
457
 
458
+ declare class AntzChatError extends Error {
459
+ readonly code: string;
460
+ readonly retryable: boolean;
461
+ readonly context?: Record<string, unknown>;
462
+ constructor(code: string, message: string, retryable?: boolean, context?: Record<string, unknown>);
463
+ }
464
+ /** Thrown on 401 (after refresh also fails) or when no refresh token exists. */
465
+ declare class AntzChatAuthError extends AntzChatError {
466
+ constructor(message: string, code?: string, context?: Record<string, unknown>);
467
+ }
468
+ /** Thrown on 400 / 422 — bad input, validation failure. */
469
+ declare class AntzChatValidationError extends AntzChatError {
470
+ /** Server-returned field error array (when the server sends message as string[]). */
471
+ readonly fields?: string[];
472
+ constructor(message: string | string[], context?: Record<string, unknown>);
473
+ }
474
+ /** Thrown on network failures, timeouts, socket disconnections, and queue overflow. retryable = true. */
475
+ declare class AntzChatNetworkError extends AntzChatError {
476
+ constructor(message: string, code?: string, context?: Record<string, unknown>);
477
+ }
478
+ /** Thrown on 403 — insufficient permissions. */
479
+ declare class AntzChatPermissionError extends AntzChatError {
480
+ constructor(message: string, context?: Record<string, unknown>);
481
+ }
482
+ /** Thrown on 5xx or other unexpected server errors. retryable = true. */
483
+ declare class AntzChatServerError extends AntzChatError {
484
+ readonly httpStatus?: number;
485
+ constructor(message: string, httpStatus?: number, context?: Record<string, unknown>);
486
+ }
487
+ /**
488
+ * Converts a raw axios error (or any unknown throw) into a typed AntzChatError.
489
+ *
490
+ * Call site: client.ts response interceptor — runs AFTER transit decryption,
491
+ * so error.response.data is always plaintext by the time this function sees it.
492
+ * If decryption itself failed, error.response.data remains the raw encrypted
493
+ * envelope — detected via isTransitEnvelope() and noted in context.
494
+ */
495
+ declare function normalizeAxiosError(error: unknown): AntzChatError;
496
+
456
497
  /**
457
498
  * Resolves viewer-aware display text for system messages.
458
499
  *
@@ -544,6 +585,7 @@ declare class AntzChatClient {
544
585
  getUnreadSummary(): Promise<UnreadSummary>;
545
586
  uploadIcon(conversationId: string, fileId: string): Promise<Conversation>;
546
587
  removeIcon(conversationId: string): Promise<Conversation>;
588
+ clearChat(conversationId: string): Promise<void>;
547
589
  };
548
590
  readonly storage: {
549
591
  requestPresignedUrl(payload: PresignedUrlRequest): Promise<PresignedUrlResponse>;
@@ -595,4 +637,4 @@ declare class AntzChatClient {
595
637
  uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
596
638
  }
597
639
 
598
- export { AntzChatClient, AntzChatConfig, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CursorPaginatedResponse, FileResponse, FileType, type LastReadEntry, type ListMessagesParams, LoginCredentials, Message, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isTransitEnvelope, messagesApi, normalizeConversation, onSocketStatus, performHandshake, reconnectSocket, refreshSocketAuth, resetAuthStore, resolveSystemMessageText, setApiClientInstance, setTransitSession, socketEmit, tryGetSocket, useChatStore, usersApi };
640
+ export { AntzChatAuthError, AntzChatClient, AntzChatConfig, AntzChatError, AntzChatNetworkError, AntzChatPermissionError, AntzChatServerError, AntzChatValidationError, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CursorPaginatedResponse, FileResponse, FileType, type LastReadEntry, type ListMessagesParams, LoginCredentials, Message, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isTransitEnvelope, messagesApi, normalizeAxiosError, normalizeConversation, onSocketStatus, performHandshake, reconnectSocket, refreshSocketAuth, resetAuthStore, resolveSystemMessageText, setApiClientInstance, setTransitSession, socketEmit, tryGetSocket, useChatStore, usersApi };
package/dist/index.d.ts CHANGED
@@ -123,6 +123,7 @@ declare const conversationsApi: {
123
123
  */
124
124
  uploadIcon(conversationId: string, fileId: string): Promise<Conversation>;
125
125
  removeIcon(conversationId: string): Promise<Conversation>;
126
+ clearChat(conversationId: string): Promise<void>;
126
127
  };
127
128
 
128
129
  /** Shared fields for every device registration. */
@@ -267,6 +268,7 @@ declare const socketEmit: {
267
268
  updateMessage(messageId: string, text: string): Promise<unknown>;
268
269
  deleteMessage(messageId: string): Promise<unknown>;
269
270
  deleteMessageForMe(messageId: string): Promise<unknown>;
271
+ clearChat(conversationId: string): Promise<unknown>;
270
272
  addReaction(messageId: string, emoji: string): Promise<unknown>;
271
273
  removeReaction(messageId: string, emoji: string): Promise<unknown>;
272
274
  pinMessage(messageId: string): Promise<unknown>;
@@ -453,6 +455,45 @@ interface ChatState {
453
455
  }
454
456
  declare const useChatStore: zustand.UseBoundStore<zustand.StoreApi<ChatState>>;
455
457
 
458
+ declare class AntzChatError extends Error {
459
+ readonly code: string;
460
+ readonly retryable: boolean;
461
+ readonly context?: Record<string, unknown>;
462
+ constructor(code: string, message: string, retryable?: boolean, context?: Record<string, unknown>);
463
+ }
464
+ /** Thrown on 401 (after refresh also fails) or when no refresh token exists. */
465
+ declare class AntzChatAuthError extends AntzChatError {
466
+ constructor(message: string, code?: string, context?: Record<string, unknown>);
467
+ }
468
+ /** Thrown on 400 / 422 — bad input, validation failure. */
469
+ declare class AntzChatValidationError extends AntzChatError {
470
+ /** Server-returned field error array (when the server sends message as string[]). */
471
+ readonly fields?: string[];
472
+ constructor(message: string | string[], context?: Record<string, unknown>);
473
+ }
474
+ /** Thrown on network failures, timeouts, socket disconnections, and queue overflow. retryable = true. */
475
+ declare class AntzChatNetworkError extends AntzChatError {
476
+ constructor(message: string, code?: string, context?: Record<string, unknown>);
477
+ }
478
+ /** Thrown on 403 — insufficient permissions. */
479
+ declare class AntzChatPermissionError extends AntzChatError {
480
+ constructor(message: string, context?: Record<string, unknown>);
481
+ }
482
+ /** Thrown on 5xx or other unexpected server errors. retryable = true. */
483
+ declare class AntzChatServerError extends AntzChatError {
484
+ readonly httpStatus?: number;
485
+ constructor(message: string, httpStatus?: number, context?: Record<string, unknown>);
486
+ }
487
+ /**
488
+ * Converts a raw axios error (or any unknown throw) into a typed AntzChatError.
489
+ *
490
+ * Call site: client.ts response interceptor — runs AFTER transit decryption,
491
+ * so error.response.data is always plaintext by the time this function sees it.
492
+ * If decryption itself failed, error.response.data remains the raw encrypted
493
+ * envelope — detected via isTransitEnvelope() and noted in context.
494
+ */
495
+ declare function normalizeAxiosError(error: unknown): AntzChatError;
496
+
456
497
  /**
457
498
  * Resolves viewer-aware display text for system messages.
458
499
  *
@@ -544,6 +585,7 @@ declare class AntzChatClient {
544
585
  getUnreadSummary(): Promise<UnreadSummary>;
545
586
  uploadIcon(conversationId: string, fileId: string): Promise<Conversation>;
546
587
  removeIcon(conversationId: string): Promise<Conversation>;
588
+ clearChat(conversationId: string): Promise<void>;
547
589
  };
548
590
  readonly storage: {
549
591
  requestPresignedUrl(payload: PresignedUrlRequest): Promise<PresignedUrlResponse>;
@@ -595,4 +637,4 @@ declare class AntzChatClient {
595
637
  uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
596
638
  }
597
639
 
598
- export { AntzChatClient, AntzChatConfig, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CursorPaginatedResponse, FileResponse, FileType, type LastReadEntry, type ListMessagesParams, LoginCredentials, Message, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isTransitEnvelope, messagesApi, normalizeConversation, onSocketStatus, performHandshake, reconnectSocket, refreshSocketAuth, resetAuthStore, resolveSystemMessageText, setApiClientInstance, setTransitSession, socketEmit, tryGetSocket, useChatStore, usersApi };
640
+ export { AntzChatAuthError, AntzChatClient, AntzChatConfig, AntzChatError, AntzChatNetworkError, AntzChatPermissionError, AntzChatServerError, AntzChatValidationError, AppConfig, AuthResponse, AuthTokens, BatchUploadResult, CompletedPart, Conversation, ConversationListParams, ConversationUnreadCount, type CreateDirectData, type CreateGroupData, CursorPaginatedResponse, FileResponse, FileType, type LastReadEntry, type ListMessagesParams, LoginCredentials, Message, MessageReceiptsResponse, type MobileDeviceToken, PaginatedResponse, Participant, PersistStorage, PresignedUrlRequest, PresignedUrlResponse, RegisterData, type RegisterDeviceTokenPayload, ResolvedCompressionConfig, ResolvedConfig, type SearchParams, type SendData, SendMessagePayload, type SocketStatus, type StatusListener, type TokenStore, UnreadSummary, type UpdateConversationData, type UpdateProfilePayload, UploadableFile, User, UserPreferences, type WebPushDeviceToken, appConfigApi, authApi, connectSocket, conversationsApi, createAuthStore, createRestTransitSession, decryptPayload, devicesApi, disconnectSocket, encryptPayload, fetchServerKeys, generateEphemeralKey, getApiClient, getAuthStore, getCompressionStrategy, getSessionId, getSessionKey, getSocket, getSocketStatus, initApiClient, initAuthStore, isTransitEnvelope, messagesApi, normalizeAxiosError, normalizeConversation, onSocketStatus, performHandshake, reconnectSocket, refreshSocketAuth, resetAuthStore, resolveSystemMessageText, setApiClientInstance, setTransitSession, socketEmit, tryGetSocket, useChatStore, usersApi };
package/dist/index.js CHANGED
@@ -1,4 +1,10 @@
1
1
  import {
2
+ AntzChatAuthError,
3
+ AntzChatError,
4
+ AntzChatNetworkError,
5
+ AntzChatPermissionError,
6
+ AntzChatServerError,
7
+ AntzChatValidationError,
2
8
  clearTransitSession,
3
9
  configureTransit,
4
10
  createRestTransitSession,
@@ -16,13 +22,14 @@ import {
16
22
  initApiClient,
17
23
  isTransitEnabled,
18
24
  isTransitEnvelope,
25
+ normalizeAxiosError,
19
26
  performHandshake,
20
27
  resetAlgoCache,
21
28
  setApiClientInstance,
22
29
  setTransitSession,
23
30
  storageApi,
24
31
  uploadBatch
25
- } from "./chunk-ZNA6B2R5.js";
32
+ } from "./chunk-XTQYF5HU.js";
26
33
  import {
27
34
  useChatStore
28
35
  } from "./chunk-EOL5B7GS.js";
@@ -501,6 +508,9 @@ var conversationsApi = {
501
508
  async removeIcon(conversationId) {
502
509
  const { data } = await getApiClient().post(`/conversations/${conversationId}/icon/remove`);
503
510
  return normalizeConversation(data);
511
+ },
512
+ async clearChat(conversationId) {
513
+ await getApiClient().post(`/conversations/${conversationId}/clear-for-me`);
504
514
  }
505
515
  };
506
516
 
@@ -694,8 +704,11 @@ async function _doConnect(config, getToken) {
694
704
  try {
695
705
  const serverKeys = await fetchServerKeys(config.apiUrl);
696
706
  if (!serverKeys.enabled) {
697
- throw new Error(
698
- "[AntzChat] Transit encryption mismatch: SDK has transitEncryption=true but server has TRANSIT_ENCRYPTION_ENABLED=false. Align the config on both sides."
707
+ throw new AntzChatError(
708
+ "TRANSIT_MISMATCH",
709
+ "[AntzChat] Transit encryption mismatch: SDK has transitEncryption=true but server has TRANSIT_ENCRYPTION_ENABLED=false. Align the config on both sides.",
710
+ false,
711
+ { sdkEnabled: true, serverEnabled: false }
699
712
  );
700
713
  }
701
714
  const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
@@ -708,12 +721,15 @@ async function _doConnect(config, getToken) {
708
721
  try {
709
722
  const serverKeys = await fetchServerKeys(config.apiUrl);
710
723
  if (serverKeys.enabled) {
711
- throw new Error(
712
- "[AntzChat] Transit encryption mismatch: SDK has transitEncryption=false but server has TRANSIT_ENCRYPTION_ENABLED=true. Align the config on both sides."
724
+ throw new AntzChatError(
725
+ "TRANSIT_MISMATCH",
726
+ "[AntzChat] Transit encryption mismatch: SDK has transitEncryption=false but server has TRANSIT_ENCRYPTION_ENABLED=true. Align the config on both sides.",
727
+ false,
728
+ { sdkEnabled: false, serverEnabled: true }
713
729
  );
714
730
  }
715
731
  } catch (err) {
716
- if (err.message?.startsWith("[AntzChat] Transit encryption mismatch")) throw err;
732
+ if (err?.code === "TRANSIT_MISMATCH") throw err;
717
733
  }
718
734
  }
719
735
  _socket = io(`${config.socketOrigin}/chat`, {
@@ -857,7 +873,7 @@ async function drainSendQueue(conversationId) {
857
873
  while (queue.length > 0) {
858
874
  const entry = queue.shift();
859
875
  if (Date.now() - entry.enqueuedAt > QUEUE_ENTRY_TTL) {
860
- entry.reject(new Error("[AntzChat] Message dropped: queued too long"));
876
+ entry.reject(new AntzChatNetworkError("Message dropped: queued too long", "MESSAGE_DROPPED"));
861
877
  continue;
862
878
  }
863
879
  entry.run().then(entry.resolve).catch(entry.reject);
@@ -870,7 +886,7 @@ function queueSendMessage(payload) {
870
886
  if (!sendQueues.has(conversationId)) sendQueues.set(conversationId, []);
871
887
  const queue = sendQueues.get(conversationId);
872
888
  if (queue.length >= QUEUE_MAX_SIZE) {
873
- return Promise.reject(new Error("[AntzChat] Send queue full: too many messages in flight"));
889
+ return Promise.reject(new AntzChatNetworkError("Send queue full: too many messages in flight", "SEND_QUEUE_FULL", { conversationId }));
874
890
  }
875
891
  return new Promise((resolve, reject) => {
876
892
  queue.push({ run: () => withAck("send_message", payload), resolve, reject, enqueuedAt: Date.now() });
@@ -881,7 +897,7 @@ function waitForReconnect() {
881
897
  return new Promise((resolve, reject) => {
882
898
  const timer = setTimeout(() => {
883
899
  unsubscribe();
884
- reject(new Error("[AntzChat] Socket reconnect timeout"));
900
+ reject(new AntzChatNetworkError("Socket reconnect timeout", "SOCKET_TIMEOUT"));
885
901
  }, RECONNECT_WAIT_TIMEOUT);
886
902
  const unsubscribe = onSocketStatus((status) => {
887
903
  if (status === "connected") {
@@ -891,7 +907,7 @@ function waitForReconnect() {
891
907
  } else if (status === "error") {
892
908
  clearTimeout(timer);
893
909
  unsubscribe();
894
- reject(new Error("[AntzChat] Socket reconnect failed"));
910
+ reject(new AntzChatNetworkError("Socket reconnect failed", "SOCKET_NOT_CONNECTED"));
895
911
  }
896
912
  });
897
913
  });
@@ -902,14 +918,14 @@ async function withAck(event, payload) {
902
918
  await waitForReconnect();
903
919
  socket = tryGetSocket();
904
920
  }
905
- if (!socket) return Promise.reject(new Error(`[AntzChat] Socket not connected (event: ${event})`));
921
+ if (!socket) return Promise.reject(new AntzChatNetworkError(`Socket not connected (event: ${event})`, "SOCKET_NOT_CONNECTED", { event }));
906
922
  return new Promise((resolve, reject) => {
907
923
  let timer;
908
924
  secureEmit(socket, event, payload, (response) => {
909
925
  clearTimeout(timer);
910
926
  resolve(response);
911
927
  }).then(() => {
912
- timer = setTimeout(() => reject(new Error(`Socket ack timeout: ${event}`)), ACK_TIMEOUT);
928
+ timer = setTimeout(() => reject(new AntzChatNetworkError(`Socket ack timeout: ${event}`, "SOCKET_TIMEOUT", { event })), ACK_TIMEOUT);
913
929
  }).catch(reject);
914
930
  });
915
931
  }
@@ -937,6 +953,9 @@ var socketEmit = {
937
953
  deleteMessageForMe(messageId) {
938
954
  return withAck("delete_message_for_me", { messageId });
939
955
  },
956
+ clearChat(conversationId) {
957
+ return withAck("clear_chat_for_me", { conversationId });
958
+ },
940
959
  addReaction(messageId, emoji) {
941
960
  return withAck("add_reaction", { messageId, emoji });
942
961
  },
@@ -972,7 +991,7 @@ var socketEmit = {
972
991
  resolve([]);
973
992
  }
974
993
  }).then(() => {
975
- timer = setTimeout(() => reject(new Error("get_online_users timeout")), ACK_TIMEOUT);
994
+ timer = setTimeout(() => reject(new AntzChatNetworkError("Socket ack timeout: get_online_users", "SOCKET_TIMEOUT", { event: "get_online_users" })), ACK_TIMEOUT);
976
995
  }).catch(reject);
977
996
  });
978
997
  },
@@ -1031,7 +1050,13 @@ var AntzChatClient = class {
1031
1050
  }
1032
1051
  };
1033
1052
  export {
1053
+ AntzChatAuthError,
1034
1054
  AntzChatClient,
1055
+ AntzChatError,
1056
+ AntzChatNetworkError,
1057
+ AntzChatPermissionError,
1058
+ AntzChatServerError,
1059
+ AntzChatValidationError,
1035
1060
  appConfigApi,
1036
1061
  authApi,
1037
1062
  connectSocket,
@@ -1055,6 +1080,7 @@ export {
1055
1080
  initAuthStore,
1056
1081
  isTransitEnvelope,
1057
1082
  messagesApi,
1083
+ normalizeAxiosError,
1058
1084
  normalizeConversation,
1059
1085
  onSocketStatus,
1060
1086
  performHandshake,