@antzsoft/chat-core 1.1.9 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/chat.store-JC6QYDDL.js +7 -0
- package/dist/{chunk-TB52RCSF.js → chunk-GUO5QQGK.js} +8 -4
- package/dist/chunk-GUO5QQGK.js.map +1 -0
- package/dist/index.cjs +18 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +15 -9
- package/dist/index.js.map +1 -1
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/{storage-Dc0__sXE.d.cts → storage-BBScliNR.d.cts} +1 -1
- package/dist/{storage-Dc0__sXE.d.ts → storage-BBScliNR.d.ts} +1 -1
- package/docs/integration-guide.html +33 -5
- package/package.json +1 -1
- package/dist/chat.store-PY3YVYGN.js +0 -7
- package/dist/chunk-TB52RCSF.js.map +0 -1
- /package/dist/{chat.store-PY3YVYGN.js.map → chat.store-JC6QYDDL.js.map} +0 -0
package/README.md
CHANGED
|
@@ -2451,6 +2451,9 @@ document.querySelectorAll('[data-conv-id]').forEach((el) => {
|
|
|
2451
2451
|
|
|
2452
2452
|
## Changelog
|
|
2453
2453
|
|
|
2454
|
+
### v1.2.0
|
|
2455
|
+
- **Fix: `getSocket()` and `tryGetSocket()` now return the transit-aware proxy** — Previously these functions returned the raw Socket.IO socket, bypassing the `secureOn` decryption wrapper. Any integrator calling `getSocket().on('new_message', ...)` or `tryGetSocket().on(...)` directly would receive raw encrypted envelopes (`{v:1, iv:..., ct:...}`) instead of decrypted payloads. Both functions now return the same secure proxy that `connectSocket()` returns — all `.on()` calls automatically decrypt via transit when enabled. **No integration changes required — existing code that uses `getSocket()` or `tryGetSocket()` will now transparently receive decrypted data.**
|
|
2456
|
+
|
|
2454
2457
|
### v1.1.9
|
|
2455
2458
|
- **Fix: Transit 403 on `GET /users/me` and `POST /users/me/devices` in external / authToken mode** — In external and authToken auth modes, `AntzChatProvider` calls `GET /users/me` immediately on mount to refresh the user profile, and push token registration (`POST /users/me/devices`) fires on auth state change — both before the socket connects and the ECDH transit session is established. With transit enforcement enabled these requests were receiving `403 Transit encryption required`. Both endpoints are now marked `@PreTransit()` on the server so they are reachable during the bootstrap window. **No integration changes required.**
|
|
2456
2459
|
- **Fix: React Native / Hermes support for transit encryption** — The core SDK (`@antzsoft/chat-core`) now works on React Native and Hermes out of the box. When `globalThis.crypto.subtle` is unavailable (Hermes does not expose it), the SDK automatically falls back to `@noble/curves` (X25519 ECDH) and `@noble/ciphers` (AES-256-GCM) for both the handshake and all payload encryption/decryption. Previously the SDK crashed with `TypeError: Cannot read property 'subtle' of undefined` on RN. **No integration changes required — no extra packages to install.**
|
|
@@ -35,9 +35,13 @@ var useChatStore = create((set) => ({
|
|
|
35
35
|
setLastRead: (conversationId, messageId, readAt) => set((state) => ({
|
|
36
36
|
lastRead: { ...state.lastRead, [conversationId]: { messageId, readAt } }
|
|
37
37
|
})),
|
|
38
|
-
setLastSeen: (userId, lastSeenAt) => set((state) =>
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
setLastSeen: (userId, lastSeenAt) => set((state) => {
|
|
39
|
+
if (lastSeenAt === null) {
|
|
40
|
+
const { [userId]: _, ...rest } = state.lastSeen;
|
|
41
|
+
return { lastSeen: rest };
|
|
42
|
+
}
|
|
43
|
+
return { lastSeen: { ...state.lastSeen, [userId]: lastSeenAt } };
|
|
44
|
+
}),
|
|
41
45
|
setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),
|
|
42
46
|
setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),
|
|
43
47
|
toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),
|
|
@@ -51,4 +55,4 @@ var useChatStore = create((set) => ({
|
|
|
51
55
|
export {
|
|
52
56
|
useChatStore
|
|
53
57
|
};
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
58
|
+
//# sourceMappingURL=chunk-GUO5QQGK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stores/chat.store.ts"],"sourcesContent":["import { create } from 'zustand';\nimport type { Message } from '../types/index.js';\n\ninterface TypingUser {\n userId: string;\n displayName: string;\n avatarUrl?: string;\n}\n\nexport interface LastReadEntry {\n messageId: string;\n readAt: string;\n}\n\ninterface ChatState {\n activeConversationId: string | null;\n pendingTarget: { conversationId: string; messageId: string } | null;\n typingUsers: Record<string, TypingUser[]>;\n onlineUsers: string[];\n /** keyed by conversationId — current user's last read pointer per conversation */\n lastRead: Record<string, LastReadEntry>;\n /** keyed by userId — last seen timestamp for each user */\n lastSeen: Record<string, string>;\n replyingTo: Message | null;\n editingMessage: Message | null;\n isSidebarOpen: boolean;\n isGroupInfoOpen: boolean;\n isStarredPanelOpen: boolean;\n\n setActiveConversation: (id: string | null) => void;\n setPendingTarget: (target: { conversationId: string; messageId: string } | null) => void;\n addTypingUser: (conversationId: string, user: TypingUser) => void;\n removeTypingUser: (conversationId: string, userId: string) => void;\n setUserOnline: (userId: string) => void;\n setUserOffline: (userId: string) => void;\n setOnlineUsers: (userIds: string[]) => void;\n setLastRead: (conversationId: string, messageId: string, readAt: string) => void;\n setLastSeen: (userId: string, lastSeenAt: string | null) => void;\n setReplyingTo: (message: Message | null) => void;\n setEditingMessage: (message: Message | null) => void;\n toggleSidebar: () => void;\n setSidebarOpen: (open: boolean) => void;\n toggleGroupInfo: () => void;\n setGroupInfoOpen: (open: boolean) => void;\n toggleStarredPanel: () => void;\n setStarredPanelOpen: (open: boolean) => void;\n}\n\nexport const useChatStore = create<ChatState>((set) => ({\n activeConversationId: null,\n pendingTarget: null,\n typingUsers: {},\n onlineUsers: [],\n lastRead: {},\n lastSeen: {},\n replyingTo: null,\n editingMessage: null,\n isSidebarOpen: true,\n isGroupInfoOpen: false,\n isStarredPanelOpen: false,\n\n setActiveConversation: (id) =>\n set({ activeConversationId: id, replyingTo: null, editingMessage: null }),\n\n setPendingTarget: (target) => set({ pendingTarget: target }),\n\n addTypingUser: (conversationId, user) =>\n set((state) => {\n const existing = state.typingUsers[conversationId] ?? [];\n const deduped = existing.filter((u) => u.userId !== user.userId);\n return { typingUsers: { ...state.typingUsers, [conversationId]: [...deduped, user] } };\n }),\n\n removeTypingUser: (conversationId, userId) =>\n set((state) => ({\n typingUsers: {\n ...state.typingUsers,\n [conversationId]: (state.typingUsers[conversationId] ?? []).filter(\n (u) => u.userId !== userId,\n ),\n },\n })),\n\n setUserOnline: (userId) =>\n set((state) => ({\n onlineUsers: state.onlineUsers.includes(userId)\n ? state.onlineUsers\n : [...state.onlineUsers, userId],\n })),\n\n setUserOffline: (userId) =>\n set((state) => ({ onlineUsers: state.onlineUsers.filter((id) => id !== userId) })),\n\n setOnlineUsers: (userIds) => set({ onlineUsers: userIds }),\n\n setLastRead: (conversationId, messageId, readAt) =>\n set((state) => ({\n lastRead: { ...state.lastRead, [conversationId]: { messageId, readAt } },\n })),\n\n setLastSeen: (userId, lastSeenAt) =>\n set((state) => {\n if (lastSeenAt === null) {\n const { [userId]: _, ...rest } = state.lastSeen;\n return { lastSeen: rest };\n }\n return { lastSeen: { ...state.lastSeen, [userId]: lastSeenAt } };\n }),\n\n setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),\n\n setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),\n\n toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),\n setSidebarOpen: (open) => set({ isSidebarOpen: open }),\n\n toggleGroupInfo: () => set((state) => ({ isGroupInfoOpen: !state.isGroupInfoOpen })),\n setGroupInfoOpen: (open) => set({ isGroupInfoOpen: open }),\n\n toggleStarredPanel: () => set((state) => ({ isStarredPanelOpen: !state.isStarredPanelOpen })),\n setStarredPanelOpen: (open) => set({ isStarredPanelOpen: open }),\n}));\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -75,9 +75,13 @@ var init_chat_store = __esm({
|
|
|
75
75
|
setLastRead: (conversationId, messageId, readAt) => set((state) => ({
|
|
76
76
|
lastRead: { ...state.lastRead, [conversationId]: { messageId, readAt } }
|
|
77
77
|
})),
|
|
78
|
-
setLastSeen: (userId, lastSeenAt) => set((state) =>
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
setLastSeen: (userId, lastSeenAt) => set((state) => {
|
|
79
|
+
if (lastSeenAt === null) {
|
|
80
|
+
const { [userId]: _, ...rest } = state.lastSeen;
|
|
81
|
+
return { lastSeen: rest };
|
|
82
|
+
}
|
|
83
|
+
return { lastSeen: { ...state.lastSeen, [userId]: lastSeenAt } };
|
|
84
|
+
}),
|
|
81
85
|
setReplyingTo: (message) => set({ replyingTo: message, editingMessage: null }),
|
|
82
86
|
setEditingMessage: (message) => set({ editingMessage: message, replyingTo: null }),
|
|
83
87
|
toggleSidebar: () => set((state) => ({ isSidebarOpen: !state.isSidebarOpen })),
|
|
@@ -1112,6 +1116,7 @@ function base64ToUint82(b64) {
|
|
|
1112
1116
|
|
|
1113
1117
|
// src/socket/socket.ts
|
|
1114
1118
|
var _socket = null;
|
|
1119
|
+
var _socketProxy = null;
|
|
1115
1120
|
var _connectingPromise = null;
|
|
1116
1121
|
var _status = "disconnected";
|
|
1117
1122
|
var _statusListeners = /* @__PURE__ */ new Set();
|
|
@@ -1123,11 +1128,11 @@ function setStatus(s) {
|
|
|
1123
1128
|
_statusListeners.forEach((l) => l(s));
|
|
1124
1129
|
}
|
|
1125
1130
|
function getSocket() {
|
|
1126
|
-
if (!
|
|
1127
|
-
return
|
|
1131
|
+
if (!_socketProxy) throw new Error("[AntzChat] Socket not initialized. Call connectSocket first.");
|
|
1132
|
+
return _socketProxy;
|
|
1128
1133
|
}
|
|
1129
1134
|
function tryGetSocket() {
|
|
1130
|
-
return _socket?.connected ?
|
|
1135
|
+
return _socket?.connected ? _socketProxy : null;
|
|
1131
1136
|
}
|
|
1132
1137
|
function getSocketStatus() {
|
|
1133
1138
|
return _status;
|
|
@@ -1286,7 +1291,10 @@ async function _doConnect(config, getToken) {
|
|
|
1286
1291
|
});
|
|
1287
1292
|
secureOn(_socket, "user_online", (event) => {
|
|
1288
1293
|
Promise.resolve().then(() => (init_chat_store(), chat_store_exports)).then(({ useChatStore: useChatStore2 }) => {
|
|
1289
|
-
useChatStore2.getState()
|
|
1294
|
+
const store = useChatStore2.getState();
|
|
1295
|
+
const e = event;
|
|
1296
|
+
store.setUserOnline(e.userId);
|
|
1297
|
+
store.setLastSeen(e.userId, null);
|
|
1290
1298
|
});
|
|
1291
1299
|
});
|
|
1292
1300
|
secureOn(_socket, "user_offline", (event) => {
|
|
@@ -1297,7 +1305,8 @@ async function _doConnect(config, getToken) {
|
|
|
1297
1305
|
if (e.lastSeenAt) store.setLastSeen(e.userId, e.lastSeenAt);
|
|
1298
1306
|
});
|
|
1299
1307
|
});
|
|
1300
|
-
|
|
1308
|
+
_socketProxy = createSecureSocketProxy(_socket);
|
|
1309
|
+
return _socketProxy;
|
|
1301
1310
|
}
|
|
1302
1311
|
function createSecureSocketProxy(socket) {
|
|
1303
1312
|
return new Proxy(socket, {
|
|
@@ -1322,6 +1331,7 @@ function disconnectSocket() {
|
|
|
1322
1331
|
if (_socket) {
|
|
1323
1332
|
_socket.disconnect();
|
|
1324
1333
|
_socket = null;
|
|
1334
|
+
_socketProxy = null;
|
|
1325
1335
|
setStatus("disconnected");
|
|
1326
1336
|
}
|
|
1327
1337
|
clearTransitSession();
|