@antzsoft/chat-core 1.1.4 → 1.1.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.cjs CHANGED
@@ -506,7 +506,7 @@ var authApi = {
506
506
  async uploadAvatar(file, mimeType) {
507
507
  const form = new FormData();
508
508
  form.append("avatar", file instanceof File ? file : new File([file], "avatar.jpg", { type: mimeType ?? "image/jpeg" }));
509
- const { data } = await getApiClient().put("/users/me/avatar", form, {
509
+ const { data } = await getApiClient().post("/users/me/avatar", form, {
510
510
  headers: { "Content-Type": "multipart/form-data" }
511
511
  });
512
512
  return data;
@@ -555,22 +555,22 @@ var messagesApi = {
555
555
  return data;
556
556
  },
557
557
  async update(messageId, text) {
558
- const { data } = await getApiClient().put(`/messages/${messageId}`, { text });
558
+ const { data } = await getApiClient().post(`/messages/${messageId}/update`, { text });
559
559
  return data;
560
560
  },
561
561
  async delete(messageId) {
562
- await getApiClient().delete(`/messages/${messageId}`);
562
+ await getApiClient().post(`/messages/${messageId}/delete`);
563
563
  },
564
564
  async deleteForMe(messageId) {
565
- await getApiClient().delete(`/messages/${messageId}/for-me`);
565
+ await getApiClient().post(`/messages/${messageId}/delete-for-me`);
566
566
  },
567
567
  async addReaction(messageId, emoji) {
568
568
  const { data } = await getApiClient().post(`/messages/${messageId}/reactions`, { emoji });
569
569
  return data;
570
570
  },
571
571
  async removeReaction(messageId, emoji) {
572
- const { data } = await getApiClient().delete(
573
- `/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`
572
+ const { data } = await getApiClient().post(
573
+ `/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/remove`
574
574
  );
575
575
  return data;
576
576
  },
@@ -578,7 +578,7 @@ var messagesApi = {
578
578
  await getApiClient().post(`/messages/${messageId}/star`);
579
579
  },
580
580
  async unstar(messageId) {
581
- await getApiClient().delete(`/messages/${messageId}/star`);
581
+ await getApiClient().post(`/messages/${messageId}/unstar`);
582
582
  },
583
583
  async getStarred(params = {}) {
584
584
  const { data } = await getApiClient().get("/messages/starred", { params });
@@ -602,7 +602,7 @@ var messagesApi = {
602
602
  return data;
603
603
  },
604
604
  async unpin(messageId) {
605
- const { data } = await getApiClient().delete(`/messages/${messageId}/pin`);
605
+ const { data } = await getApiClient().post(`/messages/${messageId}/unpin`);
606
606
  return data;
607
607
  },
608
608
  async getPinned(conversationId) {
@@ -645,10 +645,12 @@ function normalizeLastMessage(lastMsg) {
645
645
  text: lastMsg.contentPreview
646
646
  },
647
647
  reactions: [],
648
+ lastReaction: lastMsg.lastReaction ?? null,
648
649
  status: lastMsg.status ?? "sent",
649
650
  isEdited: false,
650
651
  sentAt: lastMsg.sentAt ?? "",
651
- createdAt: lastMsg.sentAt ?? ""
652
+ createdAt: lastMsg.sentAt ?? "",
653
+ ...lastMsg.senderName && { senderName: lastMsg.senderName }
652
654
  };
653
655
  }
654
656
  function normalizeConversation(conv) {
@@ -677,11 +679,11 @@ var conversationsApi = {
677
679
  return normalizeConversation(data);
678
680
  },
679
681
  async update(conversationId, payload) {
680
- const { data } = await getApiClient().put(`/conversations/${conversationId}`, payload);
682
+ const { data } = await getApiClient().post(`/conversations/${conversationId}/update`, payload);
681
683
  return normalizeConversation(data);
682
684
  },
683
685
  async delete(conversationId) {
684
- await getApiClient().delete(`/conversations/${conversationId}`);
686
+ await getApiClient().post(`/conversations/${conversationId}/delete`);
685
687
  },
686
688
  async addParticipants(conversationId, userIds, role) {
687
689
  const { data } = await getApiClient().post(
@@ -691,13 +693,13 @@ var conversationsApi = {
691
693
  return normalizeConversation(data);
692
694
  },
693
695
  async removeParticipant(conversationId, userId) {
694
- const { data } = await getApiClient().delete(
695
- `/conversations/${conversationId}/participants/${userId}`
696
+ const { data } = await getApiClient().post(
697
+ `/conversations/${conversationId}/participants/${userId}/remove`
696
698
  );
697
699
  return normalizeConversation(data);
698
700
  },
699
701
  async updateParticipantRole(conversationId, userId, role) {
700
- const { data } = await getApiClient().put(
702
+ const { data } = await getApiClient().post(
701
703
  `/conversations/${conversationId}/participants/${userId}/role`,
702
704
  { role }
703
705
  );
@@ -707,17 +709,17 @@ var conversationsApi = {
707
709
  await getApiClient().post(`/conversations/${conversationId}/mute`, mutedUntil ? { mutedUntil } : {});
708
710
  },
709
711
  async unmute(conversationId) {
710
- await getApiClient().delete(`/conversations/${conversationId}/mute`);
712
+ await getApiClient().post(`/conversations/${conversationId}/unmute`);
711
713
  },
712
714
  async pin(conversationId) {
713
715
  await getApiClient().post(`/conversations/${conversationId}/pin`);
714
716
  },
715
717
  async unpin(conversationId) {
716
- await getApiClient().delete(`/conversations/${conversationId}/pin`);
718
+ await getApiClient().post(`/conversations/${conversationId}/unpin`);
717
719
  },
718
720
  async leave(conversationId, andDelete) {
719
721
  const url = andDelete ? `/conversations/${conversationId}/leave?delete=true` : `/conversations/${conversationId}/leave`;
720
- await getApiClient().delete(url);
722
+ await getApiClient().post(url);
721
723
  },
722
724
  async getMembers(conversationId, filter) {
723
725
  const { data } = await getApiClient().get(
@@ -752,20 +754,29 @@ var conversationsApi = {
752
754
  * Server copies storageKey into conversation.iconMeta and deletes the chat_files record.
753
755
  */
754
756
  async uploadIcon(conversationId, fileId) {
755
- const { data } = await getApiClient().put(
757
+ const { data } = await getApiClient().post(
756
758
  `/conversations/${conversationId}/icon`,
757
759
  { fileId }
758
760
  );
759
761
  return normalizeConversation(data);
760
762
  },
761
763
  async removeIcon(conversationId) {
762
- const { data } = await getApiClient().delete(
763
- `/conversations/${conversationId}/icon`
764
- );
764
+ const { data } = await getApiClient().post(`/conversations/${conversationId}/icon/remove`);
765
765
  return normalizeConversation(data);
766
766
  }
767
767
  };
768
768
 
769
+ // src/crypto/uuid.ts
770
+ function generateUUID() {
771
+ if (typeof globalThis.crypto?.randomUUID === "function") {
772
+ return globalThis.crypto.randomUUID();
773
+ }
774
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
775
+ const r = Math.random() * 16 | 0;
776
+ return (c === "x" ? r : r & 3 | 8).toString(16);
777
+ });
778
+ }
779
+
769
780
  // src/api/storage.ts
770
781
  var storageApi = {
771
782
  async requestPresignedUrl(payload) {
@@ -791,7 +802,7 @@ var storageApi = {
791
802
  return data;
792
803
  },
793
804
  async deleteFile(fileId) {
794
- await getApiClient().delete(`/storage/files/${fileId}`);
805
+ await getApiClient().post(`/storage/files/${fileId}/delete`);
795
806
  },
796
807
  async getConversationFiles(conversationId, params = {}) {
797
808
  const { data } = await getApiClient().get(
@@ -805,15 +816,17 @@ var storageApi = {
805
816
  return data;
806
817
  }
807
818
  };
808
- async function uploadBatch(files, platformUploadFn, conversationId, onProgress, platformCompressFn, compressionConfig) {
819
+ async function runUploadBatch(files, platformUploadFn, slotIds, conversationId, onProgress, platformCompressFn, compressionConfig) {
809
820
  const compressedFiles = await Promise.all(
810
821
  files.map((f) => compressFile(f, platformCompressFn, compressionConfig ?? { enabled: false, imageQuality: 0.85, imageMaxDimension: 1920, compressDocuments: true }))
811
822
  );
812
- const requests = compressedFiles.map((f) => ({
823
+ const slotted = compressedFiles.map((f, i) => ({ file: f, slotId: slotIds[i], clientIndex: i }));
824
+ const requests = slotted.map(({ file: f, clientIndex }) => ({
813
825
  filename: f.name,
814
826
  mimeType: f.type,
815
827
  size: f.size,
816
828
  conversationId,
829
+ clientIndex,
817
830
  ...f.compressed && {
818
831
  metadata: {
819
832
  compressed: f.compressed,
@@ -823,6 +836,13 @@ async function uploadBatch(files, platformUploadFn, conversationId, onProgress,
823
836
  }
824
837
  }));
825
838
  const { urls, errors: requestErrors } = await storageApi.requestPresignedUrlBatch(requests);
839
+ const failedSlotIds = /* @__PURE__ */ new Set();
840
+ const failed = requestErrors.map((e) => {
841
+ const idx = e.clientIndex ?? slotted.findIndex((s) => s.file.name === e.filename);
842
+ const slotId = slotted[idx]?.slotId;
843
+ if (slotId) failedSlotIds.add(slotId);
844
+ return { filename: e.filename, error: e.error };
845
+ });
826
846
  const progressMap = {};
827
847
  const reportProgress = () => {
828
848
  if (!onProgress) return;
@@ -831,26 +851,33 @@ async function uploadBatch(files, platformUploadFn, conversationId, onProgress,
831
851
  onProgress(Math.round(avg));
832
852
  };
833
853
  const successful = [];
834
- const failed = [...requestErrors];
854
+ const slotToFile = /* @__PURE__ */ new Map();
835
855
  await Promise.all(
836
856
  urls.map(async (presigned, idx) => {
837
- const file = compressedFiles[idx];
838
- progressMap[idx] = 0;
857
+ const originalIdx = presigned.clientIndex ?? idx;
858
+ const { file, slotId } = slotted[originalIdx];
859
+ progressMap[originalIdx] = 0;
839
860
  try {
840
861
  await platformUploadFn(presigned, file, (pct) => {
841
- progressMap[idx] = Math.round(pct * 0.9);
862
+ progressMap[originalIdx] = Math.round(pct * 0.9);
842
863
  reportProgress();
843
864
  });
844
- const result = await storageApi.confirmUpload(presigned.fileId);
845
- progressMap[idx] = 100;
865
+ const fileResponse = await storageApi.confirmUpload(presigned.fileId);
866
+ progressMap[originalIdx] = 100;
846
867
  reportProgress();
847
- successful.push(result);
868
+ successful.push(fileResponse);
869
+ slotToFile.set(slotId, fileResponse);
848
870
  } catch (err) {
849
871
  failed.push({ filename: file.name, error: err.message });
850
872
  }
851
873
  })
852
874
  );
853
- return { successful, failed };
875
+ return { result: { successful, failed }, slotToFile };
876
+ }
877
+ async function uploadBatch(files, platformUploadFn, conversationId, onProgress, platformCompressFn, compressionConfig) {
878
+ const slotIds = files.map(() => generateUUID());
879
+ const { result } = await runUploadBatch(files, platformUploadFn, slotIds, conversationId, onProgress, platformCompressFn, compressionConfig);
880
+ return result;
854
881
  }
855
882
 
856
883
  // src/api/devices.ts
@@ -873,7 +900,7 @@ var devicesApi = {
873
900
  * Call this on logout so the user stops receiving push notifications on this device.
874
901
  */
875
902
  async remove(deviceId) {
876
- await getApiClient().delete(`/users/me/devices/${deviceId}`);
903
+ await getApiClient().post(`/users/me/devices/${deviceId}/remove`);
877
904
  }
878
905
  };
879
906
 
@@ -898,7 +925,7 @@ var usersApi = {
898
925
  * happened — without waiting for the next 2-hour sync cycle.
899
926
  */
900
927
  async updateProfile(payload) {
901
- const { data } = await getApiClient().put("/users/me", payload);
928
+ const { data } = await getApiClient().post("/users/me/update", payload);
902
929
  return data;
903
930
  },
904
931
  /**
@@ -908,7 +935,7 @@ var usersApi = {
908
935
  * token is first registered, so this never fails with "not found".
909
936
  */
910
937
  async updatePreferences(prefs) {
911
- const { data } = await getApiClient().put("/users/me/preferences", prefs);
938
+ const { data } = await getApiClient().post("/users/me/preferences", prefs);
912
939
  return data;
913
940
  },
914
941
  /**
@@ -1017,6 +1044,7 @@ function b64ToBuf2(b64) {
1017
1044
 
1018
1045
  // src/socket/socket.ts
1019
1046
  var _socket = null;
1047
+ var _connectingPromise = null;
1020
1048
  var _status = "disconnected";
1021
1049
  var _statusListeners = /* @__PURE__ */ new Set();
1022
1050
  var _getToken = null;
@@ -1090,6 +1118,13 @@ function secureOn(socket, event, handler) {
1090
1118
  }
1091
1119
  async function connectSocket(config, getToken) {
1092
1120
  if (_socket && !_socket.disconnected) return _socket;
1121
+ if (_connectingPromise) return _connectingPromise;
1122
+ _connectingPromise = _doConnect(config, getToken).finally(() => {
1123
+ _connectingPromise = null;
1124
+ });
1125
+ return _connectingPromise;
1126
+ }
1127
+ async function _doConnect(config, getToken) {
1093
1128
  _getToken = getToken;
1094
1129
  _userId = config.userId;
1095
1130
  _tenantId = config.tenantId;
@@ -1216,6 +1251,7 @@ function createSecureSocketProxy(socket) {
1216
1251
  });
1217
1252
  }
1218
1253
  function disconnectSocket() {
1254
+ _connectingPromise = null;
1219
1255
  if (_socket) {
1220
1256
  _socket.disconnect();
1221
1257
  _socket = null;
@@ -1334,7 +1370,7 @@ var socketEmit = {
1334
1370
  fireAndForget("leave_room", { conversationId });
1335
1371
  },
1336
1372
  sendMessage(payload) {
1337
- return queueSendMessage(payload);
1373
+ return queueSendMessage({ ...payload, sentAt: Date.now() });
1338
1374
  },
1339
1375
  updateMessage(messageId, text) {
1340
1376
  return withAck("update_message", { messageId, text });