@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/{chunk-6NMA64BX.js → chunk-ZNA6B2R5.js} +235 -62
- package/dist/chunk-ZNA6B2R5.js.map +1 -0
- package/dist/index.cjs +223 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -3
- package/dist/index.d.ts +32 -3
- package/dist/index.js +58 -137
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +1 -1
- package/dist/{storage-Bp6fk9aM.d.cts → storage-CctLCOnZ.d.cts} +1 -1
- package/dist/{storage-Bp6fk9aM.d.ts → storage-CctLCOnZ.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-6NMA64BX.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
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 {
|
|
2
|
-
export {
|
|
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-
|
|
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
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|