@antzsoft/chat-core 1.2.4 → 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
@@ -1,5 +1,5 @@
1
- import { Y as ResolvedCompressionConfig, o as LoginCredentials, c as AuthResponse, W as RegisterData, d as AuthTokens, a7 as User, a as AppConfig, a0 as SendMessagePayload, l as CursorPaginatedResponse, M as Message, P as PaginatedResponse, x as MessageReceiptsResponse, i as ConversationListParams, h as Conversation, H as Participant, k as ConversationUnreadCount, a3 as UnreadSummary, a8 as UserPreferences, Z as ResolvedConfig, I as PersistStorage, R as PresignedUrlRequest, S as PresignedUrlResponse, F as FileResponse, C as CompletedPart, n as FileType, A as AntzChatConfig, a6 as UploadableFile, B as BatchUploadResult } from './storage-Bp6fk9aM.cjs';
2
- export { b as Attachment, e as CompressedFile, f as CompressionAlgorithm, g as CompressionConfig, j as ConversationType, m as FileSizeLimits, L as LastReaction, p as MessageAckEvent, q as MessageContent, r as MessageDeletedEvent, s as MessageDeletedForMeEvent, t as MessageDeliveredEvent, u as MessageMetadata, v as MessageReaction, w as MessageReceiptEntry, y as MessageReplyReference, z as MessageUpdatedEvent, D as MessagesDeliveredEvent, E as MultipartPartUrl, G as MultipartUploadInfo, N as NewMessageEvent, O as OptimisticAttachment, J as PlatformCompressFn, K as PlatformUploadFn, Q as PlatformUploadPartFn, T as QuietHours, U as ReactionUpdatedEvent, V as ReadReceiptEvent, X as ReplyAttachmentSnapshot, _ as ResolvedFileSizeLimits, $ as SendMessageAttachment, a1 as SystemMessageMetadata, a2 as TypingIndicatorEvent, a4 as UploadConfig, a5 as UploadProgress, a9 as UserStatusEvent, aa as resolveConfig, ab as storageApi, ac as uploadBatch } from './storage-Bp6fk9aM.cjs';
1
+ import { R as ResolvedCompressionConfig, L as LoginCredentials, A as AuthResponse, a as RegisterData, b as AuthTokens, U as User, c as AppConfig, S as SendMessagePayload, C as CursorPaginatedResponse, M as Message, P as PaginatedResponse, d as MessageReceiptsResponse, e as ConversationListParams, f as Conversation, g as Participant, h as ConversationUnreadCount, i as UnreadSummary, j as UserPreferences, k as ResolvedConfig, l as PersistStorage, m as PresignedUrlRequest, n as PresignedUrlResponse, F as FileResponse, o as CompletedPart, p as FileType, q as AntzChatConfig, r as UploadableFile, B as BatchUploadResult } from './storage-CctLCOnZ.cjs';
2
+ export { s as Attachment, t as CompressedFile, u as CompressionAlgorithm, v as CompressionConfig, w as ConversationType, x as FileSizeLimits, y as LastReaction, z as MessageAckEvent, D as MessageContent, E as MessageDeletedEvent, G as MessageDeletedForMeEvent, H as MessageDeliveredEvent, I as MessageMetadata, J as MessageReaction, K as MessageReceiptEntry, N as MessageReplyReference, O as MessageUpdatedEvent, Q as MessagesDeliveredEvent, T as MultipartPartUrl, V as MultipartUploadInfo, W as NewMessageEvent, X as OptimisticAttachment, Y as PlatformCompressFn, Z as PlatformUploadFn, _ as PlatformUploadPartFn, $ as QuietHours, a0 as ReactionUpdatedEvent, a1 as ReadReceiptEvent, a2 as ReplyAttachmentSnapshot, a3 as ResolvedFileSizeLimits, a4 as SendMessageAttachment, a5 as SystemMessageMetadata, a6 as TypingIndicatorEvent, a7 as UploadConfig, a8 as UploadProgress, a9 as UserStatusEvent, aa as resolveConfig, ab as storageApi, ac as uploadBatch } from './storage-CctLCOnZ.cjs';
3
3
  import { AxiosInstance } from 'axios';
4
4
  import { Socket } from 'socket.io-client';
5
5
  import * as zustand_middleware from 'zustand/middleware';
@@ -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>;
@@ -286,6 +288,35 @@ interface TransitSession {
286
288
  enabled: boolean;
287
289
  }
288
290
  declare function setTransitSession(session: TransitSession): void;
291
+ declare function getSessionKey(): CryptoKey | Uint8Array | null;
292
+ declare function getSessionId(): string | null;
293
+
294
+ interface TransitEnvelope {
295
+ v: 1;
296
+ iv: string;
297
+ tag: string;
298
+ ct: string;
299
+ }
300
+ type AnySessionKey = CryptoKey | Uint8Array;
301
+ declare function encryptPayload(data: unknown, sessionKey: AnySessionKey): Promise<TransitEnvelope>;
302
+ declare function decryptPayload(envelope: TransitEnvelope, sessionKey: AnySessionKey): Promise<unknown>;
303
+ declare function isTransitEnvelope(v: unknown): v is TransitEnvelope;
304
+
305
+ interface ServerPublicKeys {
306
+ x25519: string;
307
+ p256: string;
308
+ enabled: boolean;
309
+ }
310
+ declare function fetchServerKeys(apiUrl: string): Promise<ServerPublicKeys>;
311
+ declare function generateEphemeralKey(algo: TransitAlgo, serverKeys: ServerPublicKeys): Promise<{
312
+ ephemeralPubB64: string;
313
+ deriveSessionKey: (sessionId: string) => Promise<unknown>;
314
+ }>;
315
+ declare function createRestTransitSession(apiUrl: string): Promise<{
316
+ sessionId: string;
317
+ sessionKey: CryptoKey | Uint8Array;
318
+ } | null>;
319
+ declare function performHandshake(algo: TransitAlgo, serverKeys: ServerPublicKeys, socketHandshakeAuth: Record<string, unknown>): Promise<(sessionId: string) => Promise<unknown>>;
289
320
 
290
321
  interface AuthState {
291
322
  user: User | null;
@@ -424,6 +455,45 @@ interface ChatState {
424
455
  }
425
456
  declare const useChatStore: zustand.UseBoundStore<zustand.StoreApi<ChatState>>;
426
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
+
427
497
  /**
428
498
  * Resolves viewer-aware display text for system messages.
429
499
  *
@@ -515,6 +585,7 @@ declare class AntzChatClient {
515
585
  getUnreadSummary(): Promise<UnreadSummary>;
516
586
  uploadIcon(conversationId: string, fileId: string): Promise<Conversation>;
517
587
  removeIcon(conversationId: string): Promise<Conversation>;
588
+ clearChat(conversationId: string): Promise<void>;
518
589
  };
519
590
  readonly storage: {
520
591
  requestPresignedUrl(payload: PresignedUrlRequest): Promise<PresignedUrlResponse>;
@@ -566,4 +637,4 @@ declare class AntzChatClient {
566
637
  uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
567
638
  }
568
639
 
569
- 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, devicesApi, disconnectSocket, getApiClient, getAuthStore, getCompressionStrategy, getSocket, getSocketStatus, initApiClient, initAuthStore, messagesApi, normalizeConversation, onSocketStatus, 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
@@ -1,5 +1,5 @@
1
- import { Y as ResolvedCompressionConfig, o as LoginCredentials, c as AuthResponse, W as RegisterData, d as AuthTokens, a7 as User, a as AppConfig, a0 as SendMessagePayload, l as CursorPaginatedResponse, M as Message, P as PaginatedResponse, x as MessageReceiptsResponse, i as ConversationListParams, h as Conversation, H as Participant, k as ConversationUnreadCount, a3 as UnreadSummary, a8 as UserPreferences, Z as ResolvedConfig, I as PersistStorage, R as PresignedUrlRequest, S as PresignedUrlResponse, F as FileResponse, C as CompletedPart, n as FileType, A as AntzChatConfig, a6 as UploadableFile, B as BatchUploadResult } from './storage-Bp6fk9aM.js';
2
- export { b as Attachment, e as CompressedFile, f as CompressionAlgorithm, g as CompressionConfig, j as ConversationType, m as FileSizeLimits, L as LastReaction, p as MessageAckEvent, q as MessageContent, r as MessageDeletedEvent, s as MessageDeletedForMeEvent, t as MessageDeliveredEvent, u as MessageMetadata, v as MessageReaction, w as MessageReceiptEntry, y as MessageReplyReference, z as MessageUpdatedEvent, D as MessagesDeliveredEvent, E as MultipartPartUrl, G as MultipartUploadInfo, N as NewMessageEvent, O as OptimisticAttachment, J as PlatformCompressFn, K as PlatformUploadFn, Q as PlatformUploadPartFn, T as QuietHours, U as ReactionUpdatedEvent, V as ReadReceiptEvent, X as ReplyAttachmentSnapshot, _ as ResolvedFileSizeLimits, $ as SendMessageAttachment, a1 as SystemMessageMetadata, a2 as TypingIndicatorEvent, a4 as UploadConfig, a5 as UploadProgress, a9 as UserStatusEvent, aa as resolveConfig, ab as storageApi, ac as uploadBatch } from './storage-Bp6fk9aM.js';
1
+ import { R as ResolvedCompressionConfig, L as LoginCredentials, A as AuthResponse, a as RegisterData, b as AuthTokens, U as User, c as AppConfig, S as SendMessagePayload, C as CursorPaginatedResponse, M as Message, P as PaginatedResponse, d as MessageReceiptsResponse, e as ConversationListParams, f as Conversation, g as Participant, h as ConversationUnreadCount, i as UnreadSummary, j as UserPreferences, k as ResolvedConfig, l as PersistStorage, m as PresignedUrlRequest, n as PresignedUrlResponse, F as FileResponse, o as CompletedPart, p as FileType, q as AntzChatConfig, r as UploadableFile, B as BatchUploadResult } from './storage-CctLCOnZ.js';
2
+ export { s as Attachment, t as CompressedFile, u as CompressionAlgorithm, v as CompressionConfig, w as ConversationType, x as FileSizeLimits, y as LastReaction, z as MessageAckEvent, D as MessageContent, E as MessageDeletedEvent, G as MessageDeletedForMeEvent, H as MessageDeliveredEvent, I as MessageMetadata, J as MessageReaction, K as MessageReceiptEntry, N as MessageReplyReference, O as MessageUpdatedEvent, Q as MessagesDeliveredEvent, T as MultipartPartUrl, V as MultipartUploadInfo, W as NewMessageEvent, X as OptimisticAttachment, Y as PlatformCompressFn, Z as PlatformUploadFn, _ as PlatformUploadPartFn, $ as QuietHours, a0 as ReactionUpdatedEvent, a1 as ReadReceiptEvent, a2 as ReplyAttachmentSnapshot, a3 as ResolvedFileSizeLimits, a4 as SendMessageAttachment, a5 as SystemMessageMetadata, a6 as TypingIndicatorEvent, a7 as UploadConfig, a8 as UploadProgress, a9 as UserStatusEvent, aa as resolveConfig, ab as storageApi, ac as uploadBatch } from './storage-CctLCOnZ.js';
3
3
  import { AxiosInstance } from 'axios';
4
4
  import { Socket } from 'socket.io-client';
5
5
  import * as zustand_middleware from 'zustand/middleware';
@@ -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>;
@@ -286,6 +288,35 @@ interface TransitSession {
286
288
  enabled: boolean;
287
289
  }
288
290
  declare function setTransitSession(session: TransitSession): void;
291
+ declare function getSessionKey(): CryptoKey | Uint8Array | null;
292
+ declare function getSessionId(): string | null;
293
+
294
+ interface TransitEnvelope {
295
+ v: 1;
296
+ iv: string;
297
+ tag: string;
298
+ ct: string;
299
+ }
300
+ type AnySessionKey = CryptoKey | Uint8Array;
301
+ declare function encryptPayload(data: unknown, sessionKey: AnySessionKey): Promise<TransitEnvelope>;
302
+ declare function decryptPayload(envelope: TransitEnvelope, sessionKey: AnySessionKey): Promise<unknown>;
303
+ declare function isTransitEnvelope(v: unknown): v is TransitEnvelope;
304
+
305
+ interface ServerPublicKeys {
306
+ x25519: string;
307
+ p256: string;
308
+ enabled: boolean;
309
+ }
310
+ declare function fetchServerKeys(apiUrl: string): Promise<ServerPublicKeys>;
311
+ declare function generateEphemeralKey(algo: TransitAlgo, serverKeys: ServerPublicKeys): Promise<{
312
+ ephemeralPubB64: string;
313
+ deriveSessionKey: (sessionId: string) => Promise<unknown>;
314
+ }>;
315
+ declare function createRestTransitSession(apiUrl: string): Promise<{
316
+ sessionId: string;
317
+ sessionKey: CryptoKey | Uint8Array;
318
+ } | null>;
319
+ declare function performHandshake(algo: TransitAlgo, serverKeys: ServerPublicKeys, socketHandshakeAuth: Record<string, unknown>): Promise<(sessionId: string) => Promise<unknown>>;
289
320
 
290
321
  interface AuthState {
291
322
  user: User | null;
@@ -424,6 +455,45 @@ interface ChatState {
424
455
  }
425
456
  declare const useChatStore: zustand.UseBoundStore<zustand.StoreApi<ChatState>>;
426
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
+
427
497
  /**
428
498
  * Resolves viewer-aware display text for system messages.
429
499
  *
@@ -515,6 +585,7 @@ declare class AntzChatClient {
515
585
  getUnreadSummary(): Promise<UnreadSummary>;
516
586
  uploadIcon(conversationId: string, fileId: string): Promise<Conversation>;
517
587
  removeIcon(conversationId: string): Promise<Conversation>;
588
+ clearChat(conversationId: string): Promise<void>;
518
589
  };
519
590
  readonly storage: {
520
591
  requestPresignedUrl(payload: PresignedUrlRequest): Promise<PresignedUrlResponse>;
@@ -566,4 +637,4 @@ declare class AntzChatClient {
566
637
  uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
567
638
  }
568
639
 
569
- 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, devicesApi, disconnectSocket, getApiClient, getAuthStore, getCompressionStrategy, getSocket, getSocketStatus, initApiClient, initAuthStore, messagesApi, normalizeConversation, onSocketStatus, 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,19 +1,35 @@
1
1
  import {
2
+ AntzChatAuthError,
3
+ AntzChatError,
4
+ AntzChatNetworkError,
5
+ AntzChatPermissionError,
6
+ AntzChatServerError,
7
+ AntzChatValidationError,
2
8
  clearTransitSession,
3
9
  configureTransit,
10
+ createRestTransitSession,
4
11
  decryptPayload,
12
+ detectTransitAlgo,
5
13
  encryptPayload,
14
+ fetchServerKeys,
15
+ generateEphemeralKey,
6
16
  getApiClient,
7
17
  getCompressionStrategy,
18
+ getSessionId,
8
19
  getSessionKey,
20
+ getTransitHandshakePromise,
21
+ getTransitSession,
9
22
  initApiClient,
10
23
  isTransitEnabled,
11
24
  isTransitEnvelope,
25
+ normalizeAxiosError,
26
+ performHandshake,
27
+ resetAlgoCache,
12
28
  setApiClientInstance,
13
29
  setTransitSession,
14
30
  storageApi,
15
31
  uploadBatch
16
- } from "./chunk-6NMA64BX.js";
32
+ } from "./chunk-XTQYF5HU.js";
17
33
  import {
18
34
  useChatStore
19
35
  } from "./chunk-EOL5B7GS.js";
@@ -378,7 +394,8 @@ function normalizeLastMessage(lastMsg) {
378
394
  isEdited: false,
379
395
  sentAt: lastMsg.sentAt ?? "",
380
396
  createdAt: lastMsg.sentAt ?? "",
381
- ...lastMsg.senderName && { senderName: lastMsg.senderName }
397
+ ...lastMsg.senderName && { senderName: lastMsg.senderName },
398
+ ...lastMsg.attachmentType && { attachmentType: lastMsg.attachmentType }
382
399
  };
383
400
  }
384
401
  function normalizeConversation(conv) {
@@ -491,6 +508,9 @@ var conversationsApi = {
491
508
  async removeIcon(conversationId) {
492
509
  const { data } = await getApiClient().post(`/conversations/${conversationId}/icon/remove`);
493
510
  return normalizeConversation(data);
511
+ },
512
+ async clearChat(conversationId) {
513
+ await getApiClient().post(`/conversations/${conversationId}/clear-for-me`);
494
514
  }
495
515
  };
496
516
 
@@ -568,122 +588,6 @@ var usersApi = {
568
588
 
569
589
  // src/socket/socket.ts
570
590
  import { io } from "socket.io-client";
571
-
572
- // src/crypto/detect.ts
573
- var _cached = null;
574
- async function detectTransitAlgo() {
575
- if (_cached) return _cached;
576
- try {
577
- await globalThis.crypto.subtle.generateKey(
578
- { name: "X25519" },
579
- false,
580
- ["deriveKey"]
581
- );
582
- _cached = "x25519";
583
- } catch {
584
- _cached = "p256";
585
- }
586
- return _cached;
587
- }
588
- function resetAlgoCache() {
589
- _cached = null;
590
- }
591
-
592
- // src/crypto/handshake.ts
593
- function hasWebCrypto() {
594
- return typeof globalThis.crypto?.subtle !== "undefined";
595
- }
596
- async function fetchServerKeys(apiUrl) {
597
- const res = await fetch(`${apiUrl}/crypto/pubkey`);
598
- if (!res.ok) throw new Error(`[AntzChat] Failed to fetch server public key: ${res.status}`);
599
- const body = await res.json();
600
- return body?.data ?? body;
601
- }
602
- async function performHandshake(algo, serverKeys, socketHandshakeAuth) {
603
- if (hasWebCrypto()) {
604
- return performWebCryptoHandshake(algo, serverKeys, socketHandshakeAuth);
605
- }
606
- return performNobleHandshake(serverKeys, socketHandshakeAuth);
607
- }
608
- async function performWebCryptoHandshake(algo, serverKeys, socketHandshakeAuth) {
609
- const ephemeral = await globalThis.crypto.subtle.generateKey(
610
- algo === "x25519" ? { name: "X25519" } : { name: "ECDH", namedCurve: "P-256" },
611
- false,
612
- ["deriveBits"]
613
- );
614
- const pubRaw = await globalThis.crypto.subtle.exportKey("raw", ephemeral.publicKey);
615
- socketHandshakeAuth["transitEphemeralPub"] = bufToB64(pubRaw);
616
- socketHandshakeAuth["transitAlgo"] = algo;
617
- const ephemeralPriv = ephemeral.privateKey;
618
- return (sessionId) => deriveWebCryptoSessionKey(ephemeralPriv, algo, serverKeys, sessionId);
619
- }
620
- async function deriveWebCryptoSessionKey(ephemeralPriv, algo, serverKeys, sessionId) {
621
- const serverPubRaw = b64ToBuf(algo === "x25519" ? serverKeys.x25519 : serverKeys.p256);
622
- const keyAlgoParams = algo === "x25519" ? { name: "X25519" } : { name: "ECDH", namedCurve: "P-256" };
623
- const serverPubKey = await globalThis.crypto.subtle.importKey("raw", serverPubRaw, keyAlgoParams, false, []);
624
- const sharedBits = await globalThis.crypto.subtle.deriveBits(
625
- { name: algo === "x25519" ? "X25519" : "ECDH", public: serverPubKey },
626
- ephemeralPriv,
627
- 256
628
- );
629
- const hkdfKey = await globalThis.crypto.subtle.importKey("raw", sharedBits, "HKDF", false, ["deriveKey"]);
630
- const salt = new TextEncoder().encode(sessionId);
631
- const info = new TextEncoder().encode("antz-transit-v1");
632
- return globalThis.crypto.subtle.deriveKey(
633
- { name: "HKDF", hash: "SHA-256", salt, info },
634
- hkdfKey,
635
- { name: "AES-GCM", length: 256 },
636
- false,
637
- ["encrypt", "decrypt"]
638
- );
639
- }
640
- async function performNobleHandshake(serverKeys, socketHandshakeAuth) {
641
- const { x25519 } = await import("@noble/curves/ed25519");
642
- const { hkdf } = await import("@noble/hashes/hkdf");
643
- const { sha256 } = await import("@noble/hashes/sha256");
644
- const { randomBytes } = await import("@noble/hashes/utils");
645
- const ephemeralPriv = randomBytes(32);
646
- const ephemeralPub = x25519.getPublicKey(ephemeralPriv);
647
- const serverPubBytes = base64ToUint8(serverKeys.x25519);
648
- socketHandshakeAuth["transitEphemeralPub"] = uint8ToBase64(ephemeralPub);
649
- socketHandshakeAuth["transitAlgo"] = "x25519";
650
- return (sessionId) => {
651
- const sharedSecret = x25519.getSharedSecret(ephemeralPriv, serverPubBytes);
652
- const salt = new TextEncoder().encode(sessionId);
653
- const info = new TextEncoder().encode("antz-transit-v1");
654
- const sessionKey = hkdf(sha256, sharedSecret, salt, info, 32);
655
- return Promise.resolve(sessionKey);
656
- };
657
- }
658
- function bufToB64(buf) {
659
- const bytes = new Uint8Array(buf);
660
- let str = "";
661
- bytes.forEach((b) => {
662
- str += String.fromCharCode(b);
663
- });
664
- return btoa(str);
665
- }
666
- function b64ToBuf(b64) {
667
- const bin = atob(b64);
668
- const buf = new Uint8Array(bin.length);
669
- for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
670
- return buf.buffer;
671
- }
672
- function uint8ToBase64(bytes) {
673
- let str = "";
674
- bytes.forEach((b) => {
675
- str += String.fromCharCode(b);
676
- });
677
- return btoa(str);
678
- }
679
- function base64ToUint8(b64) {
680
- const bin = atob(b64);
681
- const buf = new Uint8Array(bin.length);
682
- for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
683
- return buf;
684
- }
685
-
686
- // src/socket/socket.ts
687
591
  var _socket = null;
688
592
  var _socketProxy = null;
689
593
  var _connectingPromise = null;
@@ -780,28 +684,52 @@ async function _doConnect(config, getToken) {
780
684
  };
781
685
  let boundDeriveSessionKey = null;
782
686
  if (config.transitEncryption) {
783
- try {
784
- const serverKeys = await fetchServerKeys(config.apiUrl);
785
- if (!serverKeys.enabled) {
786
- throw new Error(
787
- "[AntzChat] Transit encryption mismatch: SDK has transitEncryption=true but server has TRANSIT_ENCRYPTION_ENABLED=false. Align the config on both sides."
788
- );
687
+ const inFlight = getTransitHandshakePromise();
688
+ if (inFlight) await inFlight;
689
+ const existingSession = getTransitSession();
690
+ let httpsSession = null;
691
+ if (existingSession?.enabled && existingSession.sessionId) {
692
+ httpsSession = { sessionId: existingSession.sessionId, sessionKey: existingSession.sessionKey };
693
+ } else {
694
+ httpsSession = await createRestTransitSession(config.apiUrl);
695
+ if (httpsSession) {
696
+ const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
697
+ setTransitSession({ sessionKey: httpsSession.sessionKey, algo, sessionId: httpsSession.sessionId, enabled: true });
698
+ }
699
+ }
700
+ if (httpsSession) {
701
+ socketHandshakeAuth["transitSessionId"] = httpsSession.sessionId;
702
+ boundDeriveSessionKey = null;
703
+ } else {
704
+ try {
705
+ const serverKeys = await fetchServerKeys(config.apiUrl);
706
+ if (!serverKeys.enabled) {
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 }
712
+ );
713
+ }
714
+ const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
715
+ boundDeriveSessionKey = await performHandshake(algo, serverKeys, socketHandshakeAuth);
716
+ } catch (err) {
717
+ throw err;
789
718
  }
790
- const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
791
- boundDeriveSessionKey = await performHandshake(algo, serverKeys, socketHandshakeAuth);
792
- } catch (err) {
793
- throw err;
794
719
  }
795
720
  } else {
796
721
  try {
797
722
  const serverKeys = await fetchServerKeys(config.apiUrl);
798
723
  if (serverKeys.enabled) {
799
- throw new Error(
800
- "[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 }
801
729
  );
802
730
  }
803
731
  } catch (err) {
804
- if (err.message?.startsWith("[AntzChat] Transit encryption mismatch")) throw err;
732
+ if (err?.code === "TRANSIT_MISMATCH") throw err;
805
733
  }
806
734
  }
807
735
  _socket = io(`${config.socketOrigin}/chat`, {
@@ -945,14 +873,10 @@ async function drainSendQueue(conversationId) {
945
873
  while (queue.length > 0) {
946
874
  const entry = queue.shift();
947
875
  if (Date.now() - entry.enqueuedAt > QUEUE_ENTRY_TTL) {
948
- entry.reject(new Error("[AntzChat] Message dropped: queued too long"));
876
+ entry.reject(new AntzChatNetworkError("Message dropped: queued too long", "MESSAGE_DROPPED"));
949
877
  continue;
950
878
  }
951
- try {
952
- entry.resolve(await entry.run());
953
- } catch (e) {
954
- entry.reject(e);
955
- }
879
+ entry.run().then(entry.resolve).catch(entry.reject);
956
880
  }
957
881
  sendQueues.delete(conversationId);
958
882
  sendQueueRunning.delete(conversationId);
@@ -962,7 +886,7 @@ function queueSendMessage(payload) {
962
886
  if (!sendQueues.has(conversationId)) sendQueues.set(conversationId, []);
963
887
  const queue = sendQueues.get(conversationId);
964
888
  if (queue.length >= QUEUE_MAX_SIZE) {
965
- 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 }));
966
890
  }
967
891
  return new Promise((resolve, reject) => {
968
892
  queue.push({ run: () => withAck("send_message", payload), resolve, reject, enqueuedAt: Date.now() });
@@ -973,7 +897,7 @@ function waitForReconnect() {
973
897
  return new Promise((resolve, reject) => {
974
898
  const timer = setTimeout(() => {
975
899
  unsubscribe();
976
- reject(new Error("[AntzChat] Socket reconnect timeout"));
900
+ reject(new AntzChatNetworkError("Socket reconnect timeout", "SOCKET_TIMEOUT"));
977
901
  }, RECONNECT_WAIT_TIMEOUT);
978
902
  const unsubscribe = onSocketStatus((status) => {
979
903
  if (status === "connected") {
@@ -983,7 +907,7 @@ function waitForReconnect() {
983
907
  } else if (status === "error") {
984
908
  clearTimeout(timer);
985
909
  unsubscribe();
986
- reject(new Error("[AntzChat] Socket reconnect failed"));
910
+ reject(new AntzChatNetworkError("Socket reconnect failed", "SOCKET_NOT_CONNECTED"));
987
911
  }
988
912
  });
989
913
  });
@@ -994,13 +918,15 @@ async function withAck(event, payload) {
994
918
  await waitForReconnect();
995
919
  socket = tryGetSocket();
996
920
  }
997
- 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 }));
998
922
  return new Promise((resolve, reject) => {
999
- const timer = setTimeout(() => reject(new Error(`Socket ack timeout: ${event}`)), ACK_TIMEOUT);
923
+ let timer;
1000
924
  secureEmit(socket, event, payload, (response) => {
1001
925
  clearTimeout(timer);
1002
926
  resolve(response);
1003
- });
927
+ }).then(() => {
928
+ timer = setTimeout(() => reject(new AntzChatNetworkError(`Socket ack timeout: ${event}`, "SOCKET_TIMEOUT", { event })), ACK_TIMEOUT);
929
+ }).catch(reject);
1004
930
  });
1005
931
  }
1006
932
  function fireAndForget(event, payload) {
@@ -1027,6 +953,9 @@ var socketEmit = {
1027
953
  deleteMessageForMe(messageId) {
1028
954
  return withAck("delete_message_for_me", { messageId });
1029
955
  },
956
+ clearChat(conversationId) {
957
+ return withAck("clear_chat_for_me", { conversationId });
958
+ },
1030
959
  addReaction(messageId, emoji) {
1031
960
  return withAck("add_reaction", { messageId, emoji });
1032
961
  },
@@ -1050,7 +979,7 @@ var socketEmit = {
1050
979
  const socket = tryGetSocket();
1051
980
  if (!socket) return Promise.resolve([]);
1052
981
  return new Promise((resolve, reject) => {
1053
- const timer = setTimeout(() => reject(new Error("get_online_users timeout")), ACK_TIMEOUT);
982
+ let timer;
1054
983
  secureEmit(socket, "get_online_users", { userIds }, (response) => {
1055
984
  clearTimeout(timer);
1056
985
  if (response && typeof response === "object" && "onlineStatus" in response) {
@@ -1061,7 +990,9 @@ var socketEmit = {
1061
990
  } else {
1062
991
  resolve([]);
1063
992
  }
1064
- });
993
+ }).then(() => {
994
+ timer = setTimeout(() => reject(new AntzChatNetworkError("Socket ack timeout: get_online_users", "SOCKET_TIMEOUT", { event: "get_online_users" })), ACK_TIMEOUT);
995
+ }).catch(reject);
1065
996
  });
1066
997
  },
1067
998
  getTypingUsers(conversationId) {
@@ -1119,24 +1050,40 @@ var AntzChatClient = class {
1119
1050
  }
1120
1051
  };
1121
1052
  export {
1053
+ AntzChatAuthError,
1122
1054
  AntzChatClient,
1055
+ AntzChatError,
1056
+ AntzChatNetworkError,
1057
+ AntzChatPermissionError,
1058
+ AntzChatServerError,
1059
+ AntzChatValidationError,
1123
1060
  appConfigApi,
1124
1061
  authApi,
1125
1062
  connectSocket,
1126
1063
  conversationsApi,
1127
1064
  createAuthStore,
1065
+ createRestTransitSession,
1066
+ decryptPayload,
1128
1067
  devicesApi,
1129
1068
  disconnectSocket,
1069
+ encryptPayload,
1070
+ fetchServerKeys,
1071
+ generateEphemeralKey,
1130
1072
  getApiClient,
1131
1073
  getAuthStore,
1132
1074
  getCompressionStrategy,
1075
+ getSessionId,
1076
+ getSessionKey,
1133
1077
  getSocket,
1134
1078
  getSocketStatus,
1135
1079
  initApiClient,
1136
1080
  initAuthStore,
1081
+ isTransitEnvelope,
1137
1082
  messagesApi,
1083
+ normalizeAxiosError,
1138
1084
  normalizeConversation,
1139
1085
  onSocketStatus,
1086
+ performHandshake,
1140
1087
  reconnectSocket,
1141
1088
  refreshSocketAuth,
1142
1089
  resetAuthStore,