@amityco/ts-sdk 0.0.1-beta.30 → 0.0.1-beta.31

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 (181) hide show
  1. package/dist/@types/core/cache.d.ts +3 -0
  2. package/dist/@types/core/cache.d.ts.map +1 -1
  3. package/dist/@types/core/errors.d.ts +2 -1
  4. package/dist/@types/core/errors.d.ts.map +1 -1
  5. package/dist/@types/core/events.d.ts +2 -0
  6. package/dist/@types/core/events.d.ts.map +1 -1
  7. package/dist/@types/core/live.d.ts +8 -4
  8. package/dist/@types/core/live.d.ts.map +1 -1
  9. package/dist/@types/core/query.d.ts +1 -1
  10. package/dist/@types/core/query.d.ts.map +1 -1
  11. package/dist/@types/domains/channel.d.ts +1 -0
  12. package/dist/@types/domains/channel.d.ts.map +1 -1
  13. package/dist/@types/domains/message.d.ts +13 -6
  14. package/dist/@types/domains/message.d.ts.map +1 -1
  15. package/dist/@types/domains/post.d.ts +10 -3
  16. package/dist/@types/domains/post.d.ts.map +1 -1
  17. package/dist/@types/domains/user.d.ts +1 -0
  18. package/dist/@types/domains/user.d.ts.map +1 -1
  19. package/dist/@types/index.d.ts +2 -2
  20. package/dist/@types/index.d.ts.map +1 -1
  21. package/dist/cache/api/isInTombstone.d.ts +18 -0
  22. package/dist/cache/api/isInTombstone.d.ts.map +1 -0
  23. package/dist/cache/api/pushToTombstone.d.ts +17 -0
  24. package/dist/cache/api/pushToTombstone.d.ts.map +1 -0
  25. package/dist/cache/utils/index.d.ts +17 -0
  26. package/dist/cache/utils/index.d.ts.map +1 -1
  27. package/dist/channel/api/queryChannelMembers.d.ts +1 -1
  28. package/dist/channel/api/queryChannelMembers.d.ts.map +1 -1
  29. package/dist/channel/api/queryChannels.d.ts +1 -1
  30. package/dist/channel/api/queryChannels.d.ts.map +1 -1
  31. package/dist/channel/api/tests/queryChannelMembers.test.d.ts +2 -0
  32. package/dist/channel/api/tests/queryChannelMembers.test.d.ts.map +1 -0
  33. package/dist/channel/api/tests/queryChannels.test.d.ts +2 -0
  34. package/dist/channel/api/tests/queryChannels.test.d.ts.map +1 -0
  35. package/dist/channel/events/index.d.ts +2 -0
  36. package/dist/channel/events/index.d.ts.map +1 -1
  37. package/dist/channel/events/onChannelMemberBanned.d.ts +17 -0
  38. package/dist/channel/events/onChannelMemberBanned.d.ts.map +1 -0
  39. package/dist/channel/events/onChannelMemberUnbanned.d.ts +17 -0
  40. package/dist/channel/events/onChannelMemberUnbanned.d.ts.map +1 -0
  41. package/dist/channel/events/tests/onChannelMemberBanned.test.d.ts +2 -0
  42. package/dist/channel/events/tests/onChannelMemberBanned.test.d.ts.map +1 -0
  43. package/dist/channel/events/tests/onChannelMemberUnbanned.test.d.ts +2 -0
  44. package/dist/channel/events/tests/onChannelMemberUnbanned.test.d.ts.map +1 -0
  45. package/dist/channel/observers/liveChannelMembers.d.ts.map +1 -1
  46. package/dist/channel/observers/liveChannels.d.ts.map +1 -1
  47. package/dist/channel/{tests/utils → utils/tests}/prepareChannelPayload.test.d.ts +0 -0
  48. package/dist/channel/utils/tests/prepareChannelPayload.test.d.ts.map +1 -0
  49. package/dist/core/events.d.ts +3 -3
  50. package/dist/core/events.d.ts.map +1 -1
  51. package/dist/core/query/filtering.d.ts +11 -0
  52. package/dist/core/query/filtering.d.ts.map +1 -1
  53. package/dist/core/query/query.d.ts.map +1 -1
  54. package/dist/index.cjs.js +963 -507
  55. package/dist/index.esm.js +946 -499
  56. package/dist/index.umd.js +4 -4
  57. package/dist/message/api/createMessage.d.ts +4 -1
  58. package/dist/message/api/createMessage.d.ts.map +1 -1
  59. package/dist/message/api/deleteMessage.d.ts.map +1 -1
  60. package/dist/message/api/getMessage.d.ts +1 -1
  61. package/dist/message/api/getMessage.d.ts.map +1 -1
  62. package/dist/message/api/getMessages.d.ts.map +1 -1
  63. package/dist/message/api/queryMessages.d.ts.map +1 -1
  64. package/dist/message/api/tests/createMessage.test.d.ts +2 -0
  65. package/dist/message/api/tests/createMessage.test.d.ts.map +1 -0
  66. package/dist/message/api/updateMessage.d.ts.map +1 -1
  67. package/dist/message/events/index.d.ts +1 -0
  68. package/dist/message/events/index.d.ts.map +1 -1
  69. package/dist/message/events/onMessageFetched.d.ts +17 -0
  70. package/dist/message/events/onMessageFetched.d.ts.map +1 -0
  71. package/dist/message/observers/index.d.ts +2 -1
  72. package/dist/message/observers/index.d.ts.map +1 -1
  73. package/dist/message/observers/liveMessage.d.ts +18 -0
  74. package/dist/message/observers/liveMessage.d.ts.map +1 -0
  75. package/dist/message/observers/liveMessages.d.ts.map +1 -1
  76. package/dist/message/observers/observeMessage.d.ts.map +1 -1
  77. package/dist/message/tests/api/getMessage.test.d.ts +2 -0
  78. package/dist/message/tests/api/getMessage.test.d.ts.map +1 -0
  79. package/dist/message/tests/observers/liveMessage.test.d.ts +2 -0
  80. package/dist/message/tests/observers/liveMessage.test.d.ts.map +1 -0
  81. package/dist/message/{observers/tests → tests/observers}/liveMessages.test.d.ts +0 -0
  82. package/dist/message/tests/observers/liveMessages.test.d.ts.map +1 -0
  83. package/dist/post/api/deletePost.d.ts.map +1 -1
  84. package/dist/post/api/getPost.d.ts.map +1 -1
  85. package/dist/post/api/updatePost.d.ts +6 -1
  86. package/dist/post/api/updatePost.d.ts.map +1 -1
  87. package/dist/user/api/getUser.d.ts +1 -1
  88. package/dist/user/api/getUser.d.ts.map +1 -1
  89. package/dist/user/api/getUsers.d.ts.map +1 -1
  90. package/dist/user/api/queryUsers.d.ts.map +1 -1
  91. package/dist/user/api/updateUser.d.ts.map +1 -1
  92. package/dist/user/events/index.d.ts +1 -0
  93. package/dist/user/events/index.d.ts.map +1 -1
  94. package/dist/user/events/onUserFetched.d.ts +17 -0
  95. package/dist/user/events/onUserFetched.d.ts.map +1 -0
  96. package/dist/user/observers/index.d.ts +1 -0
  97. package/dist/user/observers/index.d.ts.map +1 -1
  98. package/dist/user/observers/liveUser.d.ts +18 -0
  99. package/dist/user/observers/liveUser.d.ts.map +1 -0
  100. package/dist/user/observers/observeUser.d.ts.map +1 -1
  101. package/dist/user/tests/api/getUser.test.d.ts +2 -0
  102. package/dist/user/tests/api/getUser.test.d.ts.map +1 -0
  103. package/dist/user/tests/observers/liveUser.test.d.ts +2 -0
  104. package/dist/user/tests/observers/liveUser.test.d.ts.map +1 -0
  105. package/dist/utils/constants.d.ts +3 -0
  106. package/dist/utils/constants.d.ts.map +1 -1
  107. package/dist/utils/tests/dummy/channel.d.ts +15 -0
  108. package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
  109. package/dist/utils/tests/dummy/message.d.ts +12 -1
  110. package/dist/utils/tests/dummy/message.d.ts.map +1 -1
  111. package/dist/utils/tests/dummy/user.d.ts +10 -0
  112. package/dist/utils/tests/dummy/user.d.ts.map +1 -1
  113. package/package.json +1 -1
  114. package/src/@types/core/cache.ts +4 -0
  115. package/src/@types/core/errors.ts +1 -0
  116. package/src/@types/core/events.ts +2 -0
  117. package/src/@types/core/live.ts +10 -4
  118. package/src/@types/core/query.ts +1 -1
  119. package/src/@types/domains/channel.ts +6 -0
  120. package/src/@types/domains/message.ts +13 -10
  121. package/src/@types/domains/post.ts +10 -3
  122. package/src/@types/domains/user.ts +8 -0
  123. package/src/@types/index.ts +2 -2
  124. package/src/cache/api/index.ts +2 -1
  125. package/src/cache/api/isInTombstone.ts +41 -0
  126. package/src/cache/api/pushToTombstone.ts +33 -0
  127. package/src/cache/utils/index.ts +22 -0
  128. package/src/channel/api/queryChannelMembers.ts +53 -5
  129. package/src/channel/api/queryChannels.ts +31 -4
  130. package/src/channel/api/tests/queryChannelMembers.test.ts +115 -0
  131. package/src/channel/api/tests/queryChannels.test.ts +101 -0
  132. package/src/channel/events/index.ts +5 -0
  133. package/src/channel/events/onChannelMemberBanned.ts +36 -0
  134. package/src/channel/events/onChannelMemberUnbanned.ts +36 -0
  135. package/src/channel/events/tests/onChannelMemberBanned.test.ts +58 -0
  136. package/src/channel/events/tests/onChannelMemberUnbanned.test.ts +58 -0
  137. package/src/channel/observers/liveChannelMembers.ts +28 -4
  138. package/src/channel/observers/liveChannels.ts +7 -1
  139. package/src/channel/observers/tests/liveChannelMembers.test.ts +53 -11
  140. package/src/channel/observers/tests/liveChannels.test.ts +50 -20
  141. package/src/channel/{tests/utils → utils/tests}/prepareChannelPayload.test.ts +1 -1
  142. package/src/core/events.ts +1 -0
  143. package/src/core/query/filtering.ts +49 -0
  144. package/src/core/query/query.ts +9 -6
  145. package/src/core/tests/query/query.test.ts +12 -2
  146. package/src/message/api/createMessage.ts +15 -9
  147. package/src/message/api/deleteMessage.ts +2 -1
  148. package/src/message/api/getMessage.ts +32 -4
  149. package/src/message/api/getMessages.ts +6 -1
  150. package/src/message/api/queryMessages.ts +3 -0
  151. package/src/message/api/tests/createMessage.test.ts +76 -0
  152. package/src/message/api/updateMessage.ts +2 -0
  153. package/src/message/events/index.ts +1 -0
  154. package/src/message/events/onMessageFetched.ts +30 -0
  155. package/src/message/observers/index.ts +2 -1
  156. package/src/message/observers/liveMessage.ts +100 -0
  157. package/src/message/observers/liveMessages.ts +3 -1
  158. package/src/message/observers/observeMessage.ts +4 -0
  159. package/src/message/tests/api/getMessage.test.ts +96 -0
  160. package/src/message/tests/observers/liveMessage.test.ts +248 -0
  161. package/src/message/{observers/tests → tests/observers}/liveMessages.test.ts +29 -3
  162. package/src/post/api/deletePost.ts +4 -3
  163. package/src/post/api/getPost.ts +8 -4
  164. package/src/post/api/updatePost.ts +6 -1
  165. package/src/user/api/getUser.ts +34 -6
  166. package/src/user/api/getUsers.ts +3 -0
  167. package/src/user/api/queryUsers.ts +3 -0
  168. package/src/user/api/updateUser.ts +3 -0
  169. package/src/user/events/index.ts +1 -0
  170. package/src/user/events/onUserFetched.ts +19 -0
  171. package/src/user/observers/index.ts +1 -0
  172. package/src/user/observers/liveUser.ts +89 -0
  173. package/src/user/observers/observeUser.ts +2 -0
  174. package/src/user/tests/api/getUser.test.ts +112 -0
  175. package/src/user/tests/observers/liveUser.test.ts +224 -0
  176. package/src/utils/constants.ts +5 -0
  177. package/src/utils/tests/dummy/channel.ts +43 -0
  178. package/src/utils/tests/dummy/message.ts +16 -2
  179. package/src/utils/tests/dummy/user.ts +11 -0
  180. package/dist/channel/tests/utils/prepareChannelPayload.test.d.ts.map +0 -1
  181. package/dist/message/observers/tests/liveMessages.test.d.ts.map +0 -1
package/dist/index.cjs.js CHANGED
@@ -3,8 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var jsBase64 = require('js-base64');
6
- var mitt = require('mitt');
7
6
  var AsyncStorage = require('@react-native-async-storage/async-storage');
7
+ var mitt = require('mitt');
8
8
  var debug = require('debug');
9
9
  var axios = require('axios');
10
10
  var HttpAgent = require('agentkeepalive');
@@ -13,8 +13,8 @@ var nativeIdGenerator = require('react-native-uuid');
13
13
 
14
14
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
15
 
16
- var mitt__default = /*#__PURE__*/_interopDefaultLegacy(mitt);
17
16
  var AsyncStorage__default = /*#__PURE__*/_interopDefaultLegacy(AsyncStorage);
17
+ var mitt__default = /*#__PURE__*/_interopDefaultLegacy(mitt);
18
18
  var debug__default = /*#__PURE__*/_interopDefaultLegacy(debug);
19
19
  var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
20
20
  var HttpAgent__default = /*#__PURE__*/_interopDefaultLegacy(HttpAgent);
@@ -75,6 +75,24 @@ const VideoSize = Object.freeze({
75
75
  ORIGINAL: 'original',
76
76
  });
77
77
 
78
+ const MessageContentType = Object.freeze({
79
+ TEXT: 'text',
80
+ IMAGE: 'image',
81
+ FILE: 'file',
82
+ VIDEO: 'video',
83
+ AUDIO: 'audio',
84
+ CUSTOM: 'custom',
85
+ });
86
+
87
+ const PostContentType = Object.freeze({
88
+ TEXT: 'text',
89
+ IMAGE: 'image',
90
+ FILE: 'file',
91
+ VIDEO: 'video',
92
+ LIVESTREAM: 'liveStream',
93
+ POLL: 'poll',
94
+ });
95
+
78
96
  var _a$1;
79
97
  /* eslint-disable no-undef */
80
98
  const theGlobal =
@@ -350,6 +368,78 @@ const PAYLOAD2MODEL = {
350
368
  followCounts: 'followCount',
351
369
  };
352
370
 
371
+ // cache constants
372
+ const CACHE_KEY_GET = 'get';
373
+ const CACHE_KEY_TOMBSTONE = 'dead';
374
+ const CACHE_LIFESPAN = 1 * 60 * 1000; // 1 minute
375
+ const CACHE_LIFESPAN_TOMBSTONE = 3 * 60 * 1000; // 3 minutes
376
+ /**
377
+ * Shallow-clones an object and sort its keys
378
+ *
379
+ * @param source a plain object to clone
380
+ * @returns a clone of source, with keys sorted with default javascript sorting
381
+ *
382
+ * @category Cache
383
+ * @hidden
384
+ */
385
+ const normalize = (source) => Object.keys(source)
386
+ .sort()
387
+ .reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: source[key] })), {});
388
+ /**
389
+ * Encodes a given {@link Amity.CacheKey} to a plain string
390
+ *
391
+ * @param key the key to encode
392
+ * @returns an encoded string
393
+ *
394
+ * @category Cache
395
+ * @hidden
396
+ */
397
+ const encodeKey = (key) => JSON.stringify(key, (_, val) => (typeof val === 'object' ? normalize(val) : val));
398
+ /**
399
+ * Decodes a string back into a {@link Amity.CacheKey}
400
+
401
+ *
402
+ * @param key the string key to decode
403
+ * @returns a plain Amity.CacheKey object.
404
+ *
405
+ * @category Cache
406
+ * @hidden
407
+ */
408
+ const decodeKey = (key) => JSON.parse(key);
409
+ /**
410
+ * Performs a recursive partial deep equal check on two objects.
411
+ *
412
+ * @param predicate the reference object containing the partial information
413
+ * @param candidate the object to check against
414
+ * @returns true if the candidate contains all the values of the predicate
415
+ *
416
+ * @category Cache
417
+ */
418
+ const partialMatch = (predicate, candidate) => {
419
+ if (predicate === candidate)
420
+ return true;
421
+ // if one or the other is nullish, there can't be equality
422
+ if (!predicate || !candidate)
423
+ return false;
424
+ // we only perform recursive check on objects
425
+ if (typeof predicate !== 'object') {
426
+ return false;
427
+ }
428
+ // recursively call for partial match based on the predicate
429
+ return Object.keys(predicate).every(key => partialMatch(predicate[key], candidate[key]));
430
+ };
431
+ /**
432
+ * checks if passed error code is included in
433
+ * Tombstone errors list
434
+ *
435
+ * @param errorCode as {@link Amity.ServerError}
436
+ * @returns success boolean if the given errorCode
437
+ * is included in Tombstone errors list
438
+ *
439
+ * @category Cache
440
+ */
441
+ const checkIfShouldGoesToTombstone = (errorCode) => [400400 /* Amity.ServerError.ITEM_NOT_FOUND */, 400300 /* Amity.ServerError.FORBIDDEN */].includes(errorCode);
442
+
353
443
  /* eslint-disable no-use-before-define */
354
444
  /**
355
445
  * Type guard to check and cast that a given async function is has the ".locally" property
@@ -408,7 +498,7 @@ const isLocal = (model) => {
408
498
  *
409
499
  * @hidden
410
500
  */
411
- const isFresh = (model, lifeSpan = 0) => {
501
+ const isFresh = (model, lifeSpan = CACHE_LIFESPAN) => {
412
502
  var _a;
413
503
  return Date.now() - ((_a = model === null || model === void 0 ? void 0 : model.cachedAt) !== null && _a !== void 0 ? _a : 0) <= lifeSpan;
414
504
  };
@@ -442,12 +532,10 @@ const createQuery = (func, ...args) => ({ func, args });
442
532
  *
443
533
  * @category Query
444
534
  */
445
- const queryOptions = (policy, lifeSpan = 2 * 60 * 1000) => {
535
+ const queryOptions = (policy, lifeSpan = CACHE_LIFESPAN) => {
446
536
  if (policy === 'cache_only')
447
537
  return { lifeSpan: Infinity };
448
- if (policy === 'server_only')
449
- return { lifeSpan: 0 };
450
- return { lifeSpan };
538
+ return { lifeSpan: lifeSpan < CACHE_LIFESPAN ? CACHE_LIFESPAN : lifeSpan };
451
539
  };
452
540
  /**
453
541
  * ```js
@@ -468,8 +556,9 @@ const queryOptions = (policy, lifeSpan = 2 * 60 * 1000) => {
468
556
  */
469
557
  const runQuery = ({ func, args }, callback, options = queryOptions('cache_then_server')) => {
470
558
  let local;
559
+ const { lifeSpan } = queryOptions('cache_then_server', options.lifeSpan);
471
560
  // offline first
472
- if (isOffline(func) && options.lifeSpan !== 0) {
561
+ if (isOffline(func)) {
473
562
  try {
474
563
  local = isMutator(func) ? func.optimistically(...args) : func.locally(...args);
475
564
  }
@@ -480,7 +569,7 @@ const runQuery = ({ func, args }, callback, options = queryOptions('cache_then_s
480
569
  error,
481
570
  }));
482
571
  }
483
- const shouldAbort = isCachable(local) && isFresh(local, options.lifeSpan);
572
+ const shouldAbort = isCachable(local) && isFresh(local, lifeSpan);
484
573
  callback === null || callback === void 0 ? void 0 : callback(createSnapshot(local, {
485
574
  origin: 'local',
486
575
  loading: !(isFetcher(func) && shouldAbort),
@@ -547,54 +636,6 @@ function createSnapshot(data, options) {
547
636
  return Object.assign(Object.assign({}, options), { data });
548
637
  }
549
638
 
550
- // Note:
551
- // this file should contain a suite of filtering utilities to help the
552
- // local version of the query functions.
553
- /**
554
- * Filter a given collection with strict equality against a param
555
- *
556
- * @param collection the collection to filter
557
- * @param key the key of the collection's items to challenge
558
- * @param value the expected value
559
- * @returns a filtered collection with items only matching the criteria
560
- *
561
- * @hidden
562
- */
563
- const filterByPropEquality = (collection, key, value) => (value !== undefined ? collection.filter(item => item[key] === value) : collection);
564
- const filterByPropInclusion = (collection, key, value) => (value !== undefined ? collection.filter(item => value.includes(item[key])) : collection);
565
-
566
- // Note:
567
- // this file should contain a suite of sorting utilities to help the
568
- // local version of the query functions.
569
- /**
570
- * Alphabetic sorting of objects having a displayName
571
- */
572
- const sortByDisplayName = ({ displayName: a }, { displayName: b }) => {
573
- if (a === b)
574
- return 0;
575
- return a < b ? -1 : 1;
576
- };
577
- /**
578
- * Sorting a collection by their apparition order (oldest first)
579
- */
580
- const sortByChannelSegment = ({ channelSegment: a }, { channelSegment: b }) => a - b;
581
- /**
582
- * Sorting a collection by their apparition order (oldest first)
583
- */
584
- const sortBySegmentNumber = ({ segmentNumber: a }, { segmentNumber: b }) => a - b;
585
- /**
586
- * Sorting a collection by its oldest items
587
- */
588
- const sortByFirstCreated = ({ createdAt: a }, { createdAt: b }) => new Date(a).valueOf() - new Date(b).valueOf();
589
- /**
590
- * Sorting a collection by its newest items
591
- */
592
- const sortByLastCreated = ({ createdAt: a }, { createdAt: b }) => new Date(b).valueOf() - new Date(a).valueOf();
593
- /**
594
- * Sorting a collection by the items with most recent activity
595
- */
596
- const sortByLastActivity = ({ lastActivity: a }, { lastActivity: b }) => new Date(b).valueOf() - new Date(a).valueOf();
597
-
598
639
  /* eslint-disable max-classes-per-file */
599
640
  /**
600
641
  * Generic ASC error
@@ -684,265 +725,70 @@ const setActiveClient = (client) => {
684
725
  activeClient = client;
685
726
  };
686
727
 
687
- /* eslint-disable @typescript-eslint/ban-types */
688
- let tasks = [];
689
- let timer;
690
728
  /**
691
- * Add a function to run just before the next tick
729
+ * ```js
730
+ * import { enableCache } from '@amityco/ts-sdk'
731
+ * enableCache()
732
+ * ```
692
733
  *
693
- * @param task function to schedule for later execution
734
+ * Adds a new {@link Amity.Cache} object to
735
+ * an {@link Amity.Client} instance
736
+ *
737
+ * @param prevState a previous state of cache instance (useful for SSR)
738
+ * @param persistIf a function to determine if an entry inserted in cache
739
+ * is destined to be also saved in the persistent storage when
740
+ * calling {@link backupCache}
741
+ *
742
+ * @category Cache API
694
743
  */
695
- const scheduleTask = (task) => {
696
- clearTimeout(timer);
697
- tasks.push(task);
698
- timer = setTimeout(() => {
699
- tasks.forEach(fn => fn());
700
- tasks = [];
701
- }, 0);
744
+ const enableCache = (prevState = {}, persistIf) => {
745
+ const client = getActiveClient();
746
+ if (client.cache)
747
+ return;
748
+ client.log('cache/api/enableCache');
749
+ client.cache = { data: prevState, persistIf };
702
750
  };
703
751
 
704
- /* eslint-disable @typescript-eslint/no-unused-vars */
705
- // need to sync up the list
706
- const WS_EVENTS = [
707
- 'disconnected',
708
- 'error',
709
- 'connect_error',
710
- 'reconnect_error',
711
- 'reconnect_failed',
712
- 'v3.channel.didCreate',
713
- 'v3.channel.didUpdate',
714
- 'v3.channel.didDelete',
715
- 'v3.channel.didJoin',
716
- 'v3.channel.didLeave',
717
- 'v3.channel.didAddUsers',
718
- 'v3.channel.didRemoveUsers',
719
- 'v3.channel.didBan',
720
- 'v3.channel.didUnban',
721
- 'v3.message.didCreate',
722
- 'v3.message.didUpdate',
723
- 'v3.message.didDelete',
724
- ];
725
- const MQTT_EVENTS = [
726
- 'connect',
727
- 'message',
728
- 'disconnect',
729
- 'error',
730
- 'close',
731
- 'end',
732
- 'reconnect',
733
- ];
734
- /** @hidden */
735
- const createEventEmitter = () => {
736
- return mitt__default["default"]();
737
- };
738
752
  /**
739
- * Wraps the websocket events into the client's event emitter for
740
- * abstraction of transport.
753
+ * ```js
754
+ * import { disableCache } from '@amityco/ts-sdk'
755
+ * disableCache()
756
+ * ```
741
757
  *
742
- * @param ws A websocket connection to listen from
743
- * @param emitter An event emitter to wire the events to
758
+ * Wipes the existing {@link Amity.Cache} object attached to
759
+ * an {@link Amity.Client} instance
744
760
  *
745
- * @category Transport
746
- * @hidden
761
+ * @category Cache API
747
762
  */
748
- const proxyWebsocketEvents = (ws, emitter) => {
749
- WS_EVENTS.forEach(event => {
750
- ws.on(event, (param) => emitter.emit(event, param));
751
- });
752
- };
753
- const proxyMqttEvents = (mqttClient, emitter) => {
754
- MQTT_EVENTS.forEach(event => {
755
- mqttClient.on(event, (...params) => emitter.emit(event, params.length === 1 ? params[0] : params));
756
- });
757
- // @ts-ignore
758
- mqttClient.on('message', (topic, payload) => {
759
- const message = JSON.parse(payload.toString());
760
- emitter.emit(message.eventType, message.data);
761
- });
762
- };
763
+ const disableCache = () => {
764
+ const client = getActiveClient();
765
+ if (!client.cache)
766
+ return;
767
+ client.log('cache/api/disableCache');
768
+ // we do this so that testing if cache is enabled
769
+ // is only `if (client.cache)
770
+ delete client.cache;
771
+ };
772
+
763
773
  /**
764
- * Standardize the subscription of SSE through web sockets
774
+ * ```js
775
+ * import { restoreCache } from '@amityco/ts-sdk'
776
+ * const success = await restoreCache()
777
+ * ```
765
778
  *
766
- * @param client The current client for which to subscribe the event to
767
- * @param namespace A unique name for the logger
768
- * @param event The websocket event name
769
- * @param fn A wrapper for the callback.
770
- * @returns A dispose function to unsubscribe to the event
779
+ * Reads a previously saved {@link Amity.Cache} from a persistent storage,
780
+ * and inserts it into the current {@link Amity.Cache} instance.
771
781
  *
772
- * @category Transport
773
- * @hidden
774
- */
775
- const createEventSubscriber = (client, namespace, event, fn) => {
776
- const { log, emitter } = client;
777
- const timestamp = Date.now();
778
- log(`${namespace}(tmpid: ${timestamp}) > listen`);
779
- const handler = (...payload) => {
780
- log(`${namespace}(tmpid: ${timestamp}) > trigger`, payload);
781
- fn(...payload);
782
- };
783
- emitter.on(event, handler);
784
- return () => {
785
- log(`${namespace}(tmpid: ${timestamp}) > dispose`);
786
- emitter.off(event, handler);
787
- };
788
- };
789
- /**
790
- * Wrapper around dispatch event
791
- *
792
- * @hidden
793
- */
794
- const fireEvent = (event, payload) => {
795
- const { emitter } = getActiveClient();
796
- scheduleTask(() => {
797
- emitter.emit(event, payload);
798
- });
799
- };
800
-
801
- let activeUser = null;
802
- /**
803
- * for internal use
804
- */
805
- const getActiveUser = () => {
806
- if (!activeUser) {
807
- throw new ASCError('Connect client first', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
808
- }
809
- return activeUser;
810
- };
811
- const setActiveUser = (user) => {
812
- activeUser = {
813
- _id: user._id,
814
- userId: user.userId,
815
- path: user.path,
816
- };
817
- };
818
-
819
- exports.SubscriptionLevels = void 0;
820
- (function (SubscriptionLevels) {
821
- SubscriptionLevels["COMMUNITY"] = "community";
822
- SubscriptionLevels["POST"] = "post";
823
- SubscriptionLevels["COMMENT"] = "comment";
824
- SubscriptionLevels["POST_AND_COMMENT"] = "post_and_comment";
825
- SubscriptionLevels["USER"] = "user";
826
- })(exports.SubscriptionLevels || (exports.SubscriptionLevels = {}));
827
- const getCommunityUserTopic = (path, level) => {
828
- switch (level) {
829
- case 'post':
830
- return `${path}/post/+`;
831
- case 'comment':
832
- return `${path}/post/+/comment/+`;
833
- case 'post_and_comment':
834
- return `${path}/post/#`;
835
- default:
836
- return path;
837
- }
838
- };
839
- const getCommunityTopic = ({ path }, level = exports.SubscriptionLevels.COMMUNITY) => getCommunityUserTopic(path, level);
840
- const getUserTopic = ({ path }, level = exports.SubscriptionLevels.USER) => getCommunityUserTopic(level === exports.SubscriptionLevels.USER ? path : path.replace(/^(\w*)/, '$1/social'), level);
841
- const getPostTopic = ({ path }, level = exports.SubscriptionLevels.POST) => {
842
- switch (level) {
843
- case 'comment':
844
- return `${path}/comment/+`;
845
- default:
846
- return path;
847
- }
848
- };
849
- const getCommentTopic = ({ path }) => {
850
- return path;
851
- };
852
- const getMyFollowersTopic = () => {
853
- const user = getActiveUser();
854
- const [networkId] = user.path.split('/user/');
855
- return `${networkId}/membership/${user._id}/+/+`;
856
- };
857
- const getMyFollowingsTopic = () => {
858
- const user = getActiveUser();
859
- const [networkId] = user.path.split('/user/');
860
- return `${networkId}/membership/+/${user._id}/+`;
861
- };
862
- /** @hidden */
863
- const getNetworkTopic = () => {
864
- const user = getActiveUser();
865
- const [networkId] = user.path.split('/user/');
866
- return networkId;
867
- };
868
- let mqttAccessToken;
869
- let mqttUserId;
870
- function subscribeTopic(topic, callback) {
871
- const { mqtt, emitter, accessToken } = getActiveClient();
872
- const user = getActiveUser();
873
- if (mqttAccessToken !== accessToken || mqttUserId !== user._id) {
874
- mqttAccessToken = accessToken;
875
- mqttUserId = user._id;
876
- mqtt.connect({ accessToken: mqttAccessToken, userId: mqttUserId });
877
- proxyMqttEvents(mqtt, emitter);
878
- }
879
- return mqtt.subscribe(topic, callback);
880
- }
881
-
882
- /**
883
- * ```js
884
- * import { enableCache } from '@amityco/ts-sdk'
885
- * enableCache()
886
- * ```
887
- *
888
- * Adds a new {@link Amity.Cache} object to
889
- * an {@link Amity.Client} instance
890
- *
891
- * @param prevState a previous state of cache instance (useful for SSR)
892
- * @param persistIf a function to determine if an entry inserted in cache
893
- * is destined to be also saved in the persistent storage when
894
- * calling {@link backupCache}
895
- *
896
- * @category Cache API
897
- */
898
- const enableCache = (prevState = {}, persistIf) => {
899
- const client = getActiveClient();
900
- if (client.cache)
901
- return;
902
- client.log('cache/api/enableCache');
903
- client.cache = { data: prevState, persistIf };
904
- };
905
-
906
- /**
907
- * ```js
908
- * import { disableCache } from '@amityco/ts-sdk'
909
- * disableCache()
910
- * ```
911
- *
912
- * Wipes the existing {@link Amity.Cache} object attached to
913
- * an {@link Amity.Client} instance
914
- *
915
- * @category Cache API
916
- */
917
- const disableCache = () => {
918
- const client = getActiveClient();
919
- if (!client.cache)
920
- return;
921
- client.log('cache/api/disableCache');
922
- // we do this so that testing if cache is enabled
923
- // is only `if (client.cache)
924
- delete client.cache;
925
- };
926
-
927
- /**
928
- * ```js
929
- * import { restoreCache } from '@amityco/ts-sdk'
930
- * const success = await restoreCache()
931
- * ```
932
- *
933
- * Reads a previously saved {@link Amity.Cache} from a persistent storage,
934
- * and inserts it into the current {@link Amity.Cache} instance.
935
- *
936
- * The strategy for persistent storage will depend on the runtime,
937
- * which is supported by @react-native-async-storage/async-storage.
938
- *
939
- * The current userId will be appended to the given storageKey to ensures
940
- * the cached data concerns only the current user.
941
- *
942
- * @param storageKey the name of the persistent storage
943
- * @returns a success boolean if the cache was dumped to persistent storage
944
- *
945
- * @category Cache API
782
+ * The strategy for persistent storage will depend on the runtime,
783
+ * which is supported by @react-native-async-storage/async-storage.
784
+ *
785
+ * The current userId will be appended to the given storageKey to ensures
786
+ * the cached data concerns only the current user.
787
+ *
788
+ * @param storageKey the name of the persistent storage
789
+ * @returns a success boolean if the cache was dumped to persistent storage
790
+ *
791
+ * @category Cache API
946
792
  */
947
793
  const restoreCache = async (storageKey = 'amitySdk') => {
948
794
  var _a;
@@ -1030,62 +876,6 @@ const wipeCache = async (storageKey = 'amitySdk') => {
1030
876
  return true;
1031
877
  };
1032
878
 
1033
- /**
1034
- * Shallow-clones an object and sort its keys
1035
- *
1036
- * @param source a plain object to clone
1037
- * @returns a clone of source, with keys sorted with default javascript sorting
1038
- *
1039
- * @category Cache
1040
- * @hidden
1041
- */
1042
- const normalize = (source) => Object.keys(source)
1043
- .sort()
1044
- .reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: source[key] })), {});
1045
- /**
1046
- * Encodes a given {@link Amity.CacheKey} to a plain string
1047
- *
1048
- * @param key the key to encode
1049
- * @returns an encoded string
1050
- *
1051
- * @category Cache
1052
- * @hidden
1053
- */
1054
- const encodeKey = (key) => JSON.stringify(key, (_, val) => (typeof val === 'object' ? normalize(val) : val));
1055
- /**
1056
- * Decodes a string back into a {@link Amity.CacheKey}
1057
-
1058
- *
1059
- * @param key the string key to decode
1060
- * @returns a plain Amity.CacheKey object.
1061
- *
1062
- * @category Cache
1063
- * @hidden
1064
- */
1065
- const decodeKey = (key) => JSON.parse(key);
1066
- /**
1067
- * Performs a recursive partial deep equal check on two objects.
1068
- *
1069
- * @param predicate the reference object containing the partial information
1070
- * @param candidate the object to check against
1071
- * @returns true if the candidate contains all the values of the predicate
1072
- *
1073
- * @category Cache
1074
- */
1075
- const partialMatch = (predicate, candidate) => {
1076
- if (predicate === candidate)
1077
- return true;
1078
- // if one or the other is nullish, there can't be equality
1079
- if (!predicate || !candidate)
1080
- return false;
1081
- // we only perform recursive check on objects
1082
- if (typeof predicate !== 'object') {
1083
- return false;
1084
- }
1085
- // recursively call for partial match based on the predicate
1086
- return Object.keys(predicate).every(key => partialMatch(predicate[key], candidate[key]));
1087
- };
1088
-
1089
879
  /**
1090
880
  * ```js
1091
881
  * import { queryCache } from '@amityco/ts-sdk'
@@ -1182,86 +972,368 @@ const pushToCache = (key, data, options = { cachedAt: Date.now() }) => {
1182
972
  *
1183
973
  * Merges a new {@link Amity.Cache} object to an {@link Amity.Client} instance
1184
974
  *
1185
- * @param key the key matching the object to retrieve from cache
1186
- * @param mutation either a plain object to shallow merge, or a function.
1187
- * @returns a success boolean if the object was updated
975
+ * @param key the key matching the object to retrieve from cache
976
+ * @param mutation either a plain object to shallow merge, or a function.
977
+ * @returns a success boolean if the object was updated
978
+ *
979
+ * @category Cache API
980
+ */
981
+ const mergeInCache = (key, mutation, options) => {
982
+ const { log, cache } = getActiveClient();
983
+ if (!cache)
984
+ return false;
985
+ log('cache/api/mergeInCache', { key, mutation });
986
+ const oldVal = pullFromCache(key);
987
+ if (!oldVal)
988
+ return false;
989
+ const newVal = typeof mutation === 'function' ? mutation(oldVal.data) : Object.assign(Object.assign({}, oldVal.data), mutation);
990
+ pushToCache(key, newVal, options);
991
+ return true;
992
+ };
993
+
994
+ /**
995
+ * ```js
996
+ * import { upsertInCache } from '@amityco/ts-sdk'
997
+ * upsertInCache<Amity.User>(["user", "foobar"], user)
998
+ * ```
999
+ *
1000
+ * Insert or update any provided value as {@link Amity.CacheEntry} for
1001
+ * the matching {@link Amity.CacheKey}
1002
+ *
1003
+ * @param key the key to save the object to
1004
+ * @param data the object to save
1005
+ * @param options customisation object around cache behavior (default gives a 2mn lifespan)
1006
+ * @returns a success boolean if the object was saved in cache
1007
+ *
1008
+ * @category Cache API
1009
+ * @hidden
1010
+ */
1011
+ const upsertInCache = (key, data, options = { cachedAt: Date.now() }) => {
1012
+ const { log, cache } = getActiveClient();
1013
+ if (!cache)
1014
+ return false;
1015
+ log('cache/api/upsertInCache', { key, data, options });
1016
+ const cached = pullFromCache(key);
1017
+ return cached ? mergeInCache(key, data, options) : pushToCache(key, data, options);
1018
+ };
1019
+
1020
+ /**
1021
+ * ```js
1022
+ * import { dropFromCache } from '@amityco/ts-sdk'
1023
+ * const success = dropFromCache(['user', 'foobar'])
1024
+ * ```
1025
+ *
1026
+ * Removes an existing {@link Amity.CacheEntry} from the {@link Amity.Client}'s
1027
+ * {@link Amity.Cache} from a given {@link Amity.CacheKey}
1028
+ *
1029
+ * @param key The key of the object to delete
1030
+ * @param exact If false, the function will delete all keys satisfying the given key
1031
+ * @returns A success boolean if the object was deleted
1032
+ *
1033
+ * @category Cache API
1034
+ */
1035
+ const dropFromCache = (key, exact = false) => {
1036
+ const { log, cache } = getActiveClient();
1037
+ if (!cache)
1038
+ return false;
1039
+ log('cache/api/dropFromCache', { key, exact });
1040
+ if (!exact) {
1041
+ return Object.keys(cache.data)
1042
+ .map(stringKey => decodeKey(stringKey))
1043
+ .filter(candidate => partialMatch(key, candidate))
1044
+ .map(filteredKey => dropFromCache(filteredKey, true))
1045
+ .every(returned => returned);
1046
+ }
1047
+ const encodedKey = encodeKey(key);
1048
+ if (encodedKey in cache.data) {
1049
+ delete cache.data[encodedKey];
1050
+ return true;
1051
+ }
1052
+ return false;
1053
+ };
1054
+
1055
+ // Note:
1056
+ // this file should contain a suite of filtering utilities to help the
1057
+ // local version of the query functions.
1058
+ /**
1059
+ * Filter a given collection with strict equality against a param
1060
+ *
1061
+ * @param collection the collection to filter
1062
+ * @param key the key of the collection's items to challenge
1063
+ * @param value the expected value
1064
+ * @returns a filtered collection with items only matching the criteria
1065
+ *
1066
+ * @hidden
1067
+ */
1068
+ const filterByPropEquality = (collection, key, value) => (value !== undefined ? collection.filter(item => item[key] === value) : collection);
1069
+ const filterByPropInclusion = (collection, key, value) => (value !== undefined ? collection.filter(item => value.includes(item[key])) : collection);
1070
+ /**
1071
+ * Filter a channel collection by membership of the userId
1072
+ *
1073
+ * @param collection the channel collection to filter
1074
+ * @param membership the membership to be filtered by
1075
+ * @param userId user id to be filtered by
1076
+ * @returns a filtered collection with items only matching the criteria
1077
+ *
1078
+ * @hidden
1079
+ */
1080
+ const filterByChannelMembership = (collection, membership, userId) => {
1081
+ if (membership === 'all') {
1082
+ return collection;
1083
+ }
1084
+ return collection.filter(c => {
1085
+ var _a;
1086
+ // get resolver for the channel by user
1087
+ const channelUserCacheKey = getResolver('channelUsers')({
1088
+ channelId: c.channelId,
1089
+ userId,
1090
+ });
1091
+ const channelUser = (_a = pullFromCache([
1092
+ 'channelUsers',
1093
+ 'get',
1094
+ channelUserCacheKey,
1095
+ ])) === null || _a === void 0 ? void 0 : _a.data;
1096
+ // if channel user is defined for user, user is a member
1097
+ if (membership === 'member' && channelUser) {
1098
+ return true;
1099
+ }
1100
+ // if channel user by user id not found, user is not a member of that
1101
+ // channel
1102
+ if (membership === 'notMember' && !channelUser) {
1103
+ return true;
1104
+ }
1105
+ return false;
1106
+ });
1107
+ };
1108
+
1109
+ // Note:
1110
+ // this file should contain a suite of sorting utilities to help the
1111
+ // local version of the query functions.
1112
+ /**
1113
+ * Alphabetic sorting of objects having a displayName
1114
+ */
1115
+ const sortByDisplayName = ({ displayName: a }, { displayName: b }) => {
1116
+ if (a === b)
1117
+ return 0;
1118
+ return a < b ? -1 : 1;
1119
+ };
1120
+ /**
1121
+ * Sorting a collection by their apparition order (oldest first)
1122
+ */
1123
+ const sortByChannelSegment = ({ channelSegment: a }, { channelSegment: b }) => a - b;
1124
+ /**
1125
+ * Sorting a collection by their apparition order (oldest first)
1126
+ */
1127
+ const sortBySegmentNumber = ({ segmentNumber: a }, { segmentNumber: b }) => a - b;
1128
+ /**
1129
+ * Sorting a collection by its oldest items
1130
+ */
1131
+ const sortByFirstCreated = ({ createdAt: a }, { createdAt: b }) => new Date(a).valueOf() - new Date(b).valueOf();
1132
+ /**
1133
+ * Sorting a collection by its newest items
1134
+ */
1135
+ const sortByLastCreated = ({ createdAt: a }, { createdAt: b }) => new Date(b).valueOf() - new Date(a).valueOf();
1136
+ /**
1137
+ * Sorting a collection by the items with most recent activity
1138
+ */
1139
+ const sortByLastActivity = ({ lastActivity: a }, { lastActivity: b }) => new Date(b).valueOf() - new Date(a).valueOf();
1140
+
1141
+ /* eslint-disable @typescript-eslint/ban-types */
1142
+ let tasks = [];
1143
+ let timer;
1144
+ /**
1145
+ * Add a function to run just before the next tick
1146
+ *
1147
+ * @param task function to schedule for later execution
1148
+ */
1149
+ const scheduleTask = (task) => {
1150
+ clearTimeout(timer);
1151
+ tasks.push(task);
1152
+ timer = setTimeout(() => {
1153
+ tasks.forEach(fn => fn());
1154
+ tasks = [];
1155
+ }, 0);
1156
+ };
1157
+
1158
+ /* eslint-disable @typescript-eslint/no-unused-vars */
1159
+ // need to sync up the list
1160
+ const WS_EVENTS = [
1161
+ 'disconnected',
1162
+ 'error',
1163
+ 'connect_error',
1164
+ 'reconnect_error',
1165
+ 'reconnect_failed',
1166
+ 'v3.channel.didCreate',
1167
+ 'v3.channel.didUpdate',
1168
+ 'v3.channel.didDelete',
1169
+ 'v3.channel.didJoin',
1170
+ 'v3.channel.didLeave',
1171
+ 'v3.channel.didAddUsers',
1172
+ 'v3.channel.didRemoveUsers',
1173
+ 'v3.channel.didBan',
1174
+ 'v3.channel.didUnban',
1175
+ 'v3.message.didFetch',
1176
+ 'v3.message.didCreate',
1177
+ 'v3.message.didUpdate',
1178
+ 'v3.message.didDelete',
1179
+ ];
1180
+ const MQTT_EVENTS = [
1181
+ 'connect',
1182
+ 'message',
1183
+ 'disconnect',
1184
+ 'error',
1185
+ 'close',
1186
+ 'end',
1187
+ 'reconnect',
1188
+ ];
1189
+ /** @hidden */
1190
+ const createEventEmitter = () => {
1191
+ return mitt__default["default"]();
1192
+ };
1193
+ /**
1194
+ * Wraps the websocket events into the client's event emitter for
1195
+ * abstraction of transport.
1196
+ *
1197
+ * @param ws A websocket connection to listen from
1198
+ * @param emitter An event emitter to wire the events to
1199
+ *
1200
+ * @category Transport
1201
+ * @hidden
1202
+ */
1203
+ const proxyWebsocketEvents = (ws, emitter) => {
1204
+ WS_EVENTS.forEach(event => {
1205
+ ws.on(event, (param) => emitter.emit(event, param));
1206
+ });
1207
+ };
1208
+ const proxyMqttEvents = (mqttClient, emitter) => {
1209
+ MQTT_EVENTS.forEach(event => {
1210
+ mqttClient.on(event, (...params) => emitter.emit(event, params.length === 1 ? params[0] : params));
1211
+ });
1212
+ // @ts-ignore
1213
+ mqttClient.on('message', (topic, payload) => {
1214
+ const message = JSON.parse(payload.toString());
1215
+ emitter.emit(message.eventType, message.data);
1216
+ });
1217
+ };
1218
+ /**
1219
+ * Standardize the subscription of SSE through web sockets
1220
+ *
1221
+ * @param client The current client for which to subscribe the event to
1222
+ * @param namespace A unique name for the logger
1223
+ * @param event The websocket event name
1224
+ * @param fn A wrapper for the callback.
1225
+ * @returns A dispose function to unsubscribe to the event
1188
1226
  *
1189
- * @category Cache API
1227
+ * @category Transport
1228
+ * @hidden
1190
1229
  */
1191
- const mergeInCache = (key, mutation, options) => {
1192
- const { log, cache } = getActiveClient();
1193
- if (!cache)
1194
- return false;
1195
- log('cache/api/mergeInCache', { key, mutation });
1196
- const oldVal = pullFromCache(key);
1197
- if (!oldVal)
1198
- return false;
1199
- const newVal = typeof mutation === 'function' ? mutation(oldVal.data) : Object.assign(Object.assign({}, oldVal.data), mutation);
1200
- pushToCache(key, newVal, options);
1201
- return true;
1202
- };
1203
-
1230
+ const createEventSubscriber = (client, namespace, event, fn) => {
1231
+ const { log, emitter } = client;
1232
+ const timestamp = Date.now();
1233
+ log(`${namespace}(tmpid: ${timestamp}) > listen`);
1234
+ const handler = (...payload) => {
1235
+ log(`${namespace}(tmpid: ${timestamp}) > trigger`, payload);
1236
+ fn(...payload);
1237
+ };
1238
+ emitter.on(event, handler);
1239
+ return () => {
1240
+ log(`${namespace}(tmpid: ${timestamp}) > dispose`);
1241
+ emitter.off(event, handler);
1242
+ };
1243
+ };
1204
1244
  /**
1205
- * ```js
1206
- * import { upsertInCache } from '@amityco/ts-sdk'
1207
- * upsertInCache<Amity.User>(["user", "foobar"], user)
1208
- * ```
1209
- *
1210
- * Insert or update any provided value as {@link Amity.CacheEntry} for
1211
- * the matching {@link Amity.CacheKey}
1212
- *
1213
- * @param key the key to save the object to
1214
- * @param data the object to save
1215
- * @param options customisation object around cache behavior (default gives a 2mn lifespan)
1216
- * @returns a success boolean if the object was saved in cache
1245
+ * Wrapper around dispatch event
1217
1246
  *
1218
- * @category Cache API
1219
1247
  * @hidden
1220
1248
  */
1221
- const upsertInCache = (key, data, options = { cachedAt: Date.now() }) => {
1222
- const { log, cache } = getActiveClient();
1223
- if (!cache)
1224
- return false;
1225
- log('cache/api/upsertInCache', { key, data, options });
1226
- const cached = pullFromCache(key);
1227
- return cached ? mergeInCache(key, data, options) : pushToCache(key, data, options);
1249
+ const fireEvent = (event, payload) => {
1250
+ const { emitter } = getActiveClient();
1251
+ scheduleTask(() => {
1252
+ emitter.emit(event, payload);
1253
+ });
1228
1254
  };
1229
1255
 
1256
+ let activeUser = null;
1230
1257
  /**
1231
- * ```js
1232
- * import { dropFromCache } from '@amityco/ts-sdk'
1233
- * const success = dropFromCache(['user', 'foobar'])
1234
- * ```
1235
- *
1236
- * Removes an existing {@link Amity.CacheEntry} from the {@link Amity.Client}'s
1237
- * {@link Amity.Cache} from a given {@link Amity.CacheKey}
1238
- *
1239
- * @param key The key of the object to delete
1240
- * @param exact If false, the function will delete all keys satisfying the given key
1241
- * @returns A success boolean if the object was deleted
1242
- *
1243
- * @category Cache API
1258
+ * for internal use
1244
1259
  */
1245
- const dropFromCache = (key, exact = false) => {
1246
- const { log, cache } = getActiveClient();
1247
- if (!cache)
1248
- return false;
1249
- log('cache/api/dropFromCache', { key, exact });
1250
- if (!exact) {
1251
- return Object.keys(cache.data)
1252
- .map(stringKey => decodeKey(stringKey))
1253
- .filter(candidate => partialMatch(key, candidate))
1254
- .map(filteredKey => dropFromCache(filteredKey, true))
1255
- .every(returned => returned);
1256
- }
1257
- const encodedKey = encodeKey(key);
1258
- if (encodedKey in cache.data) {
1259
- delete cache.data[encodedKey];
1260
- return true;
1260
+ const getActiveUser = () => {
1261
+ if (!activeUser) {
1262
+ throw new ASCError('Connect client first', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
1261
1263
  }
1262
- return false;
1264
+ return activeUser;
1265
+ };
1266
+ const setActiveUser = (user) => {
1267
+ activeUser = {
1268
+ _id: user._id,
1269
+ userId: user.userId,
1270
+ path: user.path,
1271
+ };
1263
1272
  };
1264
1273
 
1274
+ exports.SubscriptionLevels = void 0;
1275
+ (function (SubscriptionLevels) {
1276
+ SubscriptionLevels["COMMUNITY"] = "community";
1277
+ SubscriptionLevels["POST"] = "post";
1278
+ SubscriptionLevels["COMMENT"] = "comment";
1279
+ SubscriptionLevels["POST_AND_COMMENT"] = "post_and_comment";
1280
+ SubscriptionLevels["USER"] = "user";
1281
+ })(exports.SubscriptionLevels || (exports.SubscriptionLevels = {}));
1282
+ const getCommunityUserTopic = (path, level) => {
1283
+ switch (level) {
1284
+ case 'post':
1285
+ return `${path}/post/+`;
1286
+ case 'comment':
1287
+ return `${path}/post/+/comment/+`;
1288
+ case 'post_and_comment':
1289
+ return `${path}/post/#`;
1290
+ default:
1291
+ return path;
1292
+ }
1293
+ };
1294
+ const getCommunityTopic = ({ path }, level = exports.SubscriptionLevels.COMMUNITY) => getCommunityUserTopic(path, level);
1295
+ const getUserTopic = ({ path }, level = exports.SubscriptionLevels.USER) => getCommunityUserTopic(level === exports.SubscriptionLevels.USER ? path : path.replace(/^(\w*)/, '$1/social'), level);
1296
+ const getPostTopic = ({ path }, level = exports.SubscriptionLevels.POST) => {
1297
+ switch (level) {
1298
+ case 'comment':
1299
+ return `${path}/comment/+`;
1300
+ default:
1301
+ return path;
1302
+ }
1303
+ };
1304
+ const getCommentTopic = ({ path }) => {
1305
+ return path;
1306
+ };
1307
+ const getMyFollowersTopic = () => {
1308
+ const user = getActiveUser();
1309
+ const [networkId] = user.path.split('/user/');
1310
+ return `${networkId}/membership/${user._id}/+/+`;
1311
+ };
1312
+ const getMyFollowingsTopic = () => {
1313
+ const user = getActiveUser();
1314
+ const [networkId] = user.path.split('/user/');
1315
+ return `${networkId}/membership/+/${user._id}/+`;
1316
+ };
1317
+ /** @hidden */
1318
+ const getNetworkTopic = () => {
1319
+ const user = getActiveUser();
1320
+ const [networkId] = user.path.split('/user/');
1321
+ return networkId;
1322
+ };
1323
+ let mqttAccessToken;
1324
+ let mqttUserId;
1325
+ function subscribeTopic(topic, callback) {
1326
+ const { mqtt, emitter, accessToken } = getActiveClient();
1327
+ const user = getActiveUser();
1328
+ if (mqttAccessToken !== accessToken || mqttUserId !== user._id) {
1329
+ mqttAccessToken = accessToken;
1330
+ mqttUserId = user._id;
1331
+ mqtt.connect({ accessToken: mqttAccessToken, userId: mqttUserId });
1332
+ proxyMqttEvents(mqtt, emitter);
1333
+ }
1334
+ return mqtt.subscribe(topic, callback);
1335
+ }
1336
+
1265
1337
  /**
1266
1338
  * Creates a pre-configured logger instance
1267
1339
  *
@@ -20578,6 +20650,61 @@ const isConnected = () => {
20578
20650
  client.ws.connected);
20579
20651
  };
20580
20652
 
20653
+ /**
20654
+ * ```js
20655
+ * import { isInTombstone } from '@amityco/ts-sdk'
20656
+ * const user = isInTombstone(["message", "messageId"])
20657
+ * ```
20658
+ *
20659
+ * Checks if the {@link Amity.TombstoneCacheOptions} exists
20660
+ * in cache and it's not expired means it's in tombstone
20661
+ * and we throw an Error
20662
+ *
20663
+ * @param model the model to check
20664
+ * @param modelId the object id to check
20665
+ * @returns the matching cache entry, or undefined.
20666
+ *
20667
+ * @category Cache API
20668
+ */
20669
+ const isInTombstone = (model, modelId) => {
20670
+ const { log, cache } = getActiveClient();
20671
+ const key = [model, CACHE_KEY_TOMBSTONE, modelId];
20672
+ if (!cache)
20673
+ return;
20674
+ log('cache/api/isInTombstone', key);
20675
+ const isInTombstone = pullFromCache(key);
20676
+ const { lifeSpan } = queryOptions('cache_then_server', CACHE_LIFESPAN_TOMBSTONE);
20677
+ if (isInTombstone && isFresh(isInTombstone.data, lifeSpan)) {
20678
+ throw new ASCApiError('Item not found!', 400400 /* Amity.ServerError.ITEM_NOT_FOUND */, "error" /* Amity.ErrorLevel.ERROR */);
20679
+ }
20680
+ };
20681
+
20682
+ /**
20683
+ * ```js
20684
+ * import { pushToTombstone } from '@amityco/ts-sdk'
20685
+ * pushToTombstone(["message", "messageId"], { cachedAt: Date.now() })
20686
+ * ```
20687
+ *
20688
+ * Removes an existing {@link Amity.CacheEntry} from the {@link Amity.Client}'s
20689
+ * {@link Amity.Cache} from a given {@link Amity.CacheKey}
20690
+ *
20691
+ * @param model the model to remove and push to Tombstone
20692
+ * @param modelId the related model id
20693
+ *
20694
+ * @category Cache API
20695
+ * @hidden
20696
+ */
20697
+ const pushToTombstone = (model, modelId) => {
20698
+ const { log, cache } = getActiveClient();
20699
+ const cacheKey = [model, CACHE_KEY_TOMBSTONE, modelId];
20700
+ const data = { cachedAt: Date.now() };
20701
+ if (!cache)
20702
+ return;
20703
+ log('cache/api/pushToTombstone', { cacheKey, data });
20704
+ dropFromCache([model, CACHE_KEY_GET, modelId], true);
20705
+ pushToCache(cacheKey, data);
20706
+ };
20707
+
20581
20708
  /**
20582
20709
  * ```js
20583
20710
  * import { getUser } from '@amityco/ts-sdk'
@@ -20592,15 +20719,30 @@ const isConnected = () => {
20592
20719
  * @category User API
20593
20720
  * @async
20594
20721
  */
20595
- const getUser = async (userId) => {
20722
+ const getUser = async (userId, isLive = false) => {
20596
20723
  const client = getActiveClient();
20597
20724
  client.log('user/getUser', userId);
20598
- // API-FIX: endpoint should not be /list, parameters should be querystring.
20599
- const { data } = await client.http.get(`/api/v3/users/${encodeURIComponent(userId)}`);
20725
+ if (!isLive) {
20726
+ console.log('getUser will be deprecated on 25th November 2022, please use liveUser instead.');
20727
+ }
20728
+ isInTombstone('user', userId);
20729
+ let data;
20730
+ try {
20731
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
20732
+ const response = await client.http.get(`/api/v3/users/${encodeURIComponent(userId)}`);
20733
+ data = response.data;
20734
+ }
20735
+ catch (error) {
20736
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
20737
+ pushToTombstone('user', userId);
20738
+ }
20739
+ throw error;
20740
+ }
20600
20741
  const cachedAt = client.cache && Date.now();
20601
20742
  if (client.cache)
20602
20743
  ingestInCache(data, { cachedAt });
20603
20744
  const { users } = data;
20745
+ fireEvent('user.fetched', data);
20604
20746
  return {
20605
20747
  data: users.find(user => user.userId === userId),
20606
20748
  cachedAt,
@@ -20650,6 +20792,7 @@ const getUsers = async (userIds) => {
20650
20792
  const cachedAt = client.cache && Date.now();
20651
20793
  if (client.cache)
20652
20794
  ingestInCache(data, { cachedAt });
20795
+ fireEvent('user.fetched', data);
20653
20796
  return {
20654
20797
  data: data.users,
20655
20798
  cachedAt,
@@ -20749,6 +20892,7 @@ const queryUsers = async (query = {}) => {
20749
20892
  const cacheKey = ['user', 'query', query];
20750
20893
  pushToCache(cacheKey, { users: users.map(getResolver('user')), paging });
20751
20894
  }
20895
+ fireEvent('user.fetched', data);
20752
20896
  const prevPage = toPage(paging.previous);
20753
20897
  const nextPage = toPage(paging.next);
20754
20898
  return { data: users, cachedAt, prevPage, nextPage };
@@ -20812,12 +20956,30 @@ const updateUser = async (userId, patch) => {
20812
20956
  if (client.cache)
20813
20957
  ingestInCache(data, { cachedAt });
20814
20958
  const { users } = data;
20959
+ fireEvent('user.updated', data);
20815
20960
  return {
20816
20961
  data: users.find(user => user.userId === userId),
20817
20962
  cachedAt,
20818
20963
  };
20819
20964
  };
20820
20965
 
20966
+ /**
20967
+ * ```js
20968
+ * import { onUserFetched } from '@amityco/ts-sdk'
20969
+ * const dispose = onUserFetched(user => {
20970
+ * // ...
20971
+ * })
20972
+ * ```
20973
+ *
20974
+ * Fired when a {@link Amity.User} has been fetched
20975
+ *
20976
+ * @param callback The function to call when the event was fired
20977
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
20978
+ *
20979
+ * @category User Events
20980
+ */
20981
+ const onUserFetched = (callback) => createUserEventSubscriber('user.fetched', callback);
20982
+
20821
20983
  /**
20822
20984
  * ```js
20823
20985
  * import { onUserUpdated } from '@amityco/ts-sdk'
@@ -20886,6 +21048,68 @@ const onUserUnflagged = (callback) => createUserEventSubscriber('user.unflagged'
20886
21048
  */
20887
21049
  const onUserFlagCleared = (callback) => createUserEventSubscriber('user.flagCleared', callback);
20888
21050
 
21051
+ const COLLECTION_DEFAULT_PAGINATION_LIMIT = 5;
21052
+ const COLLECTION_DEFAULT_CACHING_POLICY = 'cache_then_server';
21053
+ const ENABLE_CACHE_MESSAGE = 'For using Live Collection feature you need to enable Cache!';
21054
+ const LIVE_OBJECT_ENABLE_CACHE_MESSAGE = 'For using Live Object feature you need to enable Cache!';
21055
+ const UNSYNCED_OBJECT_CACHED_AT_MESSAGE = 'Observing unsynced object is not supported by Live Object.';
21056
+ const UNSYNCED_OBJECT_CACHED_AT_VALUE = -5;
21057
+
21058
+ /**
21059
+ * ```js
21060
+ * import { liveUser } from '@amityco/ts-sdk'
21061
+ *
21062
+ * let users = []
21063
+ * const unsub = liveUser(userId, response => merge(users, response.data))
21064
+ * ```
21065
+ *
21066
+ * Observe all mutation on a given {@link Amity.User}
21067
+ *
21068
+ * @param userId the ID of the user to observe
21069
+ * @param callback the function to call when new data are available
21070
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the users
21071
+ *
21072
+ * @category Message Live Object
21073
+ */
21074
+ const liveUser = (userId, callback) => {
21075
+ const { log, cache } = getActiveClient();
21076
+ let user;
21077
+ if (!cache) {
21078
+ console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
21079
+ }
21080
+ const timestamp = Date.now();
21081
+ log(`liveUser(tmpid: ${timestamp}) > listen`);
21082
+ const disposers = [];
21083
+ const dispatcher = (data) => {
21084
+ var _a;
21085
+ // we check updatedAt to see if the current snapshot is new so
21086
+ // we won't send old data back, only fresh new data
21087
+ if (user && ((_a = data.data) === null || _a === void 0 ? void 0 : _a.updatedAt) === (user === null || user === void 0 ? void 0 : user.updatedAt) && data.origin !== 'server')
21088
+ return;
21089
+ callback(data);
21090
+ user = data.data;
21091
+ };
21092
+ const realtimeRouter = (user, action) => {
21093
+ dispatcher({ loading: false, data: user, origin: 'event' });
21094
+ };
21095
+ const onFetch = () => {
21096
+ const query = createQuery(getUser, userId, true);
21097
+ runQuery(query, ({ loading, data, error, origin }) => {
21098
+ dispatcher({ loading, data, origin, error });
21099
+ if (error) {
21100
+ // Terminate observe functionality on error
21101
+ disposers.forEach(fn => fn());
21102
+ }
21103
+ });
21104
+ };
21105
+ disposers.push(onUserFetched(user => realtimeRouter(user)), onUserUpdated(user => realtimeRouter(user)), onUserDeleted(user => realtimeRouter(user)), onUserFlagged(user => realtimeRouter(user)), onUserUnflagged(user => realtimeRouter(user)), onUserFlagCleared(user => realtimeRouter(user)));
21106
+ onFetch();
21107
+ return () => {
21108
+ log(`liveUser(tmpid: ${timestamp}) > dispose`);
21109
+ disposers.forEach(fn => fn());
21110
+ };
21111
+ };
21112
+
20889
21113
  /**
20890
21114
  * ```js
20891
21115
  * import { observeUser } from '@amityco/ts-sdk'
@@ -20905,6 +21129,7 @@ const observeUser = (userId, callback) => {
20905
21129
  const { log } = getActiveClient();
20906
21130
  const timestamp = Date.now();
20907
21131
  log(`observeUser(tmpid: ${timestamp}) > listen`);
21132
+ console.log('observeUser will be deprecated on 25th November 2022, please use liveUser instead.');
20908
21133
  // wrapper function to make sure
20909
21134
  const router = (result, action) => {
20910
21135
  var _a, _b, _c;
@@ -21314,15 +21539,30 @@ const dispatchReactable = (referenceType, model) => {
21314
21539
  * @category Message API
21315
21540
  * @async
21316
21541
  */
21317
- const getMessage = async (messageId) => {
21542
+ const getMessage = async (messageId, isLive = false) => {
21318
21543
  const client = getActiveClient();
21319
21544
  client.log('message/getMessage', messageId);
21320
- // API-FIX: endpoint should not be /list, parameters should be querystring.
21321
- const { data } = await client.http.get(`/api/v3/messages/${encodeURIComponent(messageId)}`);
21545
+ if (!isLive) {
21546
+ console.log('getMessage will be deprecated on 15th November 2022, please use liveMessage instead.');
21547
+ }
21548
+ isInTombstone('message', messageId);
21549
+ let data;
21550
+ try {
21551
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
21552
+ const response = await client.http.get(`/api/v3/messages/${encodeURIComponent(messageId)}`);
21553
+ data = response.data;
21554
+ }
21555
+ catch (error) {
21556
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
21557
+ pushToTombstone('message', messageId);
21558
+ }
21559
+ throw error;
21560
+ }
21322
21561
  const cachedAt = client.cache && Date.now();
21323
21562
  if (client.cache)
21324
21563
  ingestInCache(data, { cachedAt });
21325
21564
  const { messages } = data;
21565
+ fireEvent('v3.message.didFetch', { messages });
21326
21566
  return {
21327
21567
  data: messages.find(message => message.messageId === messageId),
21328
21568
  cachedAt,
@@ -21379,8 +21619,10 @@ const getMessages = async (messageIds) => {
21379
21619
  const cachedAt = client.cache && Date.now();
21380
21620
  if (client.cache)
21381
21621
  ingestInCache(data, { cachedAt });
21622
+ const { messages } = data;
21623
+ fireEvent('v3.message.didFetch', { messages });
21382
21624
  return {
21383
- data: data.messages,
21625
+ data: messages,
21384
21626
  cachedAt,
21385
21627
  };
21386
21628
  };
@@ -21457,6 +21699,7 @@ const queryMessages = async (query) => {
21457
21699
  ];
21458
21700
  pushToCache(cacheKey, { messages: messages.map(getResolver('message')), paging });
21459
21701
  }
21702
+ fireEvent('v3.message.didFetch', { messages });
21460
21703
  const nextPage = toPage(paging.next);
21461
21704
  const prevPage = toPage(paging.previous);
21462
21705
  return { data: messages, cachedAt, prevPage, nextPage };
@@ -21522,8 +21765,8 @@ const createMessage = async (bundle) => {
21522
21765
  const cachedAt = client.cache && Date.now();
21523
21766
  if (client.cache)
21524
21767
  ingestInCache(data, { cachedAt });
21525
- // no need for event, fired by server
21526
21768
  const { messages } = data;
21769
+ fireEvent('v3.message.didCreate', { messages });
21527
21770
  return {
21528
21771
  data: messages[0],
21529
21772
  cachedAt,
@@ -21565,11 +21808,12 @@ createMessage.optimistically = (bundle) => {
21565
21808
  // as reused to update created and updated time, which should be the same
21566
21809
  const createdTime = new Date().toISOString();
21567
21810
  const message = Object.assign({ userId: client.userId, channelSegment: ((_b = channel === null || channel === void 0 ? void 0 : channel.data.messageCount) !== null && _b !== void 0 ? _b : 0) + 1, createdAt: createdTime, updatedAt: createdTime }, bundleWithMessageId);
21568
- pushToCache(['message', 'get', message.messageId], message, { cachedAt: -1 });
21811
+ const cachedAt = UNSYNCED_OBJECT_CACHED_AT_VALUE;
21812
+ pushToCache(['message', 'get', message.messageId], message, { cachedAt });
21569
21813
  fireEvent('v3.message.didCreate', { messages: [message] });
21570
21814
  return {
21815
+ cachedAt,
21571
21816
  data: message,
21572
- cachedAt: -1,
21573
21817
  };
21574
21818
  };
21575
21819
 
@@ -21598,6 +21842,7 @@ const updateMessage = async (messageId, patch) => {
21598
21842
  if (client.cache)
21599
21843
  ingestInCache(data, { cachedAt });
21600
21844
  const { messages } = data;
21845
+ fireEvent('v3.message.didUpdate', { messages });
21601
21846
  return {
21602
21847
  data: messages.find(message => message.messageId === messageId),
21603
21848
  cachedAt,
@@ -21657,7 +21902,7 @@ const deleteMessage = async (messageId) => {
21657
21902
  // API-FIX: This endpoint has not been implemented yet.
21658
21903
  await client.http.delete(`/api/v3/messages/${encodeURIComponent(messageId)}`);
21659
21904
  const deleted = await getMessage(messageId);
21660
- // no need for event, fired by server
21905
+ fireEvent('v3.message.didDelete', { messages: [deleted.data] });
21661
21906
  return deleted.data;
21662
21907
  };
21663
21908
  /**
@@ -21844,6 +22089,7 @@ getPosts.locally = (postIds) => {
21844
22089
  const getPost = async (postId) => {
21845
22090
  const client = getActiveClient();
21846
22091
  client.log('post/getPost', postId);
22092
+ isInTombstone('post', postId);
21847
22093
  let data;
21848
22094
  try {
21849
22095
  // API-FIX: endpoint should not be /list, parameters should be querystring.
@@ -21851,8 +22097,8 @@ const getPost = async (postId) => {
21851
22097
  data = response.data;
21852
22098
  }
21853
22099
  catch (error) {
21854
- if ((error === null || error === void 0 ? void 0 : error.code) === 400400 /* Amity.ServerError.ITEM_NOT_FOUND */) {
21855
- dropFromCache(['post', 'get', postId], true);
22100
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
22101
+ pushToTombstone('post', postId);
21856
22102
  }
21857
22103
  throw error;
21858
22104
  }
@@ -22632,7 +22878,7 @@ const deletePost = async (postId, permanent = false) => {
22632
22878
  fireEvent('post.deleted', { posts: [deleted] });
22633
22879
  if (permanent) {
22634
22880
  setTimeout(() => {
22635
- dropFromCache(['post', 'get', postId], true);
22881
+ pushToTombstone('post', postId);
22636
22882
  }, 0);
22637
22883
  }
22638
22884
  else {
@@ -23886,10 +24132,6 @@ const onReactorRemoved = (referenceType, referenceId, callback) => {
23886
24132
  return createEventSubscriber(client, 'comment.removeReaction', 'comment.removeReaction', filter);
23887
24133
  };
23888
24134
 
23889
- const COLLECTION_DEFAULT_PAGINATION_LIMIT = 5;
23890
- const COLLECTION_DEFAULT_CACHING_POLICY = 'cache_then_server';
23891
- const ENABLE_CACHE_MESSAGE = 'For using Live Collection feature you need to enable Cache!';
23892
-
23893
24135
  /**
23894
24136
  * ```js
23895
24137
  * import { liveReactions } from '@amityco/ts-sdk'
@@ -24166,9 +24408,24 @@ const queryChannels = async (query) => {
24166
24408
  * @category Channel API
24167
24409
  */
24168
24410
  queryChannels.locally = (query) => {
24411
+ var _a, _b;
24169
24412
  const client = getActiveClient();
24170
24413
  client.log('channel/queryChannels.locally', query);
24171
- // TODO
24414
+ const _c = query !== null && query !== void 0 ? query : {}, { page = { limit: 10 } } = _c, params = __rest(_c, ["page"]);
24415
+ const cacheKey = ['channel', 'query', Object.assign(Object.assign({}, params), { options: Object.assign({}, page) })];
24416
+ const { data, cachedAt } = (_a = pullFromCache(cacheKey)) !== null && _a !== void 0 ? _a : {};
24417
+ if (!(data === null || data === void 0 ? void 0 : data.channels.length))
24418
+ return;
24419
+ const channels = data.channels
24420
+ // ck -> cacheKey, abbrevated to avoid confusion from the above cache key
24421
+ .map(ck => pullFromCache(['channel', 'get', ck]))
24422
+ .filter(Boolean)
24423
+ .map(({ data }) => data);
24424
+ const prevPage = toPage(data === null || data === void 0 ? void 0 : data.paging.previous);
24425
+ const nextPage = toPage(data === null || data === void 0 ? void 0 : data.paging.next);
24426
+ return channels.length === ((_b = data === null || data === void 0 ? void 0 : data.channels) === null || _b === void 0 ? void 0 : _b.length)
24427
+ ? { data: channels, cachedAt, prevPage, nextPage }
24428
+ : undefined;
24172
24429
  };
24173
24430
 
24174
24431
  /**
@@ -24445,8 +24702,8 @@ const leaveChannel = async (channelId) => {
24445
24702
  const queryChannelMembers = async (query) => {
24446
24703
  const client = getActiveClient();
24447
24704
  client.log('channel/queryChannelMembers', query);
24448
- const _a = query !== null && query !== void 0 ? query : {}, { page, channelId } = _a, params = __rest(_a, ["page", "channelId"]);
24449
- const { data: queryPayload } = await client.http.get(`/api/v4/channels/${encodeURIComponent(channelId)}/users`, {
24705
+ const _a = query !== null && query !== void 0 ? query : {}, { page = { limit: 10 } } = _a, params = __rest(_a, ["page"]);
24706
+ const { data: queryPayload } = await client.http.get(`/api/v4/channels/${encodeURIComponent(params.channelId)}/users`, {
24450
24707
  params: Object.assign(Object.assign({}, params), { options: {
24451
24708
  token: toToken(page, 'skiplimit'),
24452
24709
  } }),
@@ -24457,6 +24714,15 @@ const queryChannelMembers = async (query) => {
24457
24714
  const cachedAt = client.cache && Date.now();
24458
24715
  if (client.cache) {
24459
24716
  ingestInCache(data);
24717
+ const cacheKey = [
24718
+ 'channelUsers',
24719
+ 'query',
24720
+ Object.assign(Object.assign({}, params), { options: Object.assign({}, page) }),
24721
+ ];
24722
+ pushToCache(cacheKey, {
24723
+ channelUsers: channelUsers.map(({ channelId, userId }) => getResolver('channelUsers')({ channelId, userId })),
24724
+ paging,
24725
+ });
24460
24726
  }
24461
24727
  const nextPage = toPage(paging.next);
24462
24728
  const prevPage = toPage(paging.previous);
@@ -24476,9 +24742,30 @@ const queryChannelMembers = async (query) => {
24476
24742
  * @category Post API
24477
24743
  */
24478
24744
  queryChannelMembers.locally = (query) => {
24745
+ var _a, _b;
24479
24746
  const client = getActiveClient();
24480
- client.log('channel/queryChannelMembers', query);
24481
- // TODO
24747
+ client.log('channel/queryChannelMembers.locally', query);
24748
+ if (!client.cache)
24749
+ return;
24750
+ const { page = { limit: 10 } } = query, params = __rest(query, ["page"]);
24751
+ const cacheKey = [
24752
+ 'channelUsers',
24753
+ 'query',
24754
+ Object.assign(Object.assign({}, params), { options: Object.assign({}, page) }),
24755
+ ];
24756
+ const { data, cachedAt } = (_a = pullFromCache(cacheKey)) !== null && _a !== void 0 ? _a : {};
24757
+ if (!(data === null || data === void 0 ? void 0 : data.channelUsers.length))
24758
+ return;
24759
+ const channelUsers = data.channelUsers
24760
+ // ck -> cacheKey, abbrevated to avoid confusion from the above cache key
24761
+ .map(ck => pullFromCache(['channelUsers', 'get', ck]))
24762
+ .filter(Boolean)
24763
+ .map(({ data }) => data);
24764
+ const prevPage = toPage(data === null || data === void 0 ? void 0 : data.paging.previous);
24765
+ const nextPage = toPage(data === null || data === void 0 ? void 0 : data.paging.next);
24766
+ return channelUsers.length === ((_b = data === null || data === void 0 ? void 0 : data.channelUsers) === null || _b === void 0 ? void 0 : _b.length)
24767
+ ? { data: channelUsers, cachedAt, prevPage, nextPage }
24768
+ : undefined;
24482
24769
  };
24483
24770
 
24484
24771
  /**
@@ -24826,6 +25113,56 @@ const onChannelMemberRemoved = (callback) => {
24826
25113
  return createEventSubscriber(client, 'onChannelMemberRemoved', 'v3.channel.didRemoveUsers', filter);
24827
25114
  };
24828
25115
 
25116
+ /**
25117
+ * ```js
25118
+ * import { onChannelMemberBanned } from '@amityco/ts-sdk'
25119
+ * const dispose = onChannelMemberBanned((channel, member) => {
25120
+ * // ...
25121
+ * })
25122
+ * ```
25123
+ *
25124
+ * Fired when any {@link Amity.User} has been banned from any {@link Amity.Channel}
25125
+ *
25126
+ * @param callback The function to call when the event was fired
25127
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25128
+ *
25129
+ * @category Channel Events
25130
+ */
25131
+ const onChannelMemberBanned = (callback) => {
25132
+ const client = getActiveClient();
25133
+ const filter = (payload) => {
25134
+ const data = prepareChannelPayload(payload);
25135
+ ingestInCache(data);
25136
+ callback(data.channels[0], data.channelUsers.find(cu => cu.membership === 'banned'));
25137
+ };
25138
+ return createEventSubscriber(client, 'onChannelMemberBanned', 'v3.channel.didBan', filter);
25139
+ };
25140
+
25141
+ /**
25142
+ * ```js
25143
+ * import { onChannelMemberUnbanned } from '@amityco/ts-sdk'
25144
+ * const dispose = onChannelMemberUnbanned((channel, member) => {
25145
+ * // ...
25146
+ * })
25147
+ * ```
25148
+ *
25149
+ * Fired when any {@link Amity.User} has been unbanned from any {@link Amity.Channel}
25150
+ *
25151
+ * @param callback The function to call when the event was fired
25152
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25153
+ *
25154
+ * @category Channel Events
25155
+ */
25156
+ const onChannelMemberUnbanned = (callback) => {
25157
+ const client = getActiveClient();
25158
+ const filter = (payload) => {
25159
+ const data = prepareChannelPayload(payload);
25160
+ ingestInCache(data);
25161
+ callback(data.channels[0], data.channelUsers.find(cu => cu.membership === 'none'));
25162
+ };
25163
+ return createEventSubscriber(client, 'onChannelMemberBanned', 'v3.channel.didUnban', filter);
25164
+ };
25165
+
24829
25166
  /**
24830
25167
  * ```js
24831
25168
  * import { observeChannel } from '@amityco/ts-sdk'
@@ -24920,7 +25257,7 @@ const observeChannels = (callback) => {
24920
25257
  * @category Channel Live Collection
24921
25258
  */
24922
25259
  const liveChannels = (params, callback, config) => {
24923
- const { log, cache } = getActiveClient();
25260
+ const { log, cache, userId } = getActiveClient();
24924
25261
  if (!cache) {
24925
25262
  console.log(ENABLE_CACHE_MESSAGE);
24926
25263
  }
@@ -24948,6 +25285,10 @@ const liveChannels = (params, callback, config) => {
24948
25285
  if (params.excludeTags) {
24949
25286
  channels = channels.filter(c => { var _a; return !((_a = c.tags) === null || _a === void 0 ? void 0 : _a.some(t => { var _a; return (_a = params.excludeTags) === null || _a === void 0 ? void 0 : _a.includes(t); })); });
24950
25287
  }
25288
+ // userId is required to be able to filter channel by current active user
25289
+ if (params.membership && userId) {
25290
+ channels = filterByChannelMembership(channels, params.membership, userId);
25291
+ }
24951
25292
  const sortBy = params.sortBy || 'lastCreated';
24952
25293
  if (sortBy === 'lastCreated' || sortBy === 'firstCreated') {
24953
25294
  channels = channels.sort(sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated);
@@ -25057,7 +25398,20 @@ const liveChannelMembers = (params, callback, config) => {
25057
25398
  .filter(Boolean)
25058
25399
  .map(({ data }) => data)) !== null && _a !== void 0 ? _a : [];
25059
25400
  channelMembers = filterByPropEquality(channelMembers, 'roles', params.roles);
25060
- channelMembers = filterByPropInclusion(channelMembers, 'membership', params.memberships);
25401
+ if (params.memberships) {
25402
+ /*
25403
+ * even though membership includes muted as a possible value
25404
+ * when querying the server.
25405
+ * Muted is specified under seperarte property namely isMuted
25406
+ * Hence why I've seperately checked for it's equality
25407
+ */
25408
+ if (params.memberships.some(m => ['member', 'banned'].includes(m))) {
25409
+ channelMembers = filterByPropInclusion(channelMembers, 'membership', params.memberships);
25410
+ }
25411
+ if (params.memberships.includes('muted')) {
25412
+ channelMembers = filterByPropEquality(channelMembers, 'isMuted', true);
25413
+ }
25414
+ }
25061
25415
  if (params.search) {
25062
25416
  const containsMatcher = new RegExp(params.search);
25063
25417
  channelMembers = channelMembers.filter(m => m.userId.match(containsMatcher));
@@ -25085,7 +25439,7 @@ const liveChannelMembers = (params, callback, config) => {
25085
25439
  if (action === 'onMemberAdded') {
25086
25440
  collection.data = [...new Set([channelMemberCacheId, ...collection.data])];
25087
25441
  }
25088
- else {
25442
+ if (action === 'onMemberRemoved') {
25089
25443
  collection.data = collection.data.filter(m => m !== channelMemberCacheId);
25090
25444
  }
25091
25445
  pushToCache(cacheKey, collection);
@@ -25112,7 +25466,7 @@ const liveChannelMembers = (params, callback, config) => {
25112
25466
  responder(data);
25113
25467
  }, queryOptions(policy));
25114
25468
  };
25115
- disposers.push(onChannelMemberAdded((_, member) => realtimeRouter(member, 'onMemberAdded')), onChannelMemberRemoved((_, member) => realtimeRouter(member, 'onMemberRemoved')));
25469
+ disposers.push(onChannelMemberAdded((_, member) => realtimeRouter(member, 'onMemberAdded')), onChannelMemberRemoved((_, member) => realtimeRouter(member, 'onMemberRemoved')), onChannelMemberBanned((_, member) => realtimeRouter(member, 'onChannelMemberBanned')), onChannelMemberUnbanned((_, member) => realtimeRouter(member, 'onChannelMemberUnbanned')));
25116
25470
  onFetch();
25117
25471
  return () => {
25118
25472
  log(`liveChannelMembers(tmpid: ${timestamp}) > dispose`);
@@ -25199,82 +25553,92 @@ const onMessageDeleted = (callback) => {
25199
25553
 
25200
25554
  /**
25201
25555
  * ```js
25202
- * import { observeMessage } from '@amityco/ts-sdk'
25203
- *
25204
- * let message = {}
25205
- * const unsub = observeMessage(messageId, updated => message = updated)
25556
+ * import { onMessageFetched } from '@amityco/ts-sdk'
25557
+ * const dispose = onMessageFetched(message => {
25558
+ * // ...
25559
+ * })
25206
25560
  * ```
25207
25561
  *
25208
- * Observe all mutations on a {@link Amity.Message} given a single messageId
25562
+ * Fired when an {@link Amity.Message} has been fetched
25209
25563
  *
25210
- * @param client the client to observe the message with
25211
- * @param messageId the ID of the message to observe
25212
- * @param callback the function to call when new data are available
25213
- * @param policy a query policy option for this observer
25214
- * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the message
25564
+ * @param callback The function to call when the event was fired
25565
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25215
25566
  *
25216
- * @category Message Observer
25567
+ * @category Message Events
25217
25568
  */
25218
- const observeMessage = (messageId, callback, policy = 'cache_then_server') => {
25219
- const { log } = getActiveClient();
25220
- const timestamp = Date.now();
25221
- log(`observeMessage(tmpid: ${timestamp}) > listen`);
25222
- // wrapper function to make sure
25223
- const router = (result, action) => {
25224
- var _a, _b, _c;
25225
- // filter function
25226
- if (((_a = result.data) === null || _a === void 0 ? void 0 : _a.messageId) !== messageId)
25227
- return;
25228
- if (callback instanceof Function)
25229
- return callback(result);
25230
- if (action !== 'onFetch')
25231
- (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, result);
25232
- (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, result);
25233
- };
25234
- const disposers = [];
25235
- disposers.push(onMessageUpdated(data => router({ data, loading: false, origin: 'event' }, 'onUpdate')), onMessageDeleted(data => router({ data, loading: false, origin: 'event' }, 'onDelete')));
25236
- if (policy !== 'no_fetch') {
25237
- runQuery(createQuery(getMessage, messageId), result => result.data && router(result, 'onFetch'), queryOptions(policy));
25238
- }
25239
- return () => {
25240
- log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25241
- disposers.forEach(fn => fn());
25569
+ const onMessageFetched = (callback) => {
25570
+ const client = getActiveClient();
25571
+ const filter = (payload) => {
25572
+ ingestInCache(payload);
25573
+ callback(payload.messages[0]);
25242
25574
  };
25575
+ return createEventSubscriber(client, 'message/onMessageFetched', 'v3.message.didFetch', filter);
25243
25576
  };
25244
25577
 
25245
25578
  /**
25246
25579
  * ```js
25247
- * import { observeMessages } from '@amityco/ts-sdk'
25580
+ * import { liveMessage } from '@amityco/ts-sdk'
25248
25581
  *
25249
25582
  * let messages = []
25250
- * const unsub = observeMessages(channelId, message => merge(messages, message))
25583
+ * const unsub = liveMessage(messageId, response => merge(messages, response.data))
25251
25584
  * ```
25252
25585
  *
25253
- * Observe all mutations on a list of {@link Amity.Message} for a given {@link Amity.Channel} object
25586
+ * Observe all mutation on a given {@link Amity.Message}
25254
25587
  *
25255
- * @param channelId the ID of the channel where to observe the messages
25588
+ * @param messageId the ID of the message to observe
25256
25589
  * @param callback the function to call when new data are available
25257
25590
  * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
25258
25591
  *
25259
- * @category Message Observer
25592
+ * @category Message Live Object
25260
25593
  */
25261
- const observeMessages = (channelId, callback) => {
25262
- const { log } = getActiveClient();
25594
+ const liveMessage = (messageId, callback) => {
25595
+ const { log, cache } = getActiveClient();
25596
+ let message;
25597
+ let isUnsyncedObject = false;
25598
+ if (!cache) {
25599
+ console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
25600
+ }
25263
25601
  const timestamp = Date.now();
25264
- log(`observeMessages(tmpid: ${timestamp}) > listen`);
25602
+ log(`liveMessage(tmpid: ${timestamp}) > listen`);
25265
25603
  const disposers = [];
25266
- const router = (message, action) => {
25267
- var _a, _b, _c;
25268
- if (((_a = message.data) === null || _a === void 0 ? void 0 : _a.channelId) !== channelId)
25604
+ const dispatcher = (data) => {
25605
+ var _a;
25606
+ // we check updatedAt to see if the current snapshot is new so
25607
+ // we won't send old data back, only fresh new data
25608
+ if (message && ((_a = data.data) === null || _a === void 0 ? void 0 : _a.updatedAt) === (message === null || message === void 0 ? void 0 : message.updatedAt) && data.origin !== 'server')
25269
25609
  return;
25270
- if (callback instanceof Function)
25271
- return callback(message);
25272
- (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, message);
25273
- (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, message);
25610
+ callback(data);
25611
+ message = data.data;
25274
25612
  };
25275
- disposers.push(onMessageCreated(data => router({ data, loading: false, origin: 'event' }, 'onCreate')), onMessageUpdated(data => router({ data, loading: false, origin: 'event' }, 'onUpdate')), onMessageDeleted(data => router({ data, loading: false, origin: 'event' }, 'onDelete')));
25613
+ const realtimeRouter = (message, action) => {
25614
+ dispatcher({ loading: false, data: message, origin: 'event' });
25615
+ };
25616
+ const onFetch = () => {
25617
+ const query = createQuery(getMessage, messageId, true);
25618
+ runQuery(query, ({ loading, data, error, origin, cachedAt }) => {
25619
+ if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
25620
+ dispatcher({
25621
+ data,
25622
+ origin,
25623
+ loading: false,
25624
+ error: new ASCApiError(UNSYNCED_OBJECT_CACHED_AT_MESSAGE, 800800 /* Amity.ClientError.DISALOOW_UNSYNCED_OBJECT */, "error" /* Amity.ErrorLevel.ERROR */),
25625
+ });
25626
+ isUnsyncedObject = true;
25627
+ disposers.forEach(fn => fn());
25628
+ }
25629
+ else if (!isUnsyncedObject) {
25630
+ dispatcher({ loading, data, origin, error });
25631
+ }
25632
+ if (error) {
25633
+ // Terminate observe functionality on error
25634
+ disposers.forEach(fn => fn());
25635
+ }
25636
+ });
25637
+ };
25638
+ disposers.push(onMessageFetched(message => realtimeRouter(message)), onMessageUpdated(message => realtimeRouter(message)), onMessageDeleted(message => realtimeRouter(message)));
25639
+ onFetch();
25276
25640
  return () => {
25277
- log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25641
+ log(`liveMessage(tmpid: ${timestamp}) > dispose`);
25278
25642
  disposers.forEach(fn => fn());
25279
25643
  };
25280
25644
  };
@@ -25363,7 +25727,7 @@ const liveMessages = (params, callback, config) => {
25363
25727
  responder(data);
25364
25728
  }, queryOptions(policy));
25365
25729
  };
25366
- disposers.push(onMessageCreated(message => realtimeRouter(message, 'onCreate')), onMessageDeleted(message => realtimeRouter(message, 'onDelete')), onMessageUpdated(message => realtimeRouter(message, 'onUpdate')));
25730
+ disposers.push(onMessageFetched(message => realtimeRouter(message, 'onFetch')), onMessageCreated(message => realtimeRouter(message, 'onCreate')), onMessageDeleted(message => realtimeRouter(message, 'onDelete')), onMessageUpdated(message => realtimeRouter(message, 'onUpdate')));
25367
25731
  onFetch();
25368
25732
  return () => {
25369
25733
  log(`liveMessages(tmpid: ${timestamp}) > dispose`);
@@ -25371,6 +25735,89 @@ const liveMessages = (params, callback, config) => {
25371
25735
  };
25372
25736
  };
25373
25737
 
25738
+ /**
25739
+ * ```js
25740
+ * import { observeMessage } from '@amityco/ts-sdk'
25741
+ *
25742
+ * let message = {}
25743
+ * const unsub = observeMessage(messageId, updated => message = updated)
25744
+ * ```
25745
+ *
25746
+ * Observe all mutations on a {@link Amity.Message} given a single messageId
25747
+ *
25748
+ * @param client the client to observe the message with
25749
+ * @param messageId the ID of the message to observe
25750
+ * @param callback the function to call when new data are available
25751
+ * @param policy a query policy option for this observer
25752
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the message
25753
+ *
25754
+ * @category Message Observer
25755
+ */
25756
+ const observeMessage = (messageId, callback, policy = 'cache_then_server') => {
25757
+ const { log } = getActiveClient();
25758
+ const timestamp = Date.now();
25759
+ log(`observeMessage(tmpid: ${timestamp}) > listen`);
25760
+ console.log('observeMessage will be deprecated on 15th November 2022, please use liveMessage instead.');
25761
+ // wrapper function to make sure
25762
+ const router = (result, action) => {
25763
+ var _a, _b, _c;
25764
+ // filter function
25765
+ if (((_a = result.data) === null || _a === void 0 ? void 0 : _a.messageId) !== messageId)
25766
+ return;
25767
+ if (callback instanceof Function)
25768
+ return callback(result);
25769
+ if (action !== 'onFetch')
25770
+ (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, result);
25771
+ (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, result);
25772
+ };
25773
+ const disposers = [];
25774
+ disposers.push(onMessageUpdated(data => router({ data, loading: false, origin: 'event' }, 'onUpdate')), onMessageDeleted(data => router({ data, loading: false, origin: 'event' }, 'onDelete')));
25775
+ if (policy !== 'no_fetch') {
25776
+ runQuery(createQuery(getMessage, messageId), result => result.data && router(result, 'onFetch'), queryOptions(policy));
25777
+ }
25778
+ return () => {
25779
+ log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25780
+ disposers.forEach(fn => fn());
25781
+ };
25782
+ };
25783
+
25784
+ /**
25785
+ * ```js
25786
+ * import { observeMessages } from '@amityco/ts-sdk'
25787
+ *
25788
+ * let messages = []
25789
+ * const unsub = observeMessages(channelId, message => merge(messages, message))
25790
+ * ```
25791
+ *
25792
+ * Observe all mutations on a list of {@link Amity.Message} for a given {@link Amity.Channel} object
25793
+ *
25794
+ * @param channelId the ID of the channel where to observe the messages
25795
+ * @param callback the function to call when new data are available
25796
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
25797
+ *
25798
+ * @category Message Observer
25799
+ */
25800
+ const observeMessages = (channelId, callback) => {
25801
+ const { log } = getActiveClient();
25802
+ const timestamp = Date.now();
25803
+ log(`observeMessages(tmpid: ${timestamp}) > listen`);
25804
+ const disposers = [];
25805
+ const router = (message, action) => {
25806
+ var _a, _b, _c;
25807
+ if (((_a = message.data) === null || _a === void 0 ? void 0 : _a.channelId) !== channelId)
25808
+ return;
25809
+ if (callback instanceof Function)
25810
+ return callback(message);
25811
+ (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, message);
25812
+ (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, message);
25813
+ };
25814
+ disposers.push(onMessageCreated(data => router({ data, loading: false, origin: 'event' }, 'onCreate')), onMessageUpdated(data => router({ data, loading: false, origin: 'event' }, 'onUpdate')), onMessageDeleted(data => router({ data, loading: false, origin: 'event' }, 'onDelete')));
25815
+ return () => {
25816
+ log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25817
+ disposers.forEach(fn => fn());
25818
+ };
25819
+ };
25820
+
25374
25821
  const createCommunityEventSubscriber = (event, callback) => {
25375
25822
  const client = getActiveClient();
25376
25823
  const filter = (payload) => {
@@ -27559,6 +28006,8 @@ exports.CommunityPostSettings = CommunityPostSettings;
27559
28006
  exports.ContentFeedType = ContentFeedType;
27560
28007
  exports.DefaultCommunityPostSetting = DefaultCommunityPostSetting;
27561
28008
  exports.FileType = FileType;
28009
+ exports.MessageContentType = MessageContentType;
28010
+ exports.PostContentType = PostContentType;
27562
28011
  exports.VERSION = VERSION$1;
27563
28012
  exports.VideoResolution = VideoResolution;
27564
28013
  exports.VideoSize = VideoSize;
@@ -27605,6 +28054,7 @@ exports.disposeStream = disposeStream;
27605
28054
  exports.dropFromCache = dropFromCache;
27606
28055
  exports.enableCache = enableCache;
27607
28056
  exports.fileUrlWithSize = fileUrlWithSize;
28057
+ exports.filterByChannelMembership = filterByChannelMembership;
27608
28058
  exports.filterByPropEquality = filterByPropEquality;
27609
28059
  exports.filterByPropInclusion = filterByPropInclusion;
27610
28060
  exports.follow = follow;
@@ -27658,9 +28108,11 @@ exports.liveChannels = liveChannels;
27658
28108
  exports.liveComments = liveComments;
27659
28109
  exports.liveFollowers = liveFollowers;
27660
28110
  exports.liveFollowings = liveFollowings;
28111
+ exports.liveMessage = liveMessage;
27661
28112
  exports.liveMessages = liveMessages;
27662
28113
  exports.livePosts = livePosts;
27663
28114
  exports.liveReactions = liveReactions;
28115
+ exports.liveUser = liveUser;
27664
28116
  exports.mergeInCache = mergeInCache;
27665
28117
  exports.observeChannel = observeChannel;
27666
28118
  exports.observeChannels = observeChannels;
@@ -27682,7 +28134,9 @@ exports.onChannelDeleted = onChannelDeleted;
27682
28134
  exports.onChannelJoined = onChannelJoined;
27683
28135
  exports.onChannelLeft = onChannelLeft;
27684
28136
  exports.onChannelMemberAdded = onChannelMemberAdded;
28137
+ exports.onChannelMemberBanned = onChannelMemberBanned;
27685
28138
  exports.onChannelMemberRemoved = onChannelMemberRemoved;
28139
+ exports.onChannelMemberUnbanned = onChannelMemberUnbanned;
27686
28140
  exports.onChannelUpdated = onChannelUpdated;
27687
28141
  exports.onClientBanned = onClientBanned;
27688
28142
  exports.onClientDisconnected = onClientDisconnected;
@@ -27711,6 +28165,7 @@ exports.onFollowerDeleted = onFollowerDeleted;
27711
28165
  exports.onFollowerRequested = onFollowerRequested;
27712
28166
  exports.onMessageCreated = onMessageCreated;
27713
28167
  exports.onMessageDeleted = onMessageDeleted;
28168
+ exports.onMessageFetched = onMessageFetched;
27714
28169
  exports.onMessageUpdated = onMessageUpdated;
27715
28170
  exports.onPollDeleted = onPollDeleted;
27716
28171
  exports.onPollUpdated = onPollUpdated;
@@ -27731,6 +28186,7 @@ exports.onStreamRecorded = onStreamRecorded;
27731
28186
  exports.onStreamStarted = onStreamStarted;
27732
28187
  exports.onStreamStopped = onStreamStopped;
27733
28188
  exports.onUserDeleted = onUserDeleted;
28189
+ exports.onUserFetched = onUserFetched;
27734
28190
  exports.onUserFlagCleared = onUserFlagCleared;
27735
28191
  exports.onUserFlagged = onUserFlagged;
27736
28192
  exports.onUserFollowed = onUserFollowed;