@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.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { encode, decode } from 'js-base64';
2
- import mitt from 'mitt';
3
2
  import AsyncStorage from '@react-native-async-storage/async-storage';
3
+ import mitt from 'mitt';
4
4
  import debug from 'debug';
5
5
  import axios from 'axios';
6
6
  import HttpAgent, { HttpsAgent } from 'agentkeepalive';
@@ -61,6 +61,24 @@ const VideoSize = Object.freeze({
61
61
  ORIGINAL: 'original',
62
62
  });
63
63
 
64
+ const MessageContentType = Object.freeze({
65
+ TEXT: 'text',
66
+ IMAGE: 'image',
67
+ FILE: 'file',
68
+ VIDEO: 'video',
69
+ AUDIO: 'audio',
70
+ CUSTOM: 'custom',
71
+ });
72
+
73
+ const PostContentType = Object.freeze({
74
+ TEXT: 'text',
75
+ IMAGE: 'image',
76
+ FILE: 'file',
77
+ VIDEO: 'video',
78
+ LIVESTREAM: 'liveStream',
79
+ POLL: 'poll',
80
+ });
81
+
64
82
  var _a$1;
65
83
  /* eslint-disable no-undef */
66
84
  const theGlobal =
@@ -336,6 +354,78 @@ const PAYLOAD2MODEL = {
336
354
  followCounts: 'followCount',
337
355
  };
338
356
 
357
+ // cache constants
358
+ const CACHE_KEY_GET = 'get';
359
+ const CACHE_KEY_TOMBSTONE = 'dead';
360
+ const CACHE_LIFESPAN = 1 * 60 * 1000; // 1 minute
361
+ const CACHE_LIFESPAN_TOMBSTONE = 3 * 60 * 1000; // 3 minutes
362
+ /**
363
+ * Shallow-clones an object and sort its keys
364
+ *
365
+ * @param source a plain object to clone
366
+ * @returns a clone of source, with keys sorted with default javascript sorting
367
+ *
368
+ * @category Cache
369
+ * @hidden
370
+ */
371
+ const normalize = (source) => Object.keys(source)
372
+ .sort()
373
+ .reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: source[key] })), {});
374
+ /**
375
+ * Encodes a given {@link Amity.CacheKey} to a plain string
376
+ *
377
+ * @param key the key to encode
378
+ * @returns an encoded string
379
+ *
380
+ * @category Cache
381
+ * @hidden
382
+ */
383
+ const encodeKey = (key) => JSON.stringify(key, (_, val) => (typeof val === 'object' ? normalize(val) : val));
384
+ /**
385
+ * Decodes a string back into a {@link Amity.CacheKey}
386
+
387
+ *
388
+ * @param key the string key to decode
389
+ * @returns a plain Amity.CacheKey object.
390
+ *
391
+ * @category Cache
392
+ * @hidden
393
+ */
394
+ const decodeKey = (key) => JSON.parse(key);
395
+ /**
396
+ * Performs a recursive partial deep equal check on two objects.
397
+ *
398
+ * @param predicate the reference object containing the partial information
399
+ * @param candidate the object to check against
400
+ * @returns true if the candidate contains all the values of the predicate
401
+ *
402
+ * @category Cache
403
+ */
404
+ const partialMatch = (predicate, candidate) => {
405
+ if (predicate === candidate)
406
+ return true;
407
+ // if one or the other is nullish, there can't be equality
408
+ if (!predicate || !candidate)
409
+ return false;
410
+ // we only perform recursive check on objects
411
+ if (typeof predicate !== 'object') {
412
+ return false;
413
+ }
414
+ // recursively call for partial match based on the predicate
415
+ return Object.keys(predicate).every(key => partialMatch(predicate[key], candidate[key]));
416
+ };
417
+ /**
418
+ * checks if passed error code is included in
419
+ * Tombstone errors list
420
+ *
421
+ * @param errorCode as {@link Amity.ServerError}
422
+ * @returns success boolean if the given errorCode
423
+ * is included in Tombstone errors list
424
+ *
425
+ * @category Cache
426
+ */
427
+ const checkIfShouldGoesToTombstone = (errorCode) => [400400 /* Amity.ServerError.ITEM_NOT_FOUND */, 400300 /* Amity.ServerError.FORBIDDEN */].includes(errorCode);
428
+
339
429
  /* eslint-disable no-use-before-define */
340
430
  /**
341
431
  * Type guard to check and cast that a given async function is has the ".locally" property
@@ -394,7 +484,7 @@ const isLocal = (model) => {
394
484
  *
395
485
  * @hidden
396
486
  */
397
- const isFresh = (model, lifeSpan = 0) => {
487
+ const isFresh = (model, lifeSpan = CACHE_LIFESPAN) => {
398
488
  var _a;
399
489
  return Date.now() - ((_a = model === null || model === void 0 ? void 0 : model.cachedAt) !== null && _a !== void 0 ? _a : 0) <= lifeSpan;
400
490
  };
@@ -428,12 +518,10 @@ const createQuery = (func, ...args) => ({ func, args });
428
518
  *
429
519
  * @category Query
430
520
  */
431
- const queryOptions = (policy, lifeSpan = 2 * 60 * 1000) => {
521
+ const queryOptions = (policy, lifeSpan = CACHE_LIFESPAN) => {
432
522
  if (policy === 'cache_only')
433
523
  return { lifeSpan: Infinity };
434
- if (policy === 'server_only')
435
- return { lifeSpan: 0 };
436
- return { lifeSpan };
524
+ return { lifeSpan: lifeSpan < CACHE_LIFESPAN ? CACHE_LIFESPAN : lifeSpan };
437
525
  };
438
526
  /**
439
527
  * ```js
@@ -454,8 +542,9 @@ const queryOptions = (policy, lifeSpan = 2 * 60 * 1000) => {
454
542
  */
455
543
  const runQuery = ({ func, args }, callback, options = queryOptions('cache_then_server')) => {
456
544
  let local;
545
+ const { lifeSpan } = queryOptions('cache_then_server', options.lifeSpan);
457
546
  // offline first
458
- if (isOffline(func) && options.lifeSpan !== 0) {
547
+ if (isOffline(func)) {
459
548
  try {
460
549
  local = isMutator(func) ? func.optimistically(...args) : func.locally(...args);
461
550
  }
@@ -466,7 +555,7 @@ const runQuery = ({ func, args }, callback, options = queryOptions('cache_then_s
466
555
  error,
467
556
  }));
468
557
  }
469
- const shouldAbort = isCachable(local) && isFresh(local, options.lifeSpan);
558
+ const shouldAbort = isCachable(local) && isFresh(local, lifeSpan);
470
559
  callback === null || callback === void 0 ? void 0 : callback(createSnapshot(local, {
471
560
  origin: 'local',
472
561
  loading: !(isFetcher(func) && shouldAbort),
@@ -533,54 +622,6 @@ function createSnapshot(data, options) {
533
622
  return Object.assign(Object.assign({}, options), { data });
534
623
  }
535
624
 
536
- // Note:
537
- // this file should contain a suite of filtering utilities to help the
538
- // local version of the query functions.
539
- /**
540
- * Filter a given collection with strict equality against a param
541
- *
542
- * @param collection the collection to filter
543
- * @param key the key of the collection's items to challenge
544
- * @param value the expected value
545
- * @returns a filtered collection with items only matching the criteria
546
- *
547
- * @hidden
548
- */
549
- const filterByPropEquality = (collection, key, value) => (value !== undefined ? collection.filter(item => item[key] === value) : collection);
550
- const filterByPropInclusion = (collection, key, value) => (value !== undefined ? collection.filter(item => value.includes(item[key])) : collection);
551
-
552
- // Note:
553
- // this file should contain a suite of sorting utilities to help the
554
- // local version of the query functions.
555
- /**
556
- * Alphabetic sorting of objects having a displayName
557
- */
558
- const sortByDisplayName = ({ displayName: a }, { displayName: b }) => {
559
- if (a === b)
560
- return 0;
561
- return a < b ? -1 : 1;
562
- };
563
- /**
564
- * Sorting a collection by their apparition order (oldest first)
565
- */
566
- const sortByChannelSegment = ({ channelSegment: a }, { channelSegment: b }) => a - b;
567
- /**
568
- * Sorting a collection by their apparition order (oldest first)
569
- */
570
- const sortBySegmentNumber = ({ segmentNumber: a }, { segmentNumber: b }) => a - b;
571
- /**
572
- * Sorting a collection by its oldest items
573
- */
574
- const sortByFirstCreated = ({ createdAt: a }, { createdAt: b }) => new Date(a).valueOf() - new Date(b).valueOf();
575
- /**
576
- * Sorting a collection by its newest items
577
- */
578
- const sortByLastCreated = ({ createdAt: a }, { createdAt: b }) => new Date(b).valueOf() - new Date(a).valueOf();
579
- /**
580
- * Sorting a collection by the items with most recent activity
581
- */
582
- const sortByLastActivity = ({ lastActivity: a }, { lastActivity: b }) => new Date(b).valueOf() - new Date(a).valueOf();
583
-
584
625
  /* eslint-disable max-classes-per-file */
585
626
  /**
586
627
  * Generic ASC error
@@ -670,257 +711,62 @@ const setActiveClient = (client) => {
670
711
  activeClient = client;
671
712
  };
672
713
 
673
- /* eslint-disable @typescript-eslint/ban-types */
674
- let tasks = [];
675
- let timer;
676
714
  /**
677
- * Add a function to run just before the next tick
715
+ * ```js
716
+ * import { enableCache } from '@amityco/ts-sdk'
717
+ * enableCache()
718
+ * ```
678
719
  *
679
- * @param task function to schedule for later execution
720
+ * Adds a new {@link Amity.Cache} object to
721
+ * an {@link Amity.Client} instance
722
+ *
723
+ * @param prevState a previous state of cache instance (useful for SSR)
724
+ * @param persistIf a function to determine if an entry inserted in cache
725
+ * is destined to be also saved in the persistent storage when
726
+ * calling {@link backupCache}
727
+ *
728
+ * @category Cache API
680
729
  */
681
- const scheduleTask = (task) => {
682
- clearTimeout(timer);
683
- tasks.push(task);
684
- timer = setTimeout(() => {
685
- tasks.forEach(fn => fn());
686
- tasks = [];
687
- }, 0);
730
+ const enableCache = (prevState = {}, persistIf) => {
731
+ const client = getActiveClient();
732
+ if (client.cache)
733
+ return;
734
+ client.log('cache/api/enableCache');
735
+ client.cache = { data: prevState, persistIf };
688
736
  };
689
737
 
690
- /* eslint-disable @typescript-eslint/no-unused-vars */
691
- // need to sync up the list
692
- const WS_EVENTS = [
693
- 'disconnected',
694
- 'error',
695
- 'connect_error',
696
- 'reconnect_error',
697
- 'reconnect_failed',
698
- 'v3.channel.didCreate',
699
- 'v3.channel.didUpdate',
700
- 'v3.channel.didDelete',
701
- 'v3.channel.didJoin',
702
- 'v3.channel.didLeave',
703
- 'v3.channel.didAddUsers',
704
- 'v3.channel.didRemoveUsers',
705
- 'v3.channel.didBan',
706
- 'v3.channel.didUnban',
707
- 'v3.message.didCreate',
708
- 'v3.message.didUpdate',
709
- 'v3.message.didDelete',
710
- ];
711
- const MQTT_EVENTS = [
712
- 'connect',
713
- 'message',
714
- 'disconnect',
715
- 'error',
716
- 'close',
717
- 'end',
718
- 'reconnect',
719
- ];
720
- /** @hidden */
721
- const createEventEmitter = () => {
722
- return mitt();
723
- };
724
738
  /**
725
- * Wraps the websocket events into the client's event emitter for
726
- * abstraction of transport.
739
+ * ```js
740
+ * import { disableCache } from '@amityco/ts-sdk'
741
+ * disableCache()
742
+ * ```
727
743
  *
728
- * @param ws A websocket connection to listen from
729
- * @param emitter An event emitter to wire the events to
744
+ * Wipes the existing {@link Amity.Cache} object attached to
745
+ * an {@link Amity.Client} instance
730
746
  *
731
- * @category Transport
732
- * @hidden
747
+ * @category Cache API
733
748
  */
734
- const proxyWebsocketEvents = (ws, emitter) => {
735
- WS_EVENTS.forEach(event => {
736
- ws.on(event, (param) => emitter.emit(event, param));
737
- });
738
- };
739
- const proxyMqttEvents = (mqttClient, emitter) => {
740
- MQTT_EVENTS.forEach(event => {
741
- mqttClient.on(event, (...params) => emitter.emit(event, params.length === 1 ? params[0] : params));
742
- });
743
- // @ts-ignore
744
- mqttClient.on('message', (topic, payload) => {
745
- const message = JSON.parse(payload.toString());
746
- emitter.emit(message.eventType, message.data);
747
- });
748
- };
749
+ const disableCache = () => {
750
+ const client = getActiveClient();
751
+ if (!client.cache)
752
+ return;
753
+ client.log('cache/api/disableCache');
754
+ // we do this so that testing if cache is enabled
755
+ // is only `if (client.cache)
756
+ delete client.cache;
757
+ };
758
+
749
759
  /**
750
- * Standardize the subscription of SSE through web sockets
760
+ * ```js
761
+ * import { restoreCache } from '@amityco/ts-sdk'
762
+ * const success = await restoreCache()
763
+ * ```
751
764
  *
752
- * @param client The current client for which to subscribe the event to
753
- * @param namespace A unique name for the logger
754
- * @param event The websocket event name
755
- * @param fn A wrapper for the callback.
756
- * @returns A dispose function to unsubscribe to the event
765
+ * Reads a previously saved {@link Amity.Cache} from a persistent storage,
766
+ * and inserts it into the current {@link Amity.Cache} instance.
757
767
  *
758
- * @category Transport
759
- * @hidden
760
- */
761
- const createEventSubscriber = (client, namespace, event, fn) => {
762
- const { log, emitter } = client;
763
- const timestamp = Date.now();
764
- log(`${namespace}(tmpid: ${timestamp}) > listen`);
765
- const handler = (...payload) => {
766
- log(`${namespace}(tmpid: ${timestamp}) > trigger`, payload);
767
- fn(...payload);
768
- };
769
- emitter.on(event, handler);
770
- return () => {
771
- log(`${namespace}(tmpid: ${timestamp}) > dispose`);
772
- emitter.off(event, handler);
773
- };
774
- };
775
- /**
776
- * Wrapper around dispatch event
777
- *
778
- * @hidden
779
- */
780
- const fireEvent = (event, payload) => {
781
- const { emitter } = getActiveClient();
782
- scheduleTask(() => {
783
- emitter.emit(event, payload);
784
- });
785
- };
786
-
787
- let activeUser = null;
788
- /**
789
- * for internal use
790
- */
791
- const getActiveUser = () => {
792
- if (!activeUser) {
793
- throw new ASCError('Connect client first', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
794
- }
795
- return activeUser;
796
- };
797
- const setActiveUser = (user) => {
798
- activeUser = {
799
- _id: user._id,
800
- userId: user.userId,
801
- path: user.path,
802
- };
803
- };
804
-
805
- var SubscriptionLevels;
806
- (function (SubscriptionLevels) {
807
- SubscriptionLevels["COMMUNITY"] = "community";
808
- SubscriptionLevels["POST"] = "post";
809
- SubscriptionLevels["COMMENT"] = "comment";
810
- SubscriptionLevels["POST_AND_COMMENT"] = "post_and_comment";
811
- SubscriptionLevels["USER"] = "user";
812
- })(SubscriptionLevels || (SubscriptionLevels = {}));
813
- const getCommunityUserTopic = (path, level) => {
814
- switch (level) {
815
- case 'post':
816
- return `${path}/post/+`;
817
- case 'comment':
818
- return `${path}/post/+/comment/+`;
819
- case 'post_and_comment':
820
- return `${path}/post/#`;
821
- default:
822
- return path;
823
- }
824
- };
825
- const getCommunityTopic = ({ path }, level = SubscriptionLevels.COMMUNITY) => getCommunityUserTopic(path, level);
826
- const getUserTopic = ({ path }, level = SubscriptionLevels.USER) => getCommunityUserTopic(level === SubscriptionLevels.USER ? path : path.replace(/^(\w*)/, '$1/social'), level);
827
- const getPostTopic = ({ path }, level = SubscriptionLevels.POST) => {
828
- switch (level) {
829
- case 'comment':
830
- return `${path}/comment/+`;
831
- default:
832
- return path;
833
- }
834
- };
835
- const getCommentTopic = ({ path }) => {
836
- return path;
837
- };
838
- const getMyFollowersTopic = () => {
839
- const user = getActiveUser();
840
- const [networkId] = user.path.split('/user/');
841
- return `${networkId}/membership/${user._id}/+/+`;
842
- };
843
- const getMyFollowingsTopic = () => {
844
- const user = getActiveUser();
845
- const [networkId] = user.path.split('/user/');
846
- return `${networkId}/membership/+/${user._id}/+`;
847
- };
848
- /** @hidden */
849
- const getNetworkTopic = () => {
850
- const user = getActiveUser();
851
- const [networkId] = user.path.split('/user/');
852
- return networkId;
853
- };
854
- let mqttAccessToken;
855
- let mqttUserId;
856
- function subscribeTopic(topic, callback) {
857
- const { mqtt, emitter, accessToken } = getActiveClient();
858
- const user = getActiveUser();
859
- if (mqttAccessToken !== accessToken || mqttUserId !== user._id) {
860
- mqttAccessToken = accessToken;
861
- mqttUserId = user._id;
862
- mqtt.connect({ accessToken: mqttAccessToken, userId: mqttUserId });
863
- proxyMqttEvents(mqtt, emitter);
864
- }
865
- return mqtt.subscribe(topic, callback);
866
- }
867
-
868
- /**
869
- * ```js
870
- * import { enableCache } from '@amityco/ts-sdk'
871
- * enableCache()
872
- * ```
873
- *
874
- * Adds a new {@link Amity.Cache} object to
875
- * an {@link Amity.Client} instance
876
- *
877
- * @param prevState a previous state of cache instance (useful for SSR)
878
- * @param persistIf a function to determine if an entry inserted in cache
879
- * is destined to be also saved in the persistent storage when
880
- * calling {@link backupCache}
881
- *
882
- * @category Cache API
883
- */
884
- const enableCache = (prevState = {}, persistIf) => {
885
- const client = getActiveClient();
886
- if (client.cache)
887
- return;
888
- client.log('cache/api/enableCache');
889
- client.cache = { data: prevState, persistIf };
890
- };
891
-
892
- /**
893
- * ```js
894
- * import { disableCache } from '@amityco/ts-sdk'
895
- * disableCache()
896
- * ```
897
- *
898
- * Wipes the existing {@link Amity.Cache} object attached to
899
- * an {@link Amity.Client} instance
900
- *
901
- * @category Cache API
902
- */
903
- const disableCache = () => {
904
- const client = getActiveClient();
905
- if (!client.cache)
906
- return;
907
- client.log('cache/api/disableCache');
908
- // we do this so that testing if cache is enabled
909
- // is only `if (client.cache)
910
- delete client.cache;
911
- };
912
-
913
- /**
914
- * ```js
915
- * import { restoreCache } from '@amityco/ts-sdk'
916
- * const success = await restoreCache()
917
- * ```
918
- *
919
- * Reads a previously saved {@link Amity.Cache} from a persistent storage,
920
- * and inserts it into the current {@link Amity.Cache} instance.
921
- *
922
- * The strategy for persistent storage will depend on the runtime,
923
- * which is supported by @react-native-async-storage/async-storage.
768
+ * The strategy for persistent storage will depend on the runtime,
769
+ * which is supported by @react-native-async-storage/async-storage.
924
770
  *
925
771
  * The current userId will be appended to the given storageKey to ensures
926
772
  * the cached data concerns only the current user.
@@ -1016,62 +862,6 @@ const wipeCache = async (storageKey = 'amitySdk') => {
1016
862
  return true;
1017
863
  };
1018
864
 
1019
- /**
1020
- * Shallow-clones an object and sort its keys
1021
- *
1022
- * @param source a plain object to clone
1023
- * @returns a clone of source, with keys sorted with default javascript sorting
1024
- *
1025
- * @category Cache
1026
- * @hidden
1027
- */
1028
- const normalize = (source) => Object.keys(source)
1029
- .sort()
1030
- .reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: source[key] })), {});
1031
- /**
1032
- * Encodes a given {@link Amity.CacheKey} to a plain string
1033
- *
1034
- * @param key the key to encode
1035
- * @returns an encoded string
1036
- *
1037
- * @category Cache
1038
- * @hidden
1039
- */
1040
- const encodeKey = (key) => JSON.stringify(key, (_, val) => (typeof val === 'object' ? normalize(val) : val));
1041
- /**
1042
- * Decodes a string back into a {@link Amity.CacheKey}
1043
-
1044
- *
1045
- * @param key the string key to decode
1046
- * @returns a plain Amity.CacheKey object.
1047
- *
1048
- * @category Cache
1049
- * @hidden
1050
- */
1051
- const decodeKey = (key) => JSON.parse(key);
1052
- /**
1053
- * Performs a recursive partial deep equal check on two objects.
1054
- *
1055
- * @param predicate the reference object containing the partial information
1056
- * @param candidate the object to check against
1057
- * @returns true if the candidate contains all the values of the predicate
1058
- *
1059
- * @category Cache
1060
- */
1061
- const partialMatch = (predicate, candidate) => {
1062
- if (predicate === candidate)
1063
- return true;
1064
- // if one or the other is nullish, there can't be equality
1065
- if (!predicate || !candidate)
1066
- return false;
1067
- // we only perform recursive check on objects
1068
- if (typeof predicate !== 'object') {
1069
- return false;
1070
- }
1071
- // recursively call for partial match based on the predicate
1072
- return Object.keys(predicate).every(key => partialMatch(predicate[key], candidate[key]));
1073
- };
1074
-
1075
865
  /**
1076
866
  * ```js
1077
867
  * import { queryCache } from '@amityco/ts-sdk'
@@ -1168,86 +958,368 @@ const pushToCache = (key, data, options = { cachedAt: Date.now() }) => {
1168
958
  *
1169
959
  * Merges a new {@link Amity.Cache} object to an {@link Amity.Client} instance
1170
960
  *
1171
- * @param key the key matching the object to retrieve from cache
1172
- * @param mutation either a plain object to shallow merge, or a function.
1173
- * @returns a success boolean if the object was updated
961
+ * @param key the key matching the object to retrieve from cache
962
+ * @param mutation either a plain object to shallow merge, or a function.
963
+ * @returns a success boolean if the object was updated
964
+ *
965
+ * @category Cache API
966
+ */
967
+ const mergeInCache = (key, mutation, options) => {
968
+ const { log, cache } = getActiveClient();
969
+ if (!cache)
970
+ return false;
971
+ log('cache/api/mergeInCache', { key, mutation });
972
+ const oldVal = pullFromCache(key);
973
+ if (!oldVal)
974
+ return false;
975
+ const newVal = typeof mutation === 'function' ? mutation(oldVal.data) : Object.assign(Object.assign({}, oldVal.data), mutation);
976
+ pushToCache(key, newVal, options);
977
+ return true;
978
+ };
979
+
980
+ /**
981
+ * ```js
982
+ * import { upsertInCache } from '@amityco/ts-sdk'
983
+ * upsertInCache<Amity.User>(["user", "foobar"], user)
984
+ * ```
985
+ *
986
+ * Insert or update any provided value as {@link Amity.CacheEntry} for
987
+ * the matching {@link Amity.CacheKey}
988
+ *
989
+ * @param key the key to save the object to
990
+ * @param data the object to save
991
+ * @param options customisation object around cache behavior (default gives a 2mn lifespan)
992
+ * @returns a success boolean if the object was saved in cache
993
+ *
994
+ * @category Cache API
995
+ * @hidden
996
+ */
997
+ const upsertInCache = (key, data, options = { cachedAt: Date.now() }) => {
998
+ const { log, cache } = getActiveClient();
999
+ if (!cache)
1000
+ return false;
1001
+ log('cache/api/upsertInCache', { key, data, options });
1002
+ const cached = pullFromCache(key);
1003
+ return cached ? mergeInCache(key, data, options) : pushToCache(key, data, options);
1004
+ };
1005
+
1006
+ /**
1007
+ * ```js
1008
+ * import { dropFromCache } from '@amityco/ts-sdk'
1009
+ * const success = dropFromCache(['user', 'foobar'])
1010
+ * ```
1011
+ *
1012
+ * Removes an existing {@link Amity.CacheEntry} from the {@link Amity.Client}'s
1013
+ * {@link Amity.Cache} from a given {@link Amity.CacheKey}
1014
+ *
1015
+ * @param key The key of the object to delete
1016
+ * @param exact If false, the function will delete all keys satisfying the given key
1017
+ * @returns A success boolean if the object was deleted
1018
+ *
1019
+ * @category Cache API
1020
+ */
1021
+ const dropFromCache = (key, exact = false) => {
1022
+ const { log, cache } = getActiveClient();
1023
+ if (!cache)
1024
+ return false;
1025
+ log('cache/api/dropFromCache', { key, exact });
1026
+ if (!exact) {
1027
+ return Object.keys(cache.data)
1028
+ .map(stringKey => decodeKey(stringKey))
1029
+ .filter(candidate => partialMatch(key, candidate))
1030
+ .map(filteredKey => dropFromCache(filteredKey, true))
1031
+ .every(returned => returned);
1032
+ }
1033
+ const encodedKey = encodeKey(key);
1034
+ if (encodedKey in cache.data) {
1035
+ delete cache.data[encodedKey];
1036
+ return true;
1037
+ }
1038
+ return false;
1039
+ };
1040
+
1041
+ // Note:
1042
+ // this file should contain a suite of filtering utilities to help the
1043
+ // local version of the query functions.
1044
+ /**
1045
+ * Filter a given collection with strict equality against a param
1046
+ *
1047
+ * @param collection the collection to filter
1048
+ * @param key the key of the collection's items to challenge
1049
+ * @param value the expected value
1050
+ * @returns a filtered collection with items only matching the criteria
1051
+ *
1052
+ * @hidden
1053
+ */
1054
+ const filterByPropEquality = (collection, key, value) => (value !== undefined ? collection.filter(item => item[key] === value) : collection);
1055
+ const filterByPropInclusion = (collection, key, value) => (value !== undefined ? collection.filter(item => value.includes(item[key])) : collection);
1056
+ /**
1057
+ * Filter a channel collection by membership of the userId
1058
+ *
1059
+ * @param collection the channel collection to filter
1060
+ * @param membership the membership to be filtered by
1061
+ * @param userId user id to be filtered by
1062
+ * @returns a filtered collection with items only matching the criteria
1063
+ *
1064
+ * @hidden
1065
+ */
1066
+ const filterByChannelMembership = (collection, membership, userId) => {
1067
+ if (membership === 'all') {
1068
+ return collection;
1069
+ }
1070
+ return collection.filter(c => {
1071
+ var _a;
1072
+ // get resolver for the channel by user
1073
+ const channelUserCacheKey = getResolver('channelUsers')({
1074
+ channelId: c.channelId,
1075
+ userId,
1076
+ });
1077
+ const channelUser = (_a = pullFromCache([
1078
+ 'channelUsers',
1079
+ 'get',
1080
+ channelUserCacheKey,
1081
+ ])) === null || _a === void 0 ? void 0 : _a.data;
1082
+ // if channel user is defined for user, user is a member
1083
+ if (membership === 'member' && channelUser) {
1084
+ return true;
1085
+ }
1086
+ // if channel user by user id not found, user is not a member of that
1087
+ // channel
1088
+ if (membership === 'notMember' && !channelUser) {
1089
+ return true;
1090
+ }
1091
+ return false;
1092
+ });
1093
+ };
1094
+
1095
+ // Note:
1096
+ // this file should contain a suite of sorting utilities to help the
1097
+ // local version of the query functions.
1098
+ /**
1099
+ * Alphabetic sorting of objects having a displayName
1100
+ */
1101
+ const sortByDisplayName = ({ displayName: a }, { displayName: b }) => {
1102
+ if (a === b)
1103
+ return 0;
1104
+ return a < b ? -1 : 1;
1105
+ };
1106
+ /**
1107
+ * Sorting a collection by their apparition order (oldest first)
1108
+ */
1109
+ const sortByChannelSegment = ({ channelSegment: a }, { channelSegment: b }) => a - b;
1110
+ /**
1111
+ * Sorting a collection by their apparition order (oldest first)
1112
+ */
1113
+ const sortBySegmentNumber = ({ segmentNumber: a }, { segmentNumber: b }) => a - b;
1114
+ /**
1115
+ * Sorting a collection by its oldest items
1116
+ */
1117
+ const sortByFirstCreated = ({ createdAt: a }, { createdAt: b }) => new Date(a).valueOf() - new Date(b).valueOf();
1118
+ /**
1119
+ * Sorting a collection by its newest items
1120
+ */
1121
+ const sortByLastCreated = ({ createdAt: a }, { createdAt: b }) => new Date(b).valueOf() - new Date(a).valueOf();
1122
+ /**
1123
+ * Sorting a collection by the items with most recent activity
1124
+ */
1125
+ const sortByLastActivity = ({ lastActivity: a }, { lastActivity: b }) => new Date(b).valueOf() - new Date(a).valueOf();
1126
+
1127
+ /* eslint-disable @typescript-eslint/ban-types */
1128
+ let tasks = [];
1129
+ let timer;
1130
+ /**
1131
+ * Add a function to run just before the next tick
1132
+ *
1133
+ * @param task function to schedule for later execution
1134
+ */
1135
+ const scheduleTask = (task) => {
1136
+ clearTimeout(timer);
1137
+ tasks.push(task);
1138
+ timer = setTimeout(() => {
1139
+ tasks.forEach(fn => fn());
1140
+ tasks = [];
1141
+ }, 0);
1142
+ };
1143
+
1144
+ /* eslint-disable @typescript-eslint/no-unused-vars */
1145
+ // need to sync up the list
1146
+ const WS_EVENTS = [
1147
+ 'disconnected',
1148
+ 'error',
1149
+ 'connect_error',
1150
+ 'reconnect_error',
1151
+ 'reconnect_failed',
1152
+ 'v3.channel.didCreate',
1153
+ 'v3.channel.didUpdate',
1154
+ 'v3.channel.didDelete',
1155
+ 'v3.channel.didJoin',
1156
+ 'v3.channel.didLeave',
1157
+ 'v3.channel.didAddUsers',
1158
+ 'v3.channel.didRemoveUsers',
1159
+ 'v3.channel.didBan',
1160
+ 'v3.channel.didUnban',
1161
+ 'v3.message.didFetch',
1162
+ 'v3.message.didCreate',
1163
+ 'v3.message.didUpdate',
1164
+ 'v3.message.didDelete',
1165
+ ];
1166
+ const MQTT_EVENTS = [
1167
+ 'connect',
1168
+ 'message',
1169
+ 'disconnect',
1170
+ 'error',
1171
+ 'close',
1172
+ 'end',
1173
+ 'reconnect',
1174
+ ];
1175
+ /** @hidden */
1176
+ const createEventEmitter = () => {
1177
+ return mitt();
1178
+ };
1179
+ /**
1180
+ * Wraps the websocket events into the client's event emitter for
1181
+ * abstraction of transport.
1182
+ *
1183
+ * @param ws A websocket connection to listen from
1184
+ * @param emitter An event emitter to wire the events to
1185
+ *
1186
+ * @category Transport
1187
+ * @hidden
1188
+ */
1189
+ const proxyWebsocketEvents = (ws, emitter) => {
1190
+ WS_EVENTS.forEach(event => {
1191
+ ws.on(event, (param) => emitter.emit(event, param));
1192
+ });
1193
+ };
1194
+ const proxyMqttEvents = (mqttClient, emitter) => {
1195
+ MQTT_EVENTS.forEach(event => {
1196
+ mqttClient.on(event, (...params) => emitter.emit(event, params.length === 1 ? params[0] : params));
1197
+ });
1198
+ // @ts-ignore
1199
+ mqttClient.on('message', (topic, payload) => {
1200
+ const message = JSON.parse(payload.toString());
1201
+ emitter.emit(message.eventType, message.data);
1202
+ });
1203
+ };
1204
+ /**
1205
+ * Standardize the subscription of SSE through web sockets
1206
+ *
1207
+ * @param client The current client for which to subscribe the event to
1208
+ * @param namespace A unique name for the logger
1209
+ * @param event The websocket event name
1210
+ * @param fn A wrapper for the callback.
1211
+ * @returns A dispose function to unsubscribe to the event
1174
1212
  *
1175
- * @category Cache API
1213
+ * @category Transport
1214
+ * @hidden
1176
1215
  */
1177
- const mergeInCache = (key, mutation, options) => {
1178
- const { log, cache } = getActiveClient();
1179
- if (!cache)
1180
- return false;
1181
- log('cache/api/mergeInCache', { key, mutation });
1182
- const oldVal = pullFromCache(key);
1183
- if (!oldVal)
1184
- return false;
1185
- const newVal = typeof mutation === 'function' ? mutation(oldVal.data) : Object.assign(Object.assign({}, oldVal.data), mutation);
1186
- pushToCache(key, newVal, options);
1187
- return true;
1188
- };
1189
-
1216
+ const createEventSubscriber = (client, namespace, event, fn) => {
1217
+ const { log, emitter } = client;
1218
+ const timestamp = Date.now();
1219
+ log(`${namespace}(tmpid: ${timestamp}) > listen`);
1220
+ const handler = (...payload) => {
1221
+ log(`${namespace}(tmpid: ${timestamp}) > trigger`, payload);
1222
+ fn(...payload);
1223
+ };
1224
+ emitter.on(event, handler);
1225
+ return () => {
1226
+ log(`${namespace}(tmpid: ${timestamp}) > dispose`);
1227
+ emitter.off(event, handler);
1228
+ };
1229
+ };
1190
1230
  /**
1191
- * ```js
1192
- * import { upsertInCache } from '@amityco/ts-sdk'
1193
- * upsertInCache<Amity.User>(["user", "foobar"], user)
1194
- * ```
1195
- *
1196
- * Insert or update any provided value as {@link Amity.CacheEntry} for
1197
- * the matching {@link Amity.CacheKey}
1198
- *
1199
- * @param key the key to save the object to
1200
- * @param data the object to save
1201
- * @param options customisation object around cache behavior (default gives a 2mn lifespan)
1202
- * @returns a success boolean if the object was saved in cache
1231
+ * Wrapper around dispatch event
1203
1232
  *
1204
- * @category Cache API
1205
1233
  * @hidden
1206
1234
  */
1207
- const upsertInCache = (key, data, options = { cachedAt: Date.now() }) => {
1208
- const { log, cache } = getActiveClient();
1209
- if (!cache)
1210
- return false;
1211
- log('cache/api/upsertInCache', { key, data, options });
1212
- const cached = pullFromCache(key);
1213
- return cached ? mergeInCache(key, data, options) : pushToCache(key, data, options);
1235
+ const fireEvent = (event, payload) => {
1236
+ const { emitter } = getActiveClient();
1237
+ scheduleTask(() => {
1238
+ emitter.emit(event, payload);
1239
+ });
1214
1240
  };
1215
1241
 
1242
+ let activeUser = null;
1216
1243
  /**
1217
- * ```js
1218
- * import { dropFromCache } from '@amityco/ts-sdk'
1219
- * const success = dropFromCache(['user', 'foobar'])
1220
- * ```
1221
- *
1222
- * Removes an existing {@link Amity.CacheEntry} from the {@link Amity.Client}'s
1223
- * {@link Amity.Cache} from a given {@link Amity.CacheKey}
1224
- *
1225
- * @param key The key of the object to delete
1226
- * @param exact If false, the function will delete all keys satisfying the given key
1227
- * @returns A success boolean if the object was deleted
1228
- *
1229
- * @category Cache API
1244
+ * for internal use
1230
1245
  */
1231
- const dropFromCache = (key, exact = false) => {
1232
- const { log, cache } = getActiveClient();
1233
- if (!cache)
1234
- return false;
1235
- log('cache/api/dropFromCache', { key, exact });
1236
- if (!exact) {
1237
- return Object.keys(cache.data)
1238
- .map(stringKey => decodeKey(stringKey))
1239
- .filter(candidate => partialMatch(key, candidate))
1240
- .map(filteredKey => dropFromCache(filteredKey, true))
1241
- .every(returned => returned);
1242
- }
1243
- const encodedKey = encodeKey(key);
1244
- if (encodedKey in cache.data) {
1245
- delete cache.data[encodedKey];
1246
- return true;
1246
+ const getActiveUser = () => {
1247
+ if (!activeUser) {
1248
+ throw new ASCError('Connect client first', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
1247
1249
  }
1248
- return false;
1250
+ return activeUser;
1251
+ };
1252
+ const setActiveUser = (user) => {
1253
+ activeUser = {
1254
+ _id: user._id,
1255
+ userId: user.userId,
1256
+ path: user.path,
1257
+ };
1249
1258
  };
1250
1259
 
1260
+ var SubscriptionLevels;
1261
+ (function (SubscriptionLevels) {
1262
+ SubscriptionLevels["COMMUNITY"] = "community";
1263
+ SubscriptionLevels["POST"] = "post";
1264
+ SubscriptionLevels["COMMENT"] = "comment";
1265
+ SubscriptionLevels["POST_AND_COMMENT"] = "post_and_comment";
1266
+ SubscriptionLevels["USER"] = "user";
1267
+ })(SubscriptionLevels || (SubscriptionLevels = {}));
1268
+ const getCommunityUserTopic = (path, level) => {
1269
+ switch (level) {
1270
+ case 'post':
1271
+ return `${path}/post/+`;
1272
+ case 'comment':
1273
+ return `${path}/post/+/comment/+`;
1274
+ case 'post_and_comment':
1275
+ return `${path}/post/#`;
1276
+ default:
1277
+ return path;
1278
+ }
1279
+ };
1280
+ const getCommunityTopic = ({ path }, level = SubscriptionLevels.COMMUNITY) => getCommunityUserTopic(path, level);
1281
+ const getUserTopic = ({ path }, level = SubscriptionLevels.USER) => getCommunityUserTopic(level === SubscriptionLevels.USER ? path : path.replace(/^(\w*)/, '$1/social'), level);
1282
+ const getPostTopic = ({ path }, level = SubscriptionLevels.POST) => {
1283
+ switch (level) {
1284
+ case 'comment':
1285
+ return `${path}/comment/+`;
1286
+ default:
1287
+ return path;
1288
+ }
1289
+ };
1290
+ const getCommentTopic = ({ path }) => {
1291
+ return path;
1292
+ };
1293
+ const getMyFollowersTopic = () => {
1294
+ const user = getActiveUser();
1295
+ const [networkId] = user.path.split('/user/');
1296
+ return `${networkId}/membership/${user._id}/+/+`;
1297
+ };
1298
+ const getMyFollowingsTopic = () => {
1299
+ const user = getActiveUser();
1300
+ const [networkId] = user.path.split('/user/');
1301
+ return `${networkId}/membership/+/${user._id}/+`;
1302
+ };
1303
+ /** @hidden */
1304
+ const getNetworkTopic = () => {
1305
+ const user = getActiveUser();
1306
+ const [networkId] = user.path.split('/user/');
1307
+ return networkId;
1308
+ };
1309
+ let mqttAccessToken;
1310
+ let mqttUserId;
1311
+ function subscribeTopic(topic, callback) {
1312
+ const { mqtt, emitter, accessToken } = getActiveClient();
1313
+ const user = getActiveUser();
1314
+ if (mqttAccessToken !== accessToken || mqttUserId !== user._id) {
1315
+ mqttAccessToken = accessToken;
1316
+ mqttUserId = user._id;
1317
+ mqtt.connect({ accessToken: mqttAccessToken, userId: mqttUserId });
1318
+ proxyMqttEvents(mqtt, emitter);
1319
+ }
1320
+ return mqtt.subscribe(topic, callback);
1321
+ }
1322
+
1251
1323
  /**
1252
1324
  * Creates a pre-configured logger instance
1253
1325
  *
@@ -20564,6 +20636,61 @@ const isConnected = () => {
20564
20636
  client.ws.connected);
20565
20637
  };
20566
20638
 
20639
+ /**
20640
+ * ```js
20641
+ * import { isInTombstone } from '@amityco/ts-sdk'
20642
+ * const user = isInTombstone(["message", "messageId"])
20643
+ * ```
20644
+ *
20645
+ * Checks if the {@link Amity.TombstoneCacheOptions} exists
20646
+ * in cache and it's not expired means it's in tombstone
20647
+ * and we throw an Error
20648
+ *
20649
+ * @param model the model to check
20650
+ * @param modelId the object id to check
20651
+ * @returns the matching cache entry, or undefined.
20652
+ *
20653
+ * @category Cache API
20654
+ */
20655
+ const isInTombstone = (model, modelId) => {
20656
+ const { log, cache } = getActiveClient();
20657
+ const key = [model, CACHE_KEY_TOMBSTONE, modelId];
20658
+ if (!cache)
20659
+ return;
20660
+ log('cache/api/isInTombstone', key);
20661
+ const isInTombstone = pullFromCache(key);
20662
+ const { lifeSpan } = queryOptions('cache_then_server', CACHE_LIFESPAN_TOMBSTONE);
20663
+ if (isInTombstone && isFresh(isInTombstone.data, lifeSpan)) {
20664
+ throw new ASCApiError('Item not found!', 400400 /* Amity.ServerError.ITEM_NOT_FOUND */, "error" /* Amity.ErrorLevel.ERROR */);
20665
+ }
20666
+ };
20667
+
20668
+ /**
20669
+ * ```js
20670
+ * import { pushToTombstone } from '@amityco/ts-sdk'
20671
+ * pushToTombstone(["message", "messageId"], { cachedAt: Date.now() })
20672
+ * ```
20673
+ *
20674
+ * Removes an existing {@link Amity.CacheEntry} from the {@link Amity.Client}'s
20675
+ * {@link Amity.Cache} from a given {@link Amity.CacheKey}
20676
+ *
20677
+ * @param model the model to remove and push to Tombstone
20678
+ * @param modelId the related model id
20679
+ *
20680
+ * @category Cache API
20681
+ * @hidden
20682
+ */
20683
+ const pushToTombstone = (model, modelId) => {
20684
+ const { log, cache } = getActiveClient();
20685
+ const cacheKey = [model, CACHE_KEY_TOMBSTONE, modelId];
20686
+ const data = { cachedAt: Date.now() };
20687
+ if (!cache)
20688
+ return;
20689
+ log('cache/api/pushToTombstone', { cacheKey, data });
20690
+ dropFromCache([model, CACHE_KEY_GET, modelId], true);
20691
+ pushToCache(cacheKey, data);
20692
+ };
20693
+
20567
20694
  /**
20568
20695
  * ```js
20569
20696
  * import { getUser } from '@amityco/ts-sdk'
@@ -20578,15 +20705,30 @@ const isConnected = () => {
20578
20705
  * @category User API
20579
20706
  * @async
20580
20707
  */
20581
- const getUser = async (userId) => {
20708
+ const getUser = async (userId, isLive = false) => {
20582
20709
  const client = getActiveClient();
20583
20710
  client.log('user/getUser', userId);
20584
- // API-FIX: endpoint should not be /list, parameters should be querystring.
20585
- const { data } = await client.http.get(`/api/v3/users/${encodeURIComponent(userId)}`);
20711
+ if (!isLive) {
20712
+ console.log('getUser will be deprecated on 25th November 2022, please use liveUser instead.');
20713
+ }
20714
+ isInTombstone('user', userId);
20715
+ let data;
20716
+ try {
20717
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
20718
+ const response = await client.http.get(`/api/v3/users/${encodeURIComponent(userId)}`);
20719
+ data = response.data;
20720
+ }
20721
+ catch (error) {
20722
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
20723
+ pushToTombstone('user', userId);
20724
+ }
20725
+ throw error;
20726
+ }
20586
20727
  const cachedAt = client.cache && Date.now();
20587
20728
  if (client.cache)
20588
20729
  ingestInCache(data, { cachedAt });
20589
20730
  const { users } = data;
20731
+ fireEvent('user.fetched', data);
20590
20732
  return {
20591
20733
  data: users.find(user => user.userId === userId),
20592
20734
  cachedAt,
@@ -20636,6 +20778,7 @@ const getUsers = async (userIds) => {
20636
20778
  const cachedAt = client.cache && Date.now();
20637
20779
  if (client.cache)
20638
20780
  ingestInCache(data, { cachedAt });
20781
+ fireEvent('user.fetched', data);
20639
20782
  return {
20640
20783
  data: data.users,
20641
20784
  cachedAt,
@@ -20735,6 +20878,7 @@ const queryUsers = async (query = {}) => {
20735
20878
  const cacheKey = ['user', 'query', query];
20736
20879
  pushToCache(cacheKey, { users: users.map(getResolver('user')), paging });
20737
20880
  }
20881
+ fireEvent('user.fetched', data);
20738
20882
  const prevPage = toPage(paging.previous);
20739
20883
  const nextPage = toPage(paging.next);
20740
20884
  return { data: users, cachedAt, prevPage, nextPage };
@@ -20798,12 +20942,30 @@ const updateUser = async (userId, patch) => {
20798
20942
  if (client.cache)
20799
20943
  ingestInCache(data, { cachedAt });
20800
20944
  const { users } = data;
20945
+ fireEvent('user.updated', data);
20801
20946
  return {
20802
20947
  data: users.find(user => user.userId === userId),
20803
20948
  cachedAt,
20804
20949
  };
20805
20950
  };
20806
20951
 
20952
+ /**
20953
+ * ```js
20954
+ * import { onUserFetched } from '@amityco/ts-sdk'
20955
+ * const dispose = onUserFetched(user => {
20956
+ * // ...
20957
+ * })
20958
+ * ```
20959
+ *
20960
+ * Fired when a {@link Amity.User} has been fetched
20961
+ *
20962
+ * @param callback The function to call when the event was fired
20963
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
20964
+ *
20965
+ * @category User Events
20966
+ */
20967
+ const onUserFetched = (callback) => createUserEventSubscriber('user.fetched', callback);
20968
+
20807
20969
  /**
20808
20970
  * ```js
20809
20971
  * import { onUserUpdated } from '@amityco/ts-sdk'
@@ -20872,6 +21034,68 @@ const onUserUnflagged = (callback) => createUserEventSubscriber('user.unflagged'
20872
21034
  */
20873
21035
  const onUserFlagCleared = (callback) => createUserEventSubscriber('user.flagCleared', callback);
20874
21036
 
21037
+ const COLLECTION_DEFAULT_PAGINATION_LIMIT = 5;
21038
+ const COLLECTION_DEFAULT_CACHING_POLICY = 'cache_then_server';
21039
+ const ENABLE_CACHE_MESSAGE = 'For using Live Collection feature you need to enable Cache!';
21040
+ const LIVE_OBJECT_ENABLE_CACHE_MESSAGE = 'For using Live Object feature you need to enable Cache!';
21041
+ const UNSYNCED_OBJECT_CACHED_AT_MESSAGE = 'Observing unsynced object is not supported by Live Object.';
21042
+ const UNSYNCED_OBJECT_CACHED_AT_VALUE = -5;
21043
+
21044
+ /**
21045
+ * ```js
21046
+ * import { liveUser } from '@amityco/ts-sdk'
21047
+ *
21048
+ * let users = []
21049
+ * const unsub = liveUser(userId, response => merge(users, response.data))
21050
+ * ```
21051
+ *
21052
+ * Observe all mutation on a given {@link Amity.User}
21053
+ *
21054
+ * @param userId the ID of the user to observe
21055
+ * @param callback the function to call when new data are available
21056
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the users
21057
+ *
21058
+ * @category Message Live Object
21059
+ */
21060
+ const liveUser = (userId, callback) => {
21061
+ const { log, cache } = getActiveClient();
21062
+ let user;
21063
+ if (!cache) {
21064
+ console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
21065
+ }
21066
+ const timestamp = Date.now();
21067
+ log(`liveUser(tmpid: ${timestamp}) > listen`);
21068
+ const disposers = [];
21069
+ const dispatcher = (data) => {
21070
+ var _a;
21071
+ // we check updatedAt to see if the current snapshot is new so
21072
+ // we won't send old data back, only fresh new data
21073
+ 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')
21074
+ return;
21075
+ callback(data);
21076
+ user = data.data;
21077
+ };
21078
+ const realtimeRouter = (user, action) => {
21079
+ dispatcher({ loading: false, data: user, origin: 'event' });
21080
+ };
21081
+ const onFetch = () => {
21082
+ const query = createQuery(getUser, userId, true);
21083
+ runQuery(query, ({ loading, data, error, origin }) => {
21084
+ dispatcher({ loading, data, origin, error });
21085
+ if (error) {
21086
+ // Terminate observe functionality on error
21087
+ disposers.forEach(fn => fn());
21088
+ }
21089
+ });
21090
+ };
21091
+ 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)));
21092
+ onFetch();
21093
+ return () => {
21094
+ log(`liveUser(tmpid: ${timestamp}) > dispose`);
21095
+ disposers.forEach(fn => fn());
21096
+ };
21097
+ };
21098
+
20875
21099
  /**
20876
21100
  * ```js
20877
21101
  * import { observeUser } from '@amityco/ts-sdk'
@@ -20891,6 +21115,7 @@ const observeUser = (userId, callback) => {
20891
21115
  const { log } = getActiveClient();
20892
21116
  const timestamp = Date.now();
20893
21117
  log(`observeUser(tmpid: ${timestamp}) > listen`);
21118
+ console.log('observeUser will be deprecated on 25th November 2022, please use liveUser instead.');
20894
21119
  // wrapper function to make sure
20895
21120
  const router = (result, action) => {
20896
21121
  var _a, _b, _c;
@@ -21300,15 +21525,30 @@ const dispatchReactable = (referenceType, model) => {
21300
21525
  * @category Message API
21301
21526
  * @async
21302
21527
  */
21303
- const getMessage = async (messageId) => {
21528
+ const getMessage = async (messageId, isLive = false) => {
21304
21529
  const client = getActiveClient();
21305
21530
  client.log('message/getMessage', messageId);
21306
- // API-FIX: endpoint should not be /list, parameters should be querystring.
21307
- const { data } = await client.http.get(`/api/v3/messages/${encodeURIComponent(messageId)}`);
21531
+ if (!isLive) {
21532
+ console.log('getMessage will be deprecated on 15th November 2022, please use liveMessage instead.');
21533
+ }
21534
+ isInTombstone('message', messageId);
21535
+ let data;
21536
+ try {
21537
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
21538
+ const response = await client.http.get(`/api/v3/messages/${encodeURIComponent(messageId)}`);
21539
+ data = response.data;
21540
+ }
21541
+ catch (error) {
21542
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
21543
+ pushToTombstone('message', messageId);
21544
+ }
21545
+ throw error;
21546
+ }
21308
21547
  const cachedAt = client.cache && Date.now();
21309
21548
  if (client.cache)
21310
21549
  ingestInCache(data, { cachedAt });
21311
21550
  const { messages } = data;
21551
+ fireEvent('v3.message.didFetch', { messages });
21312
21552
  return {
21313
21553
  data: messages.find(message => message.messageId === messageId),
21314
21554
  cachedAt,
@@ -21365,8 +21605,10 @@ const getMessages = async (messageIds) => {
21365
21605
  const cachedAt = client.cache && Date.now();
21366
21606
  if (client.cache)
21367
21607
  ingestInCache(data, { cachedAt });
21608
+ const { messages } = data;
21609
+ fireEvent('v3.message.didFetch', { messages });
21368
21610
  return {
21369
- data: data.messages,
21611
+ data: messages,
21370
21612
  cachedAt,
21371
21613
  };
21372
21614
  };
@@ -21443,6 +21685,7 @@ const queryMessages = async (query) => {
21443
21685
  ];
21444
21686
  pushToCache(cacheKey, { messages: messages.map(getResolver('message')), paging });
21445
21687
  }
21688
+ fireEvent('v3.message.didFetch', { messages });
21446
21689
  const nextPage = toPage(paging.next);
21447
21690
  const prevPage = toPage(paging.previous);
21448
21691
  return { data: messages, cachedAt, prevPage, nextPage };
@@ -21508,8 +21751,8 @@ const createMessage = async (bundle) => {
21508
21751
  const cachedAt = client.cache && Date.now();
21509
21752
  if (client.cache)
21510
21753
  ingestInCache(data, { cachedAt });
21511
- // no need for event, fired by server
21512
21754
  const { messages } = data;
21755
+ fireEvent('v3.message.didCreate', { messages });
21513
21756
  return {
21514
21757
  data: messages[0],
21515
21758
  cachedAt,
@@ -21551,11 +21794,12 @@ createMessage.optimistically = (bundle) => {
21551
21794
  // as reused to update created and updated time, which should be the same
21552
21795
  const createdTime = new Date().toISOString();
21553
21796
  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);
21554
- pushToCache(['message', 'get', message.messageId], message, { cachedAt: -1 });
21797
+ const cachedAt = UNSYNCED_OBJECT_CACHED_AT_VALUE;
21798
+ pushToCache(['message', 'get', message.messageId], message, { cachedAt });
21555
21799
  fireEvent('v3.message.didCreate', { messages: [message] });
21556
21800
  return {
21801
+ cachedAt,
21557
21802
  data: message,
21558
- cachedAt: -1,
21559
21803
  };
21560
21804
  };
21561
21805
 
@@ -21584,6 +21828,7 @@ const updateMessage = async (messageId, patch) => {
21584
21828
  if (client.cache)
21585
21829
  ingestInCache(data, { cachedAt });
21586
21830
  const { messages } = data;
21831
+ fireEvent('v3.message.didUpdate', { messages });
21587
21832
  return {
21588
21833
  data: messages.find(message => message.messageId === messageId),
21589
21834
  cachedAt,
@@ -21643,7 +21888,7 @@ const deleteMessage = async (messageId) => {
21643
21888
  // API-FIX: This endpoint has not been implemented yet.
21644
21889
  await client.http.delete(`/api/v3/messages/${encodeURIComponent(messageId)}`);
21645
21890
  const deleted = await getMessage(messageId);
21646
- // no need for event, fired by server
21891
+ fireEvent('v3.message.didDelete', { messages: [deleted.data] });
21647
21892
  return deleted.data;
21648
21893
  };
21649
21894
  /**
@@ -21830,6 +22075,7 @@ getPosts.locally = (postIds) => {
21830
22075
  const getPost = async (postId) => {
21831
22076
  const client = getActiveClient();
21832
22077
  client.log('post/getPost', postId);
22078
+ isInTombstone('post', postId);
21833
22079
  let data;
21834
22080
  try {
21835
22081
  // API-FIX: endpoint should not be /list, parameters should be querystring.
@@ -21837,8 +22083,8 @@ const getPost = async (postId) => {
21837
22083
  data = response.data;
21838
22084
  }
21839
22085
  catch (error) {
21840
- if ((error === null || error === void 0 ? void 0 : error.code) === 400400 /* Amity.ServerError.ITEM_NOT_FOUND */) {
21841
- dropFromCache(['post', 'get', postId], true);
22086
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
22087
+ pushToTombstone('post', postId);
21842
22088
  }
21843
22089
  throw error;
21844
22090
  }
@@ -22618,7 +22864,7 @@ const deletePost = async (postId, permanent = false) => {
22618
22864
  fireEvent('post.deleted', { posts: [deleted] });
22619
22865
  if (permanent) {
22620
22866
  setTimeout(() => {
22621
- dropFromCache(['post', 'get', postId], true);
22867
+ pushToTombstone('post', postId);
22622
22868
  }, 0);
22623
22869
  }
22624
22870
  else {
@@ -23872,10 +24118,6 @@ const onReactorRemoved = (referenceType, referenceId, callback) => {
23872
24118
  return createEventSubscriber(client, 'comment.removeReaction', 'comment.removeReaction', filter);
23873
24119
  };
23874
24120
 
23875
- const COLLECTION_DEFAULT_PAGINATION_LIMIT = 5;
23876
- const COLLECTION_DEFAULT_CACHING_POLICY = 'cache_then_server';
23877
- const ENABLE_CACHE_MESSAGE = 'For using Live Collection feature you need to enable Cache!';
23878
-
23879
24121
  /**
23880
24122
  * ```js
23881
24123
  * import { liveReactions } from '@amityco/ts-sdk'
@@ -24152,9 +24394,24 @@ const queryChannels = async (query) => {
24152
24394
  * @category Channel API
24153
24395
  */
24154
24396
  queryChannels.locally = (query) => {
24397
+ var _a, _b;
24155
24398
  const client = getActiveClient();
24156
24399
  client.log('channel/queryChannels.locally', query);
24157
- // TODO
24400
+ const _c = query !== null && query !== void 0 ? query : {}, { page = { limit: 10 } } = _c, params = __rest(_c, ["page"]);
24401
+ const cacheKey = ['channel', 'query', Object.assign(Object.assign({}, params), { options: Object.assign({}, page) })];
24402
+ const { data, cachedAt } = (_a = pullFromCache(cacheKey)) !== null && _a !== void 0 ? _a : {};
24403
+ if (!(data === null || data === void 0 ? void 0 : data.channels.length))
24404
+ return;
24405
+ const channels = data.channels
24406
+ // ck -> cacheKey, abbrevated to avoid confusion from the above cache key
24407
+ .map(ck => pullFromCache(['channel', 'get', ck]))
24408
+ .filter(Boolean)
24409
+ .map(({ data }) => data);
24410
+ const prevPage = toPage(data === null || data === void 0 ? void 0 : data.paging.previous);
24411
+ const nextPage = toPage(data === null || data === void 0 ? void 0 : data.paging.next);
24412
+ return channels.length === ((_b = data === null || data === void 0 ? void 0 : data.channels) === null || _b === void 0 ? void 0 : _b.length)
24413
+ ? { data: channels, cachedAt, prevPage, nextPage }
24414
+ : undefined;
24158
24415
  };
24159
24416
 
24160
24417
  /**
@@ -24431,8 +24688,8 @@ const leaveChannel = async (channelId) => {
24431
24688
  const queryChannelMembers = async (query) => {
24432
24689
  const client = getActiveClient();
24433
24690
  client.log('channel/queryChannelMembers', query);
24434
- const _a = query !== null && query !== void 0 ? query : {}, { page, channelId } = _a, params = __rest(_a, ["page", "channelId"]);
24435
- const { data: queryPayload } = await client.http.get(`/api/v4/channels/${encodeURIComponent(channelId)}/users`, {
24691
+ const _a = query !== null && query !== void 0 ? query : {}, { page = { limit: 10 } } = _a, params = __rest(_a, ["page"]);
24692
+ const { data: queryPayload } = await client.http.get(`/api/v4/channels/${encodeURIComponent(params.channelId)}/users`, {
24436
24693
  params: Object.assign(Object.assign({}, params), { options: {
24437
24694
  token: toToken(page, 'skiplimit'),
24438
24695
  } }),
@@ -24443,6 +24700,15 @@ const queryChannelMembers = async (query) => {
24443
24700
  const cachedAt = client.cache && Date.now();
24444
24701
  if (client.cache) {
24445
24702
  ingestInCache(data);
24703
+ const cacheKey = [
24704
+ 'channelUsers',
24705
+ 'query',
24706
+ Object.assign(Object.assign({}, params), { options: Object.assign({}, page) }),
24707
+ ];
24708
+ pushToCache(cacheKey, {
24709
+ channelUsers: channelUsers.map(({ channelId, userId }) => getResolver('channelUsers')({ channelId, userId })),
24710
+ paging,
24711
+ });
24446
24712
  }
24447
24713
  const nextPage = toPage(paging.next);
24448
24714
  const prevPage = toPage(paging.previous);
@@ -24462,9 +24728,30 @@ const queryChannelMembers = async (query) => {
24462
24728
  * @category Post API
24463
24729
  */
24464
24730
  queryChannelMembers.locally = (query) => {
24731
+ var _a, _b;
24465
24732
  const client = getActiveClient();
24466
- client.log('channel/queryChannelMembers', query);
24467
- // TODO
24733
+ client.log('channel/queryChannelMembers.locally', query);
24734
+ if (!client.cache)
24735
+ return;
24736
+ const { page = { limit: 10 } } = query, params = __rest(query, ["page"]);
24737
+ const cacheKey = [
24738
+ 'channelUsers',
24739
+ 'query',
24740
+ Object.assign(Object.assign({}, params), { options: Object.assign({}, page) }),
24741
+ ];
24742
+ const { data, cachedAt } = (_a = pullFromCache(cacheKey)) !== null && _a !== void 0 ? _a : {};
24743
+ if (!(data === null || data === void 0 ? void 0 : data.channelUsers.length))
24744
+ return;
24745
+ const channelUsers = data.channelUsers
24746
+ // ck -> cacheKey, abbrevated to avoid confusion from the above cache key
24747
+ .map(ck => pullFromCache(['channelUsers', 'get', ck]))
24748
+ .filter(Boolean)
24749
+ .map(({ data }) => data);
24750
+ const prevPage = toPage(data === null || data === void 0 ? void 0 : data.paging.previous);
24751
+ const nextPage = toPage(data === null || data === void 0 ? void 0 : data.paging.next);
24752
+ return channelUsers.length === ((_b = data === null || data === void 0 ? void 0 : data.channelUsers) === null || _b === void 0 ? void 0 : _b.length)
24753
+ ? { data: channelUsers, cachedAt, prevPage, nextPage }
24754
+ : undefined;
24468
24755
  };
24469
24756
 
24470
24757
  /**
@@ -24812,6 +25099,56 @@ const onChannelMemberRemoved = (callback) => {
24812
25099
  return createEventSubscriber(client, 'onChannelMemberRemoved', 'v3.channel.didRemoveUsers', filter);
24813
25100
  };
24814
25101
 
25102
+ /**
25103
+ * ```js
25104
+ * import { onChannelMemberBanned } from '@amityco/ts-sdk'
25105
+ * const dispose = onChannelMemberBanned((channel, member) => {
25106
+ * // ...
25107
+ * })
25108
+ * ```
25109
+ *
25110
+ * Fired when any {@link Amity.User} has been banned from any {@link Amity.Channel}
25111
+ *
25112
+ * @param callback The function to call when the event was fired
25113
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25114
+ *
25115
+ * @category Channel Events
25116
+ */
25117
+ const onChannelMemberBanned = (callback) => {
25118
+ const client = getActiveClient();
25119
+ const filter = (payload) => {
25120
+ const data = prepareChannelPayload(payload);
25121
+ ingestInCache(data);
25122
+ callback(data.channels[0], data.channelUsers.find(cu => cu.membership === 'banned'));
25123
+ };
25124
+ return createEventSubscriber(client, 'onChannelMemberBanned', 'v3.channel.didBan', filter);
25125
+ };
25126
+
25127
+ /**
25128
+ * ```js
25129
+ * import { onChannelMemberUnbanned } from '@amityco/ts-sdk'
25130
+ * const dispose = onChannelMemberUnbanned((channel, member) => {
25131
+ * // ...
25132
+ * })
25133
+ * ```
25134
+ *
25135
+ * Fired when any {@link Amity.User} has been unbanned from any {@link Amity.Channel}
25136
+ *
25137
+ * @param callback The function to call when the event was fired
25138
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25139
+ *
25140
+ * @category Channel Events
25141
+ */
25142
+ const onChannelMemberUnbanned = (callback) => {
25143
+ const client = getActiveClient();
25144
+ const filter = (payload) => {
25145
+ const data = prepareChannelPayload(payload);
25146
+ ingestInCache(data);
25147
+ callback(data.channels[0], data.channelUsers.find(cu => cu.membership === 'none'));
25148
+ };
25149
+ return createEventSubscriber(client, 'onChannelMemberBanned', 'v3.channel.didUnban', filter);
25150
+ };
25151
+
24815
25152
  /**
24816
25153
  * ```js
24817
25154
  * import { observeChannel } from '@amityco/ts-sdk'
@@ -24906,7 +25243,7 @@ const observeChannels = (callback) => {
24906
25243
  * @category Channel Live Collection
24907
25244
  */
24908
25245
  const liveChannels = (params, callback, config) => {
24909
- const { log, cache } = getActiveClient();
25246
+ const { log, cache, userId } = getActiveClient();
24910
25247
  if (!cache) {
24911
25248
  console.log(ENABLE_CACHE_MESSAGE);
24912
25249
  }
@@ -24934,6 +25271,10 @@ const liveChannels = (params, callback, config) => {
24934
25271
  if (params.excludeTags) {
24935
25272
  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); })); });
24936
25273
  }
25274
+ // userId is required to be able to filter channel by current active user
25275
+ if (params.membership && userId) {
25276
+ channels = filterByChannelMembership(channels, params.membership, userId);
25277
+ }
24937
25278
  const sortBy = params.sortBy || 'lastCreated';
24938
25279
  if (sortBy === 'lastCreated' || sortBy === 'firstCreated') {
24939
25280
  channels = channels.sort(sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated);
@@ -25043,7 +25384,20 @@ const liveChannelMembers = (params, callback, config) => {
25043
25384
  .filter(Boolean)
25044
25385
  .map(({ data }) => data)) !== null && _a !== void 0 ? _a : [];
25045
25386
  channelMembers = filterByPropEquality(channelMembers, 'roles', params.roles);
25046
- channelMembers = filterByPropInclusion(channelMembers, 'membership', params.memberships);
25387
+ if (params.memberships) {
25388
+ /*
25389
+ * even though membership includes muted as a possible value
25390
+ * when querying the server.
25391
+ * Muted is specified under seperarte property namely isMuted
25392
+ * Hence why I've seperately checked for it's equality
25393
+ */
25394
+ if (params.memberships.some(m => ['member', 'banned'].includes(m))) {
25395
+ channelMembers = filterByPropInclusion(channelMembers, 'membership', params.memberships);
25396
+ }
25397
+ if (params.memberships.includes('muted')) {
25398
+ channelMembers = filterByPropEquality(channelMembers, 'isMuted', true);
25399
+ }
25400
+ }
25047
25401
  if (params.search) {
25048
25402
  const containsMatcher = new RegExp(params.search);
25049
25403
  channelMembers = channelMembers.filter(m => m.userId.match(containsMatcher));
@@ -25071,7 +25425,7 @@ const liveChannelMembers = (params, callback, config) => {
25071
25425
  if (action === 'onMemberAdded') {
25072
25426
  collection.data = [...new Set([channelMemberCacheId, ...collection.data])];
25073
25427
  }
25074
- else {
25428
+ if (action === 'onMemberRemoved') {
25075
25429
  collection.data = collection.data.filter(m => m !== channelMemberCacheId);
25076
25430
  }
25077
25431
  pushToCache(cacheKey, collection);
@@ -25098,7 +25452,7 @@ const liveChannelMembers = (params, callback, config) => {
25098
25452
  responder(data);
25099
25453
  }, queryOptions(policy));
25100
25454
  };
25101
- disposers.push(onChannelMemberAdded((_, member) => realtimeRouter(member, 'onMemberAdded')), onChannelMemberRemoved((_, member) => realtimeRouter(member, 'onMemberRemoved')));
25455
+ disposers.push(onChannelMemberAdded((_, member) => realtimeRouter(member, 'onMemberAdded')), onChannelMemberRemoved((_, member) => realtimeRouter(member, 'onMemberRemoved')), onChannelMemberBanned((_, member) => realtimeRouter(member, 'onChannelMemberBanned')), onChannelMemberUnbanned((_, member) => realtimeRouter(member, 'onChannelMemberUnbanned')));
25102
25456
  onFetch();
25103
25457
  return () => {
25104
25458
  log(`liveChannelMembers(tmpid: ${timestamp}) > dispose`);
@@ -25185,82 +25539,92 @@ const onMessageDeleted = (callback) => {
25185
25539
 
25186
25540
  /**
25187
25541
  * ```js
25188
- * import { observeMessage } from '@amityco/ts-sdk'
25189
- *
25190
- * let message = {}
25191
- * const unsub = observeMessage(messageId, updated => message = updated)
25542
+ * import { onMessageFetched } from '@amityco/ts-sdk'
25543
+ * const dispose = onMessageFetched(message => {
25544
+ * // ...
25545
+ * })
25192
25546
  * ```
25193
25547
  *
25194
- * Observe all mutations on a {@link Amity.Message} given a single messageId
25548
+ * Fired when an {@link Amity.Message} has been fetched
25195
25549
  *
25196
- * @param client the client to observe the message with
25197
- * @param messageId the ID of the message to observe
25198
- * @param callback the function to call when new data are available
25199
- * @param policy a query policy option for this observer
25200
- * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the message
25550
+ * @param callback The function to call when the event was fired
25551
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25201
25552
  *
25202
- * @category Message Observer
25553
+ * @category Message Events
25203
25554
  */
25204
- const observeMessage = (messageId, callback, policy = 'cache_then_server') => {
25205
- const { log } = getActiveClient();
25206
- const timestamp = Date.now();
25207
- log(`observeMessage(tmpid: ${timestamp}) > listen`);
25208
- // wrapper function to make sure
25209
- const router = (result, action) => {
25210
- var _a, _b, _c;
25211
- // filter function
25212
- if (((_a = result.data) === null || _a === void 0 ? void 0 : _a.messageId) !== messageId)
25213
- return;
25214
- if (callback instanceof Function)
25215
- return callback(result);
25216
- if (action !== 'onFetch')
25217
- (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, result);
25218
- (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, result);
25219
- };
25220
- const disposers = [];
25221
- disposers.push(onMessageUpdated(data => router({ data, loading: false, origin: 'event' }, 'onUpdate')), onMessageDeleted(data => router({ data, loading: false, origin: 'event' }, 'onDelete')));
25222
- if (policy !== 'no_fetch') {
25223
- runQuery(createQuery(getMessage, messageId), result => result.data && router(result, 'onFetch'), queryOptions(policy));
25224
- }
25225
- return () => {
25226
- log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25227
- disposers.forEach(fn => fn());
25555
+ const onMessageFetched = (callback) => {
25556
+ const client = getActiveClient();
25557
+ const filter = (payload) => {
25558
+ ingestInCache(payload);
25559
+ callback(payload.messages[0]);
25228
25560
  };
25561
+ return createEventSubscriber(client, 'message/onMessageFetched', 'v3.message.didFetch', filter);
25229
25562
  };
25230
25563
 
25231
25564
  /**
25232
25565
  * ```js
25233
- * import { observeMessages } from '@amityco/ts-sdk'
25566
+ * import { liveMessage } from '@amityco/ts-sdk'
25234
25567
  *
25235
25568
  * let messages = []
25236
- * const unsub = observeMessages(channelId, message => merge(messages, message))
25569
+ * const unsub = liveMessage(messageId, response => merge(messages, response.data))
25237
25570
  * ```
25238
25571
  *
25239
- * Observe all mutations on a list of {@link Amity.Message} for a given {@link Amity.Channel} object
25572
+ * Observe all mutation on a given {@link Amity.Message}
25240
25573
  *
25241
- * @param channelId the ID of the channel where to observe the messages
25574
+ * @param messageId the ID of the message to observe
25242
25575
  * @param callback the function to call when new data are available
25243
25576
  * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
25244
25577
  *
25245
- * @category Message Observer
25578
+ * @category Message Live Object
25246
25579
  */
25247
- const observeMessages = (channelId, callback) => {
25248
- const { log } = getActiveClient();
25580
+ const liveMessage = (messageId, callback) => {
25581
+ const { log, cache } = getActiveClient();
25582
+ let message;
25583
+ let isUnsyncedObject = false;
25584
+ if (!cache) {
25585
+ console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
25586
+ }
25249
25587
  const timestamp = Date.now();
25250
- log(`observeMessages(tmpid: ${timestamp}) > listen`);
25588
+ log(`liveMessage(tmpid: ${timestamp}) > listen`);
25251
25589
  const disposers = [];
25252
- const router = (message, action) => {
25253
- var _a, _b, _c;
25254
- if (((_a = message.data) === null || _a === void 0 ? void 0 : _a.channelId) !== channelId)
25590
+ const dispatcher = (data) => {
25591
+ var _a;
25592
+ // we check updatedAt to see if the current snapshot is new so
25593
+ // we won't send old data back, only fresh new data
25594
+ 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')
25255
25595
  return;
25256
- if (callback instanceof Function)
25257
- return callback(message);
25258
- (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, message);
25259
- (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, message);
25596
+ callback(data);
25597
+ message = data.data;
25260
25598
  };
25261
- 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')));
25599
+ const realtimeRouter = (message, action) => {
25600
+ dispatcher({ loading: false, data: message, origin: 'event' });
25601
+ };
25602
+ const onFetch = () => {
25603
+ const query = createQuery(getMessage, messageId, true);
25604
+ runQuery(query, ({ loading, data, error, origin, cachedAt }) => {
25605
+ if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
25606
+ dispatcher({
25607
+ data,
25608
+ origin,
25609
+ loading: false,
25610
+ error: new ASCApiError(UNSYNCED_OBJECT_CACHED_AT_MESSAGE, 800800 /* Amity.ClientError.DISALOOW_UNSYNCED_OBJECT */, "error" /* Amity.ErrorLevel.ERROR */),
25611
+ });
25612
+ isUnsyncedObject = true;
25613
+ disposers.forEach(fn => fn());
25614
+ }
25615
+ else if (!isUnsyncedObject) {
25616
+ dispatcher({ loading, data, origin, error });
25617
+ }
25618
+ if (error) {
25619
+ // Terminate observe functionality on error
25620
+ disposers.forEach(fn => fn());
25621
+ }
25622
+ });
25623
+ };
25624
+ disposers.push(onMessageFetched(message => realtimeRouter(message)), onMessageUpdated(message => realtimeRouter(message)), onMessageDeleted(message => realtimeRouter(message)));
25625
+ onFetch();
25262
25626
  return () => {
25263
- log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25627
+ log(`liveMessage(tmpid: ${timestamp}) > dispose`);
25264
25628
  disposers.forEach(fn => fn());
25265
25629
  };
25266
25630
  };
@@ -25349,7 +25713,7 @@ const liveMessages = (params, callback, config) => {
25349
25713
  responder(data);
25350
25714
  }, queryOptions(policy));
25351
25715
  };
25352
- disposers.push(onMessageCreated(message => realtimeRouter(message, 'onCreate')), onMessageDeleted(message => realtimeRouter(message, 'onDelete')), onMessageUpdated(message => realtimeRouter(message, 'onUpdate')));
25716
+ disposers.push(onMessageFetched(message => realtimeRouter(message, 'onFetch')), onMessageCreated(message => realtimeRouter(message, 'onCreate')), onMessageDeleted(message => realtimeRouter(message, 'onDelete')), onMessageUpdated(message => realtimeRouter(message, 'onUpdate')));
25353
25717
  onFetch();
25354
25718
  return () => {
25355
25719
  log(`liveMessages(tmpid: ${timestamp}) > dispose`);
@@ -25357,6 +25721,89 @@ const liveMessages = (params, callback, config) => {
25357
25721
  };
25358
25722
  };
25359
25723
 
25724
+ /**
25725
+ * ```js
25726
+ * import { observeMessage } from '@amityco/ts-sdk'
25727
+ *
25728
+ * let message = {}
25729
+ * const unsub = observeMessage(messageId, updated => message = updated)
25730
+ * ```
25731
+ *
25732
+ * Observe all mutations on a {@link Amity.Message} given a single messageId
25733
+ *
25734
+ * @param client the client to observe the message with
25735
+ * @param messageId the ID of the message to observe
25736
+ * @param callback the function to call when new data are available
25737
+ * @param policy a query policy option for this observer
25738
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the message
25739
+ *
25740
+ * @category Message Observer
25741
+ */
25742
+ const observeMessage = (messageId, callback, policy = 'cache_then_server') => {
25743
+ const { log } = getActiveClient();
25744
+ const timestamp = Date.now();
25745
+ log(`observeMessage(tmpid: ${timestamp}) > listen`);
25746
+ console.log('observeMessage will be deprecated on 15th November 2022, please use liveMessage instead.');
25747
+ // wrapper function to make sure
25748
+ const router = (result, action) => {
25749
+ var _a, _b, _c;
25750
+ // filter function
25751
+ if (((_a = result.data) === null || _a === void 0 ? void 0 : _a.messageId) !== messageId)
25752
+ return;
25753
+ if (callback instanceof Function)
25754
+ return callback(result);
25755
+ if (action !== 'onFetch')
25756
+ (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, result);
25757
+ (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, result);
25758
+ };
25759
+ const disposers = [];
25760
+ disposers.push(onMessageUpdated(data => router({ data, loading: false, origin: 'event' }, 'onUpdate')), onMessageDeleted(data => router({ data, loading: false, origin: 'event' }, 'onDelete')));
25761
+ if (policy !== 'no_fetch') {
25762
+ runQuery(createQuery(getMessage, messageId), result => result.data && router(result, 'onFetch'), queryOptions(policy));
25763
+ }
25764
+ return () => {
25765
+ log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25766
+ disposers.forEach(fn => fn());
25767
+ };
25768
+ };
25769
+
25770
+ /**
25771
+ * ```js
25772
+ * import { observeMessages } from '@amityco/ts-sdk'
25773
+ *
25774
+ * let messages = []
25775
+ * const unsub = observeMessages(channelId, message => merge(messages, message))
25776
+ * ```
25777
+ *
25778
+ * Observe all mutations on a list of {@link Amity.Message} for a given {@link Amity.Channel} object
25779
+ *
25780
+ * @param channelId the ID of the channel where to observe the messages
25781
+ * @param callback the function to call when new data are available
25782
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
25783
+ *
25784
+ * @category Message Observer
25785
+ */
25786
+ const observeMessages = (channelId, callback) => {
25787
+ const { log } = getActiveClient();
25788
+ const timestamp = Date.now();
25789
+ log(`observeMessages(tmpid: ${timestamp}) > listen`);
25790
+ const disposers = [];
25791
+ const router = (message, action) => {
25792
+ var _a, _b, _c;
25793
+ if (((_a = message.data) === null || _a === void 0 ? void 0 : _a.channelId) !== channelId)
25794
+ return;
25795
+ if (callback instanceof Function)
25796
+ return callback(message);
25797
+ (_b = callback.onEvent) === null || _b === void 0 ? void 0 : _b.call(callback, action, message);
25798
+ (_c = callback[action]) === null || _c === void 0 ? void 0 : _c.call(callback, message);
25799
+ };
25800
+ 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')));
25801
+ return () => {
25802
+ log(`observeMessages(tmpid: ${timestamp}) > dispose`);
25803
+ disposers.forEach(fn => fn());
25804
+ };
25805
+ };
25806
+
25360
25807
  const createCommunityEventSubscriber = (event, callback) => {
25361
25808
  const client = getActiveClient();
25362
25809
  const filter = (payload) => {
@@ -27539,4 +27986,4 @@ const createUserToken = async (apiKey, apiRegion, params) => {
27539
27986
  return { accessToken: data.accessToken };
27540
27987
  };
27541
27988
 
27542
- export { API_REGIONS, CommunityPostSettingMaps, CommunityPostSettings, ContentFeedType, DefaultCommunityPostSetting, FileType, SubscriptionLevels, VERSION$1 as VERSION, VideoResolution, VideoSize, VideoTranscodingStatus, acceptFollower, addChannelMembers, addChannelMembersRole, addCommunityMembers, addCommunityMembersRoles, addReaction, approvePost, backupCache, banChannelMembers, closePoll, connectClient, createChannel, createClient, createComment, createCommunity, createFile, createImage, createMessage, createPoll, createPost, createQuery, createReport, createStream, createUserToken, createVideo, declineFollower, declinePost, deleteChannel, deleteComment, deleteCommunity, deleteFile, deleteMessage, deletePoll, deletePost, deleteReport, deleteStream, disableCache, disconnectClient, disposeStream, dropFromCache, enableCache, fileUrlWithSize, filterByPropEquality, filterByPropInclusion, follow, getActiveClient, getCategory, getChannel, getChannels, getComment, getCommentTopic, getComments, getCommunities, getCommunity, getCommunityTopic, getFeedSettings, getFile, getFollowInfo, getMessage, getMessages, getMyFollowersTopic, getMyFollowingsTopic, getNetworkTopic, getPoll, getPost, getPostTopic, getPosts, getRecommendedCommunities, getRole, getStream, getTopTrendingCommunities, getUser, getUserTopic, getUsers, isAfterBefore, isAfterBeforeRaw, isCachable, isConnected, isFetcher, isFresh, isLocal, isMutator, isOffline, isPaged, isReportedByMe, isSkipLimit, joinChannel, joinCommunity, leaveChannel, leaveCommunity, liveChannelMembers, liveChannels, liveComments, liveFollowers, liveFollowings, liveMessages, livePosts, liveReactions, mergeInCache, observeChannel, observeChannels, observeComment, observeComments, observeCommunity, observeFile, observeFollowInfo, observeFollowers, observeFollowings, observeMessage, observeMessages, observePoll, observePost, observePosts, observeUser, onChannelCreated, onChannelDeleted, onChannelJoined, onChannelLeft, onChannelMemberAdded, onChannelMemberRemoved, onChannelUpdated, onClientBanned, onClientDisconnected, onCommentCreated, onCommentDeleted, onCommentFlagged, onCommentReactionAdded, onCommentReactionRemoved, onCommentUnflagged, onCommentUpdated, onCommunityCreated, onCommunityDeleted, onCommunityJoined, onCommunityLeft, onCommunityUpdated, onCommunityUserAdded, onCommunityUserBanned, onCommunityUserRemoved, onCommunityUserUnbanned, onConnectionError, onFollowInfoUpdated, onFollowRequestAccepted, onFollowRequestCanceled, onFollowRequestDeclined, onFollowerDeleted, onFollowerRequested, onMessageCreated, onMessageDeleted, onMessageUpdated, onPollDeleted, onPollUpdated, onPostApproved, onPostCreated, onPostDeclined, onPostDeleted, onPostFlagged, onPostReactionAdded, onPostReactionRemoved, onPostUnflagged, onPostUpdated, onReactionAdded, onReactionRemoved, onReactorAdded, onReactorRemoved, onStreamRecorded, onStreamStarted, onStreamStopped, onUserDeleted, onUserFlagCleared, onUserFlagged, onUserFollowed, onUserUnflagged, onUserUnfollowed, onUserUpdated, pullFromCache, pushToCache, queryCache, queryCategories, queryChannelMembers, queryChannels, queryComments, queryCommunities, queryCommunityMembers, queryFollowers, queryFollowings, queryGlobalFeed, queryMessages, queryOptions, queryPosts, queryReactions, queryRoles, queryStreams, queryUsers, removeChannelMembers, removeChannelMembersRole, removeCommunityMembers, removeCommunityMembersRoles, removeReaction, restoreCache, runQuery, sortByChannelSegment, sortByDisplayName, sortByFirstCreated, sortByLastActivity, sortByLastCreated, sortBySegmentNumber, subscribeTopic, toPage, toPageRaw, toToken, unbanChannelMembers, unfollow, updateChannel, updateComment, updateCommunity, updateMessage, updatePost, updateStream, updateUser, upsertInCache, votePoll, wipeCache };
27989
+ export { API_REGIONS, CommunityPostSettingMaps, CommunityPostSettings, ContentFeedType, DefaultCommunityPostSetting, FileType, MessageContentType, PostContentType, SubscriptionLevels, VERSION$1 as VERSION, VideoResolution, VideoSize, VideoTranscodingStatus, acceptFollower, addChannelMembers, addChannelMembersRole, addCommunityMembers, addCommunityMembersRoles, addReaction, approvePost, backupCache, banChannelMembers, closePoll, connectClient, createChannel, createClient, createComment, createCommunity, createFile, createImage, createMessage, createPoll, createPost, createQuery, createReport, createStream, createUserToken, createVideo, declineFollower, declinePost, deleteChannel, deleteComment, deleteCommunity, deleteFile, deleteMessage, deletePoll, deletePost, deleteReport, deleteStream, disableCache, disconnectClient, disposeStream, dropFromCache, enableCache, fileUrlWithSize, filterByChannelMembership, filterByPropEquality, filterByPropInclusion, follow, getActiveClient, getCategory, getChannel, getChannels, getComment, getCommentTopic, getComments, getCommunities, getCommunity, getCommunityTopic, getFeedSettings, getFile, getFollowInfo, getMessage, getMessages, getMyFollowersTopic, getMyFollowingsTopic, getNetworkTopic, getPoll, getPost, getPostTopic, getPosts, getRecommendedCommunities, getRole, getStream, getTopTrendingCommunities, getUser, getUserTopic, getUsers, isAfterBefore, isAfterBeforeRaw, isCachable, isConnected, isFetcher, isFresh, isLocal, isMutator, isOffline, isPaged, isReportedByMe, isSkipLimit, joinChannel, joinCommunity, leaveChannel, leaveCommunity, liveChannelMembers, liveChannels, liveComments, liveFollowers, liveFollowings, liveMessage, liveMessages, livePosts, liveReactions, liveUser, mergeInCache, observeChannel, observeChannels, observeComment, observeComments, observeCommunity, observeFile, observeFollowInfo, observeFollowers, observeFollowings, observeMessage, observeMessages, observePoll, observePost, observePosts, observeUser, onChannelCreated, onChannelDeleted, onChannelJoined, onChannelLeft, onChannelMemberAdded, onChannelMemberBanned, onChannelMemberRemoved, onChannelMemberUnbanned, onChannelUpdated, onClientBanned, onClientDisconnected, onCommentCreated, onCommentDeleted, onCommentFlagged, onCommentReactionAdded, onCommentReactionRemoved, onCommentUnflagged, onCommentUpdated, onCommunityCreated, onCommunityDeleted, onCommunityJoined, onCommunityLeft, onCommunityUpdated, onCommunityUserAdded, onCommunityUserBanned, onCommunityUserRemoved, onCommunityUserUnbanned, onConnectionError, onFollowInfoUpdated, onFollowRequestAccepted, onFollowRequestCanceled, onFollowRequestDeclined, onFollowerDeleted, onFollowerRequested, onMessageCreated, onMessageDeleted, onMessageFetched, onMessageUpdated, onPollDeleted, onPollUpdated, onPostApproved, onPostCreated, onPostDeclined, onPostDeleted, onPostFlagged, onPostReactionAdded, onPostReactionRemoved, onPostUnflagged, onPostUpdated, onReactionAdded, onReactionRemoved, onReactorAdded, onReactorRemoved, onStreamRecorded, onStreamStarted, onStreamStopped, onUserDeleted, onUserFetched, onUserFlagCleared, onUserFlagged, onUserFollowed, onUserUnflagged, onUserUnfollowed, onUserUpdated, pullFromCache, pushToCache, queryCache, queryCategories, queryChannelMembers, queryChannels, queryComments, queryCommunities, queryCommunityMembers, queryFollowers, queryFollowings, queryGlobalFeed, queryMessages, queryOptions, queryPosts, queryReactions, queryRoles, queryStreams, queryUsers, removeChannelMembers, removeChannelMembersRole, removeCommunityMembers, removeCommunityMembersRoles, removeReaction, restoreCache, runQuery, sortByChannelSegment, sortByDisplayName, sortByFirstCreated, sortByLastActivity, sortByLastCreated, sortBySegmentNumber, subscribeTopic, toPage, toPageRaw, toToken, unbanChannelMembers, unfollow, updateChannel, updateComment, updateCommunity, updateMessage, updatePost, updateStream, updateUser, upsertInCache, votePoll, wipeCache };