@amityco/ts-sdk 7.23.0 → 7.23.1-39510b5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -13323,562 +13323,571 @@ var index$r = /*#__PURE__*/Object.freeze({
13323
13323
  getMyFollowInfo: getMyFollowInfo
13324
13324
  });
13325
13325
 
13326
- class StoryComputedValue {
13327
- constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
13328
- this._syncingStoriesCount = 0;
13329
- this._errorStoriesCount = 0;
13330
- this._targetId = targetId;
13331
- this._lastStoryExpiresAt = lastStoryExpiresAt;
13332
- this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
13333
- this.cacheStoryExpireTime = pullFromCache([
13334
- "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
13335
- this._targetId,
13336
- ]);
13337
- this.cacheStoreSeenTime = pullFromCache([
13338
- "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
13339
- this._targetId,
13340
- ]);
13341
- this.getTotalStoryByStatus();
13342
- }
13343
- get lastStoryExpiresAt() {
13344
- return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
13345
- }
13346
- get lastStorySeenExpiresAt() {
13347
- return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
13348
- }
13349
- get localLastStoryExpires() {
13350
- var _a, _b;
13351
- return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
13352
- ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
13353
- : 0;
13354
- }
13355
- get localLastStorySeenExpiresAt() {
13356
- var _a, _b;
13357
- return ((_a = this.cacheStoreSeenTime) === null || _a === void 0 ? void 0 : _a.data) ? new Date((_b = this.cacheStoreSeenTime) === null || _b === void 0 ? void 0 : _b.data).getTime() : 0;
13358
- }
13359
- get isContainUnSyncedStory() {
13360
- const currentSyncingState = pullFromCache([
13361
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
13362
- this._targetId,
13363
- ]);
13364
- if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
13365
- return false;
13366
- return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
13367
- }
13368
- getLocalLastSortingDate() {
13369
- if (this.isContainUnSyncedStory) {
13370
- return this.localLastStoryExpires;
13371
- }
13372
- return this.lastStoryExpiresAt;
13373
- }
13374
- getHasUnseenFlag() {
13375
- const now = new Date().getTime();
13376
- const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
13377
- pullFromCache([
13378
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
13379
- this._targetId,
13326
+ /*
13327
+ * verifies membership status
13328
+ */
13329
+ function isMember(membership) {
13330
+ return membership !== 'none';
13331
+ }
13332
+ /*
13333
+ * checks if currently logged in user is part of the community
13334
+ */
13335
+ function isCurrentUserPartOfCommunity(c, m) {
13336
+ const { userId } = getActiveUser();
13337
+ return c.communityId === m.communityId && m.userId === userId;
13338
+ }
13339
+ /*
13340
+ * For mqtt events server will not send user specific data as it's broadcasted
13341
+ * to multiple users and it also does not include communityUser
13342
+ *
13343
+ * Client SDK needs to check for the existing isJoined field in cache data before calculating.
13344
+ * Althought this can be calculated, it's not scalable.
13345
+ */
13346
+ function updateMembershipStatus(communities, communityUsers) {
13347
+ return communities.map(c => {
13348
+ const cachedCommunity = pullFromCache([
13349
+ 'community',
13350
+ 'get',
13351
+ c.communityId,
13380
13352
  ]);
13381
- if (this.isContainUnSyncedStory) {
13382
- return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
13383
- }
13384
- return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
13385
- }
13386
- getTotalStoryByStatus() {
13387
- const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
13388
- if (!stories) {
13389
- this._errorStoriesCount = 0;
13390
- this._syncingStoriesCount = 0;
13391
- return;
13353
+ if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
13354
+ return Object.assign(Object.assign({}, cachedCommunity.data), c);
13392
13355
  }
13393
- const groupByType = stories.reduce((acc, story) => {
13394
- const { data: { targetId, syncState, isDeleted }, } = story;
13395
- if (targetId === this._targetId && !isDeleted) {
13396
- acc[syncState] += 1;
13397
- }
13398
- return acc;
13399
- }, {
13400
- syncing: 0,
13401
- error: 0,
13402
- synced: 0,
13403
- });
13404
- this._errorStoriesCount = groupByType.error;
13405
- this._syncingStoriesCount = groupByType.syncing;
13406
- }
13407
- get syncingStoriesCount() {
13408
- return this._syncingStoriesCount;
13409
- }
13410
- get failedStoriesCount() {
13411
- return this._errorStoriesCount;
13412
- }
13356
+ const isJoined = c.isJoined !== undefined
13357
+ ? c.isJoined
13358
+ : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
13359
+ return Object.assign(Object.assign({}, c), { isJoined });
13360
+ });
13413
13361
  }
13414
13362
 
13415
- const storyTargetLinkedObject = (storyTarget) => {
13416
- const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
13417
- const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
13418
- return {
13419
- targetType,
13420
- targetId,
13421
- lastStoryExpiresAt,
13422
- updatedAt: targetUpdatedAt,
13423
- // Additional data
13424
- hasUnseen: computedValue.getHasUnseenFlag(),
13425
- syncingStoriesCount: computedValue.syncingStoriesCount,
13426
- failedStoriesCount: computedValue.failedStoriesCount,
13427
- localFilter,
13428
- localLastExpires: computedValue.localLastStoryExpires,
13429
- localLastSeen: computedValue.localLastStorySeenExpiresAt,
13430
- localSortingDate: computedValue.getLocalLastSortingDate(),
13431
- };
13363
+ const getMatchPostSetting = (value) => {
13364
+ var _a;
13365
+ return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
13366
+ CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
13367
+ value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
13368
+ };
13369
+ function addPostSetting({ communities }) {
13370
+ return communities.map((_a) => {
13371
+ var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
13372
+ return (Object.assign({ postSetting: getMatchPostSetting({
13373
+ needApprovalOnPostCreation,
13374
+ onlyAdminCanPost,
13375
+ }) }, restCommunityPayload));
13376
+ });
13377
+ }
13378
+ const prepareCommunityPayload = (rawPayload) => {
13379
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
13380
+ // Convert users to internal format
13381
+ const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
13382
+ // map users with community
13383
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
13384
+ const user = internalUsers.find(user => user.userId === communityUser.userId);
13385
+ return Object.assign(Object.assign({}, communityUser), { user });
13386
+ });
13387
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
13388
+ return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
13389
+ };
13390
+ const prepareCommunityJoinRequestPayload = (rawPayload) => {
13391
+ const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
13392
+ return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
13393
+ });
13394
+ const users = rawPayload.users.map(convertRawUserToInternalUser);
13395
+ return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
13396
+ };
13397
+ const prepareCommunityMembershipPayload = (rawPayload) => {
13398
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
13399
+ // map users with community
13400
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
13401
+ const user = rawPayload.users.find(user => user.userId === communityUser.userId);
13402
+ return Object.assign(Object.assign({}, communityUser), { user });
13403
+ });
13404
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
13405
+ return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
13406
+ };
13407
+ const prepareCommunityRequest = (params) => {
13408
+ const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
13409
+ return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
13410
+ // Convert story setting to the actual value. (Allow by default)
13411
+ allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
13412
+ };
13413
+ const prepareSemanticSearchCommunityPayload = (_a) => {
13414
+ var communityPayload = __rest(_a, ["searchResult"]);
13415
+ const processedCommunityPayload = prepareCommunityPayload(communityPayload);
13416
+ return Object.assign({}, processedCommunityPayload);
13432
13417
  };
13433
13418
 
13434
- const storyLinkedObject = (story) => {
13435
- const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
13436
- const storyTargetCache = pullFromCache([
13437
- "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
13419
+ /* begin_public_function
13420
+ id: joinRequest.approve
13421
+ */
13422
+ /**
13423
+ * ```js
13424
+ * import { joinRequest } from '@amityco/ts-sdk'
13425
+ * const isAccepted = await joinRequest.approve()
13426
+ * ```
13427
+ *
13428
+ * Accepts a {@link Amity.JoinRequest} object
13429
+ *
13430
+ * @param joinRequest the {@link Amity.JoinRequest} to accept
13431
+ * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
13432
+ *
13433
+ * @category Join Request API
13434
+ * @async
13435
+ */
13436
+ const approveJoinRequest = async (joinRequest) => {
13437
+ var _a;
13438
+ const client = getActiveClient();
13439
+ client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
13440
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
13441
+ userId: joinRequest.requestorInternalId,
13442
+ });
13443
+ const joinRequestCache = (_a = pullFromCache([
13444
+ 'joinRequest',
13438
13445
  'get',
13439
- story.targetId,
13440
- ]);
13441
- const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
13442
- return Object.assign(Object.assign({}, story), { analytics: {
13443
- markAsSeen: () => {
13444
- if (!story.expiresAt)
13445
- return;
13446
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
13447
- return;
13448
- analyticsEngineInstance.markStoryAsViewed(story);
13449
- },
13450
- markLinkAsClicked: () => {
13451
- if (!story.expiresAt)
13452
- return;
13453
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
13454
- return;
13455
- analyticsEngineInstance.markStoryAsClicked(story);
13456
- },
13457
- }, get videoData() {
13458
- var _a, _b;
13459
- const cache = pullFromCache([
13460
- 'file',
13461
- 'get',
13462
- (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
13463
- ]);
13464
- if (!cache)
13465
- return undefined;
13466
- const { data } = cache;
13467
- return data || undefined;
13468
- },
13469
- get imageData() {
13470
- var _a, _b;
13471
- if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
13472
- return undefined;
13473
- const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
13474
- if (!cache)
13475
- return undefined;
13476
- const { data } = cache;
13477
- if (!data)
13478
- return undefined;
13479
- return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
13480
- },
13481
- get community() {
13482
- if (story.targetType !== 'community')
13483
- return undefined;
13484
- if (!communityCacheData)
13485
- return undefined;
13486
- return (communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data) || undefined;
13487
- },
13488
- get communityCategories() {
13489
- if (story.targetType !== 'community')
13490
- return undefined;
13491
- if (!communityCacheData)
13492
- return undefined;
13493
- const { data: { categoryIds }, } = communityCacheData;
13494
- if (categoryIds.length === 0)
13446
+ joinRequest.joinRequestId,
13447
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13448
+ if (joinRequestCache) {
13449
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
13450
+ status: "approved" /* JoinRequestStatusEnum.Approved */,
13451
+ });
13452
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
13453
+ }
13454
+ return data.success;
13455
+ };
13456
+ /* end_public_function */
13457
+
13458
+ /* begin_public_function
13459
+ id: joinRequest.cancel
13460
+ */
13461
+ /**
13462
+ * ```js
13463
+ * import { joinRequest } from '@amityco/ts-sdk'
13464
+ * const isCanceled = await joinRequest.cancel()
13465
+ * ```
13466
+ *
13467
+ * Cancels a {@link Amity.JoinRequest} object
13468
+ *
13469
+ * @param joinRequest the {@link Amity.JoinRequest} to cancel
13470
+ * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
13471
+ *
13472
+ * @category Join Request API
13473
+ * @async
13474
+ */
13475
+ const cancelJoinRequest = async (joinRequest) => {
13476
+ var _a;
13477
+ const client = getActiveClient();
13478
+ client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
13479
+ const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
13480
+ const joinRequestCache = (_a = pullFromCache([
13481
+ 'joinRequest',
13482
+ 'get',
13483
+ joinRequest.joinRequestId,
13484
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13485
+ if (joinRequestCache) {
13486
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
13487
+ status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
13488
+ });
13489
+ fireEvent('local.joinRequest.deleted', [joinRequestCache]);
13490
+ }
13491
+ return data.success;
13492
+ };
13493
+ /* end_public_function */
13494
+
13495
+ /* begin_public_function
13496
+ id: joinRequest.reject
13497
+ */
13498
+ /**
13499
+ * ```js
13500
+ * import { joinRequest } from '@amityco/ts-sdk'
13501
+ * const isRejected = await joinRequest.reject()
13502
+ * ```
13503
+ *
13504
+ * Rejects a {@link Amity.JoinRequest} object
13505
+ *
13506
+ * @param joinRequest the {@link Amity.JoinRequest} to reject
13507
+ * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
13508
+ *
13509
+ * @category Join Request API
13510
+ * @async
13511
+ */
13512
+ const rejectJoinRequest = async (joinRequest) => {
13513
+ var _a;
13514
+ const client = getActiveClient();
13515
+ client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
13516
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
13517
+ userId: joinRequest.requestorInternalId,
13518
+ });
13519
+ const joinRequestCache = (_a = pullFromCache([
13520
+ 'joinRequest',
13521
+ 'get',
13522
+ joinRequest.joinRequestId,
13523
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13524
+ if (joinRequestCache) {
13525
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
13526
+ status: "rejected" /* JoinRequestStatusEnum.Rejected */,
13527
+ });
13528
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
13529
+ }
13530
+ return data.success;
13531
+ };
13532
+ /* end_public_function */
13533
+
13534
+ const joinRequestLinkedObject = (joinRequest) => {
13535
+ return Object.assign(Object.assign({}, joinRequest), { get user() {
13536
+ var _a;
13537
+ const user = (_a = pullFromCache([
13538
+ 'user',
13539
+ 'get',
13540
+ joinRequest.requestorPublicId,
13541
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13542
+ if (!user)
13495
13543
  return undefined;
13496
- return categoryIds
13497
- .map(categoryId => {
13498
- const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
13499
- return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
13500
- })
13501
- .filter(category => category !== undefined);
13502
- },
13503
- get creator() {
13504
- const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
13505
- if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
13506
- return;
13507
- return userLinkedObject(cacheData.data);
13508
- },
13509
- get storyTarget() {
13510
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
13511
- return;
13512
- return storyTargetLinkedObject(storyTargetCache.data);
13513
- },
13514
- get isSeen() {
13515
- const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
13516
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
13517
- return false;
13518
- const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
13519
- const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
13520
- const expiresAt = new Date(story.expiresAt).getTime();
13521
- return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
13544
+ return userLinkedObject(user);
13545
+ }, cancel: async () => {
13546
+ await cancelJoinRequest(joinRequest);
13547
+ }, approve: async () => {
13548
+ await approveJoinRequest(joinRequest);
13549
+ }, reject: async () => {
13550
+ await rejectJoinRequest(joinRequest);
13522
13551
  } });
13523
13552
  };
13524
13553
 
13525
13554
  /* begin_public_function
13526
- id: channel.create
13555
+ id: community.getMyJoinRequest
13527
13556
  */
13528
13557
  /**
13529
13558
  * ```js
13530
- * import { createChannel } from '@amityco/ts-sdk'
13531
- * const created = await createChannel({ displayName: 'foobar' })
13559
+ * import { community } from '@amityco/ts-sdk'
13560
+ * const isJoined = await community.getMyJoinRequest('foobar')
13532
13561
  * ```
13533
13562
  *
13534
- * Creates an {@link Amity.Channel}
13563
+ * Joins a {@link Amity.Community} object
13535
13564
  *
13536
- * @param bundle The data necessary to create a new {@link Amity.Channel}
13537
- * @returns The newly created {@link Amity.Channel}
13565
+ * @param communityId the {@link Amity.Community} to join
13566
+ * @returns A success boolean if the {@link Amity.Community} was joined
13538
13567
  *
13539
- * @category Channel API
13568
+ * @category Community API
13540
13569
  * @async
13541
13570
  */
13542
- const createChannel = async (bundle) => {
13571
+ const getMyJoinRequest = async (communityId) => {
13543
13572
  const client = getActiveClient();
13544
- client.log('user/createChannel', bundle);
13545
- let payload;
13546
- /* c8 ignore next */
13547
- if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
13548
- payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
13549
- }
13550
- else {
13551
- const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
13552
- payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
13553
- /* c8 ignore next */
13554
- isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
13555
- }
13556
- const data = await prepareChannelPayload(payload.data);
13573
+ client.log('community/myJoinRequest', communityId);
13574
+ const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
13575
+ const data = prepareCommunityJoinRequestPayload(payload);
13557
13576
  const cachedAt = client.cache && Date.now();
13558
13577
  if (client.cache)
13559
13578
  ingestInCache(data, { cachedAt });
13560
- const { channels } = data;
13561
13579
  return {
13562
- data: constructChannelObject(channels[0]),
13580
+ data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
13563
13581
  cachedAt,
13564
13582
  };
13565
13583
  };
13566
13584
  /* end_public_function */
13567
13585
 
13586
+ /* begin_public_function
13587
+ id: community.join
13588
+ */
13568
13589
  /**
13569
13590
  * ```js
13570
- * import { getChannel } from '@amityco/ts-sdk'
13571
- * const channel = await getChannel('foobar')
13591
+ * import { community } from '@amityco/ts-sdk'
13592
+ * const isJoined = await community.join('foobar')
13572
13593
  * ```
13573
13594
  *
13574
- * Fetches a {@link Amity.Channel} object
13595
+ * Joins a {@link Amity.Community} object
13575
13596
  *
13576
- * @param channelId the ID of the {@link Amity.Channel} to fetch
13577
- * @returns the associated {@link Amity.Channel} object
13597
+ * @param communityId the {@link Amity.Community} to join
13598
+ * @returns A status join result
13578
13599
  *
13579
- * @category Channel API
13600
+ * @category Community API
13580
13601
  * @async
13581
13602
  */
13582
- const getChannel$1 = async (channelId) => {
13603
+ const joinRequest = async (communityId) => {
13604
+ var _a;
13583
13605
  const client = getActiveClient();
13584
- client.log('channel/getChannel', channelId);
13585
- isInTombstone('channel', channelId);
13586
- let data;
13587
- try {
13588
- const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
13589
- data = await prepareChannelPayload(payload);
13590
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
13591
- prepareUnreadCountInfo(payload);
13606
+ client.log('community/joinRequest', communityId);
13607
+ const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
13608
+ const data = prepareCommunityJoinRequestPayload(payload);
13609
+ const cachedAt = client.cache && Date.now();
13610
+ if (client.cache)
13611
+ ingestInCache(data, { cachedAt });
13612
+ const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
13613
+ ? "success" /* JoinResultStatusEnum.Success */
13614
+ : "pending" /* JoinResultStatusEnum.Pending */;
13615
+ if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
13616
+ const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
13617
+ if (community) {
13618
+ const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
13619
+ upsertInCache(['community', 'get', communityId], updatedCommunity);
13592
13620
  }
13593
13621
  }
13594
- catch (error) {
13595
- if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
13596
- // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
13597
- pushToTombstone('channel', channelId);
13622
+ fireEvent('v4.local.community.joined', data.joinRequests);
13623
+ return status === "success" /* JoinResultStatusEnum.Success */
13624
+ ? { status }
13625
+ : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
13626
+ };
13627
+ /* end_public_function */
13628
+
13629
+ /**
13630
+ * TODO: handle cache receive cache option, and cache policy
13631
+ * TODO: check if querybyIds is supported
13632
+ */
13633
+ class JoinRequestsPaginationController extends PaginationController {
13634
+ async getRequest(queryParams, token) {
13635
+ const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
13636
+ const options = token ? { token } : { limit };
13637
+ const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
13638
+ params: Object.assign(Object.assign({}, params), { options }),
13639
+ });
13640
+ return queryResponse;
13641
+ }
13642
+ }
13643
+
13644
+ var EnumJoinRequestAction$1;
13645
+ (function (EnumJoinRequestAction) {
13646
+ EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
13647
+ EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
13648
+ EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
13649
+ })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
13650
+
13651
+ class JoinRequestsQueryStreamController extends QueryStreamController {
13652
+ constructor(query, cacheKey, notifyChange, preparePayload) {
13653
+ super(query, cacheKey);
13654
+ this.notifyChange = notifyChange;
13655
+ this.preparePayload = preparePayload;
13656
+ }
13657
+ async saveToMainDB(response) {
13658
+ const processedPayload = await this.preparePayload(response);
13659
+ const client = getActiveClient();
13660
+ const cachedAt = client.cache && Date.now();
13661
+ if (client.cache) {
13662
+ ingestInCache(processedPayload, { cachedAt });
13598
13663
  }
13599
- throw error;
13600
13664
  }
13601
- const cachedAt = client.cache && Date.now();
13602
- if (client.cache)
13603
- ingestInCache(data, { cachedAt });
13604
- const { channels } = data;
13605
- return {
13606
- data: channels.find(channel => channel.channelId === channelId),
13607
- cachedAt,
13665
+ appendToQueryStream(response, direction, refresh = false) {
13666
+ var _a, _b;
13667
+ if (refresh) {
13668
+ pushToCache(this.cacheKey, {
13669
+ data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
13670
+ });
13671
+ }
13672
+ else {
13673
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13674
+ const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
13675
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
13676
+ ...new Set([
13677
+ ...joinRequests,
13678
+ ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
13679
+ ]),
13680
+ ] }));
13681
+ }
13682
+ }
13683
+ reactor(action) {
13684
+ return (joinRequest) => {
13685
+ var _a;
13686
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13687
+ if (!collection)
13688
+ return;
13689
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
13690
+ const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
13691
+ if (!isExist)
13692
+ return;
13693
+ }
13694
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
13695
+ collection.data = [
13696
+ ...new Set([
13697
+ ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
13698
+ ...collection.data,
13699
+ ]),
13700
+ ];
13701
+ }
13702
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
13703
+ collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
13704
+ }
13705
+ pushToCache(this.cacheKey, collection);
13706
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
13707
+ };
13708
+ }
13709
+ subscribeRTE(createSubscriber) {
13710
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
13711
+ }
13712
+ }
13713
+
13714
+ /**
13715
+ * ```js
13716
+ * import { onJoinRequestCreated } from '@amityco/ts-sdk'
13717
+ * const dispose = onJoinRequestCreated(data => {
13718
+ * // ...
13719
+ * })
13720
+ * ```
13721
+ *
13722
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
13723
+ *
13724
+ * @param callback The function to call when the event was fired
13725
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13726
+ *
13727
+ * @category JoinRequest Events
13728
+ */
13729
+ const onJoinRequestCreated = (callback) => {
13730
+ const client = getActiveClient();
13731
+ const disposers = [
13732
+ createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
13733
+ ];
13734
+ return () => {
13735
+ disposers.forEach(fn => fn());
13608
13736
  };
13609
13737
  };
13738
+
13610
13739
  /**
13611
13740
  * ```js
13612
- * import { getChannel } from '@amityco/ts-sdk'
13613
- * const channel = getChannel.locally('foobar')
13741
+ * import { onJoinRequestUpdated } from '@amityco/ts-sdk'
13742
+ * const dispose = onJoinRequestUpdated(data => {
13743
+ * // ...
13744
+ * })
13614
13745
  * ```
13615
13746
  *
13616
- * Fetches a {@link Amity.Channel} object from cache
13747
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
13617
13748
  *
13618
- * @param channelId the ID of the {@link Amity.Channel} to fetch
13619
- * @returns the associated {@link Amity.Channel} object
13749
+ * @param callback The function to call when the event was fired
13750
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13620
13751
  *
13621
- * @category Channel API
13752
+ * @category JoinRequest Events
13622
13753
  */
13623
- getChannel$1.locally = (channelId) => {
13624
- var _a;
13754
+ const onJoinRequestUpdated = (callback) => {
13625
13755
  const client = getActiveClient();
13626
- client.log('channel/getChannel.locally', channelId);
13627
- if (!client.cache)
13628
- return;
13629
- // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
13630
- const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
13631
- return data.channelPublicId === channelId;
13632
- });
13633
- if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
13634
- return;
13635
- return {
13636
- data: cached[0].data,
13637
- cachedAt: cached[0].cachedAt,
13756
+ const disposers = [
13757
+ createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
13758
+ ];
13759
+ return () => {
13760
+ disposers.forEach(fn => fn());
13638
13761
  };
13639
13762
  };
13640
13763
 
13641
13764
  /**
13642
13765
  * ```js
13643
- * import { getStream } from '@amityco/ts-sdk'
13644
- * const stream = await getStream('foobar')
13766
+ * import { onJoinRequestDeleted } from '@amityco/ts-sdk'
13767
+ * const dispose = onJoinRequestDeleted(data => {
13768
+ * // ...
13769
+ * })
13645
13770
  * ```
13646
13771
  *
13647
- * Fetches a {@link Amity.Channel} object linked with a current stream
13772
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
13648
13773
  *
13649
- * @param stream {@link Amity.Stream} that has linked live channel
13650
- * @returns the associated {@link Amity.Channel<'live'>} object
13774
+ * @param callback The function to call when the event was fired
13775
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13651
13776
  *
13652
- * @category Stream API
13653
- * @async
13777
+ * @category JoinRequest Events
13654
13778
  */
13655
- const getLiveChat$1 = async (stream) => {
13656
- var _a;
13779
+ const onJoinRequestDeleted = (callback) => {
13657
13780
  const client = getActiveClient();
13658
- client.log('stream/getLiveChat', stream.streamId);
13659
- if (stream.channelId) {
13660
- const channel = (_a = pullFromCache([
13661
- 'channel',
13662
- 'get',
13663
- stream.channelId,
13664
- ])) === null || _a === void 0 ? void 0 : _a.data;
13665
- if (channel)
13666
- return channelLinkedObject(constructChannelObject(channel));
13667
- const { data } = await getChannel$1(stream.channelId);
13668
- return channelLinkedObject(constructChannelObject(data));
13669
- }
13670
- // No Channel ID
13671
- // streamer: create a new live channel
13672
- if (stream.userId === client.userId) {
13673
- const { data: channel } = await createChannel({
13674
- type: 'live',
13675
- postId: stream.postId,
13676
- videoStreamId: stream.streamId,
13677
- });
13678
- // Update channelId to stream object in cache
13679
- mergeInCache(['stream', 'get', stream.streamId], {
13680
- channelId: channel.channelId,
13681
- });
13682
- return channel;
13683
- }
13684
- // watcher: return undefined
13685
- return undefined;
13686
- };
13687
-
13688
- const GET_WATCHER_URLS = Symbol('getWatcherUrls');
13689
- const streamLinkedObject = (stream) => {
13690
- return Object.assign(Object.assign({}, stream), { get moderation() {
13691
- var _a;
13692
- return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
13693
- },
13694
- get post() {
13695
- var _a;
13696
- if (stream.referenceType !== 'post')
13697
- return;
13698
- return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
13699
- },
13700
- get community() {
13701
- var _a;
13702
- if (stream.targetType !== 'community')
13703
- return;
13704
- return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
13705
- },
13706
- get user() {
13707
- var _a;
13708
- return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
13709
- },
13710
- get childStreams() {
13711
- if (!stream.childStreamIds || stream.childStreamIds.length === 0)
13712
- return [];
13713
- return stream.childStreamIds
13714
- .map(id => {
13715
- var _a;
13716
- const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
13717
- if (!streamCache)
13718
- return undefined;
13719
- return streamLinkedObject(streamCache);
13720
- })
13721
- .filter(isNonNullable);
13722
- }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
13723
- return stream.watcherUrl;
13724
- } });
13725
- };
13726
-
13727
- const categoryLinkedObject = (category) => {
13728
- return Object.assign(Object.assign({}, category), { get avatar() {
13729
- var _a;
13730
- if (!category.avatarFileId)
13731
- return undefined;
13732
- const avatar = (_a = pullFromCache([
13733
- 'file',
13734
- 'get',
13735
- `${category.avatarFileId}`,
13736
- ])) === null || _a === void 0 ? void 0 : _a.data;
13737
- return avatar;
13738
- } });
13739
- };
13740
-
13741
- const commentLinkedObject = (comment) => {
13742
- return Object.assign(Object.assign({}, comment), { get target() {
13743
- const commentTypes = {
13744
- type: comment.targetType,
13745
- };
13746
- if (comment.targetType === 'user') {
13747
- return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
13748
- }
13749
- if (commentTypes.type === 'content') {
13750
- return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
13751
- }
13752
- if (commentTypes.type === 'community') {
13753
- const cacheData = pullFromCache([
13754
- 'communityUsers',
13755
- 'get',
13756
- `${comment.targetId}#${comment.userId}`,
13757
- ]);
13758
- return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
13759
- }
13760
- return {
13761
- type: 'unknown',
13762
- };
13763
- },
13764
- get creator() {
13765
- const cacheData = pullFromCache(['user', 'get', comment.userId]);
13766
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
13767
- return userLinkedObject(cacheData.data);
13768
- return undefined;
13769
- },
13770
- get childrenComment() {
13771
- return comment.children
13772
- .map(childCommentId => {
13773
- const commentCache = pullFromCache([
13774
- 'comment',
13775
- 'get',
13776
- childCommentId,
13777
- ]);
13778
- if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
13779
- return;
13780
- return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
13781
- })
13782
- .filter(isNonNullable)
13783
- .map(item => commentLinkedObject(item));
13784
- } });
13781
+ const disposers = [
13782
+ createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
13783
+ ];
13784
+ return () => {
13785
+ disposers.forEach(fn => fn());
13786
+ };
13785
13787
  };
13786
13788
 
13787
- function isAmityImagePost(post) {
13788
- return !!(post.data &&
13789
- typeof post.data !== 'string' &&
13790
- 'fileId' in post.data &&
13791
- post.dataType === 'image');
13792
- }
13793
- function isAmityFilePost(post) {
13794
- return !!(post.data &&
13795
- typeof post.data !== 'string' &&
13796
- 'fileId' in post.data &&
13797
- post.dataType === 'file');
13798
- }
13799
- function isAmityVideoPost(post) {
13800
- return !!(post.data &&
13801
- typeof post.data !== 'string' &&
13802
- 'videoFileId' in post.data &&
13803
- 'thumbnailFileId' in post.data &&
13804
- post.dataType === 'video');
13805
- }
13806
- function isAmityLivestreamPost(post) {
13807
- return !!(post.data &&
13808
- typeof post.data !== 'string' &&
13809
- 'streamId' in post.data &&
13810
- post.dataType === 'liveStream');
13811
- }
13812
- function isAmityPollPost(post) {
13813
- return !!(post.data &&
13814
- typeof post.data !== 'string' &&
13815
- 'pollId' in post.data &&
13816
- post.dataType === 'poll');
13817
- }
13818
- function isAmityClipPost(post) {
13819
- return !!(post.data &&
13820
- typeof post.data !== 'string' &&
13821
- 'fileId' in post.data &&
13822
- post.dataType === 'clip');
13823
- }
13824
- function isAmityAudioPost(post) {
13825
- return !!(post.data &&
13826
- typeof post.data !== 'string' &&
13827
- 'fileId' in post.data &&
13828
- post.dataType === 'audio');
13829
- }
13830
- function isAmityRoomPost(post) {
13831
- return !!(post.data &&
13832
- typeof post.data !== 'string' &&
13833
- 'roomId' in post.data &&
13834
- post.dataType === 'room');
13789
+ class JoinRequestsLiveCollectionController extends LiveCollectionController {
13790
+ constructor(query, callback) {
13791
+ const queryStreamId = hash__default["default"](query);
13792
+ const cacheKey = ['joinRequest', 'collection', queryStreamId];
13793
+ const paginationController = new JoinRequestsPaginationController(query);
13794
+ super(paginationController, queryStreamId, cacheKey, callback);
13795
+ this.query = query;
13796
+ this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
13797
+ this.callback = callback.bind(this);
13798
+ this.loadPage({ initial: true });
13799
+ }
13800
+ setup() {
13801
+ var _a;
13802
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13803
+ if (!collection) {
13804
+ pushToCache(this.cacheKey, {
13805
+ data: [],
13806
+ params: this.query,
13807
+ });
13808
+ }
13809
+ }
13810
+ async persistModel(queryPayload) {
13811
+ await this.queryStreamController.saveToMainDB(queryPayload);
13812
+ }
13813
+ persistQueryStream({ response, direction, refresh, }) {
13814
+ const joinRequestResponse = response;
13815
+ this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
13816
+ }
13817
+ startSubscription() {
13818
+ return this.queryStreamController.subscribeRTE([
13819
+ { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
13820
+ { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
13821
+ { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
13822
+ ]);
13823
+ }
13824
+ notifyChange({ origin, loading, error }) {
13825
+ var _a;
13826
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13827
+ if (!collection)
13828
+ return;
13829
+ const data = this.applyFilter(collection.data
13830
+ .map(id => pullFromCache(['joinRequest', 'get', id]))
13831
+ .filter(isNonNullable)
13832
+ .map(({ data }) => data)
13833
+ .map(joinRequestLinkedObject));
13834
+ if (!this.shouldNotify(data) && origin === 'event')
13835
+ return;
13836
+ this.callback({
13837
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
13838
+ data,
13839
+ hasNextPage: !!this.paginationController.getNextToken(),
13840
+ loading,
13841
+ error,
13842
+ });
13843
+ }
13844
+ applyFilter(data) {
13845
+ let joinRequest = data;
13846
+ if (this.query.status) {
13847
+ joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
13848
+ }
13849
+ const sortFn = (() => {
13850
+ switch (this.query.sortBy) {
13851
+ case 'firstCreated':
13852
+ return sortByFirstCreated;
13853
+ case 'lastCreated':
13854
+ return sortByLastCreated;
13855
+ default:
13856
+ return sortByLastCreated;
13857
+ }
13858
+ })();
13859
+ joinRequest = joinRequest.sort(sortFn);
13860
+ return joinRequest;
13861
+ }
13835
13862
  }
13836
13863
 
13837
13864
  /**
13838
- * ```js
13839
- * import { RoomRepository } from '@amityco/ts-sdk'
13840
- * const stream = await getStream('foobar')
13841
- * ```
13865
+ * Get Join Requests
13842
13866
  *
13843
- * Fetches a {@link Amity.Channel} object linked with a current stream
13867
+ * @param params the query parameters
13868
+ * @param callback the callback to be called when the join request are updated
13869
+ * @returns joinRequests
13844
13870
  *
13845
- * @param stream {@link Amity.Stream} that has linked live channel
13846
- * @returns the associated {@link Amity.Channel<'live'>} object
13871
+ * @category joinRequest Live Collection
13847
13872
  *
13848
- * @category Stream API
13849
- * @async
13850
13873
  */
13851
- const getLiveChat = async (room) => {
13852
- var _a;
13853
- const client = getActiveClient();
13854
- client.log('room/getLiveChat', room.roomId);
13855
- if (room.liveChannelId) {
13856
- const channel = (_a = pullFromCache([
13857
- 'channel',
13858
- 'get',
13859
- room.liveChannelId,
13860
- ])) === null || _a === void 0 ? void 0 : _a.data;
13861
- if (channel)
13862
- return channelLinkedObject(constructChannelObject(channel));
13863
- const { data } = await getChannel$1(room.liveChannelId);
13864
- return channelLinkedObject(constructChannelObject(data));
13865
- }
13866
- // No Channel ID
13867
- // streamer: create a new live channel
13868
- if (room.createdBy === client.userId) {
13869
- const { data: channel } = await createChannel({
13870
- type: 'live',
13871
- postId: room.referenceId,
13872
- roomId: room.roomId,
13873
- });
13874
- // Update channelId to stream object in cache
13875
- mergeInCache(['room', 'get', room.roomId], {
13876
- liveChannelId: channel.channelId,
13877
- });
13878
- return channel;
13874
+ const getJoinRequests = (params, callback, config) => {
13875
+ const { log, cache } = getActiveClient();
13876
+ if (!cache) {
13877
+ console.log(ENABLE_CACHE_MESSAGE);
13879
13878
  }
13880
- // watcher: return undefined
13881
- return undefined;
13879
+ const timestamp = Date.now();
13880
+ log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
13881
+ const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
13882
+ const disposers = joinRequestLiveCollection.startSubscription();
13883
+ const cacheKey = joinRequestLiveCollection.getCacheKey();
13884
+ disposers.push(() => {
13885
+ dropFromCache(cacheKey);
13886
+ });
13887
+ return () => {
13888
+ log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
13889
+ disposers.forEach(fn => fn());
13890
+ };
13882
13891
  };
13883
13892
 
13884
13893
  const convertRawInvitationToInternalInvitation = (rawInvitation) => {
@@ -14033,1391 +14042,1382 @@ const invitationLinkedObject = (invitation) => {
14033
14042
  } });
14034
14043
  };
14035
14044
 
14036
- /* begin_public_function
14037
- id: invitation.get
14038
- */
14045
+ /* begin_public_function
14046
+ id: invitation.get
14047
+ */
14048
+ /**
14049
+ * ```js
14050
+ * import { getInvitation } from '@amityco/ts-sdk'
14051
+ * const { invitation } = await getInvitation(targetType, targetId)
14052
+ * ```
14053
+ *
14054
+ * Get a {@link Amity.Invitation} object
14055
+ *
14056
+ * @param targetType The type of the target of the {@link Amity.Invitation}
14057
+ * @param targetId The ID of the target of the {@link Amity.Invitation}
14058
+ * @returns A {@link Amity.Invitation} object
14059
+ *
14060
+ * @category Invitation API
14061
+ * @async
14062
+ */
14063
+ const getInvitation = async (params) => {
14064
+ const client = getActiveClient();
14065
+ client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
14066
+ const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
14067
+ const data = prepareMyInvitationsPayload(payload);
14068
+ const cachedAt = client.cache && Date.now();
14069
+ if (client.cache)
14070
+ ingestInCache(data, { cachedAt });
14071
+ return {
14072
+ data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
14073
+ cachedAt,
14074
+ };
14075
+ };
14076
+ /* end_public_function */
14077
+
14078
+ var InvitationActionsEnum;
14079
+ (function (InvitationActionsEnum) {
14080
+ InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
14081
+ InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
14082
+ InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
14083
+ })(InvitationActionsEnum || (InvitationActionsEnum = {}));
14084
+
14085
+ class InvitationsPaginationController extends PaginationController {
14086
+ async getRequest(queryParams, token) {
14087
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
14088
+ const options = token ? { token } : { limit };
14089
+ const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
14090
+ return data;
14091
+ }
14092
+ }
14093
+
14094
+ class InvitationsQueryStreamController extends QueryStreamController {
14095
+ constructor(query, cacheKey, notifyChange, preparePayload) {
14096
+ super(query, cacheKey);
14097
+ this.notifyChange = notifyChange;
14098
+ this.preparePayload = preparePayload;
14099
+ }
14100
+ async saveToMainDB(response) {
14101
+ const processedPayload = await this.preparePayload(response);
14102
+ const client = getActiveClient();
14103
+ const cachedAt = client.cache && Date.now();
14104
+ if (client.cache) {
14105
+ ingestInCache(processedPayload, { cachedAt });
14106
+ }
14107
+ }
14108
+ appendToQueryStream(response, direction, refresh = false) {
14109
+ var _a, _b;
14110
+ if (refresh) {
14111
+ pushToCache(this.cacheKey, {
14112
+ data: response.invitations.map(getResolver('invitation')),
14113
+ });
14114
+ }
14115
+ else {
14116
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14117
+ const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
14118
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
14119
+ ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
14120
+ ] }));
14121
+ }
14122
+ }
14123
+ reactor(action) {
14124
+ return (invitations) => {
14125
+ var _a;
14126
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14127
+ if (!collection)
14128
+ return;
14129
+ if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
14130
+ const isExist = collection.data.find(id => id === invitations[0].invitationId);
14131
+ if (!isExist)
14132
+ return;
14133
+ }
14134
+ if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
14135
+ collection.data = [
14136
+ ...new Set([
14137
+ ...invitations.map(invitation => invitation.invitationId),
14138
+ ...collection.data,
14139
+ ]),
14140
+ ];
14141
+ }
14142
+ if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
14143
+ collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
14144
+ }
14145
+ pushToCache(this.cacheKey, collection);
14146
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
14147
+ };
14148
+ }
14149
+ subscribeRTE(createSubscriber) {
14150
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
14151
+ }
14152
+ }
14153
+
14154
+ /**
14155
+ * ```js
14156
+ * import { onLocalInvitationCreated } from '@amityco/ts-sdk'
14157
+ * const dispose = onLocalInvitationCreated(data => {
14158
+ * // ...
14159
+ * })
14160
+ * ```
14161
+ *
14162
+ * Fired when an {@link Amity.InvitationPayload} has been created
14163
+ *
14164
+ * @param callback The function to call when the event was fired
14165
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
14166
+ *
14167
+ * @category Invitation Events
14168
+ */
14169
+ const onLocalInvitationCreated = (callback) => {
14170
+ const client = getActiveClient();
14171
+ const disposers = [
14172
+ createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
14173
+ ];
14174
+ return () => {
14175
+ disposers.forEach(fn => fn());
14176
+ };
14177
+ };
14178
+
14179
+ /**
14180
+ * ```js
14181
+ * import { onLocalInvitationUpdated } from '@amityco/ts-sdk'
14182
+ * const dispose = onLocalInvitationUpdated(data => {
14183
+ * // ...
14184
+ * })
14185
+ * ```
14186
+ *
14187
+ * Fired when an {@link Amity.InvitationPayload} has been updated
14188
+ *
14189
+ * @param callback The function to call when the event was fired
14190
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
14191
+ *
14192
+ * @category Invitation Events
14193
+ */
14194
+ const onLocalInvitationUpdated = (callback) => {
14195
+ const client = getActiveClient();
14196
+ const disposers = [
14197
+ createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
14198
+ ];
14199
+ return () => {
14200
+ disposers.forEach(fn => fn());
14201
+ };
14202
+ };
14203
+
14039
14204
  /**
14040
14205
  * ```js
14041
- * import { getInvitation } from '@amityco/ts-sdk'
14042
- * const { invitation } = await getInvitation(targetType, targetId)
14206
+ * import { onLocalInvitationCanceled } from '@amityco/ts-sdk'
14207
+ * const dispose = onLocalInvitationCanceled(data => {
14208
+ * // ...
14209
+ * })
14043
14210
  * ```
14044
14211
  *
14045
- * Get a {@link Amity.Invitation} object
14212
+ * Fired when an {@link Amity.InvitationPayload} has been deleted
14046
14213
  *
14047
- * @param targetType The type of the target of the {@link Amity.Invitation}
14048
- * @param targetId The ID of the target of the {@link Amity.Invitation}
14049
- * @returns A {@link Amity.Invitation} object
14214
+ * @param callback The function to call when the event was fired
14215
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
14050
14216
  *
14051
- * @category Invitation API
14052
- * @async
14217
+ * @category Invitation Events
14053
14218
  */
14054
- const getInvitation = async (params) => {
14219
+ const onLocalInvitationCanceled = (callback) => {
14055
14220
  const client = getActiveClient();
14056
- client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
14057
- const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
14058
- const data = prepareMyInvitationsPayload(payload);
14059
- const cachedAt = client.cache && Date.now();
14060
- if (client.cache)
14061
- ingestInCache(data, { cachedAt });
14062
- return {
14063
- data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
14064
- cachedAt,
14221
+ const disposers = [
14222
+ createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
14223
+ ];
14224
+ return () => {
14225
+ disposers.forEach(fn => fn());
14065
14226
  };
14066
14227
  };
14067
- /* end_public_function */
14068
14228
 
14069
- /**
14070
- * WatchSessionStorage manages watch session data in memory
14071
- * Similar to UsageCollector for stream watch minutes
14072
- */
14073
- class WatchSessionStorage {
14074
- constructor() {
14075
- this.sessions = new Map();
14076
- }
14077
- /**
14078
- * Add a new watch session
14079
- */
14080
- addSession(session) {
14081
- this.sessions.set(session.sessionId, session);
14082
- }
14083
- /**
14084
- * Get a watch session by sessionId
14085
- */
14086
- getSession(sessionId) {
14087
- return this.sessions.get(sessionId);
14229
+ class InvitationsLiveCollectionController extends LiveCollectionController {
14230
+ constructor(query, callback) {
14231
+ const queryStreamId = hash__default["default"](query);
14232
+ const cacheKey = ['invitation', 'collection', queryStreamId];
14233
+ const paginationController = new InvitationsPaginationController(query);
14234
+ super(paginationController, queryStreamId, cacheKey, callback);
14235
+ this.query = query;
14236
+ this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
14237
+ this.callback = callback.bind(this);
14238
+ this.loadPage({ initial: true });
14088
14239
  }
14089
- /**
14090
- * Update a watch session
14091
- */
14092
- updateSession(sessionId, updates) {
14093
- const session = this.sessions.get(sessionId);
14094
- if (session) {
14095
- this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
14240
+ setup() {
14241
+ var _a;
14242
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14243
+ if (!collection) {
14244
+ pushToCache(this.cacheKey, {
14245
+ data: [],
14246
+ params: this.query,
14247
+ });
14096
14248
  }
14097
14249
  }
14098
- /**
14099
- * Get all sessions with a specific sync state
14100
- */
14101
- getSessionsByState(state) {
14102
- return Array.from(this.sessions.values()).filter(session => session.syncState === state);
14103
- }
14104
- /**
14105
- * Delete a session
14106
- */
14107
- deleteSession(sessionId) {
14108
- this.sessions.delete(sessionId);
14109
- }
14110
- /**
14111
- * Get all pending sessions
14112
- */
14113
- getPendingSessions() {
14114
- return this.getSessionsByState('PENDING');
14115
- }
14116
- /**
14117
- * Get all syncing sessions
14118
- */
14119
- getSyncingSessions() {
14120
- return this.getSessionsByState('SYNCING');
14121
- }
14122
- }
14123
- // Singleton instance
14124
- let storageInstance = null;
14125
- const getWatchSessionStorage = () => {
14126
- if (!storageInstance) {
14127
- storageInstance = new WatchSessionStorage();
14128
- }
14129
- return storageInstance;
14130
- };
14131
-
14132
- const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHo80SecH7FuF2\nhFYnb+l26/VN8UMLXAQFLnxciNTEwkGVFMpdezlH8rU2HtUJL4RETogbAOLVY0XM\njs6sPn8G1nALmh9qeDpUtVqFOVtBHxEZ910TLOtQiunjqJKO5nWdqZ71EC3OFluR\niGQkO84BiIFbv37ub7xl3S8XarbtKoLcyVpkDHi+1wx1pgCAn6gtBUgckPL5NR8j\nLseabl3HAXQfhTCKo4tmOFM2Dxwl1IUMmIJrJg/aIU/U0tj/1Eoo7mG0JcNWX19l\nW3EecCbi0ncCJOrkUdwlBrcjaMayaX/ubEwyUeTGiLdyc4L3GRLHjyK8xgVNXRMH\nbZWJ2a5NAgMBAAECggEASxuE+35zTFO/XydKgmvIGcWL9FbgMlXb7Vcf0nBoG945\nbiz0NVc2paraIhJXc608xbYF3qLmtAE1MVBI0ORyRdBHNxY024l/6H6SH60Ed+uI\nM4ysp5ourY6Vj+DLwpdRiI9YDjqYAQDIUmhNxJP7XPhOMoZI6st+xZQBM34ic/bv\nAMSJm9OZphSp3+qXVkFZztr2mxD2EZSJJLYxi8BCdgM2qhazalbcJ6zDKHCZWVWm\n8RRxDGldyMb/237JxETzP40tAlzOZDmBAbUgEnurDJ93RVDIE3rbZUshwgeQd18a\nem096mWgvB1AIKYgsTAR3pw+V19YWAjq/glP6fz8wQKBgQD/oQq+ukKF0PRgBeM5\ngeTjSwsdGppQLmf5ndujvoiz/TpdjDEPu6R8kigQr1rG2t4K/yfdZoI8RdmJD1al\n3Q7N9hofooSy4rj6E3txzWZCHJjHad2cnCp/O26HiReGAl7wTcfTmNdiFHhZQzm5\nJBkvWAiwuvQMNfEbnXxw6/vIDwKBgQDH7fX8gsc77JLvAWgp1MaQN/sbqVb6JeT1\nFQfR8E/WFCSmzQBtNzd5KgYuCeelwr/8DyYytvN2BzCYZXp73gI1jF3YlW5jVn74\nOY6TwQ095digwo6Z0yuxopdIOApKgAkL9PRKgNrqAf3NAyMua6lOGifzjDojC3KU\nfylQmxMn4wKBgHp2B9O/H0dEBw5JQ8W0+JX6yWQz7mEjGiR2/1W+XXb8hQ1zr709\nw1r6Gb+EghRpnZ3fBpYGGbYOMFx8wKHM+N6qW3F0ReX8v2juFGE8aRSa5oYBrWzt\nU16Idjbv8hj84cZ1PJmdyvDtpYn9rpWHOZl4rxEbPvbqkIsOMyNVqdT5AoGAOSge\nmwIIU2le2FVeohbibXiToWTYKMuMmURZ5/r72AgKMmWJKbAPe+Q3wBG01/7FRBpQ\noU8Ma0HC8s6QJbliiEyIx9JwrJWd1vkdecBHONrtA4ibm/5zD2WcOllLF+FitLhi\n3qnX6+6F0IaFGFBPJrTzlv0P4dTz/OAdv52V7GECgYEA2TttOKBAqWllgOaZOkql\nLVMJVmgR7s6tLi1+cEP8ZcapV9aRbRzTAKXm4f8AEhtlG9F9kCOvHYCYGi6JaiWJ\nZkHjeex3T+eE6Di6y5Bm/Ift5jtVhJ4jCVwHOKTMej79NPUFTJfv8hCo29haBDv6\nRXFrv+T21KCcw8k3sJeJWWQ=\n-----END PRIVATE KEY-----";
14133
- /*
14134
- * The crypto algorithm used for importing key and signing string
14135
- */
14136
- const ALGORITHM = {
14137
- name: 'RSASSA-PKCS1-v1_5',
14138
- hash: { name: 'SHA-256' },
14139
- };
14140
- /*
14141
- * IMPORTANT!
14142
- * If you are recieving key from other platforms use an online tool to convert
14143
- * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
14144
- * PKCS1.
14145
- *
14146
- * If recieving from the platform, verify if it's already in the expected
14147
- * format. Otherwise the crypto.subtle.importKey will throw a DOMException
14148
- */
14149
- const PRIVATE_KEY_SIGNATURE = 'pkcs8';
14150
- /*
14151
- * Ensure that the private key in the .env follows this format
14152
- */
14153
- const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
14154
- const PEM_FOOTER = '-----END PRIVATE KEY-----';
14155
- /*
14156
- * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
14157
- * expects a base64 string. This util helps facilitate that process
14158
- */
14159
- function base64FromArrayBuffer(buffer) {
14160
- const uint8Array = new Uint8Array(buffer);
14161
- let binary = '';
14162
- uint8Array.forEach(byte => {
14163
- binary += String.fromCharCode(byte);
14164
- });
14165
- return jsBase64.btoa(binary);
14166
- }
14167
- /*
14168
- * Encode ASN.1 length field
14169
- */
14170
- function encodeLength(length) {
14171
- if (length < 128) {
14172
- return new Uint8Array([length]);
14250
+ async persistModel(queryPayload) {
14251
+ await this.queryStreamController.saveToMainDB(queryPayload);
14173
14252
  }
14174
- if (length < 256) {
14175
- return new Uint8Array([0x81, length]);
14253
+ persistQueryStream({ response, direction, refresh, }) {
14254
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
14176
14255
  }
14177
- // eslint-disable-next-line no-bitwise
14178
- return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
14179
- }
14180
- /*
14181
- * Convert PKCS1 private key to PKCS8 format
14182
- * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
14183
- * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
14184
- */
14185
- function pkcs1ToPkcs8(pkcs1) {
14186
- // Algorithm identifier for RSA
14187
- const algorithmIdentifier = new Uint8Array([
14188
- 0x30,
14189
- 0x0d,
14190
- 0x06,
14191
- 0x09,
14192
- 0x2a,
14193
- 0x86,
14194
- 0x48,
14195
- 0x86,
14196
- 0xf7,
14197
- 0x0d,
14198
- 0x01,
14199
- 0x01,
14200
- 0x01,
14201
- 0x05,
14202
- 0x00, // NULL
14203
- ]);
14204
- // Version (INTEGER 0)
14205
- const version = new Uint8Array([0x02, 0x01, 0x00]);
14206
- // OCTET STRING tag + length + pkcs1 data
14207
- const octetStringTag = 0x04;
14208
- const octetStringLength = encodeLength(pkcs1.length);
14209
- // Calculate total content length (version + algorithm + octet string)
14210
- const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
14211
- // SEQUENCE tag + length
14212
- const sequenceTag = 0x30;
14213
- const sequenceLength = encodeLength(contentLength);
14214
- // Build the PKCS8 structure
14215
- const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
14216
- let offset = 0;
14217
- pkcs8[offset] = sequenceTag;
14218
- offset += 1;
14219
- pkcs8.set(sequenceLength, offset);
14220
- offset += sequenceLength.length;
14221
- pkcs8.set(version, offset);
14222
- offset += version.length;
14223
- pkcs8.set(algorithmIdentifier, offset);
14224
- offset += algorithmIdentifier.length;
14225
- pkcs8[offset] = octetStringTag;
14226
- offset += 1;
14227
- pkcs8.set(octetStringLength, offset);
14228
- offset += octetStringLength.length;
14229
- pkcs8.set(pkcs1, offset);
14230
- return pkcs8;
14231
- }
14232
- async function importPrivateKey(keyString) {
14233
- // Remove PEM headers if present and any whitespace
14234
- let base64Key = keyString;
14235
- if (keyString.includes(PEM_HEADER)) {
14236
- base64Key = keyString
14237
- .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
14238
- .replace(/\s/g, '');
14256
+ startSubscription() {
14257
+ return this.queryStreamController.subscribeRTE([
14258
+ {
14259
+ fn: onLocalInvitationCreated,
14260
+ action: InvitationActionsEnum.OnLocalInvitationCreated,
14261
+ },
14262
+ {
14263
+ fn: onLocalInvitationUpdated,
14264
+ action: InvitationActionsEnum.OnLocalInvitationUpdated,
14265
+ },
14266
+ {
14267
+ fn: onLocalInvitationCanceled,
14268
+ action: InvitationActionsEnum.OnLocalInvitationCanceled,
14269
+ },
14270
+ ]);
14239
14271
  }
14240
- else {
14241
- base64Key = keyString.replace(/\s/g, '');
14272
+ notifyChange({ origin, loading, error }) {
14273
+ var _a, _b;
14274
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14275
+ if (!collection)
14276
+ return;
14277
+ const data = this.applyFilter((_b = collection.data
14278
+ .map(id => pullFromCache(['invitation', 'get', id]))
14279
+ .filter(isNonNullable)
14280
+ .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
14281
+ if (!this.shouldNotify(data) && origin === 'event')
14282
+ return;
14283
+ this.callback({
14284
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
14285
+ data,
14286
+ hasNextPage: !!this.paginationController.getNextToken(),
14287
+ loading,
14288
+ error,
14289
+ });
14242
14290
  }
14243
- // Base64 decode to get binary data
14244
- const binaryDerString = jsBase64.atob(base64Key);
14245
- // Convert to Uint8Array for manipulation
14246
- const pkcs1 = new Uint8Array(binaryDerString.length);
14247
- for (let i = 0; i < binaryDerString.length; i += 1) {
14248
- pkcs1[i] = binaryDerString.charCodeAt(i);
14291
+ applyFilter(data) {
14292
+ let invitations = data;
14293
+ if (this.query.targetId) {
14294
+ invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
14295
+ }
14296
+ if (this.query.statuses) {
14297
+ invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
14298
+ }
14299
+ if (this.query.targetType) {
14300
+ invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
14301
+ }
14302
+ if (this.query.type) {
14303
+ invitations = invitations.filter(invitation => invitation.type === this.query.type);
14304
+ }
14305
+ const sortFn = (() => {
14306
+ switch (this.query.sortBy) {
14307
+ case 'firstCreated':
14308
+ return sortByFirstCreated;
14309
+ case 'lastCreated':
14310
+ return sortByLastCreated;
14311
+ default:
14312
+ return sortByLastCreated;
14313
+ }
14314
+ })();
14315
+ invitations = invitations.sort(sortFn);
14316
+ return invitations;
14249
14317
  }
14250
- // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
14251
- const pkcs8 = pkcs1ToPkcs8(pkcs1);
14252
- // Import the key
14253
- const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
14254
- return key;
14255
- }
14256
- async function createSignature({ timestamp, rooms, }) {
14257
- const dataStr = rooms
14258
- .map(item => Object.keys(item)
14259
- .sort()
14260
- .map(key => `${key}=${item[key]}`)
14261
- .join('&'))
14262
- .join(';');
14263
- /*
14264
- * nonceStr needs to be unique for each request
14265
- */
14266
- const nonceStr = uuid__default["default"].v4();
14267
- const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
14268
- const encoder = new TextEncoder();
14269
- const data = encoder.encode(signStr);
14270
- const key = await importPrivateKey(privateKey);
14271
- const sign = await crypto.subtle.sign(ALGORITHM, key, data);
14272
- return { signature: base64FromArrayBuffer(sign), nonceStr };
14273
14318
  }
14274
14319
 
14275
14320
  /**
14276
- * Sync pending watch sessions to backend
14277
- * This function implements the full sync flow with network resilience
14321
+ * Get invitations
14322
+ *
14323
+ * @param params the query parameters
14324
+ * @param callback the callback to be called when the invitations are updated
14325
+ * @returns invitations
14326
+ *
14327
+ * @category Invitation Live Collection
14328
+ *
14278
14329
  */
14279
- async function syncWatchSessions() {
14280
- const storage = getWatchSessionStorage();
14281
- // Get all pending sessions
14282
- const pendingSessions = storage.getPendingSessions();
14283
- if (pendingSessions.length === 0) {
14284
- return true;
14330
+ const getInvitations$1 = (params, callback, config) => {
14331
+ const { log, cache } = getActiveClient();
14332
+ if (!cache) {
14333
+ console.log(ENABLE_CACHE_MESSAGE);
14285
14334
  }
14286
- try {
14287
- const timestamp = new Date().toISOString();
14288
- // Convert sessions to API format - always include all fields like syncUsage does
14289
- const rooms = pendingSessions.map(session => ({
14290
- sessionId: session.sessionId,
14291
- roomId: session.roomId,
14292
- watchSeconds: session.watchSeconds,
14293
- startTime: session.startTime.toISOString(),
14294
- endTime: session.endTime ? session.endTime.toISOString() : '',
14295
- }));
14296
- // Create signature (reuse from stream feature) - pass directly like syncUsage
14297
- const signatureData = await createSignature({
14298
- timestamp,
14299
- rooms,
14300
- });
14301
- if (!signatureData || !signatureData.signature) {
14302
- throw new Error('Signature is undefined');
14303
- }
14304
- // Update sync state to SYNCING
14305
- pendingSessions.forEach(session => {
14306
- storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
14307
- });
14308
- const payload = {
14309
- signature: signatureData.signature,
14310
- nonceStr: signatureData.nonceStr,
14311
- timestamp,
14312
- rooms,
14313
- };
14314
- const client = getActiveClient();
14315
- // Send to backend
14316
- await client.http.post('/api/v3/user-event/room', payload);
14317
- // Success - update to SYNCED
14318
- pendingSessions.forEach(session => {
14319
- storage.updateSession(session.sessionId, {
14320
- syncState: 'SYNCED',
14321
- syncedAt: new Date(),
14335
+ const timestamp = Date.now();
14336
+ log(`getInvitations: (tmpid: ${timestamp}) > listen`);
14337
+ const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
14338
+ const disposers = invitationsLiveCollection.startSubscription();
14339
+ const cacheKey = invitationsLiveCollection.getCacheKey();
14340
+ disposers.push(() => {
14341
+ dropFromCache(cacheKey);
14342
+ });
14343
+ return () => {
14344
+ log(`getInvitations (tmpid: ${timestamp}) > dispose`);
14345
+ disposers.forEach(fn => fn());
14346
+ };
14347
+ };
14348
+
14349
+ const categoryLinkedObject = (category) => {
14350
+ return Object.assign(Object.assign({}, category), { get avatar() {
14351
+ var _a;
14352
+ if (!category.avatarFileId)
14353
+ return undefined;
14354
+ const avatar = (_a = pullFromCache([
14355
+ 'file',
14356
+ 'get',
14357
+ `${category.avatarFileId}`,
14358
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14359
+ return avatar;
14360
+ } });
14361
+ };
14362
+
14363
+ const communityLinkedObject = (community) => {
14364
+ return Object.assign(Object.assign({}, community), { get categories() {
14365
+ var _a;
14366
+ return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
14367
+ .map(categoryId => {
14368
+ const cacheData = pullFromCache(['category', 'get', categoryId]);
14369
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
14370
+ return categoryLinkedObject(cacheData.data);
14371
+ return undefined;
14372
+ })
14373
+ .filter(category => !!category);
14374
+ },
14375
+ get avatar() {
14376
+ var _a;
14377
+ if (!community.avatarFileId)
14378
+ return undefined;
14379
+ const avatar = (_a = pullFromCache([
14380
+ 'file',
14381
+ 'get',
14382
+ community.avatarFileId,
14383
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14384
+ return avatar;
14385
+ }, createInvitations: async (userIds) => {
14386
+ await createInvitations({
14387
+ type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
14388
+ targetType: 'community',
14389
+ targetId: community.communityId,
14390
+ userIds,
14322
14391
  });
14323
- });
14324
- return true;
14392
+ }, getMemberInvitations: (params, callback) => {
14393
+ return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
14394
+ }, getInvitation: async () => {
14395
+ const { data } = await getInvitation({
14396
+ targetType: 'community',
14397
+ targetId: community.communityId,
14398
+ });
14399
+ return data;
14400
+ }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
14401
+ return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
14402
+ }, getMyJoinRequest: async () => {
14403
+ const { data } = await getMyJoinRequest(community.communityId);
14404
+ return data;
14405
+ } });
14406
+ };
14407
+
14408
+ class StoryComputedValue {
14409
+ constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
14410
+ this._syncingStoriesCount = 0;
14411
+ this._errorStoriesCount = 0;
14412
+ this._targetId = targetId;
14413
+ this._lastStoryExpiresAt = lastStoryExpiresAt;
14414
+ this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
14415
+ this.cacheStoryExpireTime = pullFromCache([
14416
+ "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
14417
+ this._targetId,
14418
+ ]);
14419
+ this.cacheStoreSeenTime = pullFromCache([
14420
+ "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
14421
+ this._targetId,
14422
+ ]);
14423
+ this.getTotalStoryByStatus();
14325
14424
  }
14326
- catch (err) {
14327
- console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
14328
- // Failure - update back to PENDING and increment retry count
14329
- pendingSessions.forEach(session => {
14330
- const currentSession = storage.getSession(session.sessionId);
14331
- if (currentSession) {
14332
- const newRetryCount = currentSession.retryCount + 1;
14333
- if (newRetryCount >= 3) {
14334
- // Delete session if retry count exceeds 3
14335
- storage.deleteSession(session.sessionId);
14336
- }
14337
- else {
14338
- // Update to PENDING with incremented retry count
14339
- storage.updateSession(session.sessionId, {
14340
- syncState: 'PENDING',
14341
- retryCount: newRetryCount,
14342
- });
14343
- }
14344
- }
14345
- });
14346
- return false;
14425
+ get lastStoryExpiresAt() {
14426
+ return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
14427
+ }
14428
+ get lastStorySeenExpiresAt() {
14429
+ return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
14430
+ }
14431
+ get localLastStoryExpires() {
14432
+ var _a, _b;
14433
+ return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
14434
+ ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
14435
+ : 0;
14436
+ }
14437
+ get localLastStorySeenExpiresAt() {
14438
+ var _a, _b;
14439
+ return ((_a = this.cacheStoreSeenTime) === null || _a === void 0 ? void 0 : _a.data) ? new Date((_b = this.cacheStoreSeenTime) === null || _b === void 0 ? void 0 : _b.data).getTime() : 0;
14440
+ }
14441
+ get isContainUnSyncedStory() {
14442
+ const currentSyncingState = pullFromCache([
14443
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
14444
+ this._targetId,
14445
+ ]);
14446
+ if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
14447
+ return false;
14448
+ return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
14347
14449
  }
14348
- }
14349
-
14350
- /**
14351
- * Room statuses that are considered watchable
14352
- */
14353
- const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
14354
- /**
14355
- * Generate a random jitter delay between 5 and 30 seconds
14356
- */
14357
- const getJitterDelay = () => {
14358
- const minDelay = 5000; // 5 seconds
14359
- const maxDelay = 30000; // 30 seconds
14360
- return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
14361
- };
14362
- /**
14363
- * Wait for network connection with timeout
14364
- * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
14365
- * @returns Promise that resolves when network is available or timeout is reached
14366
- */
14367
- const waitForNetwork = (maxWaitTime = 60000) => {
14368
- return new Promise(resolve => {
14369
- // Simple check - if navigator.onLine is available, use it
14370
- // Otherwise, assume network is available
14371
- if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
14372
- resolve();
14373
- return;
14450
+ getLocalLastSortingDate() {
14451
+ if (this.isContainUnSyncedStory) {
14452
+ return this.localLastStoryExpires;
14374
14453
  }
14375
- const startTime = Date.now();
14376
- const checkInterval = 1000; // 1 second
14377
- const checkConnection = () => {
14378
- if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
14379
- resolve();
14380
- }
14381
- else {
14382
- setTimeout(checkConnection, checkInterval);
14383
- }
14384
- };
14385
- checkConnection();
14386
- });
14387
- };
14388
- /**
14389
- * AmityRoomAnalytics provides analytics capabilities for room watch sessions
14390
- */
14391
- class AmityRoomAnalytics {
14392
- constructor(room) {
14393
- this.storage = getWatchSessionStorage();
14394
- this.client = getActiveClient();
14395
- this.room = room;
14454
+ return this.lastStoryExpiresAt;
14396
14455
  }
14397
- /**
14398
- * Create a new watch session for the current room
14399
- * @param startedAt The timestamp when watching started
14400
- * @returns Promise<string> sessionId unique identifier for this watch session
14401
- * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
14402
- */
14403
- async createWatchSession(startedAt) {
14404
- // Validate room status
14405
- if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
14406
- throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
14456
+ getHasUnseenFlag() {
14457
+ const now = new Date().getTime();
14458
+ const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
14459
+ pullFromCache([
14460
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
14461
+ this._targetId,
14462
+ ]);
14463
+ if (this.isContainUnSyncedStory) {
14464
+ return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
14407
14465
  }
14408
- // Generate session ID with prefix
14409
- const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
14410
- const sessionId = prefix + uuid__default["default"].v4();
14411
- // Create watch session entity
14412
- const session = {
14413
- sessionId,
14414
- roomId: this.room.roomId,
14415
- watchSeconds: 0,
14416
- startTime: startedAt,
14417
- endTime: null,
14418
- syncState: 'PENDING',
14419
- syncedAt: null,
14420
- retryCount: 0,
14421
- };
14422
- // Persist to storage
14423
- this.storage.addSession(session);
14424
- return sessionId;
14466
+ return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
14425
14467
  }
14426
- /**
14427
- * Update an existing watch session with duration
14428
- * @param sessionId The unique identifier of the watch session
14429
- * @param duration The total watch duration in seconds
14430
- * @param endedAt The timestamp when this update occurred
14431
- * @returns Promise<void> Completion status
14432
- */
14433
- async updateWatchSession(sessionId, duration, endedAt) {
14434
- const session = this.storage.getSession(sessionId);
14435
- if (!session) {
14436
- throw new Error(`Watch session ${sessionId} not found`);
14468
+ getTotalStoryByStatus() {
14469
+ const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
14470
+ if (!stories) {
14471
+ this._errorStoriesCount = 0;
14472
+ this._syncingStoriesCount = 0;
14473
+ return;
14437
14474
  }
14438
- // Update session
14439
- this.storage.updateSession(sessionId, {
14440
- watchSeconds: duration,
14441
- endTime: endedAt,
14475
+ const groupByType = stories.reduce((acc, story) => {
14476
+ const { data: { targetId, syncState, isDeleted }, } = story;
14477
+ if (targetId === this._targetId && !isDeleted) {
14478
+ acc[syncState] += 1;
14479
+ }
14480
+ return acc;
14481
+ }, {
14482
+ syncing: 0,
14483
+ error: 0,
14484
+ synced: 0,
14442
14485
  });
14486
+ this._errorStoriesCount = groupByType.error;
14487
+ this._syncingStoriesCount = groupByType.syncing;
14443
14488
  }
14444
- /**
14445
- * Sync all pending watch sessions to backend
14446
- * This function uses jitter delay and handles network resilience
14447
- */
14448
- syncPendingWatchSessions() {
14449
- // Execute with jitter delay (5-30 seconds)
14450
- const jitterDelay = getJitterDelay();
14451
- this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
14452
- setTimeout(async () => {
14453
- this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
14454
- try {
14455
- // Reset any SYNCING sessions back to PENDING
14456
- const syncingSessions = this.storage.getSyncingSessions();
14457
- this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
14458
- syncingSessions.forEach(session => {
14459
- this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
14460
- });
14461
- // Wait for network connection (max 60 seconds)
14462
- await waitForNetwork(60000);
14463
- this.client.log('room/RoomAnalytics: Network available');
14464
- // Sync pending sessions
14465
- this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
14466
- await syncWatchSessions();
14467
- this.client.log('room/RoomAnalytics: syncWatchSessions completed');
14468
- }
14469
- catch (error) {
14470
- // Error is already handled in syncWatchSessions
14471
- console.error('Failed to sync watch sessions:', error);
14472
- }
14473
- }, jitterDelay);
14489
+ get syncingStoriesCount() {
14490
+ return this._syncingStoriesCount;
14491
+ }
14492
+ get failedStoriesCount() {
14493
+ return this._errorStoriesCount;
14474
14494
  }
14475
14495
  }
14476
14496
 
14477
- const roomLinkedObject = (room) => {
14478
- return Object.assign(Object.assign({}, room), { get post() {
14479
- var _a;
14480
- if (room.referenceType !== 'post')
14481
- return;
14482
- return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
14497
+ const storyTargetLinkedObject = (storyTarget) => {
14498
+ const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
14499
+ const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
14500
+ return {
14501
+ targetType,
14502
+ targetId,
14503
+ lastStoryExpiresAt,
14504
+ updatedAt: targetUpdatedAt,
14505
+ // Additional data
14506
+ hasUnseen: computedValue.getHasUnseenFlag(),
14507
+ syncingStoriesCount: computedValue.syncingStoriesCount,
14508
+ failedStoriesCount: computedValue.failedStoriesCount,
14509
+ localFilter,
14510
+ localLastExpires: computedValue.localLastStoryExpires,
14511
+ localLastSeen: computedValue.localLastStorySeenExpiresAt,
14512
+ localSortingDate: computedValue.getLocalLastSortingDate(),
14513
+ };
14514
+ };
14515
+
14516
+ const storyLinkedObject = (story) => {
14517
+ const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
14518
+ const storyTargetCache = pullFromCache([
14519
+ "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
14520
+ 'get',
14521
+ story.targetId,
14522
+ ]);
14523
+ const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
14524
+ return Object.assign(Object.assign({}, story), { analytics: {
14525
+ markAsSeen: () => {
14526
+ if (!story.expiresAt)
14527
+ return;
14528
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
14529
+ return;
14530
+ analyticsEngineInstance.markStoryAsViewed(story);
14531
+ },
14532
+ markLinkAsClicked: () => {
14533
+ if (!story.expiresAt)
14534
+ return;
14535
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
14536
+ return;
14537
+ analyticsEngineInstance.markStoryAsClicked(story);
14538
+ },
14539
+ }, get videoData() {
14540
+ var _a, _b;
14541
+ const cache = pullFromCache([
14542
+ 'file',
14543
+ 'get',
14544
+ (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
14545
+ ]);
14546
+ if (!cache)
14547
+ return undefined;
14548
+ const { data } = cache;
14549
+ return data || undefined;
14550
+ },
14551
+ get imageData() {
14552
+ var _a, _b;
14553
+ if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
14554
+ return undefined;
14555
+ const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
14556
+ if (!cache)
14557
+ return undefined;
14558
+ const { data } = cache;
14559
+ if (!data)
14560
+ return undefined;
14561
+ return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
14483
14562
  },
14484
14563
  get community() {
14485
- var _a;
14486
- if (room.targetType !== 'community')
14564
+ if (story.targetType !== 'community')
14565
+ return undefined;
14566
+ if (!(communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data))
14567
+ return undefined;
14568
+ return communityLinkedObject(communityCacheData.data);
14569
+ },
14570
+ get communityCategories() {
14571
+ if (story.targetType !== 'community')
14572
+ return undefined;
14573
+ if (!communityCacheData)
14574
+ return undefined;
14575
+ const { data: { categoryIds }, } = communityCacheData;
14576
+ if (categoryIds.length === 0)
14577
+ return undefined;
14578
+ return categoryIds
14579
+ .map(categoryId => {
14580
+ const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
14581
+ return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
14582
+ })
14583
+ .filter(category => category !== undefined);
14584
+ },
14585
+ get creator() {
14586
+ const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
14587
+ if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
14487
14588
  return;
14488
- return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
14589
+ return userLinkedObject(cacheData.data);
14489
14590
  },
14490
- get user() {
14491
- var _a;
14492
- const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
14493
- return user ? userLinkedObject(user) : user;
14591
+ get storyTarget() {
14592
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
14593
+ return;
14594
+ return storyTargetLinkedObject(storyTargetCache.data);
14494
14595
  },
14495
- get childRooms() {
14496
- if (!room.childRoomIds || room.childRoomIds.length === 0)
14497
- return [];
14498
- return room.childRoomIds
14499
- .map(id => {
14500
- var _a;
14501
- const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
14502
- if (!roomCache)
14503
- return undefined;
14504
- return roomLinkedObject(roomCache);
14505
- })
14506
- .filter(isNonNullable);
14507
- }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
14508
- var _a;
14509
- const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
14510
- return user ? userLinkedObject(user) : user;
14511
- } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
14512
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
14513
- targetType: 'room',
14514
- targetId: room.roomId,
14515
- userIds: [userId],
14516
- }), getInvitations: async () => {
14517
- const { data } = await getInvitation({
14518
- targetId: room.roomId,
14519
- targetType: 'room',
14520
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
14521
- });
14522
- return data;
14523
- }, analytics() {
14524
- // Use 'this' to avoid creating a new room object
14525
- return new AmityRoomAnalytics(this);
14596
+ get isSeen() {
14597
+ const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
14598
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
14599
+ return false;
14600
+ const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
14601
+ const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
14602
+ const expiresAt = new Date(story.expiresAt).getTime();
14603
+ return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
14526
14604
  } });
14527
14605
  };
14528
14606
 
14529
- const pollLinkedObject = (poll) => {
14530
- return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
14531
- var _a;
14532
- if (!answer.fileId)
14533
- return undefined;
14534
- return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
14535
- } }))) });
14536
- };
14537
-
14538
- /*
14539
- * verifies membership status
14540
- */
14541
- function isMember(membership) {
14542
- return membership !== 'none';
14543
- }
14544
- /*
14545
- * checks if currently logged in user is part of the community
14546
- */
14547
- function isCurrentUserPartOfCommunity(c, m) {
14548
- const { userId } = getActiveUser();
14549
- return c.communityId === m.communityId && m.userId === userId;
14550
- }
14551
- /*
14552
- * For mqtt events server will not send user specific data as it's broadcasted
14553
- * to multiple users and it also does not include communityUser
14554
- *
14555
- * Client SDK needs to check for the existing isJoined field in cache data before calculating.
14556
- * Althought this can be calculated, it's not scalable.
14557
- */
14558
- function updateMembershipStatus(communities, communityUsers) {
14559
- return communities.map(c => {
14560
- const cachedCommunity = pullFromCache([
14561
- 'community',
14562
- 'get',
14563
- c.communityId,
14564
- ]);
14565
- if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
14566
- return Object.assign(Object.assign({}, cachedCommunity.data), c);
14567
- }
14568
- const isJoined = c.isJoined !== undefined
14569
- ? c.isJoined
14570
- : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
14571
- return Object.assign(Object.assign({}, c), { isJoined });
14572
- });
14573
- }
14574
-
14575
- const getMatchPostSetting = (value) => {
14576
- var _a;
14577
- return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
14578
- CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
14579
- value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
14580
- };
14581
- function addPostSetting({ communities }) {
14582
- return communities.map((_a) => {
14583
- var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
14584
- return (Object.assign({ postSetting: getMatchPostSetting({
14585
- needApprovalOnPostCreation,
14586
- onlyAdminCanPost,
14587
- }) }, restCommunityPayload));
14588
- });
14589
- }
14590
- const prepareCommunityPayload = (rawPayload) => {
14591
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
14592
- // Convert users to internal format
14593
- const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
14594
- // map users with community
14595
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
14596
- const user = internalUsers.find(user => user.userId === communityUser.userId);
14597
- return Object.assign(Object.assign({}, communityUser), { user });
14598
- });
14599
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
14600
- return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
14601
- };
14602
- const prepareCommunityJoinRequestPayload = (rawPayload) => {
14603
- const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
14604
- return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
14605
- });
14606
- const users = rawPayload.users.map(convertRawUserToInternalUser);
14607
- return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
14608
- };
14609
- const prepareCommunityMembershipPayload = (rawPayload) => {
14610
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
14611
- // map users with community
14612
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
14613
- const user = rawPayload.users.find(user => user.userId === communityUser.userId);
14614
- return Object.assign(Object.assign({}, communityUser), { user });
14615
- });
14616
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
14617
- return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
14618
- };
14619
- const prepareCommunityRequest = (params) => {
14620
- const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
14621
- return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
14622
- // Convert story setting to the actual value. (Allow by default)
14623
- allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
14624
- };
14625
- const prepareSemanticSearchCommunityPayload = (_a) => {
14626
- var communityPayload = __rest(_a, ["searchResult"]);
14627
- const processedCommunityPayload = prepareCommunityPayload(communityPayload);
14628
- return Object.assign({}, processedCommunityPayload);
14629
- };
14630
-
14631
14607
  /* begin_public_function
14632
- id: joinRequest.approve
14608
+ id: channel.create
14633
14609
  */
14634
14610
  /**
14635
14611
  * ```js
14636
- * import { joinRequest } from '@amityco/ts-sdk'
14637
- * const isAccepted = await joinRequest.approve()
14612
+ * import { createChannel } from '@amityco/ts-sdk'
14613
+ * const created = await createChannel({ displayName: 'foobar' })
14638
14614
  * ```
14639
14615
  *
14640
- * Accepts a {@link Amity.JoinRequest} object
14616
+ * Creates an {@link Amity.Channel}
14641
14617
  *
14642
- * @param joinRequest the {@link Amity.JoinRequest} to accept
14643
- * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
14618
+ * @param bundle The data necessary to create a new {@link Amity.Channel}
14619
+ * @returns The newly created {@link Amity.Channel}
14644
14620
  *
14645
- * @category Join Request API
14621
+ * @category Channel API
14646
14622
  * @async
14647
14623
  */
14648
- const approveJoinRequest = async (joinRequest) => {
14649
- var _a;
14624
+ const createChannel = async (bundle) => {
14650
14625
  const client = getActiveClient();
14651
- client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
14652
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
14653
- userId: joinRequest.requestorInternalId,
14654
- });
14655
- const joinRequestCache = (_a = pullFromCache([
14656
- 'joinRequest',
14657
- 'get',
14658
- joinRequest.joinRequestId,
14659
- ])) === null || _a === void 0 ? void 0 : _a.data;
14660
- if (joinRequestCache) {
14661
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
14662
- status: "approved" /* JoinRequestStatusEnum.Approved */,
14663
- });
14664
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
14626
+ client.log('user/createChannel', bundle);
14627
+ let payload;
14628
+ /* c8 ignore next */
14629
+ if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
14630
+ payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
14665
14631
  }
14666
- return data.success;
14632
+ else {
14633
+ const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
14634
+ payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
14635
+ /* c8 ignore next */
14636
+ isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
14637
+ }
14638
+ const data = await prepareChannelPayload(payload.data);
14639
+ const cachedAt = client.cache && Date.now();
14640
+ if (client.cache)
14641
+ ingestInCache(data, { cachedAt });
14642
+ const { channels } = data;
14643
+ return {
14644
+ data: constructChannelObject(channels[0]),
14645
+ cachedAt,
14646
+ };
14667
14647
  };
14668
14648
  /* end_public_function */
14669
14649
 
14670
- /* begin_public_function
14671
- id: joinRequest.cancel
14672
- */
14673
14650
  /**
14674
14651
  * ```js
14675
- * import { joinRequest } from '@amityco/ts-sdk'
14676
- * const isCanceled = await joinRequest.cancel()
14652
+ * import { getChannel } from '@amityco/ts-sdk'
14653
+ * const channel = await getChannel('foobar')
14677
14654
  * ```
14678
14655
  *
14679
- * Cancels a {@link Amity.JoinRequest} object
14656
+ * Fetches a {@link Amity.Channel} object
14680
14657
  *
14681
- * @param joinRequest the {@link Amity.JoinRequest} to cancel
14682
- * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
14658
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
14659
+ * @returns the associated {@link Amity.Channel} object
14683
14660
  *
14684
- * @category Join Request API
14661
+ * @category Channel API
14685
14662
  * @async
14686
14663
  */
14687
- const cancelJoinRequest = async (joinRequest) => {
14688
- var _a;
14664
+ const getChannel$1 = async (channelId) => {
14689
14665
  const client = getActiveClient();
14690
- client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
14691
- const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
14692
- const joinRequestCache = (_a = pullFromCache([
14693
- 'joinRequest',
14694
- 'get',
14695
- joinRequest.joinRequestId,
14696
- ])) === null || _a === void 0 ? void 0 : _a.data;
14697
- if (joinRequestCache) {
14698
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
14699
- status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
14700
- });
14701
- fireEvent('local.joinRequest.deleted', [joinRequestCache]);
14666
+ client.log('channel/getChannel', channelId);
14667
+ isInTombstone('channel', channelId);
14668
+ let data;
14669
+ try {
14670
+ const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
14671
+ data = await prepareChannelPayload(payload);
14672
+ if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
14673
+ prepareUnreadCountInfo(payload);
14674
+ }
14702
14675
  }
14703
- return data.success;
14676
+ catch (error) {
14677
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
14678
+ // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
14679
+ pushToTombstone('channel', channelId);
14680
+ }
14681
+ throw error;
14682
+ }
14683
+ const cachedAt = client.cache && Date.now();
14684
+ if (client.cache)
14685
+ ingestInCache(data, { cachedAt });
14686
+ const { channels } = data;
14687
+ return {
14688
+ data: channels.find(channel => channel.channelId === channelId),
14689
+ cachedAt,
14690
+ };
14704
14691
  };
14705
- /* end_public_function */
14706
-
14707
- /* begin_public_function
14708
- id: joinRequest.reject
14709
- */
14710
14692
  /**
14711
14693
  * ```js
14712
- * import { joinRequest } from '@amityco/ts-sdk'
14713
- * const isRejected = await joinRequest.reject()
14694
+ * import { getChannel } from '@amityco/ts-sdk'
14695
+ * const channel = getChannel.locally('foobar')
14714
14696
  * ```
14715
14697
  *
14716
- * Rejects a {@link Amity.JoinRequest} object
14698
+ * Fetches a {@link Amity.Channel} object from cache
14717
14699
  *
14718
- * @param joinRequest the {@link Amity.JoinRequest} to reject
14719
- * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
14700
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
14701
+ * @returns the associated {@link Amity.Channel} object
14720
14702
  *
14721
- * @category Join Request API
14722
- * @async
14703
+ * @category Channel API
14723
14704
  */
14724
- const rejectJoinRequest = async (joinRequest) => {
14705
+ getChannel$1.locally = (channelId) => {
14725
14706
  var _a;
14726
14707
  const client = getActiveClient();
14727
- client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
14728
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
14729
- userId: joinRequest.requestorInternalId,
14708
+ client.log('channel/getChannel.locally', channelId);
14709
+ if (!client.cache)
14710
+ return;
14711
+ // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
14712
+ const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
14713
+ return data.channelPublicId === channelId;
14730
14714
  });
14731
- const joinRequestCache = (_a = pullFromCache([
14732
- 'joinRequest',
14733
- 'get',
14734
- joinRequest.joinRequestId,
14735
- ])) === null || _a === void 0 ? void 0 : _a.data;
14736
- if (joinRequestCache) {
14737
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
14738
- status: "rejected" /* JoinRequestStatusEnum.Rejected */,
14739
- });
14740
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
14741
- }
14742
- return data.success;
14743
- };
14744
- /* end_public_function */
14745
-
14746
- const joinRequestLinkedObject = (joinRequest) => {
14747
- return Object.assign(Object.assign({}, joinRequest), { get user() {
14748
- var _a;
14749
- const user = (_a = pullFromCache([
14750
- 'user',
14751
- 'get',
14752
- joinRequest.requestorPublicId,
14753
- ])) === null || _a === void 0 ? void 0 : _a.data;
14754
- if (!user)
14755
- return undefined;
14756
- return userLinkedObject(user);
14757
- }, cancel: async () => {
14758
- await cancelJoinRequest(joinRequest);
14759
- }, approve: async () => {
14760
- await approveJoinRequest(joinRequest);
14761
- }, reject: async () => {
14762
- await rejectJoinRequest(joinRequest);
14763
- } });
14715
+ if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
14716
+ return;
14717
+ return {
14718
+ data: cached[0].data,
14719
+ cachedAt: cached[0].cachedAt,
14720
+ };
14764
14721
  };
14765
14722
 
14766
- /* begin_public_function
14767
- id: community.getMyJoinRequest
14768
- */
14769
14723
  /**
14770
14724
  * ```js
14771
- * import { community } from '@amityco/ts-sdk'
14772
- * const isJoined = await community.getMyJoinRequest('foobar')
14725
+ * import { getStream } from '@amityco/ts-sdk'
14726
+ * const stream = await getStream('foobar')
14773
14727
  * ```
14774
14728
  *
14775
- * Joins a {@link Amity.Community} object
14729
+ * Fetches a {@link Amity.Channel} object linked with a current stream
14776
14730
  *
14777
- * @param communityId the {@link Amity.Community} to join
14778
- * @returns A success boolean if the {@link Amity.Community} was joined
14731
+ * @param stream {@link Amity.Stream} that has linked live channel
14732
+ * @returns the associated {@link Amity.Channel<'live'>} object
14779
14733
  *
14780
- * @category Community API
14734
+ * @category Stream API
14781
14735
  * @async
14782
14736
  */
14783
- const getMyJoinRequest = async (communityId) => {
14737
+ const getLiveChat$1 = async (stream) => {
14738
+ var _a;
14784
14739
  const client = getActiveClient();
14785
- client.log('community/myJoinRequest', communityId);
14786
- const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
14787
- const data = prepareCommunityJoinRequestPayload(payload);
14788
- const cachedAt = client.cache && Date.now();
14789
- if (client.cache)
14790
- ingestInCache(data, { cachedAt });
14791
- return {
14792
- data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
14793
- cachedAt,
14794
- };
14740
+ client.log('stream/getLiveChat', stream.streamId);
14741
+ if (stream.channelId) {
14742
+ const channel = (_a = pullFromCache([
14743
+ 'channel',
14744
+ 'get',
14745
+ stream.channelId,
14746
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14747
+ if (channel)
14748
+ return channelLinkedObject(constructChannelObject(channel));
14749
+ const { data } = await getChannel$1(stream.channelId);
14750
+ return channelLinkedObject(constructChannelObject(data));
14751
+ }
14752
+ // No Channel ID
14753
+ // streamer: create a new live channel
14754
+ if (stream.userId === client.userId) {
14755
+ const { data: channel } = await createChannel({
14756
+ type: 'live',
14757
+ postId: stream.postId,
14758
+ videoStreamId: stream.streamId,
14759
+ });
14760
+ // Update channelId to stream object in cache
14761
+ mergeInCache(['stream', 'get', stream.streamId], {
14762
+ channelId: channel.channelId,
14763
+ });
14764
+ return channel;
14765
+ }
14766
+ // watcher: return undefined
14767
+ return undefined;
14795
14768
  };
14796
- /* end_public_function */
14797
14769
 
14798
- /* begin_public_function
14799
- id: community.join
14800
- */
14770
+ const GET_WATCHER_URLS = Symbol('getWatcherUrls');
14771
+ const streamLinkedObject = (stream) => {
14772
+ return Object.assign(Object.assign({}, stream), { get moderation() {
14773
+ var _a;
14774
+ return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
14775
+ },
14776
+ get post() {
14777
+ var _a;
14778
+ if (stream.referenceType !== 'post')
14779
+ return;
14780
+ return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
14781
+ },
14782
+ get community() {
14783
+ var _a;
14784
+ if (stream.targetType !== 'community')
14785
+ return;
14786
+ return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
14787
+ },
14788
+ get user() {
14789
+ var _a;
14790
+ return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
14791
+ },
14792
+ get childStreams() {
14793
+ if (!stream.childStreamIds || stream.childStreamIds.length === 0)
14794
+ return [];
14795
+ return stream.childStreamIds
14796
+ .map(id => {
14797
+ var _a;
14798
+ const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
14799
+ if (!streamCache)
14800
+ return undefined;
14801
+ return streamLinkedObject(streamCache);
14802
+ })
14803
+ .filter(isNonNullable);
14804
+ }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
14805
+ return stream.watcherUrl;
14806
+ } });
14807
+ };
14808
+
14809
+ const commentLinkedObject = (comment) => {
14810
+ return Object.assign(Object.assign({}, comment), { get target() {
14811
+ const commentTypes = {
14812
+ type: comment.targetType,
14813
+ };
14814
+ if (comment.targetType === 'user') {
14815
+ return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
14816
+ }
14817
+ if (commentTypes.type === 'content') {
14818
+ return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
14819
+ }
14820
+ if (commentTypes.type === 'community') {
14821
+ const cacheData = pullFromCache([
14822
+ 'communityUsers',
14823
+ 'get',
14824
+ `${comment.targetId}#${comment.userId}`,
14825
+ ]);
14826
+ return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
14827
+ }
14828
+ return {
14829
+ type: 'unknown',
14830
+ };
14831
+ },
14832
+ get creator() {
14833
+ const cacheData = pullFromCache(['user', 'get', comment.userId]);
14834
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
14835
+ return userLinkedObject(cacheData.data);
14836
+ return undefined;
14837
+ },
14838
+ get childrenComment() {
14839
+ return comment.children
14840
+ .map(childCommentId => {
14841
+ const commentCache = pullFromCache([
14842
+ 'comment',
14843
+ 'get',
14844
+ childCommentId,
14845
+ ]);
14846
+ if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
14847
+ return;
14848
+ return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
14849
+ })
14850
+ .filter(isNonNullable)
14851
+ .map(item => commentLinkedObject(item));
14852
+ } });
14853
+ };
14854
+
14855
+ function isAmityImagePost(post) {
14856
+ return !!(post.data &&
14857
+ typeof post.data !== 'string' &&
14858
+ 'fileId' in post.data &&
14859
+ post.dataType === 'image');
14860
+ }
14861
+ function isAmityFilePost(post) {
14862
+ return !!(post.data &&
14863
+ typeof post.data !== 'string' &&
14864
+ 'fileId' in post.data &&
14865
+ post.dataType === 'file');
14866
+ }
14867
+ function isAmityVideoPost(post) {
14868
+ return !!(post.data &&
14869
+ typeof post.data !== 'string' &&
14870
+ 'videoFileId' in post.data &&
14871
+ 'thumbnailFileId' in post.data &&
14872
+ post.dataType === 'video');
14873
+ }
14874
+ function isAmityLivestreamPost(post) {
14875
+ return !!(post.data &&
14876
+ typeof post.data !== 'string' &&
14877
+ 'streamId' in post.data &&
14878
+ post.dataType === 'liveStream');
14879
+ }
14880
+ function isAmityPollPost(post) {
14881
+ return !!(post.data &&
14882
+ typeof post.data !== 'string' &&
14883
+ 'pollId' in post.data &&
14884
+ post.dataType === 'poll');
14885
+ }
14886
+ function isAmityClipPost(post) {
14887
+ return !!(post.data &&
14888
+ typeof post.data !== 'string' &&
14889
+ 'fileId' in post.data &&
14890
+ post.dataType === 'clip');
14891
+ }
14892
+ function isAmityAudioPost(post) {
14893
+ return !!(post.data &&
14894
+ typeof post.data !== 'string' &&
14895
+ 'fileId' in post.data &&
14896
+ post.dataType === 'audio');
14897
+ }
14898
+ function isAmityRoomPost(post) {
14899
+ return !!(post.data &&
14900
+ typeof post.data !== 'string' &&
14901
+ 'roomId' in post.data &&
14902
+ post.dataType === 'room');
14903
+ }
14904
+
14801
14905
  /**
14802
14906
  * ```js
14803
- * import { community } from '@amityco/ts-sdk'
14804
- * const isJoined = await community.join('foobar')
14907
+ * import { RoomRepository } from '@amityco/ts-sdk'
14908
+ * const stream = await getStream('foobar')
14805
14909
  * ```
14806
14910
  *
14807
- * Joins a {@link Amity.Community} object
14911
+ * Fetches a {@link Amity.Channel} object linked with a current stream
14808
14912
  *
14809
- * @param communityId the {@link Amity.Community} to join
14810
- * @returns A status join result
14913
+ * @param stream {@link Amity.Stream} that has linked live channel
14914
+ * @returns the associated {@link Amity.Channel<'live'>} object
14811
14915
  *
14812
- * @category Community API
14916
+ * @category Stream API
14813
14917
  * @async
14814
14918
  */
14815
- const joinRequest = async (communityId) => {
14919
+ const getLiveChat = async (room) => {
14816
14920
  var _a;
14817
14921
  const client = getActiveClient();
14818
- client.log('community/joinRequest', communityId);
14819
- const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
14820
- const data = prepareCommunityJoinRequestPayload(payload);
14821
- const cachedAt = client.cache && Date.now();
14822
- if (client.cache)
14823
- ingestInCache(data, { cachedAt });
14824
- const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
14825
- ? "success" /* JoinResultStatusEnum.Success */
14826
- : "pending" /* JoinResultStatusEnum.Pending */;
14827
- if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
14828
- const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
14829
- if (community) {
14830
- const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
14831
- upsertInCache(['community', 'get', communityId], updatedCommunity);
14832
- }
14922
+ client.log('room/getLiveChat', room.roomId);
14923
+ if (room.liveChannelId) {
14924
+ const channel = (_a = pullFromCache([
14925
+ 'channel',
14926
+ 'get',
14927
+ room.liveChannelId,
14928
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14929
+ if (channel)
14930
+ return channelLinkedObject(constructChannelObject(channel));
14931
+ const { data } = await getChannel$1(room.liveChannelId);
14932
+ return channelLinkedObject(constructChannelObject(data));
14833
14933
  }
14834
- fireEvent('v4.local.community.joined', data.joinRequests);
14835
- return status === "success" /* JoinResultStatusEnum.Success */
14836
- ? { status }
14837
- : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
14838
- };
14839
- /* end_public_function */
14840
-
14841
- /**
14842
- * TODO: handle cache receive cache option, and cache policy
14843
- * TODO: check if querybyIds is supported
14844
- */
14845
- class JoinRequestsPaginationController extends PaginationController {
14846
- async getRequest(queryParams, token) {
14847
- const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
14848
- const options = token ? { token } : { limit };
14849
- const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
14850
- params: Object.assign(Object.assign({}, params), { options }),
14934
+ // No Channel ID
14935
+ // streamer: create a new live channel
14936
+ if (room.createdBy === client.userId) {
14937
+ const { data: channel } = await createChannel({
14938
+ type: 'live',
14939
+ postId: room.referenceId,
14940
+ roomId: room.roomId,
14851
14941
  });
14852
- return queryResponse;
14853
- }
14854
- }
14855
-
14856
- var EnumJoinRequestAction$1;
14857
- (function (EnumJoinRequestAction) {
14858
- EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
14859
- EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
14860
- EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
14861
- })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
14862
-
14863
- class JoinRequestsQueryStreamController extends QueryStreamController {
14864
- constructor(query, cacheKey, notifyChange, preparePayload) {
14865
- super(query, cacheKey);
14866
- this.notifyChange = notifyChange;
14867
- this.preparePayload = preparePayload;
14868
- }
14869
- async saveToMainDB(response) {
14870
- const processedPayload = await this.preparePayload(response);
14871
- const client = getActiveClient();
14872
- const cachedAt = client.cache && Date.now();
14873
- if (client.cache) {
14874
- ingestInCache(processedPayload, { cachedAt });
14875
- }
14876
- }
14877
- appendToQueryStream(response, direction, refresh = false) {
14878
- var _a, _b;
14879
- if (refresh) {
14880
- pushToCache(this.cacheKey, {
14881
- data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
14882
- });
14883
- }
14884
- else {
14885
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14886
- const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
14887
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
14888
- ...new Set([
14889
- ...joinRequests,
14890
- ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
14891
- ]),
14892
- ] }));
14893
- }
14894
- }
14895
- reactor(action) {
14896
- return (joinRequest) => {
14897
- var _a;
14898
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14899
- if (!collection)
14900
- return;
14901
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
14902
- const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
14903
- if (!isExist)
14904
- return;
14905
- }
14906
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
14907
- collection.data = [
14908
- ...new Set([
14909
- ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
14910
- ...collection.data,
14911
- ]),
14912
- ];
14913
- }
14914
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
14915
- collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
14916
- }
14917
- pushToCache(this.cacheKey, collection);
14918
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
14919
- };
14920
- }
14921
- subscribeRTE(createSubscriber) {
14922
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
14942
+ // Update channelId to stream object in cache
14943
+ mergeInCache(['room', 'get', room.roomId], {
14944
+ liveChannelId: channel.channelId,
14945
+ });
14946
+ return channel;
14923
14947
  }
14924
- }
14925
-
14926
- /**
14927
- * ```js
14928
- * import { onJoinRequestCreated } from '@amityco/ts-sdk'
14929
- * const dispose = onJoinRequestCreated(data => {
14930
- * // ...
14931
- * })
14932
- * ```
14933
- *
14934
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
14935
- *
14936
- * @param callback The function to call when the event was fired
14937
- * @returns an {@link Amity.Unsubscriber} function to stop listening
14938
- *
14939
- * @category JoinRequest Events
14940
- */
14941
- const onJoinRequestCreated = (callback) => {
14942
- const client = getActiveClient();
14943
- const disposers = [
14944
- createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
14945
- ];
14946
- return () => {
14947
- disposers.forEach(fn => fn());
14948
- };
14949
- };
14950
-
14951
- /**
14952
- * ```js
14953
- * import { onJoinRequestUpdated } from '@amityco/ts-sdk'
14954
- * const dispose = onJoinRequestUpdated(data => {
14955
- * // ...
14956
- * })
14957
- * ```
14958
- *
14959
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
14960
- *
14961
- * @param callback The function to call when the event was fired
14962
- * @returns an {@link Amity.Unsubscriber} function to stop listening
14963
- *
14964
- * @category JoinRequest Events
14965
- */
14966
- const onJoinRequestUpdated = (callback) => {
14967
- const client = getActiveClient();
14968
- const disposers = [
14969
- createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
14970
- ];
14971
- return () => {
14972
- disposers.forEach(fn => fn());
14973
- };
14948
+ // watcher: return undefined
14949
+ return undefined;
14974
14950
  };
14975
14951
 
14976
14952
  /**
14977
- * ```js
14978
- * import { onJoinRequestDeleted } from '@amityco/ts-sdk'
14979
- * const dispose = onJoinRequestDeleted(data => {
14980
- * // ...
14981
- * })
14982
- * ```
14983
- *
14984
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
14985
- *
14986
- * @param callback The function to call when the event was fired
14987
- * @returns an {@link Amity.Unsubscriber} function to stop listening
14988
- *
14989
- * @category JoinRequest Events
14953
+ * WatchSessionStorage manages watch session data in memory
14954
+ * Similar to UsageCollector for stream watch minutes
14990
14955
  */
14991
- const onJoinRequestDeleted = (callback) => {
14992
- const client = getActiveClient();
14993
- const disposers = [
14994
- createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
14995
- ];
14996
- return () => {
14997
- disposers.forEach(fn => fn());
14998
- };
14999
- };
15000
-
15001
- class JoinRequestsLiveCollectionController extends LiveCollectionController {
15002
- constructor(query, callback) {
15003
- const queryStreamId = hash__default["default"](query);
15004
- const cacheKey = ['joinRequest', 'collection', queryStreamId];
15005
- const paginationController = new JoinRequestsPaginationController(query);
15006
- super(paginationController, queryStreamId, cacheKey, callback);
15007
- this.query = query;
15008
- this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
15009
- this.callback = callback.bind(this);
15010
- this.loadPage({ initial: true });
14956
+ class WatchSessionStorage {
14957
+ constructor() {
14958
+ this.sessions = new Map();
15011
14959
  }
15012
- setup() {
15013
- var _a;
15014
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15015
- if (!collection) {
15016
- pushToCache(this.cacheKey, {
15017
- data: [],
15018
- params: this.query,
15019
- });
15020
- }
14960
+ /**
14961
+ * Add a new watch session
14962
+ */
14963
+ addSession(session) {
14964
+ this.sessions.set(session.sessionId, session);
14965
+ }
14966
+ /**
14967
+ * Get a watch session by sessionId
14968
+ */
14969
+ getSession(sessionId) {
14970
+ return this.sessions.get(sessionId);
15021
14971
  }
15022
- async persistModel(queryPayload) {
15023
- await this.queryStreamController.saveToMainDB(queryPayload);
14972
+ /**
14973
+ * Update a watch session
14974
+ */
14975
+ updateSession(sessionId, updates) {
14976
+ const session = this.sessions.get(sessionId);
14977
+ if (session) {
14978
+ this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
14979
+ }
15024
14980
  }
15025
- persistQueryStream({ response, direction, refresh, }) {
15026
- const joinRequestResponse = response;
15027
- this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
14981
+ /**
14982
+ * Get all sessions with a specific sync state
14983
+ */
14984
+ getSessionsByState(state) {
14985
+ return Array.from(this.sessions.values()).filter(session => session.syncState === state);
15028
14986
  }
15029
- startSubscription() {
15030
- return this.queryStreamController.subscribeRTE([
15031
- { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
15032
- { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
15033
- { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
15034
- ]);
14987
+ /**
14988
+ * Delete a session
14989
+ */
14990
+ deleteSession(sessionId) {
14991
+ this.sessions.delete(sessionId);
15035
14992
  }
15036
- notifyChange({ origin, loading, error }) {
15037
- var _a;
15038
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15039
- if (!collection)
15040
- return;
15041
- const data = this.applyFilter(collection.data
15042
- .map(id => pullFromCache(['joinRequest', 'get', id]))
15043
- .filter(isNonNullable)
15044
- .map(({ data }) => data)
15045
- .map(joinRequestLinkedObject));
15046
- if (!this.shouldNotify(data) && origin === 'event')
15047
- return;
15048
- this.callback({
15049
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
15050
- data,
15051
- hasNextPage: !!this.paginationController.getNextToken(),
15052
- loading,
15053
- error,
15054
- });
14993
+ /**
14994
+ * Get all pending sessions
14995
+ */
14996
+ getPendingSessions() {
14997
+ return this.getSessionsByState('PENDING');
15055
14998
  }
15056
- applyFilter(data) {
15057
- let joinRequest = data;
15058
- if (this.query.status) {
15059
- joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
15060
- }
15061
- const sortFn = (() => {
15062
- switch (this.query.sortBy) {
15063
- case 'firstCreated':
15064
- return sortByFirstCreated;
15065
- case 'lastCreated':
15066
- return sortByLastCreated;
15067
- default:
15068
- return sortByLastCreated;
15069
- }
15070
- })();
15071
- joinRequest = joinRequest.sort(sortFn);
15072
- return joinRequest;
14999
+ /**
15000
+ * Get all syncing sessions
15001
+ */
15002
+ getSyncingSessions() {
15003
+ return this.getSessionsByState('SYNCING');
15073
15004
  }
15074
15005
  }
15006
+ // Singleton instance
15007
+ let storageInstance = null;
15008
+ const getWatchSessionStorage = () => {
15009
+ if (!storageInstance) {
15010
+ storageInstance = new WatchSessionStorage();
15011
+ }
15012
+ return storageInstance;
15013
+ };
15075
15014
 
15076
- /**
15077
- * Get Join Requests
15078
- *
15079
- * @param params the query parameters
15080
- * @param callback the callback to be called when the join request are updated
15081
- * @returns joinRequests
15082
- *
15083
- * @category joinRequest Live Collection
15015
+ const privateKey = "MIIEpQIBAAKCAQEAwAEc/oZgYIvKSUG/C3mONYLR4ZPgAjMEX4bJ+xqqakUDRtqlNO+eZs2blQ1Ko0DBkqPExyQezvjibH5W2UZBV5RaBTlTcNVKTToMBEGesAfaEcM3qUyQHxdbFYZv6P4sb14dcwxTQ8usmaV8ooiR1Fcaso5ZWYcZ8Hb46FbQ7OoVumsBtPWwfZ4f003o5VCl6AIM6lcLv9UDLlFVYhE+PeXpRHtfWlGqxMvqC9oinlwhL6nWv6VjQXW4nhcib72dPBzfHT7k/PMKto2SxALYdb68ENiAGuJLWi3AUHSyYCJK2w7wIlWfJUAI0v26ub10IpExr6D5QuW2577jjP93iwIDAQABAoIBAFWfqXhwIIatkFY+9Z1+ZcbDQimgsmMIsUiQaX6Lk7e0cxOj6czDlxYtVtaPiNtow2pLkjNkjkCqiP7tEHnwdK9DvylZOTa2R15NJpK3WLcTqVIGhsn/FL5owfvFah6zSsmXZParZm5zY9NZE03ALZhOB9/cz0e3kf/EbpfeL2mW7MApyiUt5i09ycchroOpcWp73ipIxvgigtZyUGFmsQicWhUs28F0D7w4Qfk76yG3nqXeb+BAMhCaIaa/k/aAxhiZG/ygEQWQrcC8gfe+jyicMAQPDEVS9YuUMGsLjIjKuVLZzp2xirQnhc2i2zVNEIvG6soprPOBEMQugzrtX5ECgYEA3b7KAbBIbDl1e4ZSCWhHdHkiWVZHaopsR/LhqDDNhXjWjq3AesgV6k0j9EdziMn/HmmOso0bz99GTV3JZf4A9ztTLumJlkHbdVtlgOqSjrFLj12rH9KXTheyIhWSpUmm8+WB1xasFbqpvJaGo7F3pd2Fqj1XR4mp5BO7c/t7LJ0CgYEA3aouEzXQ9THRKYocdfY69EI1Il1t/d/RSqqd9BxEjxBgxkM13ZiYIn/R4WW/nCUrlmhxG44Aa2Gob4Ahfsui2xKTg/g/3Zk/rAxAEGkfOLGoenaJMD41fH4wUq3FRYwkvnaMb9Hd6f/TlBHslIRa2NN58bSBGJCyBP2b59+2+EcCgYEAixDVRXvV37GlYUOa/XVdosk5Zoe6oDGRuQm0xbNdoUBoZvDHDvme7ONWEiQha/8qtVsD+CyQ7awcPfb8kK9c0bBt+bTS6d4BkTcxkEkMgtrkBVR8Nqfu5jXsLH4VCv4G61zbMhZw8+ut+az5YX2yCN7Frj9sFlxapMRPQmzMEe0CgYEAumsAzM8ZqNv4mAK65Mnr0rhLj1cbxcKRdUYACOgtEFQpzxN/HZnTeFAe5nx3pI3uFlRHq3DFEYnT6dHMWaJQmAULYpVIwMi9L6gtyJ9fzoI6uqMtxRDMUqKdaSsTGOY/kJ6KhQ/unXi1K3XXjR+yd1+C0q+HUm1+CYxvrZYLfskCgYEArsEy+IQOiqniJ0NE2vVUF+UK/IRZaic9YKcpov5Ot7Vvzm/MnnW4N1ljVskocETBWMmPUvNSExVjPebi+rxd8fa5kY8BJScPTzMFbunZn/wjtGdcM10qdlVQ9doG61A/9P3ezFKCfS4AvF/H/59LcSx2Bh28fp3/efiVIOpVd4Y=";
15016
+ /*
15017
+ * The crypto algorithm used for importing key and signing string
15018
+ */
15019
+ const ALGORITHM = {
15020
+ name: 'RSASSA-PKCS1-v1_5',
15021
+ hash: { name: 'SHA-256' },
15022
+ };
15023
+ /*
15024
+ * IMPORTANT!
15025
+ * If you are recieving key from other platforms use an online tool to convert
15026
+ * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
15027
+ * PKCS1.
15084
15028
  *
15029
+ * If recieving from the platform, verify if it's already in the expected
15030
+ * format. Otherwise the crypto.subtle.importKey will throw a DOMException
15085
15031
  */
15086
- const getJoinRequests = (params, callback, config) => {
15087
- const { log, cache } = getActiveClient();
15088
- if (!cache) {
15089
- console.log(ENABLE_CACHE_MESSAGE);
15090
- }
15091
- const timestamp = Date.now();
15092
- log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
15093
- const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
15094
- const disposers = joinRequestLiveCollection.startSubscription();
15095
- const cacheKey = joinRequestLiveCollection.getCacheKey();
15096
- disposers.push(() => {
15097
- dropFromCache(cacheKey);
15032
+ const PRIVATE_KEY_SIGNATURE = 'pkcs8';
15033
+ /*
15034
+ * Ensure that the private key in the .env follows this format
15035
+ */
15036
+ const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
15037
+ const PEM_FOOTER = '-----END PRIVATE KEY-----';
15038
+ /*
15039
+ * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
15040
+ * expects a base64 string. This util helps facilitate that process
15041
+ */
15042
+ function base64FromArrayBuffer(buffer) {
15043
+ const uint8Array = new Uint8Array(buffer);
15044
+ let binary = '';
15045
+ uint8Array.forEach(byte => {
15046
+ binary += String.fromCharCode(byte);
15098
15047
  });
15099
- return () => {
15100
- log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
15101
- disposers.forEach(fn => fn());
15102
- };
15103
- };
15104
-
15105
- var InvitationActionsEnum;
15106
- (function (InvitationActionsEnum) {
15107
- InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
15108
- InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
15109
- InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
15110
- })(InvitationActionsEnum || (InvitationActionsEnum = {}));
15111
-
15112
- class InvitationsPaginationController extends PaginationController {
15113
- async getRequest(queryParams, token) {
15114
- const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
15115
- const options = token ? { token } : { limit };
15116
- const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
15117
- return data;
15118
- }
15048
+ return jsBase64.btoa(binary);
15119
15049
  }
15120
-
15121
- class InvitationsQueryStreamController extends QueryStreamController {
15122
- constructor(query, cacheKey, notifyChange, preparePayload) {
15123
- super(query, cacheKey);
15124
- this.notifyChange = notifyChange;
15125
- this.preparePayload = preparePayload;
15126
- }
15127
- async saveToMainDB(response) {
15128
- const processedPayload = await this.preparePayload(response);
15129
- const client = getActiveClient();
15130
- const cachedAt = client.cache && Date.now();
15131
- if (client.cache) {
15132
- ingestInCache(processedPayload, { cachedAt });
15133
- }
15050
+ /*
15051
+ * Encode ASN.1 length field
15052
+ */
15053
+ function encodeLength(length) {
15054
+ if (length < 128) {
15055
+ return new Uint8Array([length]);
15134
15056
  }
15135
- appendToQueryStream(response, direction, refresh = false) {
15136
- var _a, _b;
15137
- if (refresh) {
15138
- pushToCache(this.cacheKey, {
15139
- data: response.invitations.map(getResolver('invitation')),
15140
- });
15141
- }
15142
- else {
15143
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15144
- const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
15145
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
15146
- ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
15147
- ] }));
15148
- }
15057
+ if (length < 256) {
15058
+ return new Uint8Array([0x81, length]);
15149
15059
  }
15150
- reactor(action) {
15151
- return (invitations) => {
15152
- var _a;
15153
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15154
- if (!collection)
15155
- return;
15156
- if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
15157
- const isExist = collection.data.find(id => id === invitations[0].invitationId);
15158
- if (!isExist)
15159
- return;
15160
- }
15161
- if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
15162
- collection.data = [
15163
- ...new Set([
15164
- ...invitations.map(invitation => invitation.invitationId),
15165
- ...collection.data,
15166
- ]),
15167
- ];
15168
- }
15169
- if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
15170
- collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
15171
- }
15172
- pushToCache(this.cacheKey, collection);
15173
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
15174
- };
15060
+ // eslint-disable-next-line no-bitwise
15061
+ return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
15062
+ }
15063
+ /*
15064
+ * Convert PKCS1 private key to PKCS8 format
15065
+ * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
15066
+ * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
15067
+ */
15068
+ function pkcs1ToPkcs8(pkcs1) {
15069
+ // Algorithm identifier for RSA
15070
+ const algorithmIdentifier = new Uint8Array([
15071
+ 0x30,
15072
+ 0x0d,
15073
+ 0x06,
15074
+ 0x09,
15075
+ 0x2a,
15076
+ 0x86,
15077
+ 0x48,
15078
+ 0x86,
15079
+ 0xf7,
15080
+ 0x0d,
15081
+ 0x01,
15082
+ 0x01,
15083
+ 0x01,
15084
+ 0x05,
15085
+ 0x00, // NULL
15086
+ ]);
15087
+ // Version (INTEGER 0)
15088
+ const version = new Uint8Array([0x02, 0x01, 0x00]);
15089
+ // OCTET STRING tag + length + pkcs1 data
15090
+ const octetStringTag = 0x04;
15091
+ const octetStringLength = encodeLength(pkcs1.length);
15092
+ // Calculate total content length (version + algorithm + octet string)
15093
+ const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
15094
+ // SEQUENCE tag + length
15095
+ const sequenceTag = 0x30;
15096
+ const sequenceLength = encodeLength(contentLength);
15097
+ // Build the PKCS8 structure
15098
+ const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
15099
+ let offset = 0;
15100
+ pkcs8[offset] = sequenceTag;
15101
+ offset += 1;
15102
+ pkcs8.set(sequenceLength, offset);
15103
+ offset += sequenceLength.length;
15104
+ pkcs8.set(version, offset);
15105
+ offset += version.length;
15106
+ pkcs8.set(algorithmIdentifier, offset);
15107
+ offset += algorithmIdentifier.length;
15108
+ pkcs8[offset] = octetStringTag;
15109
+ offset += 1;
15110
+ pkcs8.set(octetStringLength, offset);
15111
+ offset += octetStringLength.length;
15112
+ pkcs8.set(pkcs1, offset);
15113
+ return pkcs8;
15114
+ }
15115
+ async function importPrivateKey(keyString) {
15116
+ // Remove PEM headers if present and any whitespace
15117
+ let base64Key = keyString;
15118
+ if (keyString.includes(PEM_HEADER)) {
15119
+ base64Key = keyString
15120
+ .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
15121
+ .replace(/\s/g, '');
15175
15122
  }
15176
- subscribeRTE(createSubscriber) {
15177
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
15123
+ else {
15124
+ base64Key = keyString.replace(/\s/g, '');
15125
+ }
15126
+ // Base64 decode to get binary data
15127
+ const binaryDerString = jsBase64.atob(base64Key);
15128
+ // Convert to Uint8Array for manipulation
15129
+ const pkcs1 = new Uint8Array(binaryDerString.length);
15130
+ for (let i = 0; i < binaryDerString.length; i += 1) {
15131
+ pkcs1[i] = binaryDerString.charCodeAt(i);
15178
15132
  }
15133
+ // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
15134
+ const pkcs8 = pkcs1ToPkcs8(pkcs1);
15135
+ // Import the key
15136
+ const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
15137
+ return key;
15138
+ }
15139
+ async function createSignature({ timestamp, rooms, }) {
15140
+ const dataStr = rooms
15141
+ .map(item => Object.keys(item)
15142
+ .sort()
15143
+ .map(key => `${key}=${item[key]}`)
15144
+ .join('&'))
15145
+ .join(';');
15146
+ /*
15147
+ * nonceStr needs to be unique for each request
15148
+ */
15149
+ const nonceStr = uuid__default["default"].v4();
15150
+ const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
15151
+ const encoder = new TextEncoder();
15152
+ const data = encoder.encode(signStr);
15153
+ const key = await importPrivateKey(privateKey);
15154
+ const sign = await crypto.subtle.sign(ALGORITHM, key, data);
15155
+ return { signature: base64FromArrayBuffer(sign), nonceStr };
15179
15156
  }
15180
15157
 
15181
15158
  /**
15182
- * ```js
15183
- * import { onLocalInvitationCreated } from '@amityco/ts-sdk'
15184
- * const dispose = onLocalInvitationCreated(data => {
15185
- * // ...
15186
- * })
15187
- * ```
15188
- *
15189
- * Fired when an {@link Amity.InvitationPayload} has been created
15190
- *
15191
- * @param callback The function to call when the event was fired
15192
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15193
- *
15194
- * @category Invitation Events
15195
- */
15196
- const onLocalInvitationCreated = (callback) => {
15197
- const client = getActiveClient();
15198
- const disposers = [
15199
- createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
15200
- ];
15201
- return () => {
15202
- disposers.forEach(fn => fn());
15203
- };
15204
- };
15205
-
15206
- /**
15207
- * ```js
15208
- * import { onLocalInvitationUpdated } from '@amityco/ts-sdk'
15209
- * const dispose = onLocalInvitationUpdated(data => {
15210
- * // ...
15211
- * })
15212
- * ```
15213
- *
15214
- * Fired when an {@link Amity.InvitationPayload} has been updated
15215
- *
15216
- * @param callback The function to call when the event was fired
15217
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15218
- *
15219
- * @category Invitation Events
15220
- */
15221
- const onLocalInvitationUpdated = (callback) => {
15222
- const client = getActiveClient();
15223
- const disposers = [
15224
- createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
15225
- ];
15226
- return () => {
15227
- disposers.forEach(fn => fn());
15228
- };
15229
- };
15230
-
15231
- /**
15232
- * ```js
15233
- * import { onLocalInvitationCanceled } from '@amityco/ts-sdk'
15234
- * const dispose = onLocalInvitationCanceled(data => {
15235
- * // ...
15236
- * })
15237
- * ```
15238
- *
15239
- * Fired when an {@link Amity.InvitationPayload} has been deleted
15240
- *
15241
- * @param callback The function to call when the event was fired
15242
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15243
- *
15244
- * @category Invitation Events
15159
+ * Sync pending watch sessions to backend
15160
+ * This function implements the full sync flow with network resilience
15245
15161
  */
15246
- const onLocalInvitationCanceled = (callback) => {
15247
- const client = getActiveClient();
15248
- const disposers = [
15249
- createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
15250
- ];
15251
- return () => {
15252
- disposers.forEach(fn => fn());
15253
- };
15254
- };
15255
-
15256
- class InvitationsLiveCollectionController extends LiveCollectionController {
15257
- constructor(query, callback) {
15258
- const queryStreamId = hash__default["default"](query);
15259
- const cacheKey = ['invitation', 'collection', queryStreamId];
15260
- const paginationController = new InvitationsPaginationController(query);
15261
- super(paginationController, queryStreamId, cacheKey, callback);
15262
- this.query = query;
15263
- this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
15264
- this.callback = callback.bind(this);
15265
- this.loadPage({ initial: true });
15162
+ async function syncWatchSessions() {
15163
+ const storage = getWatchSessionStorage();
15164
+ // Get all pending sessions
15165
+ const pendingSessions = storage.getPendingSessions();
15166
+ if (pendingSessions.length === 0) {
15167
+ return true;
15266
15168
  }
15267
- setup() {
15268
- var _a;
15269
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15270
- if (!collection) {
15271
- pushToCache(this.cacheKey, {
15272
- data: [],
15273
- params: this.query,
15274
- });
15169
+ try {
15170
+ const timestamp = new Date().toISOString();
15171
+ // Convert sessions to API format - always include all fields like syncUsage does
15172
+ const rooms = pendingSessions.map(session => ({
15173
+ sessionId: session.sessionId,
15174
+ roomId: session.roomId,
15175
+ watchSeconds: session.watchSeconds,
15176
+ startTime: session.startTime.toISOString(),
15177
+ endTime: session.endTime ? session.endTime.toISOString() : '',
15178
+ }));
15179
+ // Create signature (reuse from stream feature) - pass directly like syncUsage
15180
+ const signatureData = await createSignature({
15181
+ timestamp,
15182
+ rooms,
15183
+ });
15184
+ if (!signatureData || !signatureData.signature) {
15185
+ throw new Error('Signature is undefined');
15275
15186
  }
15276
- }
15277
- async persistModel(queryPayload) {
15278
- await this.queryStreamController.saveToMainDB(queryPayload);
15279
- }
15280
- persistQueryStream({ response, direction, refresh, }) {
15281
- this.queryStreamController.appendToQueryStream(response, direction, refresh);
15282
- }
15283
- startSubscription() {
15284
- return this.queryStreamController.subscribeRTE([
15285
- {
15286
- fn: onLocalInvitationCreated,
15287
- action: InvitationActionsEnum.OnLocalInvitationCreated,
15288
- },
15289
- {
15290
- fn: onLocalInvitationUpdated,
15291
- action: InvitationActionsEnum.OnLocalInvitationUpdated,
15292
- },
15293
- {
15294
- fn: onLocalInvitationCanceled,
15295
- action: InvitationActionsEnum.OnLocalInvitationCanceled,
15296
- },
15297
- ]);
15298
- }
15299
- notifyChange({ origin, loading, error }) {
15300
- var _a, _b;
15301
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15302
- if (!collection)
15303
- return;
15304
- const data = this.applyFilter((_b = collection.data
15305
- .map(id => pullFromCache(['invitation', 'get', id]))
15306
- .filter(isNonNullable)
15307
- .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
15308
- if (!this.shouldNotify(data) && origin === 'event')
15309
- return;
15310
- this.callback({
15311
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
15312
- data,
15313
- hasNextPage: !!this.paginationController.getNextToken(),
15314
- loading,
15315
- error,
15187
+ // Update sync state to SYNCING
15188
+ pendingSessions.forEach(session => {
15189
+ storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
15190
+ });
15191
+ const payload = {
15192
+ signature: signatureData.signature,
15193
+ nonceStr: signatureData.nonceStr,
15194
+ timestamp,
15195
+ rooms,
15196
+ };
15197
+ const client = getActiveClient();
15198
+ // Send to backend
15199
+ await client.http.post('/api/v3/user-event/room', payload);
15200
+ // Success - update to SYNCED
15201
+ pendingSessions.forEach(session => {
15202
+ storage.updateSession(session.sessionId, {
15203
+ syncState: 'SYNCED',
15204
+ syncedAt: new Date(),
15205
+ });
15316
15206
  });
15207
+ return true;
15317
15208
  }
15318
- applyFilter(data) {
15319
- let invitations = data;
15320
- if (this.query.targetId) {
15321
- invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
15322
- }
15323
- if (this.query.statuses) {
15324
- invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
15325
- }
15326
- if (this.query.targetType) {
15327
- invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
15328
- }
15329
- if (this.query.type) {
15330
- invitations = invitations.filter(invitation => invitation.type === this.query.type);
15331
- }
15332
- const sortFn = (() => {
15333
- switch (this.query.sortBy) {
15334
- case 'firstCreated':
15335
- return sortByFirstCreated;
15336
- case 'lastCreated':
15337
- return sortByLastCreated;
15338
- default:
15339
- return sortByLastCreated;
15209
+ catch (err) {
15210
+ console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
15211
+ // Failure - update back to PENDING and increment retry count
15212
+ pendingSessions.forEach(session => {
15213
+ const currentSession = storage.getSession(session.sessionId);
15214
+ if (currentSession) {
15215
+ const newRetryCount = currentSession.retryCount + 1;
15216
+ if (newRetryCount >= 3) {
15217
+ // Delete session if retry count exceeds 3
15218
+ storage.deleteSession(session.sessionId);
15219
+ }
15220
+ else {
15221
+ // Update to PENDING with incremented retry count
15222
+ storage.updateSession(session.sessionId, {
15223
+ syncState: 'PENDING',
15224
+ retryCount: newRetryCount,
15225
+ });
15226
+ }
15340
15227
  }
15341
- })();
15342
- invitations = invitations.sort(sortFn);
15343
- return invitations;
15228
+ });
15229
+ return false;
15344
15230
  }
15345
15231
  }
15346
15232
 
15347
15233
  /**
15348
- * Get invitations
15349
- *
15350
- * @param params the query parameters
15351
- * @param callback the callback to be called when the invitations are updated
15352
- * @returns invitations
15353
- *
15354
- * @category Invitation Live Collection
15355
- *
15234
+ * Room statuses that are considered watchable
15356
15235
  */
15357
- const getInvitations$1 = (params, callback, config) => {
15358
- const { log, cache } = getActiveClient();
15359
- if (!cache) {
15360
- console.log(ENABLE_CACHE_MESSAGE);
15361
- }
15362
- const timestamp = Date.now();
15363
- log(`getInvitations: (tmpid: ${timestamp}) > listen`);
15364
- const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
15365
- const disposers = invitationsLiveCollection.startSubscription();
15366
- const cacheKey = invitationsLiveCollection.getCacheKey();
15367
- disposers.push(() => {
15368
- dropFromCache(cacheKey);
15236
+ const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
15237
+ /**
15238
+ * Generate a random jitter delay between 5 and 30 seconds
15239
+ */
15240
+ const getJitterDelay = () => {
15241
+ const minDelay = 5000; // 5 seconds
15242
+ const maxDelay = 30000; // 30 seconds
15243
+ return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
15244
+ };
15245
+ /**
15246
+ * Wait for network connection with timeout
15247
+ * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
15248
+ * @returns Promise that resolves when network is available or timeout is reached
15249
+ */
15250
+ const waitForNetwork = (maxWaitTime = 60000) => {
15251
+ return new Promise(resolve => {
15252
+ // Simple check - if navigator.onLine is available, use it
15253
+ // Otherwise, assume network is available
15254
+ if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
15255
+ resolve();
15256
+ return;
15257
+ }
15258
+ const startTime = Date.now();
15259
+ const checkInterval = 1000; // 1 second
15260
+ const checkConnection = () => {
15261
+ if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
15262
+ resolve();
15263
+ }
15264
+ else {
15265
+ setTimeout(checkConnection, checkInterval);
15266
+ }
15267
+ };
15268
+ checkConnection();
15369
15269
  });
15370
- return () => {
15371
- log(`getInvitations (tmpid: ${timestamp}) > dispose`);
15372
- disposers.forEach(fn => fn());
15373
- };
15374
15270
  };
15271
+ /**
15272
+ * AmityRoomAnalytics provides analytics capabilities for room watch sessions
15273
+ */
15274
+ class AmityRoomAnalytics {
15275
+ constructor(room) {
15276
+ this.storage = getWatchSessionStorage();
15277
+ this.client = getActiveClient();
15278
+ this.room = room;
15279
+ }
15280
+ /**
15281
+ * Create a new watch session for the current room
15282
+ * @param startedAt The timestamp when watching started
15283
+ * @returns Promise<string> sessionId unique identifier for this watch session
15284
+ * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
15285
+ */
15286
+ async createWatchSession(startedAt) {
15287
+ // Validate room status
15288
+ if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
15289
+ throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
15290
+ }
15291
+ // Generate session ID with prefix
15292
+ const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
15293
+ const sessionId = prefix + uuid__default["default"].v4();
15294
+ // Create watch session entity
15295
+ const session = {
15296
+ sessionId,
15297
+ roomId: this.room.roomId,
15298
+ watchSeconds: 0,
15299
+ startTime: startedAt,
15300
+ endTime: null,
15301
+ syncState: 'PENDING',
15302
+ syncedAt: null,
15303
+ retryCount: 0,
15304
+ };
15305
+ // Persist to storage
15306
+ this.storage.addSession(session);
15307
+ return sessionId;
15308
+ }
15309
+ /**
15310
+ * Update an existing watch session with duration
15311
+ * @param sessionId The unique identifier of the watch session
15312
+ * @param duration The total watch duration in seconds
15313
+ * @param endedAt The timestamp when this update occurred
15314
+ * @returns Promise<void> Completion status
15315
+ */
15316
+ async updateWatchSession(sessionId, duration, endedAt) {
15317
+ const session = this.storage.getSession(sessionId);
15318
+ if (!session) {
15319
+ throw new Error(`Watch session ${sessionId} not found`);
15320
+ }
15321
+ // Update session
15322
+ this.storage.updateSession(sessionId, {
15323
+ watchSeconds: duration,
15324
+ endTime: endedAt,
15325
+ });
15326
+ }
15327
+ /**
15328
+ * Sync all pending watch sessions to backend
15329
+ * This function uses jitter delay and handles network resilience
15330
+ */
15331
+ syncPendingWatchSessions() {
15332
+ // Execute with jitter delay (5-30 seconds)
15333
+ const jitterDelay = getJitterDelay();
15334
+ this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
15335
+ setTimeout(async () => {
15336
+ this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
15337
+ try {
15338
+ // Reset any SYNCING sessions back to PENDING
15339
+ const syncingSessions = this.storage.getSyncingSessions();
15340
+ this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
15341
+ syncingSessions.forEach(session => {
15342
+ this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
15343
+ });
15344
+ // Wait for network connection (max 60 seconds)
15345
+ await waitForNetwork(60000);
15346
+ this.client.log('room/RoomAnalytics: Network available');
15347
+ // Sync pending sessions
15348
+ this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
15349
+ await syncWatchSessions();
15350
+ this.client.log('room/RoomAnalytics: syncWatchSessions completed');
15351
+ }
15352
+ catch (error) {
15353
+ // Error is already handled in syncWatchSessions
15354
+ console.error('Failed to sync watch sessions:', error);
15355
+ }
15356
+ }, jitterDelay);
15357
+ }
15358
+ }
15375
15359
 
15376
- const communityLinkedObject = (community) => {
15377
- return Object.assign(Object.assign({}, community), { get categories() {
15360
+ const roomLinkedObject = (room) => {
15361
+ return Object.assign(Object.assign({}, room), { get post() {
15378
15362
  var _a;
15379
- return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
15380
- .map(categoryId => {
15381
- const cacheData = pullFromCache(['category', 'get', categoryId]);
15382
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
15383
- return categoryLinkedObject(cacheData.data);
15384
- return undefined;
15385
- })
15386
- .filter(category => !!category);
15363
+ if (room.referenceType !== 'post')
15364
+ return;
15365
+ return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
15387
15366
  },
15388
- get avatar() {
15367
+ get community() {
15389
15368
  var _a;
15390
- if (!community.avatarFileId)
15391
- return undefined;
15392
- const avatar = (_a = pullFromCache([
15393
- 'file',
15394
- 'get',
15395
- community.avatarFileId,
15396
- ])) === null || _a === void 0 ? void 0 : _a.data;
15397
- return avatar;
15398
- }, createInvitations: async (userIds) => {
15399
- await createInvitations({
15400
- type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
15401
- targetType: 'community',
15402
- targetId: community.communityId,
15403
- userIds,
15404
- });
15405
- }, getMemberInvitations: (params, callback) => {
15406
- return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
15407
- }, getInvitation: async () => {
15369
+ if (room.targetType !== 'community')
15370
+ return;
15371
+ return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
15372
+ },
15373
+ get user() {
15374
+ var _a;
15375
+ const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
15376
+ return user ? userLinkedObject(user) : user;
15377
+ },
15378
+ get childRooms() {
15379
+ if (!room.childRoomIds || room.childRoomIds.length === 0)
15380
+ return [];
15381
+ return room.childRoomIds
15382
+ .map(id => {
15383
+ var _a;
15384
+ const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
15385
+ if (!roomCache)
15386
+ return undefined;
15387
+ return roomLinkedObject(roomCache);
15388
+ })
15389
+ .filter(isNonNullable);
15390
+ }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
15391
+ var _a;
15392
+ const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
15393
+ return user ? userLinkedObject(user) : user;
15394
+ } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
15395
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
15396
+ targetType: 'room',
15397
+ targetId: room.roomId,
15398
+ userIds: [userId],
15399
+ }), getInvitations: async () => {
15408
15400
  const { data } = await getInvitation({
15409
- targetType: 'community',
15410
- targetId: community.communityId,
15401
+ targetId: room.roomId,
15402
+ targetType: 'room',
15403
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
15411
15404
  });
15412
15405
  return data;
15413
- }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
15414
- return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
15415
- }, getMyJoinRequest: async () => {
15416
- const { data } = await getMyJoinRequest(community.communityId);
15417
- return data;
15406
+ }, analytics() {
15407
+ // Use 'this' to avoid creating a new room object
15408
+ return new AmityRoomAnalytics(this);
15418
15409
  } });
15419
15410
  };
15420
15411
 
15412
+ const pollLinkedObject = (poll) => {
15413
+ return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
15414
+ var _a;
15415
+ if (!answer.fileId)
15416
+ return undefined;
15417
+ return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
15418
+ } }))) });
15419
+ };
15420
+
15421
15421
  const productLinkedObject = (product) => {
15422
15422
  const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
15423
15423
  return Object.assign(Object.assign({}, product), { analytics: {