@amityco/ts-sdk-react-native 7.13.0 → 7.14.0

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.
Files changed (102) hide show
  1. package/dist/@types/domains/client.d.ts +10 -1
  2. package/dist/@types/domains/client.d.ts.map +1 -1
  3. package/dist/@types/domains/feed.d.ts +17 -1
  4. package/dist/@types/domains/feed.d.ts.map +1 -1
  5. package/dist/@types/domains/message.d.ts +1 -1
  6. package/dist/@types/domains/message.d.ts.map +1 -1
  7. package/dist/@types/domains/post.d.ts +5 -0
  8. package/dist/@types/domains/post.d.ts.map +1 -1
  9. package/dist/client/api/accessTokenExpiryWatcher.d.ts +1 -1
  10. package/dist/client/api/accessTokenExpiryWatcher.d.ts.map +1 -1
  11. package/dist/client/api/index.d.ts +2 -0
  12. package/dist/client/api/index.d.ts.map +1 -1
  13. package/dist/client/api/isSameUserId.d.ts +2 -0
  14. package/dist/client/api/isSameUserId.d.ts.map +1 -0
  15. package/dist/client/api/login.d.ts.map +1 -1
  16. package/dist/client/api/loginAsBot.d.ts.map +1 -1
  17. package/dist/client/api/loginAsVisitor.d.ts.map +1 -1
  18. package/dist/client/api/loginWithAccessToken.d.ts +28 -0
  19. package/dist/client/api/loginWithAccessToken.d.ts.map +1 -0
  20. package/dist/client/api/logout.d.ts.map +1 -1
  21. package/dist/client/api/renewTokenWithHandler.d.ts +11 -0
  22. package/dist/client/api/renewTokenWithHandler.d.ts.map +1 -0
  23. package/dist/client/api/renewWithAccessToken.d.ts +2 -0
  24. package/dist/client/api/renewWithAccessToken.d.ts.map +1 -0
  25. package/dist/client/api/resumeSession.d.ts.map +1 -1
  26. package/dist/client/api/setAccessTokenHandler.d.ts +31 -0
  27. package/dist/client/api/setAccessTokenHandler.d.ts.map +1 -0
  28. package/dist/client/api/setupLoginSubscriptions.d.ts +11 -0
  29. package/dist/client/api/setupLoginSubscriptions.d.ts.map +1 -0
  30. package/dist/client/api/tests/loginWithAccessToken.test.d.ts +2 -0
  31. package/dist/client/api/tests/loginWithAccessToken.test.d.ts.map +1 -0
  32. package/dist/client/api/validateAccessToken.d.ts +11 -0
  33. package/dist/client/api/validateAccessToken.d.ts.map +1 -0
  34. package/dist/commentRepository/api/createComment.d.ts.map +1 -1
  35. package/dist/commentRepository/api/deleteComment.d.ts.map +1 -1
  36. package/dist/commentRepository/events/utils.d.ts.map +1 -1
  37. package/dist/core/subscription.d.ts +2 -2
  38. package/dist/core/subscription.d.ts.map +1 -1
  39. package/dist/feedRepository/index.d.ts +1 -1
  40. package/dist/feedRepository/index.d.ts.map +1 -1
  41. package/dist/feedRepository/observers/getCommunityFeed/LiveCollectionController.d.ts +13 -0
  42. package/dist/feedRepository/observers/getCommunityFeed/LiveCollectionController.d.ts.map +1 -0
  43. package/dist/feedRepository/observers/getCommunityFeed/PaginationController.d.ts +5 -0
  44. package/dist/feedRepository/observers/getCommunityFeed/PaginationController.d.ts.map +1 -0
  45. package/dist/feedRepository/observers/getCommunityFeed/QueryStreamController.d.ts +15 -0
  46. package/dist/feedRepository/observers/getCommunityFeed/QueryStreamController.d.ts.map +1 -0
  47. package/dist/feedRepository/observers/getCommunityFeed.d.ts +34 -0
  48. package/dist/feedRepository/observers/getCommunityFeed.d.ts.map +1 -0
  49. package/dist/feedRepository/observers/index.d.ts +1 -0
  50. package/dist/feedRepository/observers/index.d.ts.map +1 -1
  51. package/dist/feedRepository/observers/utils.d.ts.map +1 -1
  52. package/dist/index.cjs.js +995 -385
  53. package/dist/index.esm.js +979 -369
  54. package/dist/index.umd.js +3 -3
  55. package/dist/postRepository/events/utils.d.ts.map +1 -1
  56. package/dist/postRepository/observers/utils.d.ts.map +1 -1
  57. package/dist/postRepository/utils/PostCommentCountEngine/CommentChange.d.ts +11 -0
  58. package/dist/postRepository/utils/PostCommentCountEngine/CommentChange.d.ts.map +1 -0
  59. package/dist/postRepository/utils/PostCommentCountEngine/CreateTask.d.ts +8 -0
  60. package/dist/postRepository/utils/PostCommentCountEngine/CreateTask.d.ts.map +1 -0
  61. package/dist/postRepository/utils/PostCommentCountEngine/DeleteTask.d.ts +7 -0
  62. package/dist/postRepository/utils/PostCommentCountEngine/DeleteTask.d.ts.map +1 -0
  63. package/dist/postRepository/utils/PostCommentCountEngine/PostCommentCountEngine.d.ts +19 -0
  64. package/dist/postRepository/utils/PostCommentCountEngine/PostCommentCountEngine.d.ts.map +1 -0
  65. package/dist/postRepository/utils/PostCommentCountEngine/ResetTask.d.ts +8 -0
  66. package/dist/postRepository/utils/PostCommentCountEngine/ResetTask.d.ts.map +1 -0
  67. package/dist/postRepository/utils/payload.d.ts.map +1 -1
  68. package/package.json +3 -1
  69. package/dist/commentRepository/internalApi/createComment.d.ts +0 -2
  70. package/dist/commentRepository/internalApi/createComment.d.ts.map +0 -1
  71. package/dist/commentRepository/internalApi/deleteComment.d.ts +0 -2
  72. package/dist/commentRepository/internalApi/deleteComment.d.ts.map +0 -1
  73. package/dist/commentRepository/internalApi/flagComment.d.ts +0 -2
  74. package/dist/commentRepository/internalApi/flagComment.d.ts.map +0 -1
  75. package/dist/commentRepository/internalApi/hardDeleteComment.d.ts +0 -2
  76. package/dist/commentRepository/internalApi/hardDeleteComment.d.ts.map +0 -1
  77. package/dist/commentRepository/internalApi/isCommentFlaggedByMe.d.ts +0 -2
  78. package/dist/commentRepository/internalApi/isCommentFlaggedByMe.d.ts.map +0 -1
  79. package/dist/commentRepository/internalApi/queryComments.d.ts +0 -2
  80. package/dist/commentRepository/internalApi/queryComments.d.ts.map +0 -1
  81. package/dist/commentRepository/internalApi/softDeleteComment.d.ts +0 -2
  82. package/dist/commentRepository/internalApi/softDeleteComment.d.ts.map +0 -1
  83. package/dist/commentRepository/internalApi/tests/createComment.test.d.ts +0 -2
  84. package/dist/commentRepository/internalApi/tests/createComment.test.d.ts.map +0 -1
  85. package/dist/commentRepository/internalApi/tests/deleteComment.test.d.ts +0 -2
  86. package/dist/commentRepository/internalApi/tests/deleteComment.test.d.ts.map +0 -1
  87. package/dist/commentRepository/internalApi/tests/getCommentByIds.test.d.ts +0 -2
  88. package/dist/commentRepository/internalApi/tests/getCommentByIds.test.d.ts.map +0 -1
  89. package/dist/commentRepository/internalApi/tests/getComments.test.d.ts +0 -2
  90. package/dist/commentRepository/internalApi/tests/getComments.test.d.ts.map +0 -1
  91. package/dist/commentRepository/internalApi/tests/hardDeleteComment.test.d.ts +0 -2
  92. package/dist/commentRepository/internalApi/tests/hardDeleteComment.test.d.ts.map +0 -1
  93. package/dist/commentRepository/internalApi/tests/queryComments.test.d.ts +0 -2
  94. package/dist/commentRepository/internalApi/tests/queryComments.test.d.ts.map +0 -1
  95. package/dist/commentRepository/internalApi/tests/softDeleteComment.test.d.ts +0 -2
  96. package/dist/commentRepository/internalApi/tests/softDeleteComment.test.d.ts.map +0 -1
  97. package/dist/commentRepository/internalApi/tests/updateComment.test.d.ts +0 -2
  98. package/dist/commentRepository/internalApi/tests/updateComment.test.d.ts.map +0 -1
  99. package/dist/commentRepository/internalApi/unflagComment.d.ts +0 -2
  100. package/dist/commentRepository/internalApi/unflagComment.d.ts.map +0 -1
  101. package/dist/commentRepository/internalApi/updateComment.d.ts +0 -2
  102. package/dist/commentRepository/internalApi/updateComment.d.ts.map +0 -1
package/dist/index.esm.js CHANGED
@@ -190,6 +190,12 @@ var FeedSourceEnum;
190
190
  FeedSourceEnum["Community"] = "community";
191
191
  FeedSourceEnum["User"] = "user";
192
192
  })(FeedSourceEnum || (FeedSourceEnum = {}));
193
+ var FeedTypeEnum;
194
+ (function (FeedTypeEnum) {
195
+ FeedTypeEnum["Reviewing"] = "reviewing";
196
+ FeedTypeEnum["Published"] = "published";
197
+ FeedTypeEnum["Declined"] = "declined";
198
+ })(FeedTypeEnum || (FeedTypeEnum = {}));
193
199
 
194
200
  var AmityEventType;
195
201
  (function (AmityEventType) {
@@ -226,8 +232,8 @@ var AmityEventOrderOption;
226
232
 
227
233
  function getVersion() {
228
234
  try {
229
- // the string ''v7.13.0-esm'' should be replaced by actual value by @rollup/plugin-replace
230
- return 'v7.13.0-esm';
235
+ // the string ''v7.14.0-esm'' should be replaced by actual value by @rollup/plugin-replace
236
+ return 'v7.14.0-esm';
231
237
  }
232
238
  catch (error) {
233
239
  return '__dev__';
@@ -1681,10 +1687,14 @@ const getLiveReactionTopic = (post) => {
1681
1687
  };
1682
1688
  const getRoomWatcherTopic = (room) => {
1683
1689
  const user = getCurrentUser();
1690
+ if (!user)
1691
+ return;
1684
1692
  return `${getNetworkId(user)}/room/${room._id}`;
1685
1693
  };
1686
1694
  const getRoomStreamerTopic = (room) => {
1687
1695
  const user = getCurrentUser();
1696
+ if (!user)
1697
+ return;
1688
1698
  return `${getNetworkId(user)}/room/${room.roomId}/streamer`;
1689
1699
  };
1690
1700
  function subscribeTopic(topic, callback) {
@@ -1779,13 +1789,13 @@ class NetworkActivitiesWatcher {
1779
1789
  this._listener.clear();
1780
1790
  }
1781
1791
  }
1782
- let instance$7;
1792
+ let instance$8;
1783
1793
  var NetworkActivitiesWatcher$1 = {
1784
1794
  getInstance: () => {
1785
- if (!instance$7) {
1786
- instance$7 = new NetworkActivitiesWatcher();
1795
+ if (!instance$8) {
1796
+ instance$8 = new NetworkActivitiesWatcher();
1787
1797
  }
1788
- return instance$7;
1798
+ return instance$8;
1789
1799
  },
1790
1800
  };
1791
1801
 
@@ -22987,13 +22997,13 @@ class SessionWatcher {
22987
22997
  this._listener.clear();
22988
22998
  }
22989
22999
  }
22990
- let instance$6;
23000
+ let instance$7;
22991
23001
  var SessionWatcher$1 = {
22992
23002
  getInstance: () => {
22993
- if (!instance$6) {
22994
- instance$6 = new SessionWatcher();
23003
+ if (!instance$7) {
23004
+ instance$7 = new SessionWatcher();
22995
23005
  }
22996
- return instance$6;
23006
+ return instance$7;
22997
23007
  },
22998
23008
  };
22999
23009
 
@@ -23570,6 +23580,108 @@ const setVisitorClientToken = async (params) => {
23570
23580
  return { accessToken, users, userType };
23571
23581
  };
23572
23582
 
23583
+ /* begin_public_function
23584
+ id: client.logout
23585
+ */
23586
+ /**
23587
+ * ```js
23588
+ * import { Client } from '@amityco/ts-sdk-react-native';
23589
+ * const success = await Client.logout()
23590
+ * ```
23591
+ *
23592
+ * Disconnects an {@link Amity.Client} instance from ASC servers
23593
+ *
23594
+ * @returns a success boolean if disconnected
23595
+ *
23596
+ * @category Client API
23597
+ * @async
23598
+ */
23599
+ const logout = async () => {
23600
+ var _a;
23601
+ const client = getActiveClient();
23602
+ client.log('client/api/disconnectClient');
23603
+ if (client.mqtt && client.mqtt.connected) {
23604
+ client.mqtt.disconnect();
23605
+ }
23606
+ /*
23607
+ * for cases when session state is terminated (example on ban) or token expired,
23608
+ * the terminating block will set session state to terminated or for the or
23609
+ * in the case of expired token the same happens
23610
+ *
23611
+ * establishing state also ignored in cases where accessTokenExpiryWatcher
23612
+ * calls renewal. There is a possibility that renewal will be called before
23613
+ * disconnectClient finishes execution
23614
+ *
23615
+ * IMPORTANT: call this before `emitter.all.clear()`, otherwise the session
23616
+ * event will never be triggered
23617
+ */
23618
+ if (client.sessionState === "established" /* Amity.SessionStates.ESTABLISHED */)
23619
+ setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
23620
+ client.emitter.all.clear();
23621
+ (_a = client.mqtt) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
23622
+ client.userId = undefined;
23623
+ client.token = undefined;
23624
+ client.loginType = undefined;
23625
+ client.http.defaults.headers.common.Authorization = '';
23626
+ client.http.defaults.metadata = {
23627
+ tokenExpiry: '',
23628
+ isGlobalBanned: false,
23629
+ isUserDeleted: false,
23630
+ };
23631
+ if (typeof document !== 'undefined') {
23632
+ document.cookie = '_ascSession=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
23633
+ }
23634
+ /*
23635
+ * Cache should be usable if tokenExpired
23636
+ * https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#SDK-usability-based-on-Session-State
23637
+ */
23638
+ if (client.sessionState !== "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */ && client.cache) {
23639
+ client.cache = { data: {} };
23640
+ }
23641
+ return true;
23642
+ };
23643
+ /* end_public_function */
23644
+
23645
+ /**
23646
+ * Terminates {@link Amity.Client} instance
23647
+ *
23648
+ *
23649
+ *
23650
+ * @category private
23651
+ */
23652
+ const terminateClient = (terminationReason) => {
23653
+ const client = getActiveClient();
23654
+ setSessionState("terminated" /* Amity.SessionStates.TERMINATED */, terminationReason);
23655
+ if (client.http.defaults.metadata) {
23656
+ if (terminationReason === "globalBan" /* Amity.TokenTerminationReason.GLOBAL_BAN */)
23657
+ client.http.defaults.metadata.isGlobalBanned = true;
23658
+ if (terminationReason === "userDeleted" /* Amity.TokenTerminationReason.USER_DELETED */)
23659
+ client.http.defaults.metadata.isUserDeleted = true;
23660
+ }
23661
+ client.sessionHandler = undefined;
23662
+ logout();
23663
+ };
23664
+
23665
+ let currentUserType = null;
23666
+ /* begin_public_function
23667
+ id: client.get_current_user_type
23668
+ */
23669
+ const getCurrentUserType = () => {
23670
+ if (!currentUserType) {
23671
+ throw new ASCError('Connect client first', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
23672
+ }
23673
+ return currentUserType;
23674
+ };
23675
+ /* end_public_function */
23676
+ const setCurrentUserType = (userType) => {
23677
+ currentUserType = userType;
23678
+ };
23679
+
23680
+ const setCurrentUser = ({ user, userType, }) => {
23681
+ setActiveUser(user);
23682
+ setCurrentUserType(userType);
23683
+ };
23684
+
23573
23685
  const createUserEventSubscriber = (event, callback) => {
23574
23686
  const client = getActiveClient();
23575
23687
  const filter = (data) => {
@@ -23888,13 +24000,13 @@ class AnalyticsEngine {
23888
24000
  this._eventCapturer.resetAllBuckets();
23889
24001
  }
23890
24002
  }
23891
- let instance$5;
24003
+ let instance$6;
23892
24004
  var AnalyticsEngine$1 = {
23893
24005
  getInstance: () => {
23894
- if (!instance$5) {
23895
- instance$5 = new AnalyticsEngine();
24006
+ if (!instance$6) {
24007
+ instance$6 = new AnalyticsEngine();
23896
24008
  }
23897
- return instance$5;
24009
+ return instance$6;
23898
24010
  },
23899
24011
  };
23900
24012
 
@@ -24122,12 +24234,12 @@ class MessageReadReceiptSyncEngine {
24122
24234
  }
24123
24235
  }
24124
24236
  }
24125
- let instance$4 = null;
24237
+ let instance$5 = null;
24126
24238
  var ReadReceiptSyncEngine = {
24127
24239
  getInstance: () => {
24128
- if (!instance$4)
24129
- instance$4 = new MessageReadReceiptSyncEngine();
24130
- return instance$4;
24240
+ if (!instance$5)
24241
+ instance$5 = new MessageReadReceiptSyncEngine();
24242
+ return instance$5;
24131
24243
  },
24132
24244
  };
24133
24245
 
@@ -24381,12 +24493,12 @@ class LegacyMessageReadReceiptSyncEngine {
24381
24493
  }
24382
24494
  }
24383
24495
  }
24384
- let instance$3 = null;
24496
+ let instance$4 = null;
24385
24497
  var LegacyReadReceiptSyncEngine = {
24386
24498
  getInstance: () => {
24387
- if (!instance$3)
24388
- instance$3 = new LegacyMessageReadReceiptSyncEngine();
24389
- return instance$3;
24499
+ if (!instance$4)
24500
+ instance$4 = new LegacyMessageReadReceiptSyncEngine();
24501
+ return instance$4;
24390
24502
  },
24391
24503
  };
24392
24504
 
@@ -24662,12 +24774,12 @@ class ObjectResolverEngine {
24662
24774
  this.stopResolver();
24663
24775
  }
24664
24776
  }
24665
- let instance$2 = null;
24777
+ let instance$3 = null;
24666
24778
  var ObjectResolverEngine$1 = {
24667
24779
  getInstance: () => {
24668
- if (!instance$2)
24669
- instance$2 = new ObjectResolverEngine();
24670
- return instance$2;
24780
+ if (!instance$3)
24781
+ instance$3 = new ObjectResolverEngine();
24782
+ return instance$3;
24671
24783
  },
24672
24784
  };
24673
24785
 
@@ -24817,13 +24929,13 @@ class LiveReactionSyncEngine {
24817
24929
  this.stopReactionsSync();
24818
24930
  }
24819
24931
  }
24820
- let instance$1;
24932
+ let instance$2;
24821
24933
  var ReactionSyncEngine = {
24822
24934
  getInstance: () => {
24823
- if (!instance$1) {
24824
- instance$1 = new LiveReactionSyncEngine();
24935
+ if (!instance$2) {
24936
+ instance$2 = new LiveReactionSyncEngine();
24825
24937
  }
24826
- return instance$1;
24938
+ return instance$2;
24827
24939
  },
24828
24940
  };
24829
24941
 
@@ -24845,87 +24957,6 @@ var reactionSyncEngineOnLoginHandler = () => {
24845
24957
  };
24846
24958
  };
24847
24959
 
24848
- /* begin_public_function
24849
- id: client.logout
24850
- */
24851
- /**
24852
- * ```js
24853
- * import { Client } from '@amityco/ts-sdk-react-native';
24854
- * const success = await Client.logout()
24855
- * ```
24856
- *
24857
- * Disconnects an {@link Amity.Client} instance from ASC servers
24858
- *
24859
- * @returns a success boolean if disconnected
24860
- *
24861
- * @category Client API
24862
- * @async
24863
- */
24864
- const logout = async () => {
24865
- var _a;
24866
- const client = getActiveClient();
24867
- client.log('client/api/disconnectClient');
24868
- if (client.mqtt && client.mqtt.connected) {
24869
- client.mqtt.disconnect();
24870
- }
24871
- /*
24872
- * for cases when session state is terminated (example on ban) or token expired,
24873
- * the terminating block will set session state to terminated or for the or
24874
- * in the case of expired token the same happens
24875
- *
24876
- * establishing state also ignored in cases where accessTokenExpiryWatcher
24877
- * calls renewal. There is a possibility that renewal will be called before
24878
- * disconnectClient finishes execution
24879
- *
24880
- * IMPORTANT: call this before `emitter.all.clear()`, otherwise the session
24881
- * event will never be triggered
24882
- */
24883
- if (client.sessionState === "established" /* Amity.SessionStates.ESTABLISHED */)
24884
- setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
24885
- client.emitter.all.clear();
24886
- (_a = client.mqtt) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
24887
- client.userId = undefined;
24888
- client.token = undefined;
24889
- client.http.defaults.headers.common.Authorization = '';
24890
- client.http.defaults.metadata = {
24891
- tokenExpiry: '',
24892
- isGlobalBanned: false,
24893
- isUserDeleted: false,
24894
- };
24895
- if (typeof document !== 'undefined') {
24896
- document.cookie = '_ascSession=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
24897
- }
24898
- /*
24899
- * Cache should be usable if tokenExpired
24900
- * https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#SDK-usability-based-on-Session-State
24901
- */
24902
- if (client.sessionState !== "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */ && client.cache) {
24903
- client.cache = { data: {} };
24904
- }
24905
- return true;
24906
- };
24907
- /* end_public_function */
24908
-
24909
- /**
24910
- * Terminates {@link Amity.Client} instance
24911
- *
24912
- *
24913
- *
24914
- * @category private
24915
- */
24916
- const terminateClient = (terminationReason) => {
24917
- const client = getActiveClient();
24918
- setSessionState("terminated" /* Amity.SessionStates.TERMINATED */, terminationReason);
24919
- if (client.http.defaults.metadata) {
24920
- if (terminationReason === "globalBan" /* Amity.TokenTerminationReason.GLOBAL_BAN */)
24921
- client.http.defaults.metadata.isGlobalBanned = true;
24922
- if (terminationReason === "userDeleted" /* Amity.TokenTerminationReason.USER_DELETED */)
24923
- client.http.defaults.metadata.isUserDeleted = true;
24924
- }
24925
- client.sessionHandler = undefined;
24926
- logout();
24927
- };
24928
-
24929
24960
  const EVENTS = [
24930
24961
  'disconnected',
24931
24962
  'error',
@@ -25055,24 +25086,50 @@ const removeChannelMarkerCache = (channel) => {
25055
25086
  dropFromCache(['channelMarker', 'get', id], true);
25056
25087
  };
25057
25088
 
25058
- let currentUserType = null;
25059
- /* begin_public_function
25060
- id: client.get_current_user_type
25061
- */
25062
- const getCurrentUserType = () => {
25063
- if (!currentUserType) {
25064
- throw new ASCError('Connect client first', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
25089
+ /**
25090
+ * Sets up all login-related event subscriptions
25091
+ * This includes handlers for user bans, deletions, token events, and various engine initializations
25092
+ *
25093
+ * @param unsubWatcher - The unsubscriber function for the access token expiry watcher
25094
+ * @returns Array of unsubscriber functions for all registered subscriptions
25095
+ *
25096
+ * @category private
25097
+ */
25098
+ const setupLoginSubscriptions = (unsubWatcher) => {
25099
+ const client = getActiveClient();
25100
+ const subscriptions = [];
25101
+ subscriptions.push(
25102
+ // GLOBAL_BAN
25103
+ onClientBanned((_) => {
25104
+ terminateClient("globalBan" /* Amity.TokenTerminationReason.GLOBAL_BAN */);
25105
+ subscriptions.forEach(fn => fn());
25106
+ unsubWatcher();
25107
+ }), onTokenTerminated(_ => {
25108
+ terminateClient();
25109
+ subscriptions.forEach(fn => fn());
25110
+ unsubWatcher();
25111
+ }), onUserDeleted$2((user) => {
25112
+ if (user.userId === client.userId) {
25113
+ terminateClient("userDeleted" /* Amity.TokenTerminationReason.USER_DELETED */);
25114
+ subscriptions.forEach(fn => fn());
25115
+ unsubWatcher();
25116
+ }
25117
+ }), onTokenExpired(state => {
25118
+ SessionWatcher$1.getInstance().setSessionState(state);
25119
+ logout();
25120
+ subscriptions.forEach(fn => fn());
25121
+ }),
25122
+ // NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
25123
+ // the channel because currently backend can't handle this, so every time a user is banned from
25124
+ // a channel or the channel is deleted the channel's unread count will not be reset to zero
25125
+ onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler());
25126
+ if (client.useLegacyUnreadCount) {
25127
+ subscriptions.push(readReceiptSyncEngineOnLoginHandler());
25065
25128
  }
25066
- return currentUserType;
25067
- };
25068
- /* end_public_function */
25069
- const setCurrentUserType = (userType) => {
25070
- currentUserType = userType;
25071
- };
25072
-
25073
- const setCurrentUser = ({ user, userType, }) => {
25074
- setActiveUser(user);
25075
- setCurrentUserType(userType);
25129
+ else {
25130
+ subscriptions.push(legacyReadReceiptSyncEngineOnLoginHandler());
25131
+ }
25132
+ return subscriptions;
25076
25133
  };
25077
25134
 
25078
25135
  /* eslint-disable no-param-reassign */
@@ -25081,8 +25138,8 @@ const setCurrentUser = ({ user, userType, }) => {
25081
25138
  * than the one already connected, in which case the existing subscriptions need
25082
25139
  * to be cleared
25083
25140
  */
25084
- let subscriptions$3 = [];
25085
- async function runMqtt$1() {
25141
+ let subscriptions$4 = [];
25142
+ async function runMqtt$2() {
25086
25143
  await modifyMqttConnection();
25087
25144
  }
25088
25145
  /* begin_public_function
@@ -25116,8 +25173,8 @@ const login = async (params, sessionHandler, config) => {
25116
25173
  if (client.userId && client.userId !== params.userId) {
25117
25174
  await logout();
25118
25175
  // Remove subscription to ban and delete
25119
- subscriptions$3.forEach(fn => fn());
25120
- subscriptions$3 = [];
25176
+ subscriptions$4.forEach(fn => fn());
25177
+ subscriptions$4 = [];
25121
25178
  }
25122
25179
  // default values
25123
25180
  const defaultDeviceId = await getDeviceId();
@@ -25142,11 +25199,12 @@ const login = async (params, sessionHandler, config) => {
25142
25199
  }
25143
25200
  client.userId = user.userId;
25144
25201
  client.sessionHandler = sessionHandler;
25202
+ client.loginType = 'userId';
25145
25203
  /*
25146
25204
  * Cannot push to subscriptions as watcher needs to continue working even if
25147
25205
  * token expires
25148
25206
  */
25149
- unsubWatcher = client.accessTokenExpiryWatcher(sessionHandler);
25207
+ unsubWatcher = client.accessTokenExpiryWatcher();
25150
25208
  setCurrentUser({ user, userType });
25151
25209
  }
25152
25210
  catch (error) {
@@ -25159,40 +25217,11 @@ const login = async (params, sessionHandler, config) => {
25159
25217
  throw error;
25160
25218
  }
25161
25219
  if ((config === null || config === void 0 ? void 0 : config.disableRTE) !== true) {
25162
- runMqtt$1();
25220
+ runMqtt$2();
25163
25221
  }
25164
25222
  await initializeMessagePreviewSetting();
25165
- if (subscriptions$3.length === 0) {
25166
- subscriptions$3.push(
25167
- // GLOBAL_BAN
25168
- onClientBanned((_) => {
25169
- terminateClient("globalBan" /* Amity.TokenTerminationReason.GLOBAL_BAN */);
25170
- subscriptions$3.forEach(fn => fn());
25171
- unsubWatcher();
25172
- }), onTokenTerminated(_ => {
25173
- terminateClient();
25174
- subscriptions$3.forEach(fn => fn());
25175
- unsubWatcher();
25176
- }), onUserDeleted$2((user) => {
25177
- if (user.userId === client.userId) {
25178
- terminateClient("userDeleted" /* Amity.TokenTerminationReason.USER_DELETED */);
25179
- subscriptions$3.forEach(fn => fn());
25180
- unsubWatcher();
25181
- }
25182
- }), onTokenExpired(state => {
25183
- SessionWatcher$1.getInstance().setSessionState(state);
25184
- logout();
25185
- subscriptions$3.forEach(fn => fn());
25186
- }),
25187
- // NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
25188
- // the channel because currently backend can't handle this, so every time a user is banned from
25189
- // a channel or the channel is deleted the channel's unread count will not be reset to zero
25190
- onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler());
25191
- if (client.useLegacyUnreadCount) {
25192
- subscriptions$3.push(readReceiptSyncEngineOnLoginHandler());
25193
- }
25194
- else
25195
- subscriptions$3.push(legacyReadReceiptSyncEngineOnLoginHandler());
25223
+ if (subscriptions$4.length === 0) {
25224
+ subscriptions$4 = setupLoginSubscriptions(unsubWatcher);
25196
25225
  }
25197
25226
  return true;
25198
25227
  };
@@ -25204,7 +25233,7 @@ const login = async (params, sessionHandler, config) => {
25204
25233
  * than the one already connected, in which case the existing subscriptions need
25205
25234
  * to be cleared
25206
25235
  */
25207
- const subscriptions$2 = [];
25236
+ const subscriptions$3 = [];
25208
25237
  /* begin_public_function
25209
25238
  id: client.loginAsVisitor
25210
25239
  */
@@ -25247,11 +25276,12 @@ const loginAsVisitor = async (params) => {
25247
25276
  [user] = users;
25248
25277
  client.userId = user.userId;
25249
25278
  client.sessionHandler = params.sessionHandler;
25279
+ client.loginType = 'userId';
25250
25280
  /*
25251
25281
  * Cannot push to subscriptions as watcher needs to continue working even if
25252
25282
  * token expires
25253
25283
  */
25254
- unsubWatcher = client.accessTokenExpiryWatcher(params.sessionHandler);
25284
+ unsubWatcher = client.accessTokenExpiryWatcher();
25255
25285
  setCurrentUser({ user, userType });
25256
25286
  }
25257
25287
  catch (error) {
@@ -25264,16 +25294,16 @@ const loginAsVisitor = async (params) => {
25264
25294
  throw error;
25265
25295
  }
25266
25296
  await initializeMessagePreviewSetting();
25267
- if (subscriptions$2.length === 0) {
25297
+ if (subscriptions$3.length === 0) {
25268
25298
  // handling internal SDK events
25269
- subscriptions$2.push(onTokenTerminated(_ => {
25299
+ subscriptions$3.push(onTokenTerminated(_ => {
25270
25300
  terminateClient();
25271
- subscriptions$2.forEach(fn => fn());
25301
+ subscriptions$3.forEach(fn => fn());
25272
25302
  unsubWatcher();
25273
25303
  }), onTokenExpired(state => {
25274
25304
  SessionWatcher$1.getInstance().setSessionState(state);
25275
25305
  logout();
25276
- subscriptions$2.forEach(fn => fn());
25306
+ subscriptions$3.forEach(fn => fn());
25277
25307
  }));
25278
25308
  }
25279
25309
  return true;
@@ -25302,7 +25332,7 @@ const renewal = () => {
25302
25332
  * Per instance of Renewal, only one renewal is allowed
25303
25333
  */
25304
25334
  const renewToken = async (authToken) => {
25305
- const { userId, displayName } = getCurrentUser();
25335
+ const { userId, displayName } = getActiveUser();
25306
25336
  const deviceId = await getDeviceId();
25307
25337
  const params = { userId, displayName, authToken, deviceId };
25308
25338
  if (client.sessionState === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */ && client.sessionHandler) {
@@ -25377,6 +25407,242 @@ const renewal = () => {
25377
25407
  };
25378
25408
  /* end_public_function */
25379
25409
 
25410
+ const validateAccessToken = async ({ token, userId }) => {
25411
+ const client = getActiveClient();
25412
+ // Validate token using sessions API
25413
+ await client.http.get('/api/v3/sessions', {
25414
+ headers: {
25415
+ Authorization: `Bearer ${token.accessToken}`,
25416
+ },
25417
+ });
25418
+ // Get user details
25419
+ const { data: { users }, } = await client.http.get(`/api/v3/users/${userId}`, {
25420
+ headers: {
25421
+ Authorization: `Bearer ${token.accessToken}`,
25422
+ },
25423
+ });
25424
+ const user = users.find((u) => u.userId === userId);
25425
+ client.http.defaults.headers.common.Authorization = `Bearer ${token.accessToken}`;
25426
+ client.http.defaults.metadata = {
25427
+ tokenExpiry: token.expiresAt,
25428
+ isGlobalBanned: false,
25429
+ isUserDeleted: false,
25430
+ };
25431
+ client.upload.defaults.headers.common.Authorization = `Bearer ${token.accessToken}`;
25432
+ client.upload.defaults.metadata = {
25433
+ tokenExpiry: token.expiresAt,
25434
+ isGlobalBanned: false,
25435
+ isUserDeleted: false,
25436
+ };
25437
+ client.token = token;
25438
+ return user;
25439
+ };
25440
+
25441
+ const isSameUserId = (token) => {
25442
+ var _a;
25443
+ const client = getActiveClient();
25444
+ const decoded = jwtDecode(token);
25445
+ return ((_a = decoded === null || decoded === void 0 ? void 0 : decoded.user) === null || _a === void 0 ? void 0 : _a.publicUserId) === client.userId;
25446
+ };
25447
+
25448
+ let subscriptions$2 = [];
25449
+ async function runMqtt$1() {
25450
+ await modifyMqttConnection();
25451
+ }
25452
+ /* begin_public_function
25453
+ id: client.loginWithAccessToken
25454
+ */
25455
+ /**
25456
+ * ```js
25457
+ * import { loginWithAccessToken } from '@amityco/ts-sdk'
25458
+ * const success = await loginWithAccessToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...')
25459
+ * ```
25460
+ *
25461
+ * Authenticates a user using a pre-existing access token, allowing direct login without user credentials.
25462
+ * Designed for customers who manage access tokens on their own backend.
25463
+ *
25464
+ * @param accessToken JWT access token signed by customer's backend containing user identity
25465
+ * @returns true if authentication is successful
25466
+ *
25467
+ * @category Client API
25468
+ * @async
25469
+ */
25470
+ const loginWithAccessToken = async (accessToken) => {
25471
+ var _a, _b;
25472
+ const client = getActiveClient();
25473
+ let unsubWatcher;
25474
+ client.log('client/api/loginWithAccessToken', {
25475
+ apiKey: client.apiKey,
25476
+ sessionState: client.sessionState,
25477
+ });
25478
+ // Validate input
25479
+ if (!accessToken || typeof accessToken !== 'string' || accessToken.trim() === '') {
25480
+ throw new ASCError('Access token must be a non-empty string', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
25481
+ }
25482
+ let decoded;
25483
+ try {
25484
+ decoded = jwtDecode(accessToken);
25485
+ }
25486
+ catch (error) {
25487
+ throw new ASCError('Invalid access token format', 400100 /* Amity.ServerError.UNAUTHORIZED */, "error" /* Amity.ErrorLevel.ERROR */);
25488
+ }
25489
+ // Extract userId from token
25490
+ const userId = ((_a = decoded === null || decoded === void 0 ? void 0 : decoded.user) === null || _a === void 0 ? void 0 : _a.publicUserId) || ((_b = decoded === null || decoded === void 0 ? void 0 : decoded.user) === null || _b === void 0 ? void 0 : _b.userId);
25491
+ if (!userId) {
25492
+ throw new ASCError('Access token does not contain userId', 400100 /* Amity.ServerError.UNAUTHORIZED */, "error" /* Amity.ErrorLevel.ERROR */);
25493
+ }
25494
+ // Handle existing connected user
25495
+ if (client.userId) {
25496
+ const sameUser = isSameUserId(accessToken);
25497
+ if (!sameUser) {
25498
+ // Different user - do full logout
25499
+ await logout();
25500
+ }
25501
+ }
25502
+ try {
25503
+ // Set state to establishing
25504
+ setSessionState("establishing" /* Amity.SessionStates.ESTABLISHING */);
25505
+ // Prepare token object for validation
25506
+ const tokenObject = {
25507
+ accessToken,
25508
+ issuedAt: decoded.iat ? new Date(decoded.iat * 1000).toISOString() : new Date().toISOString(),
25509
+ expiresAt: new Date(decoded.exp * 1000).toISOString(),
25510
+ };
25511
+ // Validate token and get user
25512
+ const user = await validateAccessToken({
25513
+ token: tokenObject,
25514
+ userId,
25515
+ });
25516
+ if (user == null) {
25517
+ setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
25518
+ throw new ASCError(`User ${userId} has not been found`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
25519
+ }
25520
+ if (user.isDeleted) {
25521
+ setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
25522
+ throw new ASCError(`User ${userId} has been deleted`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
25523
+ }
25524
+ if (user.isGlobalBanned) {
25525
+ setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
25526
+ throw new ASCError(`User ${userId} is globally banned`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
25527
+ }
25528
+ // Set userId and login method flag
25529
+ client.userId = user.userId;
25530
+ // Set login method flag to 'accessToken' in platform-specific login session
25531
+ client.loginType = 'accessToken';
25532
+ // This will be used by the access token handler to determine if token renewal should be invoked
25533
+ // Set active user
25534
+ setActiveUser(user);
25535
+ unsubWatcher = client.accessTokenExpiryWatcher();
25536
+ setSessionState("established" /* Amity.SessionStates.ESTABLISHED */);
25537
+ }
25538
+ catch (error) {
25539
+ // If error occurs, revert session state to not logged in
25540
+ setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
25541
+ // Re-throw if it's already an ASCError
25542
+ if (error instanceof ASCError) {
25543
+ throw error;
25544
+ }
25545
+ // Wrap other errors
25546
+ throw new ASCError((error instanceof Error ? error.message : undefined) || 'Login with access token failed', 400100 /* Amity.ServerError.UNAUTHORIZED */, "error" /* Amity.ErrorLevel.ERROR */);
25547
+ }
25548
+ runMqtt$1();
25549
+ await initializeMessagePreviewSetting();
25550
+ if (subscriptions$2.length === 0) {
25551
+ subscriptions$2 = setupLoginSubscriptions(unsubWatcher);
25552
+ }
25553
+ return true;
25554
+ };
25555
+ /* end_public_function */
25556
+
25557
+ /* begin_public_function
25558
+ id: client.renew_with_accessToken
25559
+ */
25560
+ /*
25561
+ * Renewal defintion accepted by SessionHandler interface
25562
+ *
25563
+ * Tech Spec:
25564
+ * https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#Session-Handler
25565
+ *
25566
+ * @category private
25567
+ */
25568
+ const renewWithAccessToken = async (accessToken) => {
25569
+ var _a, _b;
25570
+ const client = getActiveClient();
25571
+ client.log('initiating access token renewal');
25572
+ /*
25573
+ * Renews a token if it is hasn't been renewed before. Also marks token as
25574
+ * renewed once done
25575
+ * Per instance of Renewal, only one renewal is allowed
25576
+ */
25577
+ // Validate input
25578
+ if (!accessToken || typeof accessToken !== 'string' || accessToken.trim() === '') {
25579
+ throw new ASCError('Access token must be a non-empty string', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
25580
+ }
25581
+ let decoded;
25582
+ try {
25583
+ decoded = jwtDecode(accessToken);
25584
+ }
25585
+ catch (error) {
25586
+ throw new ASCError('Invalid access token format', 400100 /* Amity.ServerError.UNAUTHORIZED */, "error" /* Amity.ErrorLevel.ERROR */);
25587
+ }
25588
+ // Extract userId from token
25589
+ const userId = ((_a = decoded === null || decoded === void 0 ? void 0 : decoded.user) === null || _a === void 0 ? void 0 : _a.publicUserId) || ((_b = decoded === null || decoded === void 0 ? void 0 : decoded.user) === null || _b === void 0 ? void 0 : _b.userId);
25590
+ if (!userId) {
25591
+ throw new ASCError('Access token does not contain userId', 400100 /* Amity.ServerError.UNAUTHORIZED */, "error" /* Amity.ErrorLevel.ERROR */);
25592
+ }
25593
+ // Handle existing connected user
25594
+ if (client.userId) {
25595
+ const sameUser = isSameUserId(accessToken);
25596
+ if (!sameUser) {
25597
+ // Different user - do full logout
25598
+ await logout();
25599
+ }
25600
+ }
25601
+ const tokenObject = {
25602
+ accessToken,
25603
+ issuedAt: decoded.iat ? new Date(decoded.iat * 1000).toISOString() : new Date().toISOString(),
25604
+ expiresAt: new Date(decoded.exp * 1000).toISOString(),
25605
+ };
25606
+ if (client.sessionState === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */ && client.sessionHandler) {
25607
+ await loginWithAccessToken(accessToken);
25608
+ }
25609
+ else {
25610
+ // about to expire
25611
+ await validateAccessToken({
25612
+ token: tokenObject,
25613
+ userId,
25614
+ });
25615
+ }
25616
+ };
25617
+ /* end_public_function */
25618
+
25619
+ /**
25620
+ * Helper function to renew access token using the accessTokenHandler
25621
+ * Handles error catching and logging
25622
+ *
25623
+ * @param useScheduledTask - Whether to wrap renewal in scheduleTask (for token expired case)
25624
+ * @category private
25625
+ */
25626
+ const renewTokenWithHandler = async ({ useScheduledTask = false, }) => {
25627
+ const client = getActiveClient();
25628
+ if (!client.userId || !client.accessTokenHandler) {
25629
+ return;
25630
+ }
25631
+ try {
25632
+ const newToken = await client.accessTokenHandler.onTokenRenew(client.userId);
25633
+ if (useScheduledTask) {
25634
+ scheduleTask(() => renewWithAccessToken(newToken));
25635
+ }
25636
+ else {
25637
+ renewWithAccessToken(newToken);
25638
+ }
25639
+ }
25640
+ catch (error) {
25641
+ client.log('Proactive token renewal failed, will retry when token expires', error);
25642
+ // Will fallback to expired token flow
25643
+ }
25644
+ };
25645
+
25380
25646
  const ABOUT_TO_EXPIRE_THRESHOLD = 80 / 100;
25381
25647
  const COMPENSATED_DELAY = 5 * MINUTE;
25382
25648
  /*
@@ -25412,10 +25678,11 @@ const isAboutToExpire = (params) => {
25412
25678
  *
25413
25679
  * @category private
25414
25680
  */
25415
- const accessTokenExpiryWatcher = (sessionHandler) => {
25416
- const interval = setInterval(() => {
25681
+ const accessTokenExpiryWatcher = () => {
25682
+ const interval = setInterval(async () => {
25417
25683
  const client = getActiveClient();
25418
- if (!client.token)
25684
+ const { sessionHandler, accessTokenHandler, loginType } = client;
25685
+ if (!client.token || !client.userId)
25419
25686
  return;
25420
25687
  const { issuedAt, expiresAt } = client.token;
25421
25688
  if (isExpired(expiresAt)) {
@@ -25426,18 +25693,38 @@ const accessTokenExpiryWatcher = (sessionHandler) => {
25426
25693
  */
25427
25694
  fireEvent('tokenExpired', "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */);
25428
25695
  /*
25429
- * https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#Automatically-initiate-renewal-flow
25430
- *
25431
- * Why sechduled task?
25432
- * Since fireEvent is scheduled, it will be called
25433
- * after sessionHandler leading to an invalid state change from
25434
- * establishing to tokenExpired
25696
+ * Check loginType to determine which handler to use:
25697
+ * - 'accessToken' = use accessTokenHandler
25698
+ * - 'userId' = use sessionHandler
25435
25699
  */
25436
- scheduleTask(() => sessionHandler.sessionWillRenewAccessToken(renewal()));
25700
+ if (loginType === 'accessToken' && accessTokenHandler) {
25701
+ await renewTokenWithHandler({ useScheduledTask: false });
25702
+ }
25703
+ else if (loginType === 'userId' && sessionHandler) {
25704
+ /*
25705
+ * https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#Automatically-initiate-renewal-flow
25706
+ *
25707
+ * Why scheduled task?
25708
+ * Since fireEvent is scheduled, it will be called
25709
+ * after sessionHandler leading to an invalid state change from
25710
+ * establishing to tokenExpired
25711
+ */
25712
+ scheduleTask(() => sessionHandler.sessionWillRenewAccessToken(renewal()));
25713
+ }
25437
25714
  return;
25438
25715
  }
25439
25716
  if (isAboutToExpire({ expiresAt, issuedAt })) {
25440
- sessionHandler.sessionWillRenewAccessToken(renewal());
25717
+ /*
25718
+ * Check loginType to determine which handler to use for proactive renewal:
25719
+ * - 'accessToken' = use accessTokenHandler
25720
+ * - 'userId' = use sessionHandler
25721
+ */
25722
+ if (loginType === 'accessToken' && accessTokenHandler) {
25723
+ await renewTokenWithHandler({ useScheduledTask: false });
25724
+ }
25725
+ else if (loginType === 'userId' && sessionHandler) {
25726
+ sessionHandler.sessionWillRenewAccessToken(renewal());
25727
+ }
25441
25728
  }
25442
25729
  }, ACCESS_TOKEN_WATCHER_INTERVAL);
25443
25730
  return () => clearInterval(interval);
@@ -25991,6 +26278,7 @@ const secureLogout = async () => {
25991
26278
  };
25992
26279
  /* end_public_function */
25993
26280
 
26281
+ /* eslint-disable no-param-reassign */
25994
26282
  /*
25995
26283
  * declared earlier to accomodate case when logging in with a different user
25996
26284
  * than the one already connected, in which case the existing subscriptions need
@@ -26000,38 +26288,6 @@ let subscriptions$1 = [];
26000
26288
  async function runMqtt() {
26001
26289
  await modifyMqttConnection();
26002
26290
  }
26003
- const isSameUserId = (token) => {
26004
- var _a;
26005
- const client = getActiveClient();
26006
- const decoded = jwtDecode(token);
26007
- return ((_a = decoded === null || decoded === void 0 ? void 0 : decoded.user) === null || _a === void 0 ? void 0 : _a.publicUserId) === client.userId;
26008
- };
26009
- const validateAccessToken = async ({ token, userId }) => {
26010
- const client = getActiveClient();
26011
- // begin establishing session
26012
- setSessionState("establishing" /* Amity.SessionStates.ESTABLISHING */);
26013
- const { data: { users }, } = await client.http.get(`/api/v3/users/${userId}`, {
26014
- headers: {
26015
- Authorization: `Bearer ${token.accessToken}`,
26016
- },
26017
- });
26018
- const user = users.find((u) => u.userId === userId);
26019
- client.http.defaults.headers.common.Authorization = `Bearer ${token.accessToken}`;
26020
- client.http.defaults.metadata = {
26021
- tokenExpiry: token.expiresAt,
26022
- isGlobalBanned: false,
26023
- isUserDeleted: false,
26024
- };
26025
- client.upload.defaults.headers.common.Authorization = `Bearer ${token.accessToken}`;
26026
- client.upload.defaults.metadata = {
26027
- tokenExpiry: token.expiresAt,
26028
- isGlobalBanned: false,
26029
- isUserDeleted: false,
26030
- };
26031
- client.token = token;
26032
- setSessionState("established" /* Amity.SessionStates.ESTABLISHED */);
26033
- return user;
26034
- };
26035
26291
  /* begin_public_function
26036
26292
  id: client.resumeSession
26037
26293
  */
@@ -26080,6 +26336,7 @@ const resumeSession = async (params, sessionHandler, config) => {
26080
26336
  }
26081
26337
  }
26082
26338
  try {
26339
+ setSessionState("establishing" /* Amity.SessionStates.ESTABLISHING */);
26083
26340
  const user = await validateAccessToken(params);
26084
26341
  if (user == null) {
26085
26342
  throw new ASCError(`${params.userId} has not been found`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
@@ -26186,13 +26443,13 @@ class GlobalFileAccessType {
26186
26443
  }
26187
26444
  }
26188
26445
  _GlobalFileAccessType_fileAccessType = new WeakMap();
26189
- let instance;
26446
+ let instance$1;
26190
26447
  var GlobalFileAccessType$1 = {
26191
26448
  getInstance: () => {
26192
- if (!instance) {
26193
- instance = new GlobalFileAccessType();
26449
+ if (!instance$1) {
26450
+ instance$1 = new GlobalFileAccessType();
26194
26451
  }
26195
- return instance;
26452
+ return instance$1;
26196
26453
  },
26197
26454
  };
26198
26455
 
@@ -26407,11 +26664,12 @@ const loginAsBot = async (params) => {
26407
26664
  [user] = users;
26408
26665
  client.userId = user.userId;
26409
26666
  client.sessionHandler = params.sessionHandler;
26667
+ client.loginType = 'userId';
26410
26668
  /*
26411
26669
  * Cannot push to subscriptions as watcher needs to continue working even if
26412
26670
  * token expires
26413
26671
  */
26414
- unsubWatcher = client.accessTokenExpiryWatcher(params.sessionHandler);
26672
+ unsubWatcher = client.accessTokenExpiryWatcher();
26415
26673
  setCurrentUser({ user, userType });
26416
26674
  }
26417
26675
  catch (error) {
@@ -26440,6 +26698,53 @@ const loginAsBot = async (params) => {
26440
26698
  };
26441
26699
  /* end_public_function */
26442
26700
 
26701
+ /* begin_public_function
26702
+ id: client.setAccessTokenHandler
26703
+ */
26704
+ /**
26705
+ * ```js
26706
+ * import { setAccessTokenHandler } from '@amityco/ts-sdk'
26707
+ *
26708
+ * const tokenHandler = {
26709
+ * async onTokenRenew() {
26710
+ * const response = await fetch('https://your-backend.com/api/refresh-token', {
26711
+ * method: 'POST',
26712
+ * credentials: 'include',
26713
+ * });
26714
+ * const data = await response.json();
26715
+ * return data.accessToken;
26716
+ * }
26717
+ * };
26718
+ *
26719
+ * setAccessTokenHandler(tokenHandler);
26720
+ * ```
26721
+ *
26722
+ * Registers a custom handler for managing access token renewal and expiration events.
26723
+ * This enables automatic token refresh and graceful handling of expired tokens.
26724
+ *
26725
+ * Must be called before loginWithAccessToken() to ensure the handler is available
26726
+ * when token expiry is detected.
26727
+ *
26728
+ * @param accessTokenHandler Handler object implementing token renewal callbacks
26729
+ * @returns void
26730
+ *
26731
+ * @category Client API
26732
+ */
26733
+ const setAccessTokenHandler = (accessTokenHandler) => {
26734
+ const client = getActiveClient();
26735
+ client.log('client/api/setAccessTokenHandler', {
26736
+ apiKey: client.apiKey,
26737
+ sessionState: client.sessionState,
26738
+ hasOnTokenRenew: typeof (accessTokenHandler === null || accessTokenHandler === void 0 ? void 0 : accessTokenHandler.onTokenRenew) === 'function',
26739
+ });
26740
+ // Validate handler has required method
26741
+ if (!accessTokenHandler || typeof accessTokenHandler.onTokenRenew !== 'function') {
26742
+ throw new Error('AccessTokenHandler must implement onTokenRenew() method');
26743
+ }
26744
+ // Register the handler
26745
+ client.accessTokenHandler = accessTokenHandler;
26746
+ };
26747
+
26443
26748
  /**
26444
26749
  * ```js
26445
26750
  * import { onChannelMarkerFetched } from '@amityco/ts-sdk-react-native'
@@ -26799,6 +27104,7 @@ var index$r = /*#__PURE__*/Object.freeze({
26799
27104
  setActiveUser: setActiveUser,
26800
27105
  createClient: createClient,
26801
27106
  login: login,
27107
+ loginWithAccessToken: loginWithAccessToken,
26802
27108
  logout: logout,
26803
27109
  secureLogout: secureLogout,
26804
27110
  resumeSession: resumeSession,
@@ -26820,6 +27126,7 @@ var index$r = /*#__PURE__*/Object.freeze({
26820
27126
  getCurrentUser: getCurrentUser,
26821
27127
  getCurrentUserType: getCurrentUserType,
26822
27128
  setCurrentUserType: setCurrentUserType,
27129
+ setAccessTokenHandler: setAccessTokenHandler,
26823
27130
  onConnectionError: onConnectionError,
26824
27131
  onClientDisconnected: onClientDisconnected,
26825
27132
  onClientBanned: onClientBanned,
@@ -33177,6 +33484,147 @@ removeReaction.optimistically = (referenceType, referenceId, reactionName) => {
33177
33484
  return !((_d = reaction === null || reaction === void 0 ? void 0 : reaction.myReactions) === null || _d === void 0 ? void 0 : _d.includes(reactionName));
33178
33485
  };
33179
33486
 
33487
+ class ResetTask {
33488
+ constructor(postId, latestCreatedAt, serverCommentCount) {
33489
+ this.postId = postId;
33490
+ this.latestCreatedAt = latestCreatedAt;
33491
+ this.serverCommentCount = serverCommentCount;
33492
+ }
33493
+ }
33494
+
33495
+ // Task to track comment creation
33496
+ class CreateTask {
33497
+ constructor(postId, commentId, createdAt) {
33498
+ this.postId = postId;
33499
+ this.commentId = commentId;
33500
+ this.createdAt = createdAt;
33501
+ }
33502
+ }
33503
+
33504
+ // Task to track comment deletion
33505
+ class DeleteTask {
33506
+ constructor(postId, commentId) {
33507
+ this.postId = postId;
33508
+ this.commentId = commentId;
33509
+ }
33510
+ }
33511
+
33512
+ class CommentChange {
33513
+ constructor(latestCreatedAt, serverCommentCount) {
33514
+ this.latestCommentCreatedAt = latestCreatedAt;
33515
+ this.serverCommentCount = serverCommentCount;
33516
+ this.createdCommentIds = new Set();
33517
+ this.deletedCommentIds = new Set();
33518
+ }
33519
+ }
33520
+
33521
+ class PostCommentCountEngine {
33522
+ constructor() {
33523
+ this.isProcessing = false;
33524
+ this.tasks = [];
33525
+ this.commentChangeTracker = new Map();
33526
+ }
33527
+ queueCommentChangeTask(task) {
33528
+ this.tasks.push(task);
33529
+ if (!this.isProcessing) {
33530
+ this.processCommentChangeTask();
33531
+ }
33532
+ }
33533
+ processCommentChangeTask() {
33534
+ if (this.isProcessing) {
33535
+ return;
33536
+ }
33537
+ this.isProcessing = true;
33538
+ if (this.tasks.length === 0) {
33539
+ this.isProcessing = false;
33540
+ return;
33541
+ }
33542
+ // Process in capped batches, coalescing updates
33543
+ const batch = this.tasks.splice(0, PostCommentCountEngine.BATCH_SIZE);
33544
+ const modifiedPostIds = new Set();
33545
+ batch.forEach(task => {
33546
+ let modified = false;
33547
+ if (task instanceof ResetTask) {
33548
+ modified = this.processResetTaskInternal(task);
33549
+ }
33550
+ else if (task instanceof CreateTask) {
33551
+ modified = this.processCreateTaskInternal(task);
33552
+ }
33553
+ else if (task instanceof DeleteTask) {
33554
+ modified = this.processDeleteTaskInternal(task);
33555
+ }
33556
+ if (modified) {
33557
+ modifiedPostIds.add(task.postId);
33558
+ }
33559
+ });
33560
+ // Publish one update per modified post
33561
+ modifiedPostIds.forEach(postId => {
33562
+ const count = this.computeCommentCount(postId);
33563
+ PostCommentCountEngine.publishUpdate(postId, count);
33564
+ });
33565
+ this.isProcessing = false;
33566
+ // Recurse if more tasks remain
33567
+ if (this.tasks.length > 0) {
33568
+ this.processCommentChangeTask();
33569
+ }
33570
+ }
33571
+ processResetTaskInternal(task) {
33572
+ // Always creates/overwrites tracker
33573
+ this.commentChangeTracker.set(task.postId, new CommentChange(task.latestCreatedAt, task.serverCommentCount));
33574
+ return true;
33575
+ }
33576
+ processCreateTaskInternal(task) {
33577
+ const tracker = this.commentChangeTracker.get(task.postId);
33578
+ if (!tracker)
33579
+ return false; // No tracker, skip
33580
+ if (tracker.createdCommentIds.has(task.commentId))
33581
+ return false; // Deduplication
33582
+ if (task.createdAt <= tracker.latestCommentCreatedAt)
33583
+ return false; // Timestamp filtering
33584
+ tracker.createdCommentIds.add(task.commentId);
33585
+ return true;
33586
+ }
33587
+ processDeleteTaskInternal(task) {
33588
+ const tracker = this.commentChangeTracker.get(task.postId);
33589
+ if (!tracker)
33590
+ return false; // No tracker, skip
33591
+ if (tracker.deletedCommentIds.has(task.commentId))
33592
+ return false; // Deduplication
33593
+ tracker.deletedCommentIds.add(task.commentId);
33594
+ return true;
33595
+ }
33596
+ computeCommentCount(postId) {
33597
+ const tracker = this.commentChangeTracker.get(postId);
33598
+ if (!tracker)
33599
+ return 0;
33600
+ const count = tracker.serverCommentCount + tracker.createdCommentIds.size - tracker.deletedCommentIds.size;
33601
+ return Math.max(0, count);
33602
+ }
33603
+ static publishUpdate(postId, newCount) {
33604
+ var _a;
33605
+ const queryKey = ['post', 'get', postId];
33606
+ mergeInCache(queryKey, {
33607
+ localCommentCount: newCount,
33608
+ });
33609
+ const postPayload = (_a = pullFromCache(queryKey)) === null || _a === void 0 ? void 0 : _a.data;
33610
+ if (!postPayload)
33611
+ return;
33612
+ fireEvent('local.post.updated', {
33613
+ posts: [postPayload],
33614
+ });
33615
+ }
33616
+ }
33617
+ PostCommentCountEngine.BATCH_SIZE = 50;
33618
+ let instance;
33619
+ var PostCommentCountEngine$1 = {
33620
+ getInstance: () => {
33621
+ if (!instance) {
33622
+ instance = new PostCommentCountEngine();
33623
+ }
33624
+ return instance;
33625
+ },
33626
+ };
33627
+
33180
33628
  const updateStreamReferences = (streams, streamId, postId) => {
33181
33629
  if (!streamId)
33182
33630
  return streams;
@@ -33196,14 +33644,26 @@ const preparePostPayload = (payload) => {
33196
33644
  let mappedNewStream = [];
33197
33645
  // feed type
33198
33646
  const posts = postsData.map(post => {
33199
- var _a, _b;
33647
+ var _a, _b, _c, _d;
33200
33648
  const feedType = (_a = postPayload.feeds.find(feed => feed.feedId === post.feedId)) === null || _a === void 0 ? void 0 : _a.feedType;
33201
33649
  const childPosts = payload.postChildren.filter(children => children.parentPostId === post.postId);
33202
33650
  if (childPosts.length > 0 && isAmityLivestreamPost(childPosts[0])) {
33203
33651
  mappedNewStream = updateStreamReferences(videoStreamings, (_b = childPosts[0].data) === null || _b === void 0 ? void 0 : _b.streamId, post.postId);
33204
33652
  }
33653
+ // --- Computed Comment Count: ResetTask integration ---
33654
+ // Find all comments for this post (referenceType === 'post' && referenceId === postId)
33655
+ const allComments = (payload.comments || []).filter((c) => c.referenceType === 'post' && c.referenceId === post.postId);
33656
+ // Compute latestCreatedAt
33657
+ const latestCreatedAt = allComments.length === 0
33658
+ ? new Date().toISOString()
33659
+ : allComments
33660
+ .map(c => c.createdAt)
33661
+ .sort()
33662
+ .at(-1);
33663
+ // Queue ResetTask for this post
33664
+ PostCommentCountEngine$1.getInstance().queueCommentChangeTask(new ResetTask(post.postId, latestCreatedAt, (_c = post.commentsCount) !== null && _c !== void 0 ? _c : 0));
33205
33665
  return Object.assign(Object.assign({}, post), { childPosts,
33206
- feedType });
33666
+ feedType, localCommentCount: (_d = post.localCommentCount) !== null && _d !== void 0 ? _d : post.commentsCount });
33207
33667
  });
33208
33668
  return Object.assign(Object.assign({}, postPayload), { postChildren, videoStreamings: mappedNewStream, posts, communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
33209
33669
  };
@@ -33305,14 +33765,12 @@ const createLocalPostEventSubscriber = (event, callback) => {
33305
33765
  callback(payload.posts[0]);
33306
33766
  }
33307
33767
  else {
33308
- const data = preparePostPayload(payload);
33309
- const { communities } = data;
33310
- ingestInCache(data);
33768
+ const { communities } = payload;
33311
33769
  if ((communities === null || communities === void 0 ? void 0 : communities[0]) && !['local.post.updated'].includes(event)) {
33312
33770
  fireEvent('community.updated', {
33313
33771
  communities,
33314
33772
  categories: [],
33315
- communityUsers: data.communityUsers,
33773
+ communityUsers: payload.communityUsers,
33316
33774
  feeds: [],
33317
33775
  files: [],
33318
33776
  users: [],
@@ -33583,7 +34041,7 @@ const createCommentEventSubscriber = (event, callback) => {
33583
34041
  const createLocalCommentEventSubscriber = (event, callback) => {
33584
34042
  const client = getActiveClient();
33585
34043
  const filter = (payload) => {
33586
- var _a, _b;
34044
+ var _a, _b, _c, _d, _e;
33587
34045
  if (!client.cache) {
33588
34046
  // TODO: here we are missing specific properties here!
33589
34047
  callback(LinkedObject.comment(payload.comments[0]));
@@ -33623,7 +34081,13 @@ const createLocalCommentEventSubscriber = (event, callback) => {
33623
34081
  }
33624
34082
  }
33625
34083
  }
33626
- const queries = (_a = queryCache(['comment', 'query'])) === null || _a === void 0 ? void 0 : _a.filter(({ key }) => { var _a; return ((_a = key[2]) === null || _a === void 0 ? void 0 : _a.referenceId) === comment.data.referenceId; });
34084
+ else {
34085
+ const postCacheKey = ['post', 'get', comments[0].referenceId];
34086
+ const postCache = (_a = pullFromCache(postCacheKey)) === null || _a === void 0 ? void 0 : _a.data;
34087
+ postCache === null || postCache === void 0 ? void 0 : postCache.comments.push((_b = comments[0]) === null || _b === void 0 ? void 0 : _b.commentId);
34088
+ pushToCache(postCacheKey, postCache);
34089
+ }
34090
+ const queries = (_c = queryCache(['comment', 'query'])) === null || _c === void 0 ? void 0 : _c.filter(({ key }) => { var _a; return ((_a = key[2]) === null || _a === void 0 ? void 0 : _a.referenceId) === comment.data.referenceId; });
33627
34091
  queries === null || queries === void 0 ? void 0 : queries.map(({ key, data }) => upsertInCache(key, data, { cachedAt: -1 }));
33628
34092
  }
33629
34093
  if (['local.comment.deleted'].includes(event)) {
@@ -33655,7 +34119,13 @@ const createLocalCommentEventSubscriber = (event, callback) => {
33655
34119
  }
33656
34120
  }
33657
34121
  }
33658
- const queries = (_b = queryCache(['comment', 'query'])) === null || _b === void 0 ? void 0 : _b.filter(({ key }) => { var _a; return ((_a = key[2]) === null || _a === void 0 ? void 0 : _a.referenceId) === comment.data.referenceId; });
34122
+ else {
34123
+ const postCacheKey = ['post', 'get', comments[0].referenceId];
34124
+ const postCache = (_d = pullFromCache(postCacheKey)) === null || _d === void 0 ? void 0 : _d.data;
34125
+ const updatedPost = Object.assign(Object.assign({}, postCache), { comments: postCache === null || postCache === void 0 ? void 0 : postCache.comments.filter(commentId => { var _a; return commentId !== ((_a = comments[0]) === null || _a === void 0 ? void 0 : _a.commentId); }) });
34126
+ pushToCache(postCacheKey, updatedPost);
34127
+ }
34128
+ const queries = (_e = queryCache(['comment', 'query'])) === null || _e === void 0 ? void 0 : _e.filter(({ key }) => { var _a; return ((_a = key[2]) === null || _a === void 0 ? void 0 : _a.referenceId) === comment.data.referenceId; });
33659
34129
  queries === null || queries === void 0 ? void 0 : queries.map(({ key, data }) => upsertInCache(key, data, { cachedAt: -1 }));
33660
34130
  }
33661
34131
  callback(LinkedObject.comment(comment.data));
@@ -41365,7 +41835,6 @@ getCommentByIds.locally = (commentIds) => {
41365
41835
  * @async
41366
41836
  */
41367
41837
  const createComment = async (bundle) => {
41368
- var _a;
41369
41838
  const client = getActiveClient();
41370
41839
  client.log('comment/createComment', bundle);
41371
41840
  const { data } = await client.http.post('/api/v3/comments', bundle);
@@ -41377,22 +41846,7 @@ const createComment = async (bundle) => {
41377
41846
  if (client.cache)
41378
41847
  ingestInCache(data, { cachedAt });
41379
41848
  if (['post', 'content'].includes(bundle.referenceType)) {
41380
- const post = (_a = pullFromCache(['post', 'get', bundle.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
41381
- if (post) {
41382
- post.commentsCount += 1;
41383
- fireEvent('local.post.updated', {
41384
- posts: [post],
41385
- categories: [],
41386
- comments: [],
41387
- communities: [],
41388
- communityUsers: data.communityUsers,
41389
- feeds: [],
41390
- files: data.files,
41391
- postChildren: [],
41392
- users: data.users,
41393
- videoStreamings: [],
41394
- });
41395
- }
41849
+ PostCommentCountEngine$1.getInstance().queueCommentChangeTask(new CreateTask(bundle.referenceId, comments[0].commentId, data.comments[0].createdAt));
41396
41850
  }
41397
41851
  else if (bundle.referenceType === 'story') {
41398
41852
  const storyIndex = pullFromCache([
@@ -41551,7 +42005,7 @@ getStoryByStoryId$1.locally = (storyId) => {
41551
42005
  * @async
41552
42006
  */
41553
42007
  const deleteComment = async (commentId, permanent = false) => {
41554
- var _a;
42008
+ var _a, _b;
41555
42009
  const client = getActiveClient();
41556
42010
  const comment = await getComment$2(commentId);
41557
42011
  // API-FIX: This endpoint has not been implemented yet.
@@ -41584,26 +42038,14 @@ const deleteComment = async (commentId, permanent = false) => {
41584
42038
  else {
41585
42039
  const post = (_a = pullFromCache(['post', 'get', comment.data.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
41586
42040
  if (post) {
41587
- let removeCount;
41588
- if (!deleted.parentId) {
41589
- // NOTE: delete the parent comment will remove all children comments
41590
- removeCount = deleted.childrenNumber + 1;
42041
+ const engine = PostCommentCountEngine$1.getInstance();
42042
+ engine.queueCommentChangeTask(new DeleteTask(post.postId, commentId));
42043
+ if (!deleted.parentId && ((_b = deleted.children) === null || _b === void 0 ? void 0 : _b.length) > 0) {
42044
+ // NOTE: delete the parent comment will also remove all children comments
42045
+ deleted.children.forEach((childCommentId) => {
42046
+ engine.queueCommentChangeTask(new DeleteTask(post.postId, childCommentId));
42047
+ });
41591
42048
  }
41592
- else
41593
- removeCount = 1;
41594
- post.commentsCount -= removeCount;
41595
- fireEvent('local.post.updated', {
41596
- posts: [post],
41597
- categories: [],
41598
- comments: [],
41599
- communities: [],
41600
- communityUsers: [],
41601
- feeds: [],
41602
- files: [],
41603
- postChildren: [],
41604
- users: [],
41605
- videoStreamings: [],
41606
- });
41607
42049
  }
41608
42050
  }
41609
42051
  fireEvent('local.comment.deleted', {
@@ -42169,47 +42611,6 @@ var index$d = /*#__PURE__*/Object.freeze({
42169
42611
  getComments: getComments
42170
42612
  });
42171
42613
 
42172
- const getPost$1 = async (postId) => {
42173
- const client = getActiveClient();
42174
- client.log('post/getPost', postId);
42175
- isInTombstone('post', postId);
42176
- let payload;
42177
- try {
42178
- // API-FIX: endpoint should not be /list, parameters should be querystring.
42179
- const response = await client.http.get(`/api/v3/posts/${encodeURIComponent(postId)}`);
42180
- payload = response.data;
42181
- }
42182
- catch (error) {
42183
- if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
42184
- pushToTombstone('post', postId);
42185
- }
42186
- throw error;
42187
- }
42188
- const data = prepareMembershipPayload(payload, 'communityUsers');
42189
- const cachedAt = client.cache && Date.now();
42190
- if (client.cache)
42191
- ingestInCache(data, { cachedAt });
42192
- const { posts } = data;
42193
- const result = posts.find(post => post.postId === postId);
42194
- return {
42195
- data: result,
42196
- cachedAt,
42197
- };
42198
- };
42199
- getPost$1.locally = (postId) => {
42200
- const client = getActiveClient();
42201
- client.log('post/getPost.locally', postId);
42202
- if (!client.cache)
42203
- return;
42204
- const cached = pullFromCache(['post', 'get', postId]);
42205
- if (!cached)
42206
- return;
42207
- return {
42208
- data: cached.data,
42209
- cachedAt: cached.cachedAt,
42210
- };
42211
- };
42212
-
42213
42614
  /**
42214
42615
  * ```js
42215
42616
  * import { onLocalPostDeleted } from '@amityco/ts-sdk-react-native'
@@ -42308,7 +42709,6 @@ const commentEventHandler$1 = (callback, eventHandler, cacheKey) => {
42308
42709
  const currentCollection = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
42309
42710
  if (!currentCollection || !currentCollection.data.includes(comment.referenceId))
42310
42711
  return;
42311
- await getPost$1(comment.referenceId);
42312
42712
  callback(comment);
42313
42713
  });
42314
42714
  };
@@ -42316,12 +42716,8 @@ const generateCommentSubscriptions$1 = (cacheKey) => {
42316
42716
  const eventHandlers = [
42317
42717
  onCommentCreated,
42318
42718
  onCommentDeleted,
42319
- onCommentReactionAdded,
42320
- onCommentReactionRemoved,
42321
42719
  onCommentCreatedLocal,
42322
42720
  onCommentDeleteLocal,
42323
- onLocalCommentReactionAdded,
42324
- onLocalCommentReactionRemoved,
42325
42721
  ];
42326
42722
  return eventHandlers.map(handler => ({
42327
42723
  fn: convertEventPayload((callback) => commentEventHandler$1(callback, handler, cacheKey), 'referenceId', 'post'),
@@ -42685,6 +43081,47 @@ class UserFeedQueryStreamController extends QueryStreamController {
42685
43081
  }
42686
43082
  }
42687
43083
 
43084
+ const getPost$1 = async (postId) => {
43085
+ const client = getActiveClient();
43086
+ client.log('post/getPost', postId);
43087
+ isInTombstone('post', postId);
43088
+ let payload;
43089
+ try {
43090
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
43091
+ const response = await client.http.get(`/api/v3/posts/${encodeURIComponent(postId)}`);
43092
+ payload = response.data;
43093
+ }
43094
+ catch (error) {
43095
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
43096
+ pushToTombstone('post', postId);
43097
+ }
43098
+ throw error;
43099
+ }
43100
+ const data = prepareMembershipPayload(payload, 'communityUsers');
43101
+ const cachedAt = client.cache && Date.now();
43102
+ if (client.cache)
43103
+ ingestInCache(data, { cachedAt });
43104
+ const { posts } = data;
43105
+ const result = posts.find(post => post.postId === postId);
43106
+ return {
43107
+ data: result,
43108
+ cachedAt,
43109
+ };
43110
+ };
43111
+ getPost$1.locally = (postId) => {
43112
+ const client = getActiveClient();
43113
+ client.log('post/getPost.locally', postId);
43114
+ if (!client.cache)
43115
+ return;
43116
+ const cached = pullFromCache(['post', 'get', postId]);
43117
+ if (!cached)
43118
+ return;
43119
+ return {
43120
+ data: cached.data,
43121
+ cachedAt: cached.cachedAt,
43122
+ };
43123
+ };
43124
+
42688
43125
  class UserFeedLiveCollectionController extends LiveCollectionController {
42689
43126
  constructor(query, callback) {
42690
43127
  const queryStreamId = hash(query);
@@ -42818,12 +43255,240 @@ const getUserFeed = (params, callback, config) => {
42818
43255
  };
42819
43256
  /* end_public_function */
42820
43257
 
43258
+ class CommunityFeedPaginationController extends PaginationController {
43259
+ async getRequest(queryParams, token) {
43260
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT, includeDeleted, communityId } = queryParams, params = __rest(queryParams, ["limit", "includeDeleted", "communityId"]);
43261
+ const options = token ? { token } : { limit };
43262
+ const { data: queryResponse } = await this.http.get(`/api/v5/posts`, {
43263
+ params: Object.assign(Object.assign({}, params), { targetId: communityId, targetType: 'community', isDeleted: inferIsDeleted(includeDeleted), matchingOnlyParentPost: true, options }),
43264
+ });
43265
+ return queryResponse;
43266
+ }
43267
+ }
43268
+
43269
+ class CommunityFeedQueryStreamController extends QueryStreamController {
43270
+ constructor(query, cacheKey, notifyChange, preparePayload) {
43271
+ super(query, cacheKey);
43272
+ this.notifyChange = notifyChange;
43273
+ this.preparePayload = preparePayload;
43274
+ }
43275
+ async saveToMainDB(response) {
43276
+ const processedPayload = await this.preparePayload(response);
43277
+ const client = getActiveClient();
43278
+ const cachedAt = client.cache && Date.now();
43279
+ if (client.cache) {
43280
+ ingestInCache(processedPayload, { cachedAt });
43281
+ }
43282
+ }
43283
+ appendToQueryStream(response, direction, refresh = false) {
43284
+ var _a, _b;
43285
+ if (refresh) {
43286
+ pushToCache(this.cacheKey, {
43287
+ data: response.posts.map(getResolver('post')),
43288
+ });
43289
+ }
43290
+ else {
43291
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
43292
+ const posts = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
43293
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [...new Set([...posts, ...response.posts.map(getResolver('post'))])] }));
43294
+ }
43295
+ }
43296
+ reactor(action) {
43297
+ return (post) => {
43298
+ var _a, _b;
43299
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
43300
+ if (!collection)
43301
+ return;
43302
+ if (action === EnumPostActions.OnPostDeleted) {
43303
+ collection.data = collection.data.filter(postId => postId !== post.postId);
43304
+ }
43305
+ if (post.parentPostId && post.isDeleted) {
43306
+ const parentPost = (_b = pullFromCache([
43307
+ 'post',
43308
+ 'get',
43309
+ post.parentPostId,
43310
+ ])) === null || _b === void 0 ? void 0 : _b.data;
43311
+ if (!parentPost)
43312
+ return;
43313
+ parentPost.children = parentPost.children.filter(childId => childId !== post.postId);
43314
+ pushToCache(['post', 'get', parentPost.postId], parentPost);
43315
+ }
43316
+ if (action === EnumPostActions.OnPostDeclined) {
43317
+ collection.data = collection.data.filter(postId => postId !== post.postId);
43318
+ }
43319
+ if (action === EnumPostActions.OnPostCreated || action === EnumPostActions.OnPostApproved) {
43320
+ collection.data = [...new Set([post.postId, ...collection.data])];
43321
+ }
43322
+ pushToCache(this.cacheKey, collection);
43323
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
43324
+ };
43325
+ }
43326
+ subscribeRTE(createSubscriber) {
43327
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
43328
+ }
43329
+ }
43330
+
43331
+ const commentEventHandler = (callback, eventHandler, cacheKey, resolveId) => {
43332
+ return eventHandler(async (comment) => {
43333
+ var _a;
43334
+ const currentCollection = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
43335
+ if (!currentCollection ||
43336
+ !currentCollection.data.includes(resolveId ? resolveId(comment.referenceId) : comment.referenceId))
43337
+ return;
43338
+ callback(comment);
43339
+ });
43340
+ };
43341
+ const generateCommentSubscriptions = ({ cacheKey, resolveId, }) => {
43342
+ const eventHandlers = [
43343
+ onCommentCreated,
43344
+ onCommentDeleted,
43345
+ onCommentCreatedLocal,
43346
+ onCommentDeleteLocal,
43347
+ ];
43348
+ return eventHandlers.map(handler => ({
43349
+ fn: convertEventPayload((callback) => commentEventHandler(callback, handler, cacheKey, resolveId), 'referenceId', 'post'),
43350
+ action: EnumPostActions.OnPostUpdated,
43351
+ }));
43352
+ };
43353
+ const getPostSubscription = (cacheKey) => {
43354
+ return [
43355
+ { fn: onPostCreated, action: EnumPostActions.OnPostCreated },
43356
+ { fn: onPostUpdated, action: EnumPostActions.OnPostUpdated },
43357
+ { fn: onPostUpdatedLocal, action: EnumPostActions.OnPostUpdated },
43358
+ { fn: onPostDeleted, action: EnumPostActions.OnPostDeleted },
43359
+ { fn: onPostFlagged, action: EnumPostActions.OnPostFlagged },
43360
+ { fn: onPostUnflagged, action: EnumPostActions.OnPostUnflagged },
43361
+ { fn: onPostApproved, action: EnumPostActions.OnPostApproved },
43362
+ { fn: onPostDeclined, action: EnumPostActions.OnPostDeclined },
43363
+ { fn: onPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
43364
+ { fn: onPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
43365
+ { fn: onLocalPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
43366
+ { fn: onLocalPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
43367
+ { fn: onLocalPostDeleted, action: EnumPostActions.OnPostDeleted },
43368
+ ...generateCommentSubscriptions({ cacheKey }),
43369
+ ];
43370
+ };
43371
+ const resolvePostIdsFromRooms = (rooms, posts) => {
43372
+ var _a;
43373
+ return ((_a = rooms
43374
+ .map(room => {
43375
+ const post = posts.find(post => post.postId === room.referenceId);
43376
+ return post ? getResolver('post')({ postId: post === null || post === void 0 ? void 0 : post.postId }) : undefined;
43377
+ })
43378
+ .filter(isNonNullable)) !== null && _a !== void 0 ? _a : []);
43379
+ };
43380
+
43381
+ class CommunityFeedLiveCollectionController extends LiveCollectionController {
43382
+ constructor(query, callback) {
43383
+ const queryStreamId = hash(query);
43384
+ const cacheKey = ['communityFeed', 'collection', queryStreamId];
43385
+ const paginationController = new CommunityFeedPaginationController(query);
43386
+ super(paginationController, queryStreamId, cacheKey, callback);
43387
+ this.query = query;
43388
+ this.queryStreamController = new CommunityFeedQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), preparePostPayload);
43389
+ this.callback = callback.bind(this);
43390
+ this.loadPage({ initial: true });
43391
+ }
43392
+ setup() {
43393
+ var _a;
43394
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
43395
+ if (!collection) {
43396
+ pushToCache(this.cacheKey, {
43397
+ data: [],
43398
+ params: {},
43399
+ });
43400
+ }
43401
+ }
43402
+ async persistModel(queryPayload) {
43403
+ await this.queryStreamController.saveToMainDB(queryPayload);
43404
+ }
43405
+ persistQueryStream({ response, direction, refresh, }) {
43406
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
43407
+ }
43408
+ startSubscription() {
43409
+ return this.queryStreamController.subscribeRTE(getPostSubscription(this.cacheKey));
43410
+ }
43411
+ notifyChange({ origin, loading, error }) {
43412
+ var _a, _b;
43413
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
43414
+ if (!collection)
43415
+ return;
43416
+ const data = ((_b = collection.data
43417
+ .map(id => pullFromCache(['post', 'get', id]))
43418
+ .filter(isNonNullable)
43419
+ .map(({ data }) => data)) !== null && _b !== void 0 ? _b : []).map(LinkedObject.post);
43420
+ if (!this.shouldNotify(data) && origin === 'event')
43421
+ return;
43422
+ this.callback({
43423
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
43424
+ data,
43425
+ hasNextPage: !!this.paginationController.getNextToken(),
43426
+ loading,
43427
+ error,
43428
+ });
43429
+ }
43430
+ }
43431
+
43432
+ /* begin_public_function
43433
+ id: feed.query.community_feed
43434
+ */
43435
+ /**
43436
+ * ```js
43437
+ * import { FeedRepository } from '@amityco/ts-sdk'
43438
+ *
43439
+ * let posts = []
43440
+ * const unsubscribe = FeedRepository.getCommunityFeed({
43441
+ * communityId: 'community-id',
43442
+ * sortBy?: 'lastCreated' | 'firstCreated' | 'lastUpdated' | 'firstUpdated',
43443
+ * includeDeleted?: boolean,
43444
+ * feedType?: 'reviewing' | 'published' | 'declined',
43445
+ * tags?: string[],
43446
+ * includeMixedStructure?: boolean,
43447
+ * limit?: number,
43448
+ * }, response => processResponse(response))
43449
+ * ```
43450
+ *
43451
+ * Observe all mutations on a list of {@link Amity.Post} for a given community feed.
43452
+ *
43453
+ * @param params - Parameters for querying the community feed:
43454
+ * @param params.communityId The ID of the community (required)
43455
+ * @param params.sortBy The sorting order of the feed (optional)
43456
+ * @param params.includeDeleted Whether to include deleted posts (optional)
43457
+ * @param params.feedType The type of the feed: 'reviewing', 'published', or 'declined' (optional)
43458
+ * @param params.tags Array of tags to filter posts (optional)
43459
+ * @param params.includeMixedStructure Whether to include mixed structure posts (optional)
43460
+ * @param params.limit The maximum number of posts to retrieve (optional)
43461
+ * @param callback The function to call when new data are available
43462
+ * @param config Additional live collection configuration (optional)
43463
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the feed
43464
+ *
43465
+ * @category Posts Live Collection
43466
+ */
43467
+ const getCommunityFeed = (params, callback, config) => {
43468
+ const { log, cache } = getActiveClient();
43469
+ if (!cache) {
43470
+ console.log(ENABLE_CACHE_MESSAGE);
43471
+ }
43472
+ const timestamp = Date.now();
43473
+ log(`getCommunityFeed(tmpid: ${timestamp}) > listen`);
43474
+ const communityFeedLiveCollection = new CommunityFeedLiveCollectionController(params, callback);
43475
+ const disposers = communityFeedLiveCollection.startSubscription();
43476
+ const cacheKey = communityFeedLiveCollection.getCacheKey();
43477
+ disposers.push(() => dropFromCache(cacheKey));
43478
+ return () => {
43479
+ log(`getCommunityFeed(tmpid: ${timestamp}) > dispose`);
43480
+ disposers.forEach(fn => fn());
43481
+ };
43482
+ };
43483
+ /* end_public_function */
43484
+
42821
43485
  var index$c = /*#__PURE__*/Object.freeze({
42822
43486
  __proto__: null,
42823
43487
  queryGlobalFeed: queryGlobalFeed,
42824
43488
  getCustomRankingGlobalFeed: getCustomRankingGlobalFeed,
42825
43489
  getGlobalFeed: getGlobalFeed,
42826
- getUserFeed: getUserFeed
43490
+ getUserFeed: getUserFeed,
43491
+ getCommunityFeed: getCommunityFeed
42827
43492
  });
42828
43493
 
42829
43494
  /* begin_public_function
@@ -43569,61 +44234,6 @@ class PostQueryStreamController extends QueryStreamController {
43569
44234
  }
43570
44235
  }
43571
44236
 
43572
- const commentEventHandler = (callback, eventHandler, cacheKey, resolveId) => {
43573
- return eventHandler(async (comment) => {
43574
- var _a;
43575
- const currentCollection = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
43576
- if (!currentCollection ||
43577
- !currentCollection.data.includes(resolveId ? resolveId(comment.referenceId) : comment.referenceId))
43578
- return;
43579
- await getPost$1(comment.referenceId);
43580
- callback(comment);
43581
- });
43582
- };
43583
- const generateCommentSubscriptions = ({ cacheKey, resolveId, }) => {
43584
- const eventHandlers = [
43585
- onCommentCreated,
43586
- onCommentDeleted,
43587
- onCommentReactionAdded,
43588
- onCommentReactionRemoved,
43589
- onCommentCreatedLocal,
43590
- onCommentDeleteLocal,
43591
- onLocalCommentReactionAdded,
43592
- onLocalCommentReactionRemoved,
43593
- ];
43594
- return eventHandlers.map(handler => ({
43595
- fn: convertEventPayload((callback) => commentEventHandler(callback, handler, cacheKey, resolveId), 'referenceId', 'post'),
43596
- action: EnumPostActions.OnPostUpdated,
43597
- }));
43598
- };
43599
- const getPostSubscription = (cacheKey) => {
43600
- return [
43601
- { fn: onPostCreated, action: EnumPostActions.OnPostCreated },
43602
- { fn: onPostUpdated, action: EnumPostActions.OnPostUpdated },
43603
- { fn: onPostUpdatedLocal, action: EnumPostActions.OnPostUpdated },
43604
- { fn: onPostDeleted, action: EnumPostActions.OnPostDeleted },
43605
- { fn: onPostFlagged, action: EnumPostActions.OnPostFlagged },
43606
- { fn: onPostUnflagged, action: EnumPostActions.OnPostUnflagged },
43607
- { fn: onPostApproved, action: EnumPostActions.OnPostApproved },
43608
- { fn: onPostDeclined, action: EnumPostActions.OnPostDeclined },
43609
- { fn: onPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
43610
- { fn: onPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
43611
- { fn: onLocalPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
43612
- { fn: onLocalPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
43613
- { fn: onLocalPostDeleted, action: EnumPostActions.OnPostDeleted },
43614
- ...generateCommentSubscriptions({ cacheKey }),
43615
- ];
43616
- };
43617
- const resolvePostIdsFromRooms = (rooms, posts) => {
43618
- var _a;
43619
- return ((_a = rooms
43620
- .map(room => {
43621
- const post = posts.find(post => post.postId === room.referenceId);
43622
- return post ? getResolver('post')({ postId: post === null || post === void 0 ? void 0 : post.postId }) : undefined;
43623
- })
43624
- .filter(isNonNullable)) !== null && _a !== void 0 ? _a : []);
43625
- };
43626
-
43627
44237
  class PostLiveCollectionController extends LiveCollectionController {
43628
44238
  constructor(query, callback) {
43629
44239
  const queryStreamId = hash(query);
@@ -49979,4 +50589,4 @@ var index = /*#__PURE__*/Object.freeze({
49979
50589
  getRSVPs: getRSVPs
49980
50590
  });
49981
50591
 
49982
- export { API_REGIONS, index$4 as AdRepository, AmityCommunityType, AmityEventOrderOption, AmityEventOriginType, AmityEventResponseStatus, AmityEventSortOption, AmityEventStatus, AmityEventType, index$e as CategoryRepository, index$i as ChannelRepository, index$r as Client, index$d as CommentRepository, CommunityPostSettingMaps, CommunityPostSettings, index$f as CommunityRepository, ContentFeedType, ContentFlagReasonEnum, DefaultCommunityPostSetting, index as EventRepository, FeedDataTypeEnum, index$c as FeedRepository, FeedSortByEnum, FeedSourceEnum, FileAccessTypeEnum, index$o as FileRepository, FileType, GET_WATCHER_URLS, index$2 as InvitationRepository, InvitationSortByEnum, InvitationStatusEnum, InvitationTargetTypeEnum, InvitationTypeEnum, JoinRequestStatusEnum, JoinResultStatusEnum, index$1 as LiveReactionRepository, index$6 as LiveStreamPlayer, MembershipAcceptanceTypeEnum, MessageContentType, index$m as MessageRepository, index$7 as PollRepository, PostContentType, index$a as PostRepository, PostStructureType, index$n as ReactionRepository, index$8 as RoomPresenceRepository, index$b as RoomRepository, index$5 as StoryRepository, index$9 as StreamRepository, index$l as SubChannelRepository, SubscriptionLevels, index$p as UserRepository, UserTypeEnum, VERSION, VideoResolution, VideoSize, VideoTranscodingStatus, backupCache, createQuery, createReport, createUserToken, deleteReport, disableCache, dropFromCache, enableCache, filterByChannelMembership, filterByCommunityMembership, filterByFeedType, filterByPostDataTypes, filterByPropEquality, filterByPropInclusion, filterByPropIntersection, filterBySearchTerm, filterByStringComparePartially, getChannelTopic, getCommentTopic, getCommunityStoriesTopic, getCommunityTopic, getLiveReactionTopic, getLiveStreamTopic, getMarkedMessageTopic, getMarkerUserFeedTopic, getMessageTopic, getMyFollowersTopic, getMyFollowingsTopic, getNetworkTopic, getPostTopic, getRole, getRoomStreamerTopic, getRoomWatcherTopic, getSmartFeedChannelTopic, getSmartFeedMessageTopic, getSmartFeedSubChannelTopic, getStoryTopic, getSubChannelTopic, getUserTopic, isAfterBefore, isAfterBeforeRaw, isCachable, isFetcher, isFresh, isLocal, isMutator, isOffline, isPaged, isReportedByMe, isSkip, mergeInCache, index$3 as notificationTray, onChannelMarkerFetched, onFeedMarkerFetched, onFeedMarkerUpdated, onMessageMarked, onMessageMarkerFetched, onSubChannelMarkerFetched, onSubChannelMarkerUpdated, onUserMarkerFetched, onUserMarkerFetchedLegacy, pullFromCache, pushToCache, queryCache, queryOptions, queryRoles, restoreCache, runQuery, sortByChannelSegment, sortByDisplayName, sortByFirstCreated, sortByFirstUpdated, sortByLastActivity, sortByLastCreated, sortByLastUpdated, sortByLocalSortingDate, sortByName, sortBySegmentNumber, subscribeTopic, toPage, toPageRaw, toToken, upsertInCache, wipeCache };
50592
+ export { API_REGIONS, index$4 as AdRepository, AmityCommunityType, AmityEventOrderOption, AmityEventOriginType, AmityEventResponseStatus, AmityEventSortOption, AmityEventStatus, AmityEventType, index$e as CategoryRepository, index$i as ChannelRepository, index$r as Client, index$d as CommentRepository, CommunityPostSettingMaps, CommunityPostSettings, index$f as CommunityRepository, ContentFeedType, ContentFlagReasonEnum, DefaultCommunityPostSetting, index as EventRepository, FeedDataTypeEnum, index$c as FeedRepository, FeedSortByEnum, FeedSourceEnum, FeedTypeEnum, FileAccessTypeEnum, index$o as FileRepository, FileType, GET_WATCHER_URLS, index$2 as InvitationRepository, InvitationSortByEnum, InvitationStatusEnum, InvitationTargetTypeEnum, InvitationTypeEnum, JoinRequestStatusEnum, JoinResultStatusEnum, index$1 as LiveReactionRepository, index$6 as LiveStreamPlayer, MembershipAcceptanceTypeEnum, MessageContentType, index$m as MessageRepository, index$7 as PollRepository, PostContentType, index$a as PostRepository, PostStructureType, index$n as ReactionRepository, index$8 as RoomPresenceRepository, index$b as RoomRepository, index$5 as StoryRepository, index$9 as StreamRepository, index$l as SubChannelRepository, SubscriptionLevels, index$p as UserRepository, UserTypeEnum, VERSION, VideoResolution, VideoSize, VideoTranscodingStatus, backupCache, createQuery, createReport, createUserToken, deleteReport, disableCache, dropFromCache, enableCache, filterByChannelMembership, filterByCommunityMembership, filterByFeedType, filterByPostDataTypes, filterByPropEquality, filterByPropInclusion, filterByPropIntersection, filterBySearchTerm, filterByStringComparePartially, getChannelTopic, getCommentTopic, getCommunityStoriesTopic, getCommunityTopic, getLiveReactionTopic, getLiveStreamTopic, getMarkedMessageTopic, getMarkerUserFeedTopic, getMessageTopic, getMyFollowersTopic, getMyFollowingsTopic, getNetworkTopic, getPostTopic, getRole, getRoomStreamerTopic, getRoomWatcherTopic, getSmartFeedChannelTopic, getSmartFeedMessageTopic, getSmartFeedSubChannelTopic, getStoryTopic, getSubChannelTopic, getUserTopic, isAfterBefore, isAfterBeforeRaw, isCachable, isFetcher, isFresh, isLocal, isMutator, isOffline, isPaged, isReportedByMe, isSkip, mergeInCache, index$3 as notificationTray, onChannelMarkerFetched, onFeedMarkerFetched, onFeedMarkerUpdated, onMessageMarked, onMessageMarkerFetched, onSubChannelMarkerFetched, onSubChannelMarkerUpdated, onUserMarkerFetched, onUserMarkerFetchedLegacy, pullFromCache, pushToCache, queryCache, queryOptions, queryRoles, restoreCache, runQuery, sortByChannelSegment, sortByDisplayName, sortByFirstCreated, sortByFirstUpdated, sortByLastActivity, sortByLastCreated, sortByLastUpdated, sortByLocalSortingDate, sortByName, sortBySegmentNumber, subscribeTopic, toPage, toPageRaw, toToken, upsertInCache, wipeCache };