@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.
- package/dist/@types/core/cache.d.ts +3 -0
- package/dist/@types/core/cache.d.ts.map +1 -1
- package/dist/@types/core/errors.d.ts +2 -1
- package/dist/@types/core/errors.d.ts.map +1 -1
- package/dist/@types/core/events.d.ts +2 -0
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/core/live.d.ts +8 -4
- package/dist/@types/core/live.d.ts.map +1 -1
- package/dist/@types/core/query.d.ts +1 -1
- package/dist/@types/core/query.d.ts.map +1 -1
- package/dist/@types/domains/channel.d.ts +1 -0
- package/dist/@types/domains/channel.d.ts.map +1 -1
- package/dist/@types/domains/message.d.ts +13 -6
- package/dist/@types/domains/message.d.ts.map +1 -1
- package/dist/@types/domains/post.d.ts +10 -3
- package/dist/@types/domains/post.d.ts.map +1 -1
- package/dist/@types/domains/user.d.ts +1 -0
- package/dist/@types/domains/user.d.ts.map +1 -1
- package/dist/@types/index.d.ts +2 -2
- package/dist/@types/index.d.ts.map +1 -1
- package/dist/cache/api/isInTombstone.d.ts +18 -0
- package/dist/cache/api/isInTombstone.d.ts.map +1 -0
- package/dist/cache/api/pushToTombstone.d.ts +17 -0
- package/dist/cache/api/pushToTombstone.d.ts.map +1 -0
- package/dist/cache/utils/index.d.ts +17 -0
- package/dist/cache/utils/index.d.ts.map +1 -1
- package/dist/channel/api/queryChannelMembers.d.ts +1 -1
- package/dist/channel/api/queryChannelMembers.d.ts.map +1 -1
- package/dist/channel/api/queryChannels.d.ts +1 -1
- package/dist/channel/api/queryChannels.d.ts.map +1 -1
- package/dist/channel/api/tests/queryChannelMembers.test.d.ts +2 -0
- package/dist/channel/api/tests/queryChannelMembers.test.d.ts.map +1 -0
- package/dist/channel/api/tests/queryChannels.test.d.ts +2 -0
- package/dist/channel/api/tests/queryChannels.test.d.ts.map +1 -0
- package/dist/channel/events/index.d.ts +2 -0
- package/dist/channel/events/index.d.ts.map +1 -1
- package/dist/channel/events/onChannelMemberBanned.d.ts +17 -0
- package/dist/channel/events/onChannelMemberBanned.d.ts.map +1 -0
- package/dist/channel/events/onChannelMemberUnbanned.d.ts +17 -0
- package/dist/channel/events/onChannelMemberUnbanned.d.ts.map +1 -0
- package/dist/channel/events/tests/onChannelMemberBanned.test.d.ts +2 -0
- package/dist/channel/events/tests/onChannelMemberBanned.test.d.ts.map +1 -0
- package/dist/channel/events/tests/onChannelMemberUnbanned.test.d.ts +2 -0
- package/dist/channel/events/tests/onChannelMemberUnbanned.test.d.ts.map +1 -0
- package/dist/channel/observers/liveChannelMembers.d.ts.map +1 -1
- package/dist/channel/observers/liveChannels.d.ts.map +1 -1
- package/dist/channel/{tests/utils → utils/tests}/prepareChannelPayload.test.d.ts +0 -0
- package/dist/channel/utils/tests/prepareChannelPayload.test.d.ts.map +1 -0
- package/dist/core/events.d.ts +3 -3
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/query/filtering.d.ts +11 -0
- package/dist/core/query/filtering.d.ts.map +1 -1
- package/dist/core/query/query.d.ts.map +1 -1
- package/dist/index.cjs.js +963 -507
- package/dist/index.esm.js +946 -499
- package/dist/index.umd.js +4 -4
- package/dist/message/api/createMessage.d.ts +4 -1
- package/dist/message/api/createMessage.d.ts.map +1 -1
- package/dist/message/api/deleteMessage.d.ts.map +1 -1
- package/dist/message/api/getMessage.d.ts +1 -1
- package/dist/message/api/getMessage.d.ts.map +1 -1
- package/dist/message/api/getMessages.d.ts.map +1 -1
- package/dist/message/api/queryMessages.d.ts.map +1 -1
- package/dist/message/api/tests/createMessage.test.d.ts +2 -0
- package/dist/message/api/tests/createMessage.test.d.ts.map +1 -0
- package/dist/message/api/updateMessage.d.ts.map +1 -1
- package/dist/message/events/index.d.ts +1 -0
- package/dist/message/events/index.d.ts.map +1 -1
- package/dist/message/events/onMessageFetched.d.ts +17 -0
- package/dist/message/events/onMessageFetched.d.ts.map +1 -0
- package/dist/message/observers/index.d.ts +2 -1
- package/dist/message/observers/index.d.ts.map +1 -1
- package/dist/message/observers/liveMessage.d.ts +18 -0
- package/dist/message/observers/liveMessage.d.ts.map +1 -0
- package/dist/message/observers/liveMessages.d.ts.map +1 -1
- package/dist/message/observers/observeMessage.d.ts.map +1 -1
- package/dist/message/tests/api/getMessage.test.d.ts +2 -0
- package/dist/message/tests/api/getMessage.test.d.ts.map +1 -0
- package/dist/message/tests/observers/liveMessage.test.d.ts +2 -0
- package/dist/message/tests/observers/liveMessage.test.d.ts.map +1 -0
- package/dist/message/{observers/tests → tests/observers}/liveMessages.test.d.ts +0 -0
- package/dist/message/tests/observers/liveMessages.test.d.ts.map +1 -0
- package/dist/post/api/deletePost.d.ts.map +1 -1
- package/dist/post/api/getPost.d.ts.map +1 -1
- package/dist/post/api/updatePost.d.ts +6 -1
- package/dist/post/api/updatePost.d.ts.map +1 -1
- package/dist/user/api/getUser.d.ts +1 -1
- package/dist/user/api/getUser.d.ts.map +1 -1
- package/dist/user/api/getUsers.d.ts.map +1 -1
- package/dist/user/api/queryUsers.d.ts.map +1 -1
- package/dist/user/api/updateUser.d.ts.map +1 -1
- package/dist/user/events/index.d.ts +1 -0
- package/dist/user/events/index.d.ts.map +1 -1
- package/dist/user/events/onUserFetched.d.ts +17 -0
- package/dist/user/events/onUserFetched.d.ts.map +1 -0
- package/dist/user/observers/index.d.ts +1 -0
- package/dist/user/observers/index.d.ts.map +1 -1
- package/dist/user/observers/liveUser.d.ts +18 -0
- package/dist/user/observers/liveUser.d.ts.map +1 -0
- package/dist/user/observers/observeUser.d.ts.map +1 -1
- package/dist/user/tests/api/getUser.test.d.ts +2 -0
- package/dist/user/tests/api/getUser.test.d.ts.map +1 -0
- package/dist/user/tests/observers/liveUser.test.d.ts +2 -0
- package/dist/user/tests/observers/liveUser.test.d.ts.map +1 -0
- package/dist/utils/constants.d.ts +3 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/tests/dummy/channel.d.ts +15 -0
- package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
- package/dist/utils/tests/dummy/message.d.ts +12 -1
- package/dist/utils/tests/dummy/message.d.ts.map +1 -1
- package/dist/utils/tests/dummy/user.d.ts +10 -0
- package/dist/utils/tests/dummy/user.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/@types/core/cache.ts +4 -0
- package/src/@types/core/errors.ts +1 -0
- package/src/@types/core/events.ts +2 -0
- package/src/@types/core/live.ts +10 -4
- package/src/@types/core/query.ts +1 -1
- package/src/@types/domains/channel.ts +6 -0
- package/src/@types/domains/message.ts +13 -10
- package/src/@types/domains/post.ts +10 -3
- package/src/@types/domains/user.ts +8 -0
- package/src/@types/index.ts +2 -2
- package/src/cache/api/index.ts +2 -1
- package/src/cache/api/isInTombstone.ts +41 -0
- package/src/cache/api/pushToTombstone.ts +33 -0
- package/src/cache/utils/index.ts +22 -0
- package/src/channel/api/queryChannelMembers.ts +53 -5
- package/src/channel/api/queryChannels.ts +31 -4
- package/src/channel/api/tests/queryChannelMembers.test.ts +115 -0
- package/src/channel/api/tests/queryChannels.test.ts +101 -0
- package/src/channel/events/index.ts +5 -0
- package/src/channel/events/onChannelMemberBanned.ts +36 -0
- package/src/channel/events/onChannelMemberUnbanned.ts +36 -0
- package/src/channel/events/tests/onChannelMemberBanned.test.ts +58 -0
- package/src/channel/events/tests/onChannelMemberUnbanned.test.ts +58 -0
- package/src/channel/observers/liveChannelMembers.ts +28 -4
- package/src/channel/observers/liveChannels.ts +7 -1
- package/src/channel/observers/tests/liveChannelMembers.test.ts +53 -11
- package/src/channel/observers/tests/liveChannels.test.ts +50 -20
- package/src/channel/{tests/utils → utils/tests}/prepareChannelPayload.test.ts +1 -1
- package/src/core/events.ts +1 -0
- package/src/core/query/filtering.ts +49 -0
- package/src/core/query/query.ts +9 -6
- package/src/core/tests/query/query.test.ts +12 -2
- package/src/message/api/createMessage.ts +15 -9
- package/src/message/api/deleteMessage.ts +2 -1
- package/src/message/api/getMessage.ts +32 -4
- package/src/message/api/getMessages.ts +6 -1
- package/src/message/api/queryMessages.ts +3 -0
- package/src/message/api/tests/createMessage.test.ts +76 -0
- package/src/message/api/updateMessage.ts +2 -0
- package/src/message/events/index.ts +1 -0
- package/src/message/events/onMessageFetched.ts +30 -0
- package/src/message/observers/index.ts +2 -1
- package/src/message/observers/liveMessage.ts +100 -0
- package/src/message/observers/liveMessages.ts +3 -1
- package/src/message/observers/observeMessage.ts +4 -0
- package/src/message/tests/api/getMessage.test.ts +96 -0
- package/src/message/tests/observers/liveMessage.test.ts +248 -0
- package/src/message/{observers/tests → tests/observers}/liveMessages.test.ts +29 -3
- package/src/post/api/deletePost.ts +4 -3
- package/src/post/api/getPost.ts +8 -4
- package/src/post/api/updatePost.ts +6 -1
- package/src/user/api/getUser.ts +34 -6
- package/src/user/api/getUsers.ts +3 -0
- package/src/user/api/queryUsers.ts +3 -0
- package/src/user/api/updateUser.ts +3 -0
- package/src/user/events/index.ts +1 -0
- package/src/user/events/onUserFetched.ts +19 -0
- package/src/user/observers/index.ts +1 -0
- package/src/user/observers/liveUser.ts +89 -0
- package/src/user/observers/observeUser.ts +2 -0
- package/src/user/tests/api/getUser.test.ts +112 -0
- package/src/user/tests/observers/liveUser.test.ts +224 -0
- package/src/utils/constants.ts +5 -0
- package/src/utils/tests/dummy/channel.ts +43 -0
- package/src/utils/tests/dummy/message.ts +16 -2
- package/src/utils/tests/dummy/user.ts +11 -0
- package/dist/channel/tests/utils/prepareChannelPayload.test.d.ts.map +0 -1
- 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 =
|
|
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 =
|
|
521
|
+
const queryOptions = (policy, lifeSpan = CACHE_LIFESPAN) => {
|
|
432
522
|
if (policy === 'cache_only')
|
|
433
523
|
return { lifeSpan: Infinity };
|
|
434
|
-
|
|
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)
|
|
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,
|
|
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
|
-
*
|
|
715
|
+
* ```js
|
|
716
|
+
* import { enableCache } from '@amityco/ts-sdk'
|
|
717
|
+
* enableCache()
|
|
718
|
+
* ```
|
|
678
719
|
*
|
|
679
|
-
*
|
|
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
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
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
|
-
*
|
|
726
|
-
*
|
|
739
|
+
* ```js
|
|
740
|
+
* import { disableCache } from '@amityco/ts-sdk'
|
|
741
|
+
* disableCache()
|
|
742
|
+
* ```
|
|
727
743
|
*
|
|
728
|
-
*
|
|
729
|
-
* @
|
|
744
|
+
* Wipes the existing {@link Amity.Cache} object attached to
|
|
745
|
+
* an {@link Amity.Client} instance
|
|
730
746
|
*
|
|
731
|
-
* @category
|
|
732
|
-
* @hidden
|
|
747
|
+
* @category Cache API
|
|
733
748
|
*/
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
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
|
-
*
|
|
760
|
+
* ```js
|
|
761
|
+
* import { restoreCache } from '@amityco/ts-sdk'
|
|
762
|
+
* const success = await restoreCache()
|
|
763
|
+
* ```
|
|
751
764
|
*
|
|
752
|
-
*
|
|
753
|
-
*
|
|
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
|
-
*
|
|
759
|
-
* @
|
|
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
|
|
1213
|
+
* @category Transport
|
|
1214
|
+
* @hidden
|
|
1176
1215
|
*/
|
|
1177
|
-
const
|
|
1178
|
-
const { log,
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
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
|
-
*
|
|
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
|
|
1208
|
-
const {
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
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
|
-
*
|
|
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
|
|
1232
|
-
|
|
1233
|
-
|
|
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
|
|
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
|
-
|
|
20585
|
-
|
|
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
|
-
|
|
21307
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
21841
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
25189
|
-
*
|
|
25190
|
-
*
|
|
25191
|
-
*
|
|
25542
|
+
* import { onMessageFetched } from '@amityco/ts-sdk'
|
|
25543
|
+
* const dispose = onMessageFetched(message => {
|
|
25544
|
+
* // ...
|
|
25545
|
+
* })
|
|
25192
25546
|
* ```
|
|
25193
25547
|
*
|
|
25194
|
-
*
|
|
25548
|
+
* Fired when an {@link Amity.Message} has been fetched
|
|
25195
25549
|
*
|
|
25196
|
-
* @param
|
|
25197
|
-
* @
|
|
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
|
|
25553
|
+
* @category Message Events
|
|
25203
25554
|
*/
|
|
25204
|
-
const
|
|
25205
|
-
const
|
|
25206
|
-
const
|
|
25207
|
-
|
|
25208
|
-
|
|
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 {
|
|
25566
|
+
* import { liveMessage } from '@amityco/ts-sdk'
|
|
25234
25567
|
*
|
|
25235
25568
|
* let messages = []
|
|
25236
|
-
* const unsub =
|
|
25569
|
+
* const unsub = liveMessage(messageId, response => merge(messages, response.data))
|
|
25237
25570
|
* ```
|
|
25238
25571
|
*
|
|
25239
|
-
* Observe all
|
|
25572
|
+
* Observe all mutation on a given {@link Amity.Message}
|
|
25240
25573
|
*
|
|
25241
|
-
* @param
|
|
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
|
|
25578
|
+
* @category Message Live Object
|
|
25246
25579
|
*/
|
|
25247
|
-
const
|
|
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(`
|
|
25588
|
+
log(`liveMessage(tmpid: ${timestamp}) > listen`);
|
|
25251
25589
|
const disposers = [];
|
|
25252
|
-
const
|
|
25253
|
-
var _a
|
|
25254
|
-
|
|
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
|
-
|
|
25257
|
-
|
|
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
|
-
|
|
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(`
|
|
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 };
|