@antzsoft/chat-core 1.2.4 → 1.2.5

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';
@@ -286,6 +286,35 @@ interface TransitSession {
286
286
  enabled: boolean;
287
287
  }
288
288
  declare function setTransitSession(session: TransitSession): void;
289
+ declare function getSessionKey(): CryptoKey | Uint8Array | null;
290
+ declare function getSessionId(): string | null;
291
+
292
+ interface TransitEnvelope {
293
+ v: 1;
294
+ iv: string;
295
+ tag: string;
296
+ ct: string;
297
+ }
298
+ type AnySessionKey = CryptoKey | Uint8Array;
299
+ declare function encryptPayload(data: unknown, sessionKey: AnySessionKey): Promise<TransitEnvelope>;
300
+ declare function decryptPayload(envelope: TransitEnvelope, sessionKey: AnySessionKey): Promise<unknown>;
301
+ declare function isTransitEnvelope(v: unknown): v is TransitEnvelope;
302
+
303
+ interface ServerPublicKeys {
304
+ x25519: string;
305
+ p256: string;
306
+ enabled: boolean;
307
+ }
308
+ declare function fetchServerKeys(apiUrl: string): Promise<ServerPublicKeys>;
309
+ declare function generateEphemeralKey(algo: TransitAlgo, serverKeys: ServerPublicKeys): Promise<{
310
+ ephemeralPubB64: string;
311
+ deriveSessionKey: (sessionId: string) => Promise<unknown>;
312
+ }>;
313
+ declare function createRestTransitSession(apiUrl: string): Promise<{
314
+ sessionId: string;
315
+ sessionKey: CryptoKey | Uint8Array;
316
+ } | null>;
317
+ declare function performHandshake(algo: TransitAlgo, serverKeys: ServerPublicKeys, socketHandshakeAuth: Record<string, unknown>): Promise<(sessionId: string) => Promise<unknown>>;
289
318
 
290
319
  interface AuthState {
291
320
  user: User | null;
@@ -566,4 +595,4 @@ declare class AntzChatClient {
566
595
  uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
567
596
  }
568
597
 
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 };
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 };
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';
@@ -286,6 +286,35 @@ interface TransitSession {
286
286
  enabled: boolean;
287
287
  }
288
288
  declare function setTransitSession(session: TransitSession): void;
289
+ declare function getSessionKey(): CryptoKey | Uint8Array | null;
290
+ declare function getSessionId(): string | null;
291
+
292
+ interface TransitEnvelope {
293
+ v: 1;
294
+ iv: string;
295
+ tag: string;
296
+ ct: string;
297
+ }
298
+ type AnySessionKey = CryptoKey | Uint8Array;
299
+ declare function encryptPayload(data: unknown, sessionKey: AnySessionKey): Promise<TransitEnvelope>;
300
+ declare function decryptPayload(envelope: TransitEnvelope, sessionKey: AnySessionKey): Promise<unknown>;
301
+ declare function isTransitEnvelope(v: unknown): v is TransitEnvelope;
302
+
303
+ interface ServerPublicKeys {
304
+ x25519: string;
305
+ p256: string;
306
+ enabled: boolean;
307
+ }
308
+ declare function fetchServerKeys(apiUrl: string): Promise<ServerPublicKeys>;
309
+ declare function generateEphemeralKey(algo: TransitAlgo, serverKeys: ServerPublicKeys): Promise<{
310
+ ephemeralPubB64: string;
311
+ deriveSessionKey: (sessionId: string) => Promise<unknown>;
312
+ }>;
313
+ declare function createRestTransitSession(apiUrl: string): Promise<{
314
+ sessionId: string;
315
+ sessionKey: CryptoKey | Uint8Array;
316
+ } | null>;
317
+ declare function performHandshake(algo: TransitAlgo, serverKeys: ServerPublicKeys, socketHandshakeAuth: Record<string, unknown>): Promise<(sessionId: string) => Promise<unknown>>;
289
318
 
290
319
  interface AuthState {
291
320
  user: User | null;
@@ -566,4 +595,4 @@ declare class AntzChatClient {
566
595
  uploadIcon(conversationId: string, file: UploadableFile): Promise<Conversation>;
567
596
  }
568
597
 
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 };
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 };
package/dist/index.js CHANGED
@@ -1,19 +1,28 @@
1
1
  import {
2
2
  clearTransitSession,
3
3
  configureTransit,
4
+ createRestTransitSession,
4
5
  decryptPayload,
6
+ detectTransitAlgo,
5
7
  encryptPayload,
8
+ fetchServerKeys,
9
+ generateEphemeralKey,
6
10
  getApiClient,
7
11
  getCompressionStrategy,
12
+ getSessionId,
8
13
  getSessionKey,
14
+ getTransitHandshakePromise,
15
+ getTransitSession,
9
16
  initApiClient,
10
17
  isTransitEnabled,
11
18
  isTransitEnvelope,
19
+ performHandshake,
20
+ resetAlgoCache,
12
21
  setApiClientInstance,
13
22
  setTransitSession,
14
23
  storageApi,
15
24
  uploadBatch
16
- } from "./chunk-6NMA64BX.js";
25
+ } from "./chunk-ZNA6B2R5.js";
17
26
  import {
18
27
  useChatStore
19
28
  } from "./chunk-EOL5B7GS.js";
@@ -378,7 +387,8 @@ function normalizeLastMessage(lastMsg) {
378
387
  isEdited: false,
379
388
  sentAt: lastMsg.sentAt ?? "",
380
389
  createdAt: lastMsg.sentAt ?? "",
381
- ...lastMsg.senderName && { senderName: lastMsg.senderName }
390
+ ...lastMsg.senderName && { senderName: lastMsg.senderName },
391
+ ...lastMsg.attachmentType && { attachmentType: lastMsg.attachmentType }
382
392
  };
383
393
  }
384
394
  function normalizeConversation(conv) {
@@ -568,122 +578,6 @@ var usersApi = {
568
578
 
569
579
  // src/socket/socket.ts
570
580
  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
581
  var _socket = null;
688
582
  var _socketProxy = null;
689
583
  var _connectingPromise = null;
@@ -780,17 +674,35 @@ async function _doConnect(config, getToken) {
780
674
  };
781
675
  let boundDeriveSessionKey = null;
782
676
  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
- );
677
+ const inFlight = getTransitHandshakePromise();
678
+ if (inFlight) await inFlight;
679
+ const existingSession = getTransitSession();
680
+ let httpsSession = null;
681
+ if (existingSession?.enabled && existingSession.sessionId) {
682
+ httpsSession = { sessionId: existingSession.sessionId, sessionKey: existingSession.sessionKey };
683
+ } else {
684
+ httpsSession = await createRestTransitSession(config.apiUrl);
685
+ if (httpsSession) {
686
+ const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
687
+ setTransitSession({ sessionKey: httpsSession.sessionKey, algo, sessionId: httpsSession.sessionId, enabled: true });
688
+ }
689
+ }
690
+ if (httpsSession) {
691
+ socketHandshakeAuth["transitSessionId"] = httpsSession.sessionId;
692
+ boundDeriveSessionKey = null;
693
+ } else {
694
+ try {
695
+ const serverKeys = await fetchServerKeys(config.apiUrl);
696
+ 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."
699
+ );
700
+ }
701
+ const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
702
+ boundDeriveSessionKey = await performHandshake(algo, serverKeys, socketHandshakeAuth);
703
+ } catch (err) {
704
+ throw err;
789
705
  }
790
- const algo = globalThis.crypto?.subtle ? await detectTransitAlgo() : "x25519";
791
- boundDeriveSessionKey = await performHandshake(algo, serverKeys, socketHandshakeAuth);
792
- } catch (err) {
793
- throw err;
794
706
  }
795
707
  } else {
796
708
  try {
@@ -948,11 +860,7 @@ async function drainSendQueue(conversationId) {
948
860
  entry.reject(new Error("[AntzChat] Message dropped: queued too long"));
949
861
  continue;
950
862
  }
951
- try {
952
- entry.resolve(await entry.run());
953
- } catch (e) {
954
- entry.reject(e);
955
- }
863
+ entry.run().then(entry.resolve).catch(entry.reject);
956
864
  }
957
865
  sendQueues.delete(conversationId);
958
866
  sendQueueRunning.delete(conversationId);
@@ -996,11 +904,13 @@ async function withAck(event, payload) {
996
904
  }
997
905
  if (!socket) return Promise.reject(new Error(`[AntzChat] Socket not connected (event: ${event})`));
998
906
  return new Promise((resolve, reject) => {
999
- const timer = setTimeout(() => reject(new Error(`Socket ack timeout: ${event}`)), ACK_TIMEOUT);
907
+ let timer;
1000
908
  secureEmit(socket, event, payload, (response) => {
1001
909
  clearTimeout(timer);
1002
910
  resolve(response);
1003
- });
911
+ }).then(() => {
912
+ timer = setTimeout(() => reject(new Error(`Socket ack timeout: ${event}`)), ACK_TIMEOUT);
913
+ }).catch(reject);
1004
914
  });
1005
915
  }
1006
916
  function fireAndForget(event, payload) {
@@ -1050,7 +960,7 @@ var socketEmit = {
1050
960
  const socket = tryGetSocket();
1051
961
  if (!socket) return Promise.resolve([]);
1052
962
  return new Promise((resolve, reject) => {
1053
- const timer = setTimeout(() => reject(new Error("get_online_users timeout")), ACK_TIMEOUT);
963
+ let timer;
1054
964
  secureEmit(socket, "get_online_users", { userIds }, (response) => {
1055
965
  clearTimeout(timer);
1056
966
  if (response && typeof response === "object" && "onlineStatus" in response) {
@@ -1061,7 +971,9 @@ var socketEmit = {
1061
971
  } else {
1062
972
  resolve([]);
1063
973
  }
1064
- });
974
+ }).then(() => {
975
+ timer = setTimeout(() => reject(new Error("get_online_users timeout")), ACK_TIMEOUT);
976
+ }).catch(reject);
1065
977
  });
1066
978
  },
1067
979
  getTypingUsers(conversationId) {
@@ -1125,18 +1037,27 @@ export {
1125
1037
  connectSocket,
1126
1038
  conversationsApi,
1127
1039
  createAuthStore,
1040
+ createRestTransitSession,
1041
+ decryptPayload,
1128
1042
  devicesApi,
1129
1043
  disconnectSocket,
1044
+ encryptPayload,
1045
+ fetchServerKeys,
1046
+ generateEphemeralKey,
1130
1047
  getApiClient,
1131
1048
  getAuthStore,
1132
1049
  getCompressionStrategy,
1050
+ getSessionId,
1051
+ getSessionKey,
1133
1052
  getSocket,
1134
1053
  getSocketStatus,
1135
1054
  initApiClient,
1136
1055
  initAuthStore,
1056
+ isTransitEnvelope,
1137
1057
  messagesApi,
1138
1058
  normalizeConversation,
1139
1059
  onSocketStatus,
1060
+ performHandshake,
1140
1061
  reconnectSocket,
1141
1062
  refreshSocketAuth,
1142
1063
  resetAuthStore,