@amityco/ts-sdk 7.23.0 → 7.23.1-d9c32194.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.esm.js CHANGED
@@ -29415,562 +29415,571 @@ var index$r = /*#__PURE__*/Object.freeze({
29415
29415
  getMyFollowInfo: getMyFollowInfo
29416
29416
  });
29417
29417
 
29418
- class StoryComputedValue {
29419
- constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
29420
- this._syncingStoriesCount = 0;
29421
- this._errorStoriesCount = 0;
29422
- this._targetId = targetId;
29423
- this._lastStoryExpiresAt = lastStoryExpiresAt;
29424
- this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
29425
- this.cacheStoryExpireTime = pullFromCache([
29426
- "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
29427
- this._targetId,
29428
- ]);
29429
- this.cacheStoreSeenTime = pullFromCache([
29430
- "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
29431
- this._targetId,
29432
- ]);
29433
- this.getTotalStoryByStatus();
29434
- }
29435
- get lastStoryExpiresAt() {
29436
- return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
29437
- }
29438
- get lastStorySeenExpiresAt() {
29439
- return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
29440
- }
29441
- get localLastStoryExpires() {
29442
- var _a, _b;
29443
- return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
29444
- ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
29445
- : 0;
29446
- }
29447
- get localLastStorySeenExpiresAt() {
29448
- var _a, _b;
29449
- 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;
29450
- }
29451
- get isContainUnSyncedStory() {
29452
- const currentSyncingState = pullFromCache([
29453
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
29454
- this._targetId,
29455
- ]);
29456
- if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
29457
- return false;
29458
- return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
29459
- }
29460
- getLocalLastSortingDate() {
29461
- if (this.isContainUnSyncedStory) {
29462
- return this.localLastStoryExpires;
29463
- }
29464
- return this.lastStoryExpiresAt;
29465
- }
29466
- getHasUnseenFlag() {
29467
- const now = new Date().getTime();
29468
- const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
29469
- pullFromCache([
29470
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
29471
- this._targetId,
29418
+ /*
29419
+ * verifies membership status
29420
+ */
29421
+ function isMember(membership) {
29422
+ return membership !== 'none';
29423
+ }
29424
+ /*
29425
+ * checks if currently logged in user is part of the community
29426
+ */
29427
+ function isCurrentUserPartOfCommunity(c, m) {
29428
+ const { userId } = getActiveUser();
29429
+ return c.communityId === m.communityId && m.userId === userId;
29430
+ }
29431
+ /*
29432
+ * For mqtt events server will not send user specific data as it's broadcasted
29433
+ * to multiple users and it also does not include communityUser
29434
+ *
29435
+ * Client SDK needs to check for the existing isJoined field in cache data before calculating.
29436
+ * Althought this can be calculated, it's not scalable.
29437
+ */
29438
+ function updateMembershipStatus(communities, communityUsers) {
29439
+ return communities.map(c => {
29440
+ const cachedCommunity = pullFromCache([
29441
+ 'community',
29442
+ 'get',
29443
+ c.communityId,
29472
29444
  ]);
29473
- if (this.isContainUnSyncedStory) {
29474
- return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
29475
- }
29476
- return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
29477
- }
29478
- getTotalStoryByStatus() {
29479
- const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
29480
- if (!stories) {
29481
- this._errorStoriesCount = 0;
29482
- this._syncingStoriesCount = 0;
29483
- return;
29445
+ if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
29446
+ return Object.assign(Object.assign({}, cachedCommunity.data), c);
29484
29447
  }
29485
- const groupByType = stories.reduce((acc, story) => {
29486
- const { data: { targetId, syncState, isDeleted }, } = story;
29487
- if (targetId === this._targetId && !isDeleted) {
29488
- acc[syncState] += 1;
29489
- }
29490
- return acc;
29491
- }, {
29492
- syncing: 0,
29493
- error: 0,
29494
- synced: 0,
29495
- });
29496
- this._errorStoriesCount = groupByType.error;
29497
- this._syncingStoriesCount = groupByType.syncing;
29498
- }
29499
- get syncingStoriesCount() {
29500
- return this._syncingStoriesCount;
29501
- }
29502
- get failedStoriesCount() {
29503
- return this._errorStoriesCount;
29504
- }
29448
+ const isJoined = c.isJoined !== undefined
29449
+ ? c.isJoined
29450
+ : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
29451
+ return Object.assign(Object.assign({}, c), { isJoined });
29452
+ });
29505
29453
  }
29506
29454
 
29507
- const storyTargetLinkedObject = (storyTarget) => {
29508
- const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
29509
- const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
29510
- return {
29511
- targetType,
29512
- targetId,
29513
- lastStoryExpiresAt,
29514
- updatedAt: targetUpdatedAt,
29515
- // Additional data
29516
- hasUnseen: computedValue.getHasUnseenFlag(),
29517
- syncingStoriesCount: computedValue.syncingStoriesCount,
29518
- failedStoriesCount: computedValue.failedStoriesCount,
29519
- localFilter,
29520
- localLastExpires: computedValue.localLastStoryExpires,
29521
- localLastSeen: computedValue.localLastStorySeenExpiresAt,
29522
- localSortingDate: computedValue.getLocalLastSortingDate(),
29523
- };
29455
+ const getMatchPostSetting = (value) => {
29456
+ var _a;
29457
+ return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
29458
+ CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
29459
+ value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
29460
+ };
29461
+ function addPostSetting({ communities }) {
29462
+ return communities.map((_a) => {
29463
+ var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
29464
+ return (Object.assign({ postSetting: getMatchPostSetting({
29465
+ needApprovalOnPostCreation,
29466
+ onlyAdminCanPost,
29467
+ }) }, restCommunityPayload));
29468
+ });
29469
+ }
29470
+ const prepareCommunityPayload = (rawPayload) => {
29471
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
29472
+ // Convert users to internal format
29473
+ const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
29474
+ // map users with community
29475
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
29476
+ const user = internalUsers.find(user => user.userId === communityUser.userId);
29477
+ return Object.assign(Object.assign({}, communityUser), { user });
29478
+ });
29479
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
29480
+ return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
29481
+ };
29482
+ const prepareCommunityJoinRequestPayload = (rawPayload) => {
29483
+ const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
29484
+ return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
29485
+ });
29486
+ const users = rawPayload.users.map(convertRawUserToInternalUser);
29487
+ return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
29488
+ };
29489
+ const prepareCommunityMembershipPayload = (rawPayload) => {
29490
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
29491
+ // map users with community
29492
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
29493
+ const user = rawPayload.users.find(user => user.userId === communityUser.userId);
29494
+ return Object.assign(Object.assign({}, communityUser), { user });
29495
+ });
29496
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
29497
+ return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
29498
+ };
29499
+ const prepareCommunityRequest = (params) => {
29500
+ const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
29501
+ return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
29502
+ // Convert story setting to the actual value. (Allow by default)
29503
+ allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
29504
+ };
29505
+ const prepareSemanticSearchCommunityPayload = (_a) => {
29506
+ var communityPayload = __rest(_a, ["searchResult"]);
29507
+ const processedCommunityPayload = prepareCommunityPayload(communityPayload);
29508
+ return Object.assign({}, processedCommunityPayload);
29524
29509
  };
29525
29510
 
29526
- const storyLinkedObject = (story) => {
29527
- const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
29528
- const storyTargetCache = pullFromCache([
29529
- "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
29511
+ /* begin_public_function
29512
+ id: joinRequest.approve
29513
+ */
29514
+ /**
29515
+ * ```js
29516
+ * import { joinRequest } from '@amityco/ts-sdk'
29517
+ * const isAccepted = await joinRequest.approve()
29518
+ * ```
29519
+ *
29520
+ * Accepts a {@link Amity.JoinRequest} object
29521
+ *
29522
+ * @param joinRequest the {@link Amity.JoinRequest} to accept
29523
+ * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
29524
+ *
29525
+ * @category Join Request API
29526
+ * @async
29527
+ */
29528
+ const approveJoinRequest = async (joinRequest) => {
29529
+ var _a;
29530
+ const client = getActiveClient();
29531
+ client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
29532
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
29533
+ userId: joinRequest.requestorInternalId,
29534
+ });
29535
+ const joinRequestCache = (_a = pullFromCache([
29536
+ 'joinRequest',
29530
29537
  'get',
29531
- story.targetId,
29532
- ]);
29533
- const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
29534
- return Object.assign(Object.assign({}, story), { analytics: {
29535
- markAsSeen: () => {
29536
- if (!story.expiresAt)
29537
- return;
29538
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
29539
- return;
29540
- analyticsEngineInstance.markStoryAsViewed(story);
29541
- },
29542
- markLinkAsClicked: () => {
29543
- if (!story.expiresAt)
29544
- return;
29545
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
29546
- return;
29547
- analyticsEngineInstance.markStoryAsClicked(story);
29548
- },
29549
- }, get videoData() {
29550
- var _a, _b;
29551
- const cache = pullFromCache([
29552
- 'file',
29553
- 'get',
29554
- (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
29555
- ]);
29556
- if (!cache)
29557
- return undefined;
29558
- const { data } = cache;
29559
- return data || undefined;
29560
- },
29561
- get imageData() {
29562
- var _a, _b;
29563
- if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
29564
- return undefined;
29565
- const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
29566
- if (!cache)
29567
- return undefined;
29568
- const { data } = cache;
29569
- if (!data)
29570
- return undefined;
29571
- return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
29572
- },
29573
- get community() {
29574
- if (story.targetType !== 'community')
29575
- return undefined;
29576
- if (!communityCacheData)
29577
- return undefined;
29578
- return (communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data) || undefined;
29579
- },
29580
- get communityCategories() {
29581
- if (story.targetType !== 'community')
29582
- return undefined;
29583
- if (!communityCacheData)
29584
- return undefined;
29585
- const { data: { categoryIds }, } = communityCacheData;
29586
- if (categoryIds.length === 0)
29538
+ joinRequest.joinRequestId,
29539
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29540
+ if (joinRequestCache) {
29541
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
29542
+ status: "approved" /* JoinRequestStatusEnum.Approved */,
29543
+ });
29544
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
29545
+ }
29546
+ return data.success;
29547
+ };
29548
+ /* end_public_function */
29549
+
29550
+ /* begin_public_function
29551
+ id: joinRequest.cancel
29552
+ */
29553
+ /**
29554
+ * ```js
29555
+ * import { joinRequest } from '@amityco/ts-sdk'
29556
+ * const isCanceled = await joinRequest.cancel()
29557
+ * ```
29558
+ *
29559
+ * Cancels a {@link Amity.JoinRequest} object
29560
+ *
29561
+ * @param joinRequest the {@link Amity.JoinRequest} to cancel
29562
+ * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
29563
+ *
29564
+ * @category Join Request API
29565
+ * @async
29566
+ */
29567
+ const cancelJoinRequest = async (joinRequest) => {
29568
+ var _a;
29569
+ const client = getActiveClient();
29570
+ client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
29571
+ const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
29572
+ const joinRequestCache = (_a = pullFromCache([
29573
+ 'joinRequest',
29574
+ 'get',
29575
+ joinRequest.joinRequestId,
29576
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29577
+ if (joinRequestCache) {
29578
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
29579
+ status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
29580
+ });
29581
+ fireEvent('local.joinRequest.deleted', [joinRequestCache]);
29582
+ }
29583
+ return data.success;
29584
+ };
29585
+ /* end_public_function */
29586
+
29587
+ /* begin_public_function
29588
+ id: joinRequest.reject
29589
+ */
29590
+ /**
29591
+ * ```js
29592
+ * import { joinRequest } from '@amityco/ts-sdk'
29593
+ * const isRejected = await joinRequest.reject()
29594
+ * ```
29595
+ *
29596
+ * Rejects a {@link Amity.JoinRequest} object
29597
+ *
29598
+ * @param joinRequest the {@link Amity.JoinRequest} to reject
29599
+ * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
29600
+ *
29601
+ * @category Join Request API
29602
+ * @async
29603
+ */
29604
+ const rejectJoinRequest = async (joinRequest) => {
29605
+ var _a;
29606
+ const client = getActiveClient();
29607
+ client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
29608
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
29609
+ userId: joinRequest.requestorInternalId,
29610
+ });
29611
+ const joinRequestCache = (_a = pullFromCache([
29612
+ 'joinRequest',
29613
+ 'get',
29614
+ joinRequest.joinRequestId,
29615
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29616
+ if (joinRequestCache) {
29617
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
29618
+ status: "rejected" /* JoinRequestStatusEnum.Rejected */,
29619
+ });
29620
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
29621
+ }
29622
+ return data.success;
29623
+ };
29624
+ /* end_public_function */
29625
+
29626
+ const joinRequestLinkedObject = (joinRequest) => {
29627
+ return Object.assign(Object.assign({}, joinRequest), { get user() {
29628
+ var _a;
29629
+ const user = (_a = pullFromCache([
29630
+ 'user',
29631
+ 'get',
29632
+ joinRequest.requestorPublicId,
29633
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29634
+ if (!user)
29587
29635
  return undefined;
29588
- return categoryIds
29589
- .map(categoryId => {
29590
- const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
29591
- return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
29592
- })
29593
- .filter(category => category !== undefined);
29594
- },
29595
- get creator() {
29596
- const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
29597
- if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
29598
- return;
29599
- return userLinkedObject(cacheData.data);
29600
- },
29601
- get storyTarget() {
29602
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
29603
- return;
29604
- return storyTargetLinkedObject(storyTargetCache.data);
29605
- },
29606
- get isSeen() {
29607
- const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
29608
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
29609
- return false;
29610
- const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
29611
- const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
29612
- const expiresAt = new Date(story.expiresAt).getTime();
29613
- return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
29636
+ return userLinkedObject(user);
29637
+ }, cancel: async () => {
29638
+ await cancelJoinRequest(joinRequest);
29639
+ }, approve: async () => {
29640
+ await approveJoinRequest(joinRequest);
29641
+ }, reject: async () => {
29642
+ await rejectJoinRequest(joinRequest);
29614
29643
  } });
29615
29644
  };
29616
29645
 
29617
29646
  /* begin_public_function
29618
- id: channel.create
29647
+ id: community.getMyJoinRequest
29619
29648
  */
29620
29649
  /**
29621
29650
  * ```js
29622
- * import { createChannel } from '@amityco/ts-sdk'
29623
- * const created = await createChannel({ displayName: 'foobar' })
29651
+ * import { community } from '@amityco/ts-sdk'
29652
+ * const isJoined = await community.getMyJoinRequest('foobar')
29624
29653
  * ```
29625
29654
  *
29626
- * Creates an {@link Amity.Channel}
29655
+ * Joins a {@link Amity.Community} object
29627
29656
  *
29628
- * @param bundle The data necessary to create a new {@link Amity.Channel}
29629
- * @returns The newly created {@link Amity.Channel}
29657
+ * @param communityId the {@link Amity.Community} to join
29658
+ * @returns A success boolean if the {@link Amity.Community} was joined
29630
29659
  *
29631
- * @category Channel API
29660
+ * @category Community API
29632
29661
  * @async
29633
29662
  */
29634
- const createChannel = async (bundle) => {
29663
+ const getMyJoinRequest = async (communityId) => {
29635
29664
  const client = getActiveClient();
29636
- client.log('user/createChannel', bundle);
29637
- let payload;
29638
- /* c8 ignore next */
29639
- if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
29640
- payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
29641
- }
29642
- else {
29643
- const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
29644
- payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
29645
- /* c8 ignore next */
29646
- isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
29647
- }
29648
- const data = await prepareChannelPayload(payload.data);
29665
+ client.log('community/myJoinRequest', communityId);
29666
+ const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
29667
+ const data = prepareCommunityJoinRequestPayload(payload);
29649
29668
  const cachedAt = client.cache && Date.now();
29650
29669
  if (client.cache)
29651
29670
  ingestInCache(data, { cachedAt });
29652
- const { channels } = data;
29653
29671
  return {
29654
- data: constructChannelObject(channels[0]),
29672
+ data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
29655
29673
  cachedAt,
29656
29674
  };
29657
29675
  };
29658
29676
  /* end_public_function */
29659
29677
 
29678
+ /* begin_public_function
29679
+ id: community.join
29680
+ */
29660
29681
  /**
29661
29682
  * ```js
29662
- * import { getChannel } from '@amityco/ts-sdk'
29663
- * const channel = await getChannel('foobar')
29683
+ * import { community } from '@amityco/ts-sdk'
29684
+ * const isJoined = await community.join('foobar')
29664
29685
  * ```
29665
29686
  *
29666
- * Fetches a {@link Amity.Channel} object
29687
+ * Joins a {@link Amity.Community} object
29667
29688
  *
29668
- * @param channelId the ID of the {@link Amity.Channel} to fetch
29669
- * @returns the associated {@link Amity.Channel} object
29689
+ * @param communityId the {@link Amity.Community} to join
29690
+ * @returns A status join result
29670
29691
  *
29671
- * @category Channel API
29692
+ * @category Community API
29672
29693
  * @async
29673
29694
  */
29674
- const getChannel$1 = async (channelId) => {
29695
+ const joinRequest = async (communityId) => {
29696
+ var _a;
29675
29697
  const client = getActiveClient();
29676
- client.log('channel/getChannel', channelId);
29677
- isInTombstone('channel', channelId);
29678
- let data;
29679
- try {
29680
- const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
29681
- data = await prepareChannelPayload(payload);
29682
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
29683
- prepareUnreadCountInfo(payload);
29698
+ client.log('community/joinRequest', communityId);
29699
+ const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
29700
+ const data = prepareCommunityJoinRequestPayload(payload);
29701
+ const cachedAt = client.cache && Date.now();
29702
+ if (client.cache)
29703
+ ingestInCache(data, { cachedAt });
29704
+ const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
29705
+ ? "success" /* JoinResultStatusEnum.Success */
29706
+ : "pending" /* JoinResultStatusEnum.Pending */;
29707
+ if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
29708
+ const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
29709
+ if (community) {
29710
+ const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
29711
+ upsertInCache(['community', 'get', communityId], updatedCommunity);
29684
29712
  }
29685
29713
  }
29686
- catch (error) {
29687
- if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
29688
- // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
29689
- pushToTombstone('channel', channelId);
29714
+ fireEvent('v4.local.community.joined', data.joinRequests);
29715
+ return status === "success" /* JoinResultStatusEnum.Success */
29716
+ ? { status }
29717
+ : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
29718
+ };
29719
+ /* end_public_function */
29720
+
29721
+ /**
29722
+ * TODO: handle cache receive cache option, and cache policy
29723
+ * TODO: check if querybyIds is supported
29724
+ */
29725
+ class JoinRequestsPaginationController extends PaginationController {
29726
+ async getRequest(queryParams, token) {
29727
+ const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
29728
+ const options = token ? { token } : { limit };
29729
+ const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
29730
+ params: Object.assign(Object.assign({}, params), { options }),
29731
+ });
29732
+ return queryResponse;
29733
+ }
29734
+ }
29735
+
29736
+ var EnumJoinRequestAction$1;
29737
+ (function (EnumJoinRequestAction) {
29738
+ EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
29739
+ EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
29740
+ EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
29741
+ })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
29742
+
29743
+ class JoinRequestsQueryStreamController extends QueryStreamController {
29744
+ constructor(query, cacheKey, notifyChange, preparePayload) {
29745
+ super(query, cacheKey);
29746
+ this.notifyChange = notifyChange;
29747
+ this.preparePayload = preparePayload;
29748
+ }
29749
+ async saveToMainDB(response) {
29750
+ const processedPayload = await this.preparePayload(response);
29751
+ const client = getActiveClient();
29752
+ const cachedAt = client.cache && Date.now();
29753
+ if (client.cache) {
29754
+ ingestInCache(processedPayload, { cachedAt });
29690
29755
  }
29691
- throw error;
29692
29756
  }
29693
- const cachedAt = client.cache && Date.now();
29694
- if (client.cache)
29695
- ingestInCache(data, { cachedAt });
29696
- const { channels } = data;
29697
- return {
29698
- data: channels.find(channel => channel.channelId === channelId),
29699
- cachedAt,
29757
+ appendToQueryStream(response, direction, refresh = false) {
29758
+ var _a, _b;
29759
+ if (refresh) {
29760
+ pushToCache(this.cacheKey, {
29761
+ data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
29762
+ });
29763
+ }
29764
+ else {
29765
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
29766
+ const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
29767
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
29768
+ ...new Set([
29769
+ ...joinRequests,
29770
+ ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
29771
+ ]),
29772
+ ] }));
29773
+ }
29774
+ }
29775
+ reactor(action) {
29776
+ return (joinRequest) => {
29777
+ var _a;
29778
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
29779
+ if (!collection)
29780
+ return;
29781
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
29782
+ const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
29783
+ if (!isExist)
29784
+ return;
29785
+ }
29786
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
29787
+ collection.data = [
29788
+ ...new Set([
29789
+ ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
29790
+ ...collection.data,
29791
+ ]),
29792
+ ];
29793
+ }
29794
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
29795
+ collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
29796
+ }
29797
+ pushToCache(this.cacheKey, collection);
29798
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
29799
+ };
29800
+ }
29801
+ subscribeRTE(createSubscriber) {
29802
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
29803
+ }
29804
+ }
29805
+
29806
+ /**
29807
+ * ```js
29808
+ * import { onJoinRequestCreated } from '@amityco/ts-sdk'
29809
+ * const dispose = onJoinRequestCreated(data => {
29810
+ * // ...
29811
+ * })
29812
+ * ```
29813
+ *
29814
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
29815
+ *
29816
+ * @param callback The function to call when the event was fired
29817
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
29818
+ *
29819
+ * @category JoinRequest Events
29820
+ */
29821
+ const onJoinRequestCreated = (callback) => {
29822
+ const client = getActiveClient();
29823
+ const disposers = [
29824
+ createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
29825
+ ];
29826
+ return () => {
29827
+ disposers.forEach(fn => fn());
29700
29828
  };
29701
29829
  };
29830
+
29702
29831
  /**
29703
29832
  * ```js
29704
- * import { getChannel } from '@amityco/ts-sdk'
29705
- * const channel = getChannel.locally('foobar')
29833
+ * import { onJoinRequestUpdated } from '@amityco/ts-sdk'
29834
+ * const dispose = onJoinRequestUpdated(data => {
29835
+ * // ...
29836
+ * })
29706
29837
  * ```
29707
29838
  *
29708
- * Fetches a {@link Amity.Channel} object from cache
29839
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
29709
29840
  *
29710
- * @param channelId the ID of the {@link Amity.Channel} to fetch
29711
- * @returns the associated {@link Amity.Channel} object
29841
+ * @param callback The function to call when the event was fired
29842
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
29712
29843
  *
29713
- * @category Channel API
29844
+ * @category JoinRequest Events
29714
29845
  */
29715
- getChannel$1.locally = (channelId) => {
29716
- var _a;
29846
+ const onJoinRequestUpdated = (callback) => {
29717
29847
  const client = getActiveClient();
29718
- client.log('channel/getChannel.locally', channelId);
29719
- if (!client.cache)
29720
- return;
29721
- // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
29722
- const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
29723
- return data.channelPublicId === channelId;
29724
- });
29725
- if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
29726
- return;
29727
- return {
29728
- data: cached[0].data,
29729
- cachedAt: cached[0].cachedAt,
29848
+ const disposers = [
29849
+ createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
29850
+ ];
29851
+ return () => {
29852
+ disposers.forEach(fn => fn());
29730
29853
  };
29731
29854
  };
29732
29855
 
29733
29856
  /**
29734
29857
  * ```js
29735
- * import { getStream } from '@amityco/ts-sdk'
29736
- * const stream = await getStream('foobar')
29858
+ * import { onJoinRequestDeleted } from '@amityco/ts-sdk'
29859
+ * const dispose = onJoinRequestDeleted(data => {
29860
+ * // ...
29861
+ * })
29737
29862
  * ```
29738
29863
  *
29739
- * Fetches a {@link Amity.Channel} object linked with a current stream
29864
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
29740
29865
  *
29741
- * @param stream {@link Amity.Stream} that has linked live channel
29742
- * @returns the associated {@link Amity.Channel<'live'>} object
29866
+ * @param callback The function to call when the event was fired
29867
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
29743
29868
  *
29744
- * @category Stream API
29745
- * @async
29869
+ * @category JoinRequest Events
29746
29870
  */
29747
- const getLiveChat$1 = async (stream) => {
29748
- var _a;
29871
+ const onJoinRequestDeleted = (callback) => {
29749
29872
  const client = getActiveClient();
29750
- client.log('stream/getLiveChat', stream.streamId);
29751
- if (stream.channelId) {
29752
- const channel = (_a = pullFromCache([
29753
- 'channel',
29754
- 'get',
29755
- stream.channelId,
29756
- ])) === null || _a === void 0 ? void 0 : _a.data;
29757
- if (channel)
29758
- return channelLinkedObject(constructChannelObject(channel));
29759
- const { data } = await getChannel$1(stream.channelId);
29760
- return channelLinkedObject(constructChannelObject(data));
29761
- }
29762
- // No Channel ID
29763
- // streamer: create a new live channel
29764
- if (stream.userId === client.userId) {
29765
- const { data: channel } = await createChannel({
29766
- type: 'live',
29767
- postId: stream.postId,
29768
- videoStreamId: stream.streamId,
29769
- });
29770
- // Update channelId to stream object in cache
29771
- mergeInCache(['stream', 'get', stream.streamId], {
29772
- channelId: channel.channelId,
29773
- });
29774
- return channel;
29775
- }
29776
- // watcher: return undefined
29777
- return undefined;
29778
- };
29779
-
29780
- const GET_WATCHER_URLS = Symbol('getWatcherUrls');
29781
- const streamLinkedObject = (stream) => {
29782
- return Object.assign(Object.assign({}, stream), { get moderation() {
29783
- var _a;
29784
- return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
29785
- },
29786
- get post() {
29787
- var _a;
29788
- if (stream.referenceType !== 'post')
29789
- return;
29790
- return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
29791
- },
29792
- get community() {
29793
- var _a;
29794
- if (stream.targetType !== 'community')
29795
- return;
29796
- return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
29797
- },
29798
- get user() {
29799
- var _a;
29800
- return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
29801
- },
29802
- get childStreams() {
29803
- if (!stream.childStreamIds || stream.childStreamIds.length === 0)
29804
- return [];
29805
- return stream.childStreamIds
29806
- .map(id => {
29807
- var _a;
29808
- const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
29809
- if (!streamCache)
29810
- return undefined;
29811
- return streamLinkedObject(streamCache);
29812
- })
29813
- .filter(isNonNullable);
29814
- }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
29815
- return stream.watcherUrl;
29816
- } });
29817
- };
29818
-
29819
- const categoryLinkedObject = (category) => {
29820
- return Object.assign(Object.assign({}, category), { get avatar() {
29821
- var _a;
29822
- if (!category.avatarFileId)
29823
- return undefined;
29824
- const avatar = (_a = pullFromCache([
29825
- 'file',
29826
- 'get',
29827
- `${category.avatarFileId}`,
29828
- ])) === null || _a === void 0 ? void 0 : _a.data;
29829
- return avatar;
29830
- } });
29831
- };
29832
-
29833
- const commentLinkedObject = (comment) => {
29834
- return Object.assign(Object.assign({}, comment), { get target() {
29835
- const commentTypes = {
29836
- type: comment.targetType,
29837
- };
29838
- if (comment.targetType === 'user') {
29839
- return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
29840
- }
29841
- if (commentTypes.type === 'content') {
29842
- return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
29843
- }
29844
- if (commentTypes.type === 'community') {
29845
- const cacheData = pullFromCache([
29846
- 'communityUsers',
29847
- 'get',
29848
- `${comment.targetId}#${comment.userId}`,
29849
- ]);
29850
- return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
29851
- }
29852
- return {
29853
- type: 'unknown',
29854
- };
29855
- },
29856
- get creator() {
29857
- const cacheData = pullFromCache(['user', 'get', comment.userId]);
29858
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
29859
- return userLinkedObject(cacheData.data);
29860
- return undefined;
29861
- },
29862
- get childrenComment() {
29863
- return comment.children
29864
- .map(childCommentId => {
29865
- const commentCache = pullFromCache([
29866
- 'comment',
29867
- 'get',
29868
- childCommentId,
29869
- ]);
29870
- if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
29871
- return;
29872
- return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
29873
- })
29874
- .filter(isNonNullable)
29875
- .map(item => commentLinkedObject(item));
29876
- } });
29873
+ const disposers = [
29874
+ createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
29875
+ ];
29876
+ return () => {
29877
+ disposers.forEach(fn => fn());
29878
+ };
29877
29879
  };
29878
29880
 
29879
- function isAmityImagePost(post) {
29880
- return !!(post.data &&
29881
- typeof post.data !== 'string' &&
29882
- 'fileId' in post.data &&
29883
- post.dataType === 'image');
29884
- }
29885
- function isAmityFilePost(post) {
29886
- return !!(post.data &&
29887
- typeof post.data !== 'string' &&
29888
- 'fileId' in post.data &&
29889
- post.dataType === 'file');
29890
- }
29891
- function isAmityVideoPost(post) {
29892
- return !!(post.data &&
29893
- typeof post.data !== 'string' &&
29894
- 'videoFileId' in post.data &&
29895
- 'thumbnailFileId' in post.data &&
29896
- post.dataType === 'video');
29897
- }
29898
- function isAmityLivestreamPost(post) {
29899
- return !!(post.data &&
29900
- typeof post.data !== 'string' &&
29901
- 'streamId' in post.data &&
29902
- post.dataType === 'liveStream');
29903
- }
29904
- function isAmityPollPost(post) {
29905
- return !!(post.data &&
29906
- typeof post.data !== 'string' &&
29907
- 'pollId' in post.data &&
29908
- post.dataType === 'poll');
29909
- }
29910
- function isAmityClipPost(post) {
29911
- return !!(post.data &&
29912
- typeof post.data !== 'string' &&
29913
- 'fileId' in post.data &&
29914
- post.dataType === 'clip');
29915
- }
29916
- function isAmityAudioPost(post) {
29917
- return !!(post.data &&
29918
- typeof post.data !== 'string' &&
29919
- 'fileId' in post.data &&
29920
- post.dataType === 'audio');
29921
- }
29922
- function isAmityRoomPost(post) {
29923
- return !!(post.data &&
29924
- typeof post.data !== 'string' &&
29925
- 'roomId' in post.data &&
29926
- post.dataType === 'room');
29881
+ class JoinRequestsLiveCollectionController extends LiveCollectionController {
29882
+ constructor(query, callback) {
29883
+ const queryStreamId = hash(query);
29884
+ const cacheKey = ['joinRequest', 'collection', queryStreamId];
29885
+ const paginationController = new JoinRequestsPaginationController(query);
29886
+ super(paginationController, queryStreamId, cacheKey, callback);
29887
+ this.query = query;
29888
+ this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
29889
+ this.callback = callback.bind(this);
29890
+ this.loadPage({ initial: true });
29891
+ }
29892
+ setup() {
29893
+ var _a;
29894
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
29895
+ if (!collection) {
29896
+ pushToCache(this.cacheKey, {
29897
+ data: [],
29898
+ params: this.query,
29899
+ });
29900
+ }
29901
+ }
29902
+ async persistModel(queryPayload) {
29903
+ await this.queryStreamController.saveToMainDB(queryPayload);
29904
+ }
29905
+ persistQueryStream({ response, direction, refresh, }) {
29906
+ const joinRequestResponse = response;
29907
+ this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
29908
+ }
29909
+ startSubscription() {
29910
+ return this.queryStreamController.subscribeRTE([
29911
+ { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
29912
+ { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
29913
+ { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
29914
+ ]);
29915
+ }
29916
+ notifyChange({ origin, loading, error }) {
29917
+ var _a;
29918
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
29919
+ if (!collection)
29920
+ return;
29921
+ const data = this.applyFilter(collection.data
29922
+ .map(id => pullFromCache(['joinRequest', 'get', id]))
29923
+ .filter(isNonNullable)
29924
+ .map(({ data }) => data)
29925
+ .map(joinRequestLinkedObject));
29926
+ if (!this.shouldNotify(data) && origin === 'event')
29927
+ return;
29928
+ this.callback({
29929
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
29930
+ data,
29931
+ hasNextPage: !!this.paginationController.getNextToken(),
29932
+ loading,
29933
+ error,
29934
+ });
29935
+ }
29936
+ applyFilter(data) {
29937
+ let joinRequest = data;
29938
+ if (this.query.status) {
29939
+ joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
29940
+ }
29941
+ const sortFn = (() => {
29942
+ switch (this.query.sortBy) {
29943
+ case 'firstCreated':
29944
+ return sortByFirstCreated;
29945
+ case 'lastCreated':
29946
+ return sortByLastCreated;
29947
+ default:
29948
+ return sortByLastCreated;
29949
+ }
29950
+ })();
29951
+ joinRequest = joinRequest.sort(sortFn);
29952
+ return joinRequest;
29953
+ }
29927
29954
  }
29928
29955
 
29929
29956
  /**
29930
- * ```js
29931
- * import { RoomRepository } from '@amityco/ts-sdk'
29932
- * const stream = await getStream('foobar')
29933
- * ```
29957
+ * Get Join Requests
29934
29958
  *
29935
- * Fetches a {@link Amity.Channel} object linked with a current stream
29959
+ * @param params the query parameters
29960
+ * @param callback the callback to be called when the join request are updated
29961
+ * @returns joinRequests
29936
29962
  *
29937
- * @param stream {@link Amity.Stream} that has linked live channel
29938
- * @returns the associated {@link Amity.Channel<'live'>} object
29963
+ * @category joinRequest Live Collection
29939
29964
  *
29940
- * @category Stream API
29941
- * @async
29942
29965
  */
29943
- const getLiveChat = async (room) => {
29944
- var _a;
29945
- const client = getActiveClient();
29946
- client.log('room/getLiveChat', room.roomId);
29947
- if (room.liveChannelId) {
29948
- const channel = (_a = pullFromCache([
29949
- 'channel',
29950
- 'get',
29951
- room.liveChannelId,
29952
- ])) === null || _a === void 0 ? void 0 : _a.data;
29953
- if (channel)
29954
- return channelLinkedObject(constructChannelObject(channel));
29955
- const { data } = await getChannel$1(room.liveChannelId);
29956
- return channelLinkedObject(constructChannelObject(data));
29957
- }
29958
- // No Channel ID
29959
- // streamer: create a new live channel
29960
- if (room.createdBy === client.userId) {
29961
- const { data: channel } = await createChannel({
29962
- type: 'live',
29963
- postId: room.referenceId,
29964
- roomId: room.roomId,
29965
- });
29966
- // Update channelId to stream object in cache
29967
- mergeInCache(['room', 'get', room.roomId], {
29968
- liveChannelId: channel.channelId,
29969
- });
29970
- return channel;
29966
+ const getJoinRequests = (params, callback, config) => {
29967
+ const { log, cache } = getActiveClient();
29968
+ if (!cache) {
29969
+ console.log(ENABLE_CACHE_MESSAGE);
29971
29970
  }
29972
- // watcher: return undefined
29973
- return undefined;
29971
+ const timestamp = Date.now();
29972
+ log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
29973
+ const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
29974
+ const disposers = joinRequestLiveCollection.startSubscription();
29975
+ const cacheKey = joinRequestLiveCollection.getCacheKey();
29976
+ disposers.push(() => {
29977
+ dropFromCache(cacheKey);
29978
+ });
29979
+ return () => {
29980
+ log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
29981
+ disposers.forEach(fn => fn());
29982
+ };
29974
29983
  };
29975
29984
 
29976
29985
  const convertRawInvitationToInternalInvitation = (rawInvitation) => {
@@ -30125,1391 +30134,1382 @@ const invitationLinkedObject = (invitation) => {
30125
30134
  } });
30126
30135
  };
30127
30136
 
30128
- /* begin_public_function
30129
- id: invitation.get
30130
- */
30137
+ /* begin_public_function
30138
+ id: invitation.get
30139
+ */
30140
+ /**
30141
+ * ```js
30142
+ * import { getInvitation } from '@amityco/ts-sdk'
30143
+ * const { invitation } = await getInvitation(targetType, targetId)
30144
+ * ```
30145
+ *
30146
+ * Get a {@link Amity.Invitation} object
30147
+ *
30148
+ * @param targetType The type of the target of the {@link Amity.Invitation}
30149
+ * @param targetId The ID of the target of the {@link Amity.Invitation}
30150
+ * @returns A {@link Amity.Invitation} object
30151
+ *
30152
+ * @category Invitation API
30153
+ * @async
30154
+ */
30155
+ const getInvitation = async (params) => {
30156
+ const client = getActiveClient();
30157
+ client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
30158
+ const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
30159
+ const data = prepareMyInvitationsPayload(payload);
30160
+ const cachedAt = client.cache && Date.now();
30161
+ if (client.cache)
30162
+ ingestInCache(data, { cachedAt });
30163
+ return {
30164
+ data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
30165
+ cachedAt,
30166
+ };
30167
+ };
30168
+ /* end_public_function */
30169
+
30170
+ var InvitationActionsEnum;
30171
+ (function (InvitationActionsEnum) {
30172
+ InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
30173
+ InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
30174
+ InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
30175
+ })(InvitationActionsEnum || (InvitationActionsEnum = {}));
30176
+
30177
+ class InvitationsPaginationController extends PaginationController {
30178
+ async getRequest(queryParams, token) {
30179
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
30180
+ const options = token ? { token } : { limit };
30181
+ const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
30182
+ return data;
30183
+ }
30184
+ }
30185
+
30186
+ class InvitationsQueryStreamController extends QueryStreamController {
30187
+ constructor(query, cacheKey, notifyChange, preparePayload) {
30188
+ super(query, cacheKey);
30189
+ this.notifyChange = notifyChange;
30190
+ this.preparePayload = preparePayload;
30191
+ }
30192
+ async saveToMainDB(response) {
30193
+ const processedPayload = await this.preparePayload(response);
30194
+ const client = getActiveClient();
30195
+ const cachedAt = client.cache && Date.now();
30196
+ if (client.cache) {
30197
+ ingestInCache(processedPayload, { cachedAt });
30198
+ }
30199
+ }
30200
+ appendToQueryStream(response, direction, refresh = false) {
30201
+ var _a, _b;
30202
+ if (refresh) {
30203
+ pushToCache(this.cacheKey, {
30204
+ data: response.invitations.map(getResolver('invitation')),
30205
+ });
30206
+ }
30207
+ else {
30208
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30209
+ const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
30210
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
30211
+ ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
30212
+ ] }));
30213
+ }
30214
+ }
30215
+ reactor(action) {
30216
+ return (invitations) => {
30217
+ var _a;
30218
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30219
+ if (!collection)
30220
+ return;
30221
+ if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
30222
+ const isExist = collection.data.find(id => id === invitations[0].invitationId);
30223
+ if (!isExist)
30224
+ return;
30225
+ }
30226
+ if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
30227
+ collection.data = [
30228
+ ...new Set([
30229
+ ...invitations.map(invitation => invitation.invitationId),
30230
+ ...collection.data,
30231
+ ]),
30232
+ ];
30233
+ }
30234
+ if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
30235
+ collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
30236
+ }
30237
+ pushToCache(this.cacheKey, collection);
30238
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
30239
+ };
30240
+ }
30241
+ subscribeRTE(createSubscriber) {
30242
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
30243
+ }
30244
+ }
30245
+
30246
+ /**
30247
+ * ```js
30248
+ * import { onLocalInvitationCreated } from '@amityco/ts-sdk'
30249
+ * const dispose = onLocalInvitationCreated(data => {
30250
+ * // ...
30251
+ * })
30252
+ * ```
30253
+ *
30254
+ * Fired when an {@link Amity.InvitationPayload} has been created
30255
+ *
30256
+ * @param callback The function to call when the event was fired
30257
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
30258
+ *
30259
+ * @category Invitation Events
30260
+ */
30261
+ const onLocalInvitationCreated = (callback) => {
30262
+ const client = getActiveClient();
30263
+ const disposers = [
30264
+ createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
30265
+ ];
30266
+ return () => {
30267
+ disposers.forEach(fn => fn());
30268
+ };
30269
+ };
30270
+
30271
+ /**
30272
+ * ```js
30273
+ * import { onLocalInvitationUpdated } from '@amityco/ts-sdk'
30274
+ * const dispose = onLocalInvitationUpdated(data => {
30275
+ * // ...
30276
+ * })
30277
+ * ```
30278
+ *
30279
+ * Fired when an {@link Amity.InvitationPayload} has been updated
30280
+ *
30281
+ * @param callback The function to call when the event was fired
30282
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
30283
+ *
30284
+ * @category Invitation Events
30285
+ */
30286
+ const onLocalInvitationUpdated = (callback) => {
30287
+ const client = getActiveClient();
30288
+ const disposers = [
30289
+ createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
30290
+ ];
30291
+ return () => {
30292
+ disposers.forEach(fn => fn());
30293
+ };
30294
+ };
30295
+
30131
30296
  /**
30132
30297
  * ```js
30133
- * import { getInvitation } from '@amityco/ts-sdk'
30134
- * const { invitation } = await getInvitation(targetType, targetId)
30298
+ * import { onLocalInvitationCanceled } from '@amityco/ts-sdk'
30299
+ * const dispose = onLocalInvitationCanceled(data => {
30300
+ * // ...
30301
+ * })
30135
30302
  * ```
30136
30303
  *
30137
- * Get a {@link Amity.Invitation} object
30304
+ * Fired when an {@link Amity.InvitationPayload} has been deleted
30138
30305
  *
30139
- * @param targetType The type of the target of the {@link Amity.Invitation}
30140
- * @param targetId The ID of the target of the {@link Amity.Invitation}
30141
- * @returns A {@link Amity.Invitation} object
30306
+ * @param callback The function to call when the event was fired
30307
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
30142
30308
  *
30143
- * @category Invitation API
30144
- * @async
30309
+ * @category Invitation Events
30145
30310
  */
30146
- const getInvitation = async (params) => {
30311
+ const onLocalInvitationCanceled = (callback) => {
30147
30312
  const client = getActiveClient();
30148
- client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
30149
- const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
30150
- const data = prepareMyInvitationsPayload(payload);
30151
- const cachedAt = client.cache && Date.now();
30152
- if (client.cache)
30153
- ingestInCache(data, { cachedAt });
30154
- return {
30155
- data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
30156
- cachedAt,
30313
+ const disposers = [
30314
+ createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
30315
+ ];
30316
+ return () => {
30317
+ disposers.forEach(fn => fn());
30157
30318
  };
30158
30319
  };
30159
- /* end_public_function */
30160
30320
 
30161
- /**
30162
- * WatchSessionStorage manages watch session data in memory
30163
- * Similar to UsageCollector for stream watch minutes
30164
- */
30165
- class WatchSessionStorage {
30166
- constructor() {
30167
- this.sessions = new Map();
30168
- }
30169
- /**
30170
- * Add a new watch session
30171
- */
30172
- addSession(session) {
30173
- this.sessions.set(session.sessionId, session);
30174
- }
30175
- /**
30176
- * Get a watch session by sessionId
30177
- */
30178
- getSession(sessionId) {
30179
- return this.sessions.get(sessionId);
30321
+ class InvitationsLiveCollectionController extends LiveCollectionController {
30322
+ constructor(query, callback) {
30323
+ const queryStreamId = hash(query);
30324
+ const cacheKey = ['invitation', 'collection', queryStreamId];
30325
+ const paginationController = new InvitationsPaginationController(query);
30326
+ super(paginationController, queryStreamId, cacheKey, callback);
30327
+ this.query = query;
30328
+ this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
30329
+ this.callback = callback.bind(this);
30330
+ this.loadPage({ initial: true });
30180
30331
  }
30181
- /**
30182
- * Update a watch session
30183
- */
30184
- updateSession(sessionId, updates) {
30185
- const session = this.sessions.get(sessionId);
30186
- if (session) {
30187
- this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
30332
+ setup() {
30333
+ var _a;
30334
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30335
+ if (!collection) {
30336
+ pushToCache(this.cacheKey, {
30337
+ data: [],
30338
+ params: this.query,
30339
+ });
30188
30340
  }
30189
30341
  }
30190
- /**
30191
- * Get all sessions with a specific sync state
30192
- */
30193
- getSessionsByState(state) {
30194
- return Array.from(this.sessions.values()).filter(session => session.syncState === state);
30195
- }
30196
- /**
30197
- * Delete a session
30198
- */
30199
- deleteSession(sessionId) {
30200
- this.sessions.delete(sessionId);
30201
- }
30202
- /**
30203
- * Get all pending sessions
30204
- */
30205
- getPendingSessions() {
30206
- return this.getSessionsByState('PENDING');
30207
- }
30208
- /**
30209
- * Get all syncing sessions
30210
- */
30211
- getSyncingSessions() {
30212
- return this.getSessionsByState('SYNCING');
30213
- }
30214
- }
30215
- // Singleton instance
30216
- let storageInstance = null;
30217
- const getWatchSessionStorage = () => {
30218
- if (!storageInstance) {
30219
- storageInstance = new WatchSessionStorage();
30220
- }
30221
- return storageInstance;
30222
- };
30223
-
30224
- 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-----";
30225
- /*
30226
- * The crypto algorithm used for importing key and signing string
30227
- */
30228
- const ALGORITHM = {
30229
- name: 'RSASSA-PKCS1-v1_5',
30230
- hash: { name: 'SHA-256' },
30231
- };
30232
- /*
30233
- * IMPORTANT!
30234
- * If you are recieving key from other platforms use an online tool to convert
30235
- * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
30236
- * PKCS1.
30237
- *
30238
- * If recieving from the platform, verify if it's already in the expected
30239
- * format. Otherwise the crypto.subtle.importKey will throw a DOMException
30240
- */
30241
- const PRIVATE_KEY_SIGNATURE = 'pkcs8';
30242
- /*
30243
- * Ensure that the private key in the .env follows this format
30244
- */
30245
- const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
30246
- const PEM_FOOTER = '-----END PRIVATE KEY-----';
30247
- /*
30248
- * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
30249
- * expects a base64 string. This util helps facilitate that process
30250
- */
30251
- function base64FromArrayBuffer(buffer) {
30252
- const uint8Array = new Uint8Array(buffer);
30253
- let binary = '';
30254
- uint8Array.forEach(byte => {
30255
- binary += String.fromCharCode(byte);
30256
- });
30257
- return btoa(binary);
30258
- }
30259
- /*
30260
- * Encode ASN.1 length field
30261
- */
30262
- function encodeLength(length) {
30263
- if (length < 128) {
30264
- return new Uint8Array([length]);
30342
+ async persistModel(queryPayload) {
30343
+ await this.queryStreamController.saveToMainDB(queryPayload);
30265
30344
  }
30266
- if (length < 256) {
30267
- return new Uint8Array([0x81, length]);
30345
+ persistQueryStream({ response, direction, refresh, }) {
30346
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
30268
30347
  }
30269
- // eslint-disable-next-line no-bitwise
30270
- return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
30271
- }
30272
- /*
30273
- * Convert PKCS1 private key to PKCS8 format
30274
- * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
30275
- * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
30276
- */
30277
- function pkcs1ToPkcs8(pkcs1) {
30278
- // Algorithm identifier for RSA
30279
- const algorithmIdentifier = new Uint8Array([
30280
- 0x30,
30281
- 0x0d,
30282
- 0x06,
30283
- 0x09,
30284
- 0x2a,
30285
- 0x86,
30286
- 0x48,
30287
- 0x86,
30288
- 0xf7,
30289
- 0x0d,
30290
- 0x01,
30291
- 0x01,
30292
- 0x01,
30293
- 0x05,
30294
- 0x00, // NULL
30295
- ]);
30296
- // Version (INTEGER 0)
30297
- const version = new Uint8Array([0x02, 0x01, 0x00]);
30298
- // OCTET STRING tag + length + pkcs1 data
30299
- const octetStringTag = 0x04;
30300
- const octetStringLength = encodeLength(pkcs1.length);
30301
- // Calculate total content length (version + algorithm + octet string)
30302
- const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
30303
- // SEQUENCE tag + length
30304
- const sequenceTag = 0x30;
30305
- const sequenceLength = encodeLength(contentLength);
30306
- // Build the PKCS8 structure
30307
- const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
30308
- let offset = 0;
30309
- pkcs8[offset] = sequenceTag;
30310
- offset += 1;
30311
- pkcs8.set(sequenceLength, offset);
30312
- offset += sequenceLength.length;
30313
- pkcs8.set(version, offset);
30314
- offset += version.length;
30315
- pkcs8.set(algorithmIdentifier, offset);
30316
- offset += algorithmIdentifier.length;
30317
- pkcs8[offset] = octetStringTag;
30318
- offset += 1;
30319
- pkcs8.set(octetStringLength, offset);
30320
- offset += octetStringLength.length;
30321
- pkcs8.set(pkcs1, offset);
30322
- return pkcs8;
30323
- }
30324
- async function importPrivateKey(keyString) {
30325
- // Remove PEM headers if present and any whitespace
30326
- let base64Key = keyString;
30327
- if (keyString.includes(PEM_HEADER)) {
30328
- base64Key = keyString
30329
- .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
30330
- .replace(/\s/g, '');
30348
+ startSubscription() {
30349
+ return this.queryStreamController.subscribeRTE([
30350
+ {
30351
+ fn: onLocalInvitationCreated,
30352
+ action: InvitationActionsEnum.OnLocalInvitationCreated,
30353
+ },
30354
+ {
30355
+ fn: onLocalInvitationUpdated,
30356
+ action: InvitationActionsEnum.OnLocalInvitationUpdated,
30357
+ },
30358
+ {
30359
+ fn: onLocalInvitationCanceled,
30360
+ action: InvitationActionsEnum.OnLocalInvitationCanceled,
30361
+ },
30362
+ ]);
30331
30363
  }
30332
- else {
30333
- base64Key = keyString.replace(/\s/g, '');
30364
+ notifyChange({ origin, loading, error }) {
30365
+ var _a, _b;
30366
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30367
+ if (!collection)
30368
+ return;
30369
+ const data = this.applyFilter((_b = collection.data
30370
+ .map(id => pullFromCache(['invitation', 'get', id]))
30371
+ .filter(isNonNullable)
30372
+ .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
30373
+ if (!this.shouldNotify(data) && origin === 'event')
30374
+ return;
30375
+ this.callback({
30376
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
30377
+ data,
30378
+ hasNextPage: !!this.paginationController.getNextToken(),
30379
+ loading,
30380
+ error,
30381
+ });
30334
30382
  }
30335
- // Base64 decode to get binary data
30336
- const binaryDerString = atob(base64Key);
30337
- // Convert to Uint8Array for manipulation
30338
- const pkcs1 = new Uint8Array(binaryDerString.length);
30339
- for (let i = 0; i < binaryDerString.length; i += 1) {
30340
- pkcs1[i] = binaryDerString.charCodeAt(i);
30383
+ applyFilter(data) {
30384
+ let invitations = data;
30385
+ if (this.query.targetId) {
30386
+ invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
30387
+ }
30388
+ if (this.query.statuses) {
30389
+ invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
30390
+ }
30391
+ if (this.query.targetType) {
30392
+ invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
30393
+ }
30394
+ if (this.query.type) {
30395
+ invitations = invitations.filter(invitation => invitation.type === this.query.type);
30396
+ }
30397
+ const sortFn = (() => {
30398
+ switch (this.query.sortBy) {
30399
+ case 'firstCreated':
30400
+ return sortByFirstCreated;
30401
+ case 'lastCreated':
30402
+ return sortByLastCreated;
30403
+ default:
30404
+ return sortByLastCreated;
30405
+ }
30406
+ })();
30407
+ invitations = invitations.sort(sortFn);
30408
+ return invitations;
30341
30409
  }
30342
- // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
30343
- const pkcs8 = pkcs1ToPkcs8(pkcs1);
30344
- // Import the key
30345
- const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
30346
- return key;
30347
- }
30348
- async function createSignature({ timestamp, rooms, }) {
30349
- const dataStr = rooms
30350
- .map(item => Object.keys(item)
30351
- .sort()
30352
- .map(key => `${key}=${item[key]}`)
30353
- .join('&'))
30354
- .join(';');
30355
- /*
30356
- * nonceStr needs to be unique for each request
30357
- */
30358
- const nonceStr = uuid$1.v4();
30359
- const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
30360
- const encoder = new TextEncoder();
30361
- const data = encoder.encode(signStr);
30362
- const key = await importPrivateKey(privateKey);
30363
- const sign = await crypto.subtle.sign(ALGORITHM, key, data);
30364
- return { signature: base64FromArrayBuffer(sign), nonceStr };
30365
30410
  }
30366
30411
 
30367
30412
  /**
30368
- * Sync pending watch sessions to backend
30369
- * This function implements the full sync flow with network resilience
30413
+ * Get invitations
30414
+ *
30415
+ * @param params the query parameters
30416
+ * @param callback the callback to be called when the invitations are updated
30417
+ * @returns invitations
30418
+ *
30419
+ * @category Invitation Live Collection
30420
+ *
30370
30421
  */
30371
- async function syncWatchSessions() {
30372
- const storage = getWatchSessionStorage();
30373
- // Get all pending sessions
30374
- const pendingSessions = storage.getPendingSessions();
30375
- if (pendingSessions.length === 0) {
30376
- return true;
30422
+ const getInvitations$1 = (params, callback, config) => {
30423
+ const { log, cache } = getActiveClient();
30424
+ if (!cache) {
30425
+ console.log(ENABLE_CACHE_MESSAGE);
30377
30426
  }
30378
- try {
30379
- const timestamp = new Date().toISOString();
30380
- // Convert sessions to API format - always include all fields like syncUsage does
30381
- const rooms = pendingSessions.map(session => ({
30382
- sessionId: session.sessionId,
30383
- roomId: session.roomId,
30384
- watchSeconds: session.watchSeconds,
30385
- startTime: session.startTime.toISOString(),
30386
- endTime: session.endTime ? session.endTime.toISOString() : '',
30387
- }));
30388
- // Create signature (reuse from stream feature) - pass directly like syncUsage
30389
- const signatureData = await createSignature({
30390
- timestamp,
30391
- rooms,
30392
- });
30393
- if (!signatureData || !signatureData.signature) {
30394
- throw new Error('Signature is undefined');
30395
- }
30396
- // Update sync state to SYNCING
30397
- pendingSessions.forEach(session => {
30398
- storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
30399
- });
30400
- const payload = {
30401
- signature: signatureData.signature,
30402
- nonceStr: signatureData.nonceStr,
30403
- timestamp,
30404
- rooms,
30405
- };
30406
- const client = getActiveClient();
30407
- // Send to backend
30408
- await client.http.post('/api/v3/user-event/room', payload);
30409
- // Success - update to SYNCED
30410
- pendingSessions.forEach(session => {
30411
- storage.updateSession(session.sessionId, {
30412
- syncState: 'SYNCED',
30413
- syncedAt: new Date(),
30427
+ const timestamp = Date.now();
30428
+ log(`getInvitations: (tmpid: ${timestamp}) > listen`);
30429
+ const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
30430
+ const disposers = invitationsLiveCollection.startSubscription();
30431
+ const cacheKey = invitationsLiveCollection.getCacheKey();
30432
+ disposers.push(() => {
30433
+ dropFromCache(cacheKey);
30434
+ });
30435
+ return () => {
30436
+ log(`getInvitations (tmpid: ${timestamp}) > dispose`);
30437
+ disposers.forEach(fn => fn());
30438
+ };
30439
+ };
30440
+
30441
+ const categoryLinkedObject = (category) => {
30442
+ return Object.assign(Object.assign({}, category), { get avatar() {
30443
+ var _a;
30444
+ if (!category.avatarFileId)
30445
+ return undefined;
30446
+ const avatar = (_a = pullFromCache([
30447
+ 'file',
30448
+ 'get',
30449
+ `${category.avatarFileId}`,
30450
+ ])) === null || _a === void 0 ? void 0 : _a.data;
30451
+ return avatar;
30452
+ } });
30453
+ };
30454
+
30455
+ const communityLinkedObject = (community) => {
30456
+ return Object.assign(Object.assign({}, community), { get categories() {
30457
+ var _a;
30458
+ return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
30459
+ .map(categoryId => {
30460
+ const cacheData = pullFromCache(['category', 'get', categoryId]);
30461
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
30462
+ return categoryLinkedObject(cacheData.data);
30463
+ return undefined;
30464
+ })
30465
+ .filter(category => !!category);
30466
+ },
30467
+ get avatar() {
30468
+ var _a;
30469
+ if (!community.avatarFileId)
30470
+ return undefined;
30471
+ const avatar = (_a = pullFromCache([
30472
+ 'file',
30473
+ 'get',
30474
+ community.avatarFileId,
30475
+ ])) === null || _a === void 0 ? void 0 : _a.data;
30476
+ return avatar;
30477
+ }, createInvitations: async (userIds) => {
30478
+ await createInvitations({
30479
+ type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
30480
+ targetType: 'community',
30481
+ targetId: community.communityId,
30482
+ userIds,
30414
30483
  });
30415
- });
30416
- return true;
30484
+ }, getMemberInvitations: (params, callback) => {
30485
+ return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
30486
+ }, getInvitation: async () => {
30487
+ const { data } = await getInvitation({
30488
+ targetType: 'community',
30489
+ targetId: community.communityId,
30490
+ });
30491
+ return data;
30492
+ }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
30493
+ return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
30494
+ }, getMyJoinRequest: async () => {
30495
+ const { data } = await getMyJoinRequest(community.communityId);
30496
+ return data;
30497
+ } });
30498
+ };
30499
+
30500
+ class StoryComputedValue {
30501
+ constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
30502
+ this._syncingStoriesCount = 0;
30503
+ this._errorStoriesCount = 0;
30504
+ this._targetId = targetId;
30505
+ this._lastStoryExpiresAt = lastStoryExpiresAt;
30506
+ this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
30507
+ this.cacheStoryExpireTime = pullFromCache([
30508
+ "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
30509
+ this._targetId,
30510
+ ]);
30511
+ this.cacheStoreSeenTime = pullFromCache([
30512
+ "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
30513
+ this._targetId,
30514
+ ]);
30515
+ this.getTotalStoryByStatus();
30417
30516
  }
30418
- catch (err) {
30419
- console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
30420
- // Failure - update back to PENDING and increment retry count
30421
- pendingSessions.forEach(session => {
30422
- const currentSession = storage.getSession(session.sessionId);
30423
- if (currentSession) {
30424
- const newRetryCount = currentSession.retryCount + 1;
30425
- if (newRetryCount >= 3) {
30426
- // Delete session if retry count exceeds 3
30427
- storage.deleteSession(session.sessionId);
30428
- }
30429
- else {
30430
- // Update to PENDING with incremented retry count
30431
- storage.updateSession(session.sessionId, {
30432
- syncState: 'PENDING',
30433
- retryCount: newRetryCount,
30434
- });
30435
- }
30436
- }
30437
- });
30438
- return false;
30517
+ get lastStoryExpiresAt() {
30518
+ return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
30519
+ }
30520
+ get lastStorySeenExpiresAt() {
30521
+ return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
30522
+ }
30523
+ get localLastStoryExpires() {
30524
+ var _a, _b;
30525
+ return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
30526
+ ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
30527
+ : 0;
30528
+ }
30529
+ get localLastStorySeenExpiresAt() {
30530
+ var _a, _b;
30531
+ 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;
30532
+ }
30533
+ get isContainUnSyncedStory() {
30534
+ const currentSyncingState = pullFromCache([
30535
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
30536
+ this._targetId,
30537
+ ]);
30538
+ if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
30539
+ return false;
30540
+ return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
30439
30541
  }
30440
- }
30441
-
30442
- /**
30443
- * Room statuses that are considered watchable
30444
- */
30445
- const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
30446
- /**
30447
- * Generate a random jitter delay between 5 and 30 seconds
30448
- */
30449
- const getJitterDelay = () => {
30450
- const minDelay = 5000; // 5 seconds
30451
- const maxDelay = 30000; // 30 seconds
30452
- return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
30453
- };
30454
- /**
30455
- * Wait for network connection with timeout
30456
- * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
30457
- * @returns Promise that resolves when network is available or timeout is reached
30458
- */
30459
- const waitForNetwork = (maxWaitTime = 60000) => {
30460
- return new Promise(resolve => {
30461
- // Simple check - if navigator.onLine is available, use it
30462
- // Otherwise, assume network is available
30463
- if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
30464
- resolve();
30465
- return;
30542
+ getLocalLastSortingDate() {
30543
+ if (this.isContainUnSyncedStory) {
30544
+ return this.localLastStoryExpires;
30466
30545
  }
30467
- const startTime = Date.now();
30468
- const checkInterval = 1000; // 1 second
30469
- const checkConnection = () => {
30470
- if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
30471
- resolve();
30472
- }
30473
- else {
30474
- setTimeout(checkConnection, checkInterval);
30475
- }
30476
- };
30477
- checkConnection();
30478
- });
30479
- };
30480
- /**
30481
- * AmityRoomAnalytics provides analytics capabilities for room watch sessions
30482
- */
30483
- class AmityRoomAnalytics {
30484
- constructor(room) {
30485
- this.storage = getWatchSessionStorage();
30486
- this.client = getActiveClient();
30487
- this.room = room;
30546
+ return this.lastStoryExpiresAt;
30488
30547
  }
30489
- /**
30490
- * Create a new watch session for the current room
30491
- * @param startedAt The timestamp when watching started
30492
- * @returns Promise<string> sessionId unique identifier for this watch session
30493
- * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
30494
- */
30495
- async createWatchSession(startedAt) {
30496
- // Validate room status
30497
- if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
30498
- throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
30548
+ getHasUnseenFlag() {
30549
+ const now = new Date().getTime();
30550
+ const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
30551
+ pullFromCache([
30552
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
30553
+ this._targetId,
30554
+ ]);
30555
+ if (this.isContainUnSyncedStory) {
30556
+ return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
30499
30557
  }
30500
- // Generate session ID with prefix
30501
- const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
30502
- const sessionId = prefix + uuid$1.v4();
30503
- // Create watch session entity
30504
- const session = {
30505
- sessionId,
30506
- roomId: this.room.roomId,
30507
- watchSeconds: 0,
30508
- startTime: startedAt,
30509
- endTime: null,
30510
- syncState: 'PENDING',
30511
- syncedAt: null,
30512
- retryCount: 0,
30513
- };
30514
- // Persist to storage
30515
- this.storage.addSession(session);
30516
- return sessionId;
30558
+ return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
30517
30559
  }
30518
- /**
30519
- * Update an existing watch session with duration
30520
- * @param sessionId The unique identifier of the watch session
30521
- * @param duration The total watch duration in seconds
30522
- * @param endedAt The timestamp when this update occurred
30523
- * @returns Promise<void> Completion status
30524
- */
30525
- async updateWatchSession(sessionId, duration, endedAt) {
30526
- const session = this.storage.getSession(sessionId);
30527
- if (!session) {
30528
- throw new Error(`Watch session ${sessionId} not found`);
30560
+ getTotalStoryByStatus() {
30561
+ const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
30562
+ if (!stories) {
30563
+ this._errorStoriesCount = 0;
30564
+ this._syncingStoriesCount = 0;
30565
+ return;
30529
30566
  }
30530
- // Update session
30531
- this.storage.updateSession(sessionId, {
30532
- watchSeconds: duration,
30533
- endTime: endedAt,
30567
+ const groupByType = stories.reduce((acc, story) => {
30568
+ const { data: { targetId, syncState, isDeleted }, } = story;
30569
+ if (targetId === this._targetId && !isDeleted) {
30570
+ acc[syncState] += 1;
30571
+ }
30572
+ return acc;
30573
+ }, {
30574
+ syncing: 0,
30575
+ error: 0,
30576
+ synced: 0,
30534
30577
  });
30578
+ this._errorStoriesCount = groupByType.error;
30579
+ this._syncingStoriesCount = groupByType.syncing;
30535
30580
  }
30536
- /**
30537
- * Sync all pending watch sessions to backend
30538
- * This function uses jitter delay and handles network resilience
30539
- */
30540
- syncPendingWatchSessions() {
30541
- // Execute with jitter delay (5-30 seconds)
30542
- const jitterDelay = getJitterDelay();
30543
- this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
30544
- setTimeout(async () => {
30545
- this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
30546
- try {
30547
- // Reset any SYNCING sessions back to PENDING
30548
- const syncingSessions = this.storage.getSyncingSessions();
30549
- this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
30550
- syncingSessions.forEach(session => {
30551
- this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
30552
- });
30553
- // Wait for network connection (max 60 seconds)
30554
- await waitForNetwork(60000);
30555
- this.client.log('room/RoomAnalytics: Network available');
30556
- // Sync pending sessions
30557
- this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
30558
- await syncWatchSessions();
30559
- this.client.log('room/RoomAnalytics: syncWatchSessions completed');
30560
- }
30561
- catch (error) {
30562
- // Error is already handled in syncWatchSessions
30563
- console.error('Failed to sync watch sessions:', error);
30564
- }
30565
- }, jitterDelay);
30581
+ get syncingStoriesCount() {
30582
+ return this._syncingStoriesCount;
30583
+ }
30584
+ get failedStoriesCount() {
30585
+ return this._errorStoriesCount;
30566
30586
  }
30567
30587
  }
30568
30588
 
30569
- const roomLinkedObject = (room) => {
30570
- return Object.assign(Object.assign({}, room), { get post() {
30571
- var _a;
30572
- if (room.referenceType !== 'post')
30573
- return;
30574
- return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
30589
+ const storyTargetLinkedObject = (storyTarget) => {
30590
+ const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
30591
+ const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
30592
+ return {
30593
+ targetType,
30594
+ targetId,
30595
+ lastStoryExpiresAt,
30596
+ updatedAt: targetUpdatedAt,
30597
+ // Additional data
30598
+ hasUnseen: computedValue.getHasUnseenFlag(),
30599
+ syncingStoriesCount: computedValue.syncingStoriesCount,
30600
+ failedStoriesCount: computedValue.failedStoriesCount,
30601
+ localFilter,
30602
+ localLastExpires: computedValue.localLastStoryExpires,
30603
+ localLastSeen: computedValue.localLastStorySeenExpiresAt,
30604
+ localSortingDate: computedValue.getLocalLastSortingDate(),
30605
+ };
30606
+ };
30607
+
30608
+ const storyLinkedObject = (story) => {
30609
+ const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
30610
+ const storyTargetCache = pullFromCache([
30611
+ "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
30612
+ 'get',
30613
+ story.targetId,
30614
+ ]);
30615
+ const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
30616
+ return Object.assign(Object.assign({}, story), { analytics: {
30617
+ markAsSeen: () => {
30618
+ if (!story.expiresAt)
30619
+ return;
30620
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
30621
+ return;
30622
+ analyticsEngineInstance.markStoryAsViewed(story);
30623
+ },
30624
+ markLinkAsClicked: () => {
30625
+ if (!story.expiresAt)
30626
+ return;
30627
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
30628
+ return;
30629
+ analyticsEngineInstance.markStoryAsClicked(story);
30630
+ },
30631
+ }, get videoData() {
30632
+ var _a, _b;
30633
+ const cache = pullFromCache([
30634
+ 'file',
30635
+ 'get',
30636
+ (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
30637
+ ]);
30638
+ if (!cache)
30639
+ return undefined;
30640
+ const { data } = cache;
30641
+ return data || undefined;
30642
+ },
30643
+ get imageData() {
30644
+ var _a, _b;
30645
+ if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
30646
+ return undefined;
30647
+ const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
30648
+ if (!cache)
30649
+ return undefined;
30650
+ const { data } = cache;
30651
+ if (!data)
30652
+ return undefined;
30653
+ return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
30575
30654
  },
30576
30655
  get community() {
30577
- var _a;
30578
- if (room.targetType !== 'community')
30656
+ if (story.targetType !== 'community')
30657
+ return undefined;
30658
+ if (!(communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data))
30659
+ return undefined;
30660
+ return communityLinkedObject(communityCacheData.data);
30661
+ },
30662
+ get communityCategories() {
30663
+ if (story.targetType !== 'community')
30664
+ return undefined;
30665
+ if (!communityCacheData)
30666
+ return undefined;
30667
+ const { data: { categoryIds }, } = communityCacheData;
30668
+ if (categoryIds.length === 0)
30669
+ return undefined;
30670
+ return categoryIds
30671
+ .map(categoryId => {
30672
+ const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
30673
+ return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
30674
+ })
30675
+ .filter(category => category !== undefined);
30676
+ },
30677
+ get creator() {
30678
+ const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
30679
+ if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
30579
30680
  return;
30580
- return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
30681
+ return userLinkedObject(cacheData.data);
30581
30682
  },
30582
- get user() {
30583
- var _a;
30584
- const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
30585
- return user ? userLinkedObject(user) : user;
30683
+ get storyTarget() {
30684
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
30685
+ return;
30686
+ return storyTargetLinkedObject(storyTargetCache.data);
30586
30687
  },
30587
- get childRooms() {
30588
- if (!room.childRoomIds || room.childRoomIds.length === 0)
30589
- return [];
30590
- return room.childRoomIds
30591
- .map(id => {
30592
- var _a;
30593
- const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
30594
- if (!roomCache)
30595
- return undefined;
30596
- return roomLinkedObject(roomCache);
30597
- })
30598
- .filter(isNonNullable);
30599
- }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
30600
- var _a;
30601
- const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
30602
- return user ? userLinkedObject(user) : user;
30603
- } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
30604
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
30605
- targetType: 'room',
30606
- targetId: room.roomId,
30607
- userIds: [userId],
30608
- }), getInvitations: async () => {
30609
- const { data } = await getInvitation({
30610
- targetId: room.roomId,
30611
- targetType: 'room',
30612
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
30613
- });
30614
- return data;
30615
- }, analytics() {
30616
- // Use 'this' to avoid creating a new room object
30617
- return new AmityRoomAnalytics(this);
30688
+ get isSeen() {
30689
+ const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
30690
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
30691
+ return false;
30692
+ const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
30693
+ const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
30694
+ const expiresAt = new Date(story.expiresAt).getTime();
30695
+ return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
30618
30696
  } });
30619
30697
  };
30620
30698
 
30621
- const pollLinkedObject = (poll) => {
30622
- return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
30623
- var _a;
30624
- if (!answer.fileId)
30625
- return undefined;
30626
- return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
30627
- } }))) });
30628
- };
30629
-
30630
- /*
30631
- * verifies membership status
30632
- */
30633
- function isMember(membership) {
30634
- return membership !== 'none';
30635
- }
30636
- /*
30637
- * checks if currently logged in user is part of the community
30638
- */
30639
- function isCurrentUserPartOfCommunity(c, m) {
30640
- const { userId } = getActiveUser();
30641
- return c.communityId === m.communityId && m.userId === userId;
30642
- }
30643
- /*
30644
- * For mqtt events server will not send user specific data as it's broadcasted
30645
- * to multiple users and it also does not include communityUser
30646
- *
30647
- * Client SDK needs to check for the existing isJoined field in cache data before calculating.
30648
- * Althought this can be calculated, it's not scalable.
30649
- */
30650
- function updateMembershipStatus(communities, communityUsers) {
30651
- return communities.map(c => {
30652
- const cachedCommunity = pullFromCache([
30653
- 'community',
30654
- 'get',
30655
- c.communityId,
30656
- ]);
30657
- if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
30658
- return Object.assign(Object.assign({}, cachedCommunity.data), c);
30659
- }
30660
- const isJoined = c.isJoined !== undefined
30661
- ? c.isJoined
30662
- : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
30663
- return Object.assign(Object.assign({}, c), { isJoined });
30664
- });
30665
- }
30666
-
30667
- const getMatchPostSetting = (value) => {
30668
- var _a;
30669
- return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
30670
- CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
30671
- value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
30672
- };
30673
- function addPostSetting({ communities }) {
30674
- return communities.map((_a) => {
30675
- var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
30676
- return (Object.assign({ postSetting: getMatchPostSetting({
30677
- needApprovalOnPostCreation,
30678
- onlyAdminCanPost,
30679
- }) }, restCommunityPayload));
30680
- });
30681
- }
30682
- const prepareCommunityPayload = (rawPayload) => {
30683
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
30684
- // Convert users to internal format
30685
- const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
30686
- // map users with community
30687
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
30688
- const user = internalUsers.find(user => user.userId === communityUser.userId);
30689
- return Object.assign(Object.assign({}, communityUser), { user });
30690
- });
30691
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
30692
- return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
30693
- };
30694
- const prepareCommunityJoinRequestPayload = (rawPayload) => {
30695
- const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
30696
- return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
30697
- });
30698
- const users = rawPayload.users.map(convertRawUserToInternalUser);
30699
- return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
30700
- };
30701
- const prepareCommunityMembershipPayload = (rawPayload) => {
30702
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
30703
- // map users with community
30704
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
30705
- const user = rawPayload.users.find(user => user.userId === communityUser.userId);
30706
- return Object.assign(Object.assign({}, communityUser), { user });
30707
- });
30708
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
30709
- return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
30710
- };
30711
- const prepareCommunityRequest = (params) => {
30712
- const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
30713
- return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
30714
- // Convert story setting to the actual value. (Allow by default)
30715
- allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
30716
- };
30717
- const prepareSemanticSearchCommunityPayload = (_a) => {
30718
- var communityPayload = __rest(_a, ["searchResult"]);
30719
- const processedCommunityPayload = prepareCommunityPayload(communityPayload);
30720
- return Object.assign({}, processedCommunityPayload);
30721
- };
30722
-
30723
30699
  /* begin_public_function
30724
- id: joinRequest.approve
30700
+ id: channel.create
30725
30701
  */
30726
30702
  /**
30727
30703
  * ```js
30728
- * import { joinRequest } from '@amityco/ts-sdk'
30729
- * const isAccepted = await joinRequest.approve()
30704
+ * import { createChannel } from '@amityco/ts-sdk'
30705
+ * const created = await createChannel({ displayName: 'foobar' })
30730
30706
  * ```
30731
30707
  *
30732
- * Accepts a {@link Amity.JoinRequest} object
30708
+ * Creates an {@link Amity.Channel}
30733
30709
  *
30734
- * @param joinRequest the {@link Amity.JoinRequest} to accept
30735
- * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
30710
+ * @param bundle The data necessary to create a new {@link Amity.Channel}
30711
+ * @returns The newly created {@link Amity.Channel}
30736
30712
  *
30737
- * @category Join Request API
30713
+ * @category Channel API
30738
30714
  * @async
30739
30715
  */
30740
- const approveJoinRequest = async (joinRequest) => {
30741
- var _a;
30716
+ const createChannel = async (bundle) => {
30742
30717
  const client = getActiveClient();
30743
- client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
30744
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
30745
- userId: joinRequest.requestorInternalId,
30746
- });
30747
- const joinRequestCache = (_a = pullFromCache([
30748
- 'joinRequest',
30749
- 'get',
30750
- joinRequest.joinRequestId,
30751
- ])) === null || _a === void 0 ? void 0 : _a.data;
30752
- if (joinRequestCache) {
30753
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
30754
- status: "approved" /* JoinRequestStatusEnum.Approved */,
30755
- });
30756
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
30718
+ client.log('user/createChannel', bundle);
30719
+ let payload;
30720
+ /* c8 ignore next */
30721
+ if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
30722
+ payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
30757
30723
  }
30758
- return data.success;
30724
+ else {
30725
+ const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
30726
+ payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
30727
+ /* c8 ignore next */
30728
+ isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
30729
+ }
30730
+ const data = await prepareChannelPayload(payload.data);
30731
+ const cachedAt = client.cache && Date.now();
30732
+ if (client.cache)
30733
+ ingestInCache(data, { cachedAt });
30734
+ const { channels } = data;
30735
+ return {
30736
+ data: constructChannelObject(channels[0]),
30737
+ cachedAt,
30738
+ };
30759
30739
  };
30760
30740
  /* end_public_function */
30761
30741
 
30762
- /* begin_public_function
30763
- id: joinRequest.cancel
30764
- */
30765
30742
  /**
30766
30743
  * ```js
30767
- * import { joinRequest } from '@amityco/ts-sdk'
30768
- * const isCanceled = await joinRequest.cancel()
30744
+ * import { getChannel } from '@amityco/ts-sdk'
30745
+ * const channel = await getChannel('foobar')
30769
30746
  * ```
30770
30747
  *
30771
- * Cancels a {@link Amity.JoinRequest} object
30748
+ * Fetches a {@link Amity.Channel} object
30772
30749
  *
30773
- * @param joinRequest the {@link Amity.JoinRequest} to cancel
30774
- * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
30750
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
30751
+ * @returns the associated {@link Amity.Channel} object
30775
30752
  *
30776
- * @category Join Request API
30753
+ * @category Channel API
30777
30754
  * @async
30778
30755
  */
30779
- const cancelJoinRequest = async (joinRequest) => {
30780
- var _a;
30756
+ const getChannel$1 = async (channelId) => {
30781
30757
  const client = getActiveClient();
30782
- client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
30783
- const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
30784
- const joinRequestCache = (_a = pullFromCache([
30785
- 'joinRequest',
30786
- 'get',
30787
- joinRequest.joinRequestId,
30788
- ])) === null || _a === void 0 ? void 0 : _a.data;
30789
- if (joinRequestCache) {
30790
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
30791
- status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
30792
- });
30793
- fireEvent('local.joinRequest.deleted', [joinRequestCache]);
30758
+ client.log('channel/getChannel', channelId);
30759
+ isInTombstone('channel', channelId);
30760
+ let data;
30761
+ try {
30762
+ const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
30763
+ data = await prepareChannelPayload(payload);
30764
+ if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
30765
+ prepareUnreadCountInfo(payload);
30766
+ }
30794
30767
  }
30795
- return data.success;
30768
+ catch (error) {
30769
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
30770
+ // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
30771
+ pushToTombstone('channel', channelId);
30772
+ }
30773
+ throw error;
30774
+ }
30775
+ const cachedAt = client.cache && Date.now();
30776
+ if (client.cache)
30777
+ ingestInCache(data, { cachedAt });
30778
+ const { channels } = data;
30779
+ return {
30780
+ data: channels.find(channel => channel.channelId === channelId),
30781
+ cachedAt,
30782
+ };
30796
30783
  };
30797
- /* end_public_function */
30798
-
30799
- /* begin_public_function
30800
- id: joinRequest.reject
30801
- */
30802
30784
  /**
30803
30785
  * ```js
30804
- * import { joinRequest } from '@amityco/ts-sdk'
30805
- * const isRejected = await joinRequest.reject()
30786
+ * import { getChannel } from '@amityco/ts-sdk'
30787
+ * const channel = getChannel.locally('foobar')
30806
30788
  * ```
30807
30789
  *
30808
- * Rejects a {@link Amity.JoinRequest} object
30790
+ * Fetches a {@link Amity.Channel} object from cache
30809
30791
  *
30810
- * @param joinRequest the {@link Amity.JoinRequest} to reject
30811
- * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
30792
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
30793
+ * @returns the associated {@link Amity.Channel} object
30812
30794
  *
30813
- * @category Join Request API
30814
- * @async
30795
+ * @category Channel API
30815
30796
  */
30816
- const rejectJoinRequest = async (joinRequest) => {
30797
+ getChannel$1.locally = (channelId) => {
30817
30798
  var _a;
30818
30799
  const client = getActiveClient();
30819
- client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
30820
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
30821
- userId: joinRequest.requestorInternalId,
30800
+ client.log('channel/getChannel.locally', channelId);
30801
+ if (!client.cache)
30802
+ return;
30803
+ // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
30804
+ const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
30805
+ return data.channelPublicId === channelId;
30822
30806
  });
30823
- const joinRequestCache = (_a = pullFromCache([
30824
- 'joinRequest',
30825
- 'get',
30826
- joinRequest.joinRequestId,
30827
- ])) === null || _a === void 0 ? void 0 : _a.data;
30828
- if (joinRequestCache) {
30829
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
30830
- status: "rejected" /* JoinRequestStatusEnum.Rejected */,
30831
- });
30832
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
30833
- }
30834
- return data.success;
30835
- };
30836
- /* end_public_function */
30837
-
30838
- const joinRequestLinkedObject = (joinRequest) => {
30839
- return Object.assign(Object.assign({}, joinRequest), { get user() {
30840
- var _a;
30841
- const user = (_a = pullFromCache([
30842
- 'user',
30843
- 'get',
30844
- joinRequest.requestorPublicId,
30845
- ])) === null || _a === void 0 ? void 0 : _a.data;
30846
- if (!user)
30847
- return undefined;
30848
- return userLinkedObject(user);
30849
- }, cancel: async () => {
30850
- await cancelJoinRequest(joinRequest);
30851
- }, approve: async () => {
30852
- await approveJoinRequest(joinRequest);
30853
- }, reject: async () => {
30854
- await rejectJoinRequest(joinRequest);
30855
- } });
30807
+ if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
30808
+ return;
30809
+ return {
30810
+ data: cached[0].data,
30811
+ cachedAt: cached[0].cachedAt,
30812
+ };
30856
30813
  };
30857
30814
 
30858
- /* begin_public_function
30859
- id: community.getMyJoinRequest
30860
- */
30861
30815
  /**
30862
30816
  * ```js
30863
- * import { community } from '@amityco/ts-sdk'
30864
- * const isJoined = await community.getMyJoinRequest('foobar')
30817
+ * import { getStream } from '@amityco/ts-sdk'
30818
+ * const stream = await getStream('foobar')
30865
30819
  * ```
30866
30820
  *
30867
- * Joins a {@link Amity.Community} object
30821
+ * Fetches a {@link Amity.Channel} object linked with a current stream
30868
30822
  *
30869
- * @param communityId the {@link Amity.Community} to join
30870
- * @returns A success boolean if the {@link Amity.Community} was joined
30823
+ * @param stream {@link Amity.Stream} that has linked live channel
30824
+ * @returns the associated {@link Amity.Channel<'live'>} object
30871
30825
  *
30872
- * @category Community API
30826
+ * @category Stream API
30873
30827
  * @async
30874
30828
  */
30875
- const getMyJoinRequest = async (communityId) => {
30829
+ const getLiveChat$1 = async (stream) => {
30830
+ var _a;
30876
30831
  const client = getActiveClient();
30877
- client.log('community/myJoinRequest', communityId);
30878
- const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
30879
- const data = prepareCommunityJoinRequestPayload(payload);
30880
- const cachedAt = client.cache && Date.now();
30881
- if (client.cache)
30882
- ingestInCache(data, { cachedAt });
30883
- return {
30884
- data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
30885
- cachedAt,
30886
- };
30832
+ client.log('stream/getLiveChat', stream.streamId);
30833
+ if (stream.channelId) {
30834
+ const channel = (_a = pullFromCache([
30835
+ 'channel',
30836
+ 'get',
30837
+ stream.channelId,
30838
+ ])) === null || _a === void 0 ? void 0 : _a.data;
30839
+ if (channel)
30840
+ return channelLinkedObject(constructChannelObject(channel));
30841
+ const { data } = await getChannel$1(stream.channelId);
30842
+ return channelLinkedObject(constructChannelObject(data));
30843
+ }
30844
+ // No Channel ID
30845
+ // streamer: create a new live channel
30846
+ if (stream.userId === client.userId) {
30847
+ const { data: channel } = await createChannel({
30848
+ type: 'live',
30849
+ postId: stream.postId,
30850
+ videoStreamId: stream.streamId,
30851
+ });
30852
+ // Update channelId to stream object in cache
30853
+ mergeInCache(['stream', 'get', stream.streamId], {
30854
+ channelId: channel.channelId,
30855
+ });
30856
+ return channel;
30857
+ }
30858
+ // watcher: return undefined
30859
+ return undefined;
30887
30860
  };
30888
- /* end_public_function */
30889
30861
 
30890
- /* begin_public_function
30891
- id: community.join
30892
- */
30862
+ const GET_WATCHER_URLS = Symbol('getWatcherUrls');
30863
+ const streamLinkedObject = (stream) => {
30864
+ return Object.assign(Object.assign({}, stream), { get moderation() {
30865
+ var _a;
30866
+ return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
30867
+ },
30868
+ get post() {
30869
+ var _a;
30870
+ if (stream.referenceType !== 'post')
30871
+ return;
30872
+ return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
30873
+ },
30874
+ get community() {
30875
+ var _a;
30876
+ if (stream.targetType !== 'community')
30877
+ return;
30878
+ return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
30879
+ },
30880
+ get user() {
30881
+ var _a;
30882
+ return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
30883
+ },
30884
+ get childStreams() {
30885
+ if (!stream.childStreamIds || stream.childStreamIds.length === 0)
30886
+ return [];
30887
+ return stream.childStreamIds
30888
+ .map(id => {
30889
+ var _a;
30890
+ const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
30891
+ if (!streamCache)
30892
+ return undefined;
30893
+ return streamLinkedObject(streamCache);
30894
+ })
30895
+ .filter(isNonNullable);
30896
+ }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
30897
+ return stream.watcherUrl;
30898
+ } });
30899
+ };
30900
+
30901
+ const commentLinkedObject = (comment) => {
30902
+ return Object.assign(Object.assign({}, comment), { get target() {
30903
+ const commentTypes = {
30904
+ type: comment.targetType,
30905
+ };
30906
+ if (comment.targetType === 'user') {
30907
+ return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
30908
+ }
30909
+ if (commentTypes.type === 'content') {
30910
+ return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
30911
+ }
30912
+ if (commentTypes.type === 'community') {
30913
+ const cacheData = pullFromCache([
30914
+ 'communityUsers',
30915
+ 'get',
30916
+ `${comment.targetId}#${comment.userId}`,
30917
+ ]);
30918
+ return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
30919
+ }
30920
+ return {
30921
+ type: 'unknown',
30922
+ };
30923
+ },
30924
+ get creator() {
30925
+ const cacheData = pullFromCache(['user', 'get', comment.userId]);
30926
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
30927
+ return userLinkedObject(cacheData.data);
30928
+ return undefined;
30929
+ },
30930
+ get childrenComment() {
30931
+ return comment.children
30932
+ .map(childCommentId => {
30933
+ const commentCache = pullFromCache([
30934
+ 'comment',
30935
+ 'get',
30936
+ childCommentId,
30937
+ ]);
30938
+ if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
30939
+ return;
30940
+ return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
30941
+ })
30942
+ .filter(isNonNullable)
30943
+ .map(item => commentLinkedObject(item));
30944
+ } });
30945
+ };
30946
+
30947
+ function isAmityImagePost(post) {
30948
+ return !!(post.data &&
30949
+ typeof post.data !== 'string' &&
30950
+ 'fileId' in post.data &&
30951
+ post.dataType === 'image');
30952
+ }
30953
+ function isAmityFilePost(post) {
30954
+ return !!(post.data &&
30955
+ typeof post.data !== 'string' &&
30956
+ 'fileId' in post.data &&
30957
+ post.dataType === 'file');
30958
+ }
30959
+ function isAmityVideoPost(post) {
30960
+ return !!(post.data &&
30961
+ typeof post.data !== 'string' &&
30962
+ 'videoFileId' in post.data &&
30963
+ 'thumbnailFileId' in post.data &&
30964
+ post.dataType === 'video');
30965
+ }
30966
+ function isAmityLivestreamPost(post) {
30967
+ return !!(post.data &&
30968
+ typeof post.data !== 'string' &&
30969
+ 'streamId' in post.data &&
30970
+ post.dataType === 'liveStream');
30971
+ }
30972
+ function isAmityPollPost(post) {
30973
+ return !!(post.data &&
30974
+ typeof post.data !== 'string' &&
30975
+ 'pollId' in post.data &&
30976
+ post.dataType === 'poll');
30977
+ }
30978
+ function isAmityClipPost(post) {
30979
+ return !!(post.data &&
30980
+ typeof post.data !== 'string' &&
30981
+ 'fileId' in post.data &&
30982
+ post.dataType === 'clip');
30983
+ }
30984
+ function isAmityAudioPost(post) {
30985
+ return !!(post.data &&
30986
+ typeof post.data !== 'string' &&
30987
+ 'fileId' in post.data &&
30988
+ post.dataType === 'audio');
30989
+ }
30990
+ function isAmityRoomPost(post) {
30991
+ return !!(post.data &&
30992
+ typeof post.data !== 'string' &&
30993
+ 'roomId' in post.data &&
30994
+ post.dataType === 'room');
30995
+ }
30996
+
30893
30997
  /**
30894
30998
  * ```js
30895
- * import { community } from '@amityco/ts-sdk'
30896
- * const isJoined = await community.join('foobar')
30999
+ * import { RoomRepository } from '@amityco/ts-sdk'
31000
+ * const stream = await getStream('foobar')
30897
31001
  * ```
30898
31002
  *
30899
- * Joins a {@link Amity.Community} object
31003
+ * Fetches a {@link Amity.Channel} object linked with a current stream
30900
31004
  *
30901
- * @param communityId the {@link Amity.Community} to join
30902
- * @returns A status join result
31005
+ * @param stream {@link Amity.Stream} that has linked live channel
31006
+ * @returns the associated {@link Amity.Channel<'live'>} object
30903
31007
  *
30904
- * @category Community API
31008
+ * @category Stream API
30905
31009
  * @async
30906
31010
  */
30907
- const joinRequest = async (communityId) => {
31011
+ const getLiveChat = async (room) => {
30908
31012
  var _a;
30909
31013
  const client = getActiveClient();
30910
- client.log('community/joinRequest', communityId);
30911
- const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
30912
- const data = prepareCommunityJoinRequestPayload(payload);
30913
- const cachedAt = client.cache && Date.now();
30914
- if (client.cache)
30915
- ingestInCache(data, { cachedAt });
30916
- const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
30917
- ? "success" /* JoinResultStatusEnum.Success */
30918
- : "pending" /* JoinResultStatusEnum.Pending */;
30919
- if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
30920
- const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
30921
- if (community) {
30922
- const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
30923
- upsertInCache(['community', 'get', communityId], updatedCommunity);
30924
- }
31014
+ client.log('room/getLiveChat', room.roomId);
31015
+ if (room.liveChannelId) {
31016
+ const channel = (_a = pullFromCache([
31017
+ 'channel',
31018
+ 'get',
31019
+ room.liveChannelId,
31020
+ ])) === null || _a === void 0 ? void 0 : _a.data;
31021
+ if (channel)
31022
+ return channelLinkedObject(constructChannelObject(channel));
31023
+ const { data } = await getChannel$1(room.liveChannelId);
31024
+ return channelLinkedObject(constructChannelObject(data));
30925
31025
  }
30926
- fireEvent('v4.local.community.joined', data.joinRequests);
30927
- return status === "success" /* JoinResultStatusEnum.Success */
30928
- ? { status }
30929
- : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
30930
- };
30931
- /* end_public_function */
30932
-
30933
- /**
30934
- * TODO: handle cache receive cache option, and cache policy
30935
- * TODO: check if querybyIds is supported
30936
- */
30937
- class JoinRequestsPaginationController extends PaginationController {
30938
- async getRequest(queryParams, token) {
30939
- const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
30940
- const options = token ? { token } : { limit };
30941
- const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
30942
- params: Object.assign(Object.assign({}, params), { options }),
31026
+ // No Channel ID
31027
+ // streamer: create a new live channel
31028
+ if (room.createdBy === client.userId) {
31029
+ const { data: channel } = await createChannel({
31030
+ type: 'live',
31031
+ postId: room.referenceId,
31032
+ roomId: room.roomId,
30943
31033
  });
30944
- return queryResponse;
30945
- }
30946
- }
30947
-
30948
- var EnumJoinRequestAction$1;
30949
- (function (EnumJoinRequestAction) {
30950
- EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
30951
- EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
30952
- EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
30953
- })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
30954
-
30955
- class JoinRequestsQueryStreamController extends QueryStreamController {
30956
- constructor(query, cacheKey, notifyChange, preparePayload) {
30957
- super(query, cacheKey);
30958
- this.notifyChange = notifyChange;
30959
- this.preparePayload = preparePayload;
30960
- }
30961
- async saveToMainDB(response) {
30962
- const processedPayload = await this.preparePayload(response);
30963
- const client = getActiveClient();
30964
- const cachedAt = client.cache && Date.now();
30965
- if (client.cache) {
30966
- ingestInCache(processedPayload, { cachedAt });
30967
- }
30968
- }
30969
- appendToQueryStream(response, direction, refresh = false) {
30970
- var _a, _b;
30971
- if (refresh) {
30972
- pushToCache(this.cacheKey, {
30973
- data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
30974
- });
30975
- }
30976
- else {
30977
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30978
- const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
30979
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
30980
- ...new Set([
30981
- ...joinRequests,
30982
- ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
30983
- ]),
30984
- ] }));
30985
- }
30986
- }
30987
- reactor(action) {
30988
- return (joinRequest) => {
30989
- var _a;
30990
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30991
- if (!collection)
30992
- return;
30993
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
30994
- const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
30995
- if (!isExist)
30996
- return;
30997
- }
30998
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
30999
- collection.data = [
31000
- ...new Set([
31001
- ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
31002
- ...collection.data,
31003
- ]),
31004
- ];
31005
- }
31006
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
31007
- collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
31008
- }
31009
- pushToCache(this.cacheKey, collection);
31010
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
31011
- };
31012
- }
31013
- subscribeRTE(createSubscriber) {
31014
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
31034
+ // Update channelId to stream object in cache
31035
+ mergeInCache(['room', 'get', room.roomId], {
31036
+ liveChannelId: channel.channelId,
31037
+ });
31038
+ return channel;
31015
31039
  }
31016
- }
31017
-
31018
- /**
31019
- * ```js
31020
- * import { onJoinRequestCreated } from '@amityco/ts-sdk'
31021
- * const dispose = onJoinRequestCreated(data => {
31022
- * // ...
31023
- * })
31024
- * ```
31025
- *
31026
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
31027
- *
31028
- * @param callback The function to call when the event was fired
31029
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31030
- *
31031
- * @category JoinRequest Events
31032
- */
31033
- const onJoinRequestCreated = (callback) => {
31034
- const client = getActiveClient();
31035
- const disposers = [
31036
- createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
31037
- ];
31038
- return () => {
31039
- disposers.forEach(fn => fn());
31040
- };
31041
- };
31042
-
31043
- /**
31044
- * ```js
31045
- * import { onJoinRequestUpdated } from '@amityco/ts-sdk'
31046
- * const dispose = onJoinRequestUpdated(data => {
31047
- * // ...
31048
- * })
31049
- * ```
31050
- *
31051
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
31052
- *
31053
- * @param callback The function to call when the event was fired
31054
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31055
- *
31056
- * @category JoinRequest Events
31057
- */
31058
- const onJoinRequestUpdated = (callback) => {
31059
- const client = getActiveClient();
31060
- const disposers = [
31061
- createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
31062
- ];
31063
- return () => {
31064
- disposers.forEach(fn => fn());
31065
- };
31040
+ // watcher: return undefined
31041
+ return undefined;
31066
31042
  };
31067
31043
 
31068
31044
  /**
31069
- * ```js
31070
- * import { onJoinRequestDeleted } from '@amityco/ts-sdk'
31071
- * const dispose = onJoinRequestDeleted(data => {
31072
- * // ...
31073
- * })
31074
- * ```
31075
- *
31076
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
31077
- *
31078
- * @param callback The function to call when the event was fired
31079
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31080
- *
31081
- * @category JoinRequest Events
31045
+ * WatchSessionStorage manages watch session data in memory
31046
+ * Similar to UsageCollector for stream watch minutes
31082
31047
  */
31083
- const onJoinRequestDeleted = (callback) => {
31084
- const client = getActiveClient();
31085
- const disposers = [
31086
- createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
31087
- ];
31088
- return () => {
31089
- disposers.forEach(fn => fn());
31090
- };
31091
- };
31092
-
31093
- class JoinRequestsLiveCollectionController extends LiveCollectionController {
31094
- constructor(query, callback) {
31095
- const queryStreamId = hash(query);
31096
- const cacheKey = ['joinRequest', 'collection', queryStreamId];
31097
- const paginationController = new JoinRequestsPaginationController(query);
31098
- super(paginationController, queryStreamId, cacheKey, callback);
31099
- this.query = query;
31100
- this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
31101
- this.callback = callback.bind(this);
31102
- this.loadPage({ initial: true });
31048
+ class WatchSessionStorage {
31049
+ constructor() {
31050
+ this.sessions = new Map();
31103
31051
  }
31104
- setup() {
31105
- var _a;
31106
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31107
- if (!collection) {
31108
- pushToCache(this.cacheKey, {
31109
- data: [],
31110
- params: this.query,
31111
- });
31112
- }
31052
+ /**
31053
+ * Add a new watch session
31054
+ */
31055
+ addSession(session) {
31056
+ this.sessions.set(session.sessionId, session);
31057
+ }
31058
+ /**
31059
+ * Get a watch session by sessionId
31060
+ */
31061
+ getSession(sessionId) {
31062
+ return this.sessions.get(sessionId);
31113
31063
  }
31114
- async persistModel(queryPayload) {
31115
- await this.queryStreamController.saveToMainDB(queryPayload);
31064
+ /**
31065
+ * Update a watch session
31066
+ */
31067
+ updateSession(sessionId, updates) {
31068
+ const session = this.sessions.get(sessionId);
31069
+ if (session) {
31070
+ this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
31071
+ }
31116
31072
  }
31117
- persistQueryStream({ response, direction, refresh, }) {
31118
- const joinRequestResponse = response;
31119
- this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
31073
+ /**
31074
+ * Get all sessions with a specific sync state
31075
+ */
31076
+ getSessionsByState(state) {
31077
+ return Array.from(this.sessions.values()).filter(session => session.syncState === state);
31120
31078
  }
31121
- startSubscription() {
31122
- return this.queryStreamController.subscribeRTE([
31123
- { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
31124
- { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
31125
- { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
31126
- ]);
31079
+ /**
31080
+ * Delete a session
31081
+ */
31082
+ deleteSession(sessionId) {
31083
+ this.sessions.delete(sessionId);
31127
31084
  }
31128
- notifyChange({ origin, loading, error }) {
31129
- var _a;
31130
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31131
- if (!collection)
31132
- return;
31133
- const data = this.applyFilter(collection.data
31134
- .map(id => pullFromCache(['joinRequest', 'get', id]))
31135
- .filter(isNonNullable)
31136
- .map(({ data }) => data)
31137
- .map(joinRequestLinkedObject));
31138
- if (!this.shouldNotify(data) && origin === 'event')
31139
- return;
31140
- this.callback({
31141
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
31142
- data,
31143
- hasNextPage: !!this.paginationController.getNextToken(),
31144
- loading,
31145
- error,
31146
- });
31085
+ /**
31086
+ * Get all pending sessions
31087
+ */
31088
+ getPendingSessions() {
31089
+ return this.getSessionsByState('PENDING');
31147
31090
  }
31148
- applyFilter(data) {
31149
- let joinRequest = data;
31150
- if (this.query.status) {
31151
- joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
31152
- }
31153
- const sortFn = (() => {
31154
- switch (this.query.sortBy) {
31155
- case 'firstCreated':
31156
- return sortByFirstCreated;
31157
- case 'lastCreated':
31158
- return sortByLastCreated;
31159
- default:
31160
- return sortByLastCreated;
31161
- }
31162
- })();
31163
- joinRequest = joinRequest.sort(sortFn);
31164
- return joinRequest;
31091
+ /**
31092
+ * Get all syncing sessions
31093
+ */
31094
+ getSyncingSessions() {
31095
+ return this.getSessionsByState('SYNCING');
31165
31096
  }
31166
31097
  }
31098
+ // Singleton instance
31099
+ let storageInstance = null;
31100
+ const getWatchSessionStorage = () => {
31101
+ if (!storageInstance) {
31102
+ storageInstance = new WatchSessionStorage();
31103
+ }
31104
+ return storageInstance;
31105
+ };
31167
31106
 
31168
- /**
31169
- * Get Join Requests
31170
- *
31171
- * @param params the query parameters
31172
- * @param callback the callback to be called when the join request are updated
31173
- * @returns joinRequests
31174
- *
31175
- * @category joinRequest Live Collection
31107
+ 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=";
31108
+ /*
31109
+ * The crypto algorithm used for importing key and signing string
31110
+ */
31111
+ const ALGORITHM = {
31112
+ name: 'RSASSA-PKCS1-v1_5',
31113
+ hash: { name: 'SHA-256' },
31114
+ };
31115
+ /*
31116
+ * IMPORTANT!
31117
+ * If you are recieving key from other platforms use an online tool to convert
31118
+ * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
31119
+ * PKCS1.
31176
31120
  *
31121
+ * If recieving from the platform, verify if it's already in the expected
31122
+ * format. Otherwise the crypto.subtle.importKey will throw a DOMException
31177
31123
  */
31178
- const getJoinRequests = (params, callback, config) => {
31179
- const { log, cache } = getActiveClient();
31180
- if (!cache) {
31181
- console.log(ENABLE_CACHE_MESSAGE);
31182
- }
31183
- const timestamp = Date.now();
31184
- log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
31185
- const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
31186
- const disposers = joinRequestLiveCollection.startSubscription();
31187
- const cacheKey = joinRequestLiveCollection.getCacheKey();
31188
- disposers.push(() => {
31189
- dropFromCache(cacheKey);
31124
+ const PRIVATE_KEY_SIGNATURE = 'pkcs8';
31125
+ /*
31126
+ * Ensure that the private key in the .env follows this format
31127
+ */
31128
+ const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
31129
+ const PEM_FOOTER = '-----END PRIVATE KEY-----';
31130
+ /*
31131
+ * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
31132
+ * expects a base64 string. This util helps facilitate that process
31133
+ */
31134
+ function base64FromArrayBuffer(buffer) {
31135
+ const uint8Array = new Uint8Array(buffer);
31136
+ let binary = '';
31137
+ uint8Array.forEach(byte => {
31138
+ binary += String.fromCharCode(byte);
31190
31139
  });
31191
- return () => {
31192
- log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
31193
- disposers.forEach(fn => fn());
31194
- };
31195
- };
31196
-
31197
- var InvitationActionsEnum;
31198
- (function (InvitationActionsEnum) {
31199
- InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
31200
- InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
31201
- InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
31202
- })(InvitationActionsEnum || (InvitationActionsEnum = {}));
31203
-
31204
- class InvitationsPaginationController extends PaginationController {
31205
- async getRequest(queryParams, token) {
31206
- const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
31207
- const options = token ? { token } : { limit };
31208
- const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
31209
- return data;
31210
- }
31140
+ return btoa(binary);
31211
31141
  }
31212
-
31213
- class InvitationsQueryStreamController extends QueryStreamController {
31214
- constructor(query, cacheKey, notifyChange, preparePayload) {
31215
- super(query, cacheKey);
31216
- this.notifyChange = notifyChange;
31217
- this.preparePayload = preparePayload;
31218
- }
31219
- async saveToMainDB(response) {
31220
- const processedPayload = await this.preparePayload(response);
31221
- const client = getActiveClient();
31222
- const cachedAt = client.cache && Date.now();
31223
- if (client.cache) {
31224
- ingestInCache(processedPayload, { cachedAt });
31225
- }
31142
+ /*
31143
+ * Encode ASN.1 length field
31144
+ */
31145
+ function encodeLength(length) {
31146
+ if (length < 128) {
31147
+ return new Uint8Array([length]);
31226
31148
  }
31227
- appendToQueryStream(response, direction, refresh = false) {
31228
- var _a, _b;
31229
- if (refresh) {
31230
- pushToCache(this.cacheKey, {
31231
- data: response.invitations.map(getResolver('invitation')),
31232
- });
31233
- }
31234
- else {
31235
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31236
- const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
31237
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
31238
- ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
31239
- ] }));
31240
- }
31149
+ if (length < 256) {
31150
+ return new Uint8Array([0x81, length]);
31241
31151
  }
31242
- reactor(action) {
31243
- return (invitations) => {
31244
- var _a;
31245
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31246
- if (!collection)
31247
- return;
31248
- if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
31249
- const isExist = collection.data.find(id => id === invitations[0].invitationId);
31250
- if (!isExist)
31251
- return;
31252
- }
31253
- if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
31254
- collection.data = [
31255
- ...new Set([
31256
- ...invitations.map(invitation => invitation.invitationId),
31257
- ...collection.data,
31258
- ]),
31259
- ];
31260
- }
31261
- if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
31262
- collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
31263
- }
31264
- pushToCache(this.cacheKey, collection);
31265
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
31266
- };
31152
+ // eslint-disable-next-line no-bitwise
31153
+ return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
31154
+ }
31155
+ /*
31156
+ * Convert PKCS1 private key to PKCS8 format
31157
+ * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
31158
+ * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
31159
+ */
31160
+ function pkcs1ToPkcs8(pkcs1) {
31161
+ // Algorithm identifier for RSA
31162
+ const algorithmIdentifier = new Uint8Array([
31163
+ 0x30,
31164
+ 0x0d,
31165
+ 0x06,
31166
+ 0x09,
31167
+ 0x2a,
31168
+ 0x86,
31169
+ 0x48,
31170
+ 0x86,
31171
+ 0xf7,
31172
+ 0x0d,
31173
+ 0x01,
31174
+ 0x01,
31175
+ 0x01,
31176
+ 0x05,
31177
+ 0x00, // NULL
31178
+ ]);
31179
+ // Version (INTEGER 0)
31180
+ const version = new Uint8Array([0x02, 0x01, 0x00]);
31181
+ // OCTET STRING tag + length + pkcs1 data
31182
+ const octetStringTag = 0x04;
31183
+ const octetStringLength = encodeLength(pkcs1.length);
31184
+ // Calculate total content length (version + algorithm + octet string)
31185
+ const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
31186
+ // SEQUENCE tag + length
31187
+ const sequenceTag = 0x30;
31188
+ const sequenceLength = encodeLength(contentLength);
31189
+ // Build the PKCS8 structure
31190
+ const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
31191
+ let offset = 0;
31192
+ pkcs8[offset] = sequenceTag;
31193
+ offset += 1;
31194
+ pkcs8.set(sequenceLength, offset);
31195
+ offset += sequenceLength.length;
31196
+ pkcs8.set(version, offset);
31197
+ offset += version.length;
31198
+ pkcs8.set(algorithmIdentifier, offset);
31199
+ offset += algorithmIdentifier.length;
31200
+ pkcs8[offset] = octetStringTag;
31201
+ offset += 1;
31202
+ pkcs8.set(octetStringLength, offset);
31203
+ offset += octetStringLength.length;
31204
+ pkcs8.set(pkcs1, offset);
31205
+ return pkcs8;
31206
+ }
31207
+ async function importPrivateKey(keyString) {
31208
+ // Remove PEM headers if present and any whitespace
31209
+ let base64Key = keyString;
31210
+ if (keyString.includes(PEM_HEADER)) {
31211
+ base64Key = keyString
31212
+ .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
31213
+ .replace(/\s/g, '');
31267
31214
  }
31268
- subscribeRTE(createSubscriber) {
31269
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
31215
+ else {
31216
+ base64Key = keyString.replace(/\s/g, '');
31217
+ }
31218
+ // Base64 decode to get binary data
31219
+ const binaryDerString = atob(base64Key);
31220
+ // Convert to Uint8Array for manipulation
31221
+ const pkcs1 = new Uint8Array(binaryDerString.length);
31222
+ for (let i = 0; i < binaryDerString.length; i += 1) {
31223
+ pkcs1[i] = binaryDerString.charCodeAt(i);
31270
31224
  }
31225
+ // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
31226
+ const pkcs8 = pkcs1ToPkcs8(pkcs1);
31227
+ // Import the key
31228
+ const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
31229
+ return key;
31230
+ }
31231
+ async function createSignature({ timestamp, rooms, }) {
31232
+ const dataStr = rooms
31233
+ .map(item => Object.keys(item)
31234
+ .sort()
31235
+ .map(key => `${key}=${item[key]}`)
31236
+ .join('&'))
31237
+ .join(';');
31238
+ /*
31239
+ * nonceStr needs to be unique for each request
31240
+ */
31241
+ const nonceStr = uuid$1.v4();
31242
+ const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
31243
+ const encoder = new TextEncoder();
31244
+ const data = encoder.encode(signStr);
31245
+ const key = await importPrivateKey(privateKey);
31246
+ const sign = await crypto.subtle.sign(ALGORITHM, key, data);
31247
+ return { signature: base64FromArrayBuffer(sign), nonceStr };
31271
31248
  }
31272
31249
 
31273
31250
  /**
31274
- * ```js
31275
- * import { onLocalInvitationCreated } from '@amityco/ts-sdk'
31276
- * const dispose = onLocalInvitationCreated(data => {
31277
- * // ...
31278
- * })
31279
- * ```
31280
- *
31281
- * Fired when an {@link Amity.InvitationPayload} has been created
31282
- *
31283
- * @param callback The function to call when the event was fired
31284
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31285
- *
31286
- * @category Invitation Events
31287
- */
31288
- const onLocalInvitationCreated = (callback) => {
31289
- const client = getActiveClient();
31290
- const disposers = [
31291
- createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
31292
- ];
31293
- return () => {
31294
- disposers.forEach(fn => fn());
31295
- };
31296
- };
31297
-
31298
- /**
31299
- * ```js
31300
- * import { onLocalInvitationUpdated } from '@amityco/ts-sdk'
31301
- * const dispose = onLocalInvitationUpdated(data => {
31302
- * // ...
31303
- * })
31304
- * ```
31305
- *
31306
- * Fired when an {@link Amity.InvitationPayload} has been updated
31307
- *
31308
- * @param callback The function to call when the event was fired
31309
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31310
- *
31311
- * @category Invitation Events
31312
- */
31313
- const onLocalInvitationUpdated = (callback) => {
31314
- const client = getActiveClient();
31315
- const disposers = [
31316
- createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
31317
- ];
31318
- return () => {
31319
- disposers.forEach(fn => fn());
31320
- };
31321
- };
31322
-
31323
- /**
31324
- * ```js
31325
- * import { onLocalInvitationCanceled } from '@amityco/ts-sdk'
31326
- * const dispose = onLocalInvitationCanceled(data => {
31327
- * // ...
31328
- * })
31329
- * ```
31330
- *
31331
- * Fired when an {@link Amity.InvitationPayload} has been deleted
31332
- *
31333
- * @param callback The function to call when the event was fired
31334
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31335
- *
31336
- * @category Invitation Events
31251
+ * Sync pending watch sessions to backend
31252
+ * This function implements the full sync flow with network resilience
31337
31253
  */
31338
- const onLocalInvitationCanceled = (callback) => {
31339
- const client = getActiveClient();
31340
- const disposers = [
31341
- createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
31342
- ];
31343
- return () => {
31344
- disposers.forEach(fn => fn());
31345
- };
31346
- };
31347
-
31348
- class InvitationsLiveCollectionController extends LiveCollectionController {
31349
- constructor(query, callback) {
31350
- const queryStreamId = hash(query);
31351
- const cacheKey = ['invitation', 'collection', queryStreamId];
31352
- const paginationController = new InvitationsPaginationController(query);
31353
- super(paginationController, queryStreamId, cacheKey, callback);
31354
- this.query = query;
31355
- this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
31356
- this.callback = callback.bind(this);
31357
- this.loadPage({ initial: true });
31254
+ async function syncWatchSessions() {
31255
+ const storage = getWatchSessionStorage();
31256
+ // Get all pending sessions
31257
+ const pendingSessions = storage.getPendingSessions();
31258
+ if (pendingSessions.length === 0) {
31259
+ return true;
31358
31260
  }
31359
- setup() {
31360
- var _a;
31361
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31362
- if (!collection) {
31363
- pushToCache(this.cacheKey, {
31364
- data: [],
31365
- params: this.query,
31366
- });
31261
+ try {
31262
+ const timestamp = new Date().toISOString();
31263
+ // Convert sessions to API format - always include all fields like syncUsage does
31264
+ const rooms = pendingSessions.map(session => ({
31265
+ sessionId: session.sessionId,
31266
+ roomId: session.roomId,
31267
+ watchSeconds: session.watchSeconds,
31268
+ startTime: session.startTime.toISOString(),
31269
+ endTime: session.endTime ? session.endTime.toISOString() : '',
31270
+ }));
31271
+ // Create signature (reuse from stream feature) - pass directly like syncUsage
31272
+ const signatureData = await createSignature({
31273
+ timestamp,
31274
+ rooms,
31275
+ });
31276
+ if (!signatureData || !signatureData.signature) {
31277
+ throw new Error('Signature is undefined');
31367
31278
  }
31368
- }
31369
- async persistModel(queryPayload) {
31370
- await this.queryStreamController.saveToMainDB(queryPayload);
31371
- }
31372
- persistQueryStream({ response, direction, refresh, }) {
31373
- this.queryStreamController.appendToQueryStream(response, direction, refresh);
31374
- }
31375
- startSubscription() {
31376
- return this.queryStreamController.subscribeRTE([
31377
- {
31378
- fn: onLocalInvitationCreated,
31379
- action: InvitationActionsEnum.OnLocalInvitationCreated,
31380
- },
31381
- {
31382
- fn: onLocalInvitationUpdated,
31383
- action: InvitationActionsEnum.OnLocalInvitationUpdated,
31384
- },
31385
- {
31386
- fn: onLocalInvitationCanceled,
31387
- action: InvitationActionsEnum.OnLocalInvitationCanceled,
31388
- },
31389
- ]);
31390
- }
31391
- notifyChange({ origin, loading, error }) {
31392
- var _a, _b;
31393
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31394
- if (!collection)
31395
- return;
31396
- const data = this.applyFilter((_b = collection.data
31397
- .map(id => pullFromCache(['invitation', 'get', id]))
31398
- .filter(isNonNullable)
31399
- .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
31400
- if (!this.shouldNotify(data) && origin === 'event')
31401
- return;
31402
- this.callback({
31403
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
31404
- data,
31405
- hasNextPage: !!this.paginationController.getNextToken(),
31406
- loading,
31407
- error,
31279
+ // Update sync state to SYNCING
31280
+ pendingSessions.forEach(session => {
31281
+ storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
31282
+ });
31283
+ const payload = {
31284
+ signature: signatureData.signature,
31285
+ nonceStr: signatureData.nonceStr,
31286
+ timestamp,
31287
+ rooms,
31288
+ };
31289
+ const client = getActiveClient();
31290
+ // Send to backend
31291
+ await client.http.post('/api/v3/user-event/room', payload);
31292
+ // Success - update to SYNCED
31293
+ pendingSessions.forEach(session => {
31294
+ storage.updateSession(session.sessionId, {
31295
+ syncState: 'SYNCED',
31296
+ syncedAt: new Date(),
31297
+ });
31408
31298
  });
31299
+ return true;
31409
31300
  }
31410
- applyFilter(data) {
31411
- let invitations = data;
31412
- if (this.query.targetId) {
31413
- invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
31414
- }
31415
- if (this.query.statuses) {
31416
- invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
31417
- }
31418
- if (this.query.targetType) {
31419
- invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
31420
- }
31421
- if (this.query.type) {
31422
- invitations = invitations.filter(invitation => invitation.type === this.query.type);
31423
- }
31424
- const sortFn = (() => {
31425
- switch (this.query.sortBy) {
31426
- case 'firstCreated':
31427
- return sortByFirstCreated;
31428
- case 'lastCreated':
31429
- return sortByLastCreated;
31430
- default:
31431
- return sortByLastCreated;
31301
+ catch (err) {
31302
+ console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
31303
+ // Failure - update back to PENDING and increment retry count
31304
+ pendingSessions.forEach(session => {
31305
+ const currentSession = storage.getSession(session.sessionId);
31306
+ if (currentSession) {
31307
+ const newRetryCount = currentSession.retryCount + 1;
31308
+ if (newRetryCount >= 3) {
31309
+ // Delete session if retry count exceeds 3
31310
+ storage.deleteSession(session.sessionId);
31311
+ }
31312
+ else {
31313
+ // Update to PENDING with incremented retry count
31314
+ storage.updateSession(session.sessionId, {
31315
+ syncState: 'PENDING',
31316
+ retryCount: newRetryCount,
31317
+ });
31318
+ }
31432
31319
  }
31433
- })();
31434
- invitations = invitations.sort(sortFn);
31435
- return invitations;
31320
+ });
31321
+ return false;
31436
31322
  }
31437
31323
  }
31438
31324
 
31439
31325
  /**
31440
- * Get invitations
31441
- *
31442
- * @param params the query parameters
31443
- * @param callback the callback to be called when the invitations are updated
31444
- * @returns invitations
31445
- *
31446
- * @category Invitation Live Collection
31447
- *
31326
+ * Room statuses that are considered watchable
31448
31327
  */
31449
- const getInvitations$1 = (params, callback, config) => {
31450
- const { log, cache } = getActiveClient();
31451
- if (!cache) {
31452
- console.log(ENABLE_CACHE_MESSAGE);
31453
- }
31454
- const timestamp = Date.now();
31455
- log(`getInvitations: (tmpid: ${timestamp}) > listen`);
31456
- const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
31457
- const disposers = invitationsLiveCollection.startSubscription();
31458
- const cacheKey = invitationsLiveCollection.getCacheKey();
31459
- disposers.push(() => {
31460
- dropFromCache(cacheKey);
31328
+ const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
31329
+ /**
31330
+ * Generate a random jitter delay between 5 and 30 seconds
31331
+ */
31332
+ const getJitterDelay = () => {
31333
+ const minDelay = 5000; // 5 seconds
31334
+ const maxDelay = 30000; // 30 seconds
31335
+ return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
31336
+ };
31337
+ /**
31338
+ * Wait for network connection with timeout
31339
+ * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
31340
+ * @returns Promise that resolves when network is available or timeout is reached
31341
+ */
31342
+ const waitForNetwork = (maxWaitTime = 60000) => {
31343
+ return new Promise(resolve => {
31344
+ // Simple check - if navigator.onLine is available, use it
31345
+ // Otherwise, assume network is available
31346
+ if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
31347
+ resolve();
31348
+ return;
31349
+ }
31350
+ const startTime = Date.now();
31351
+ const checkInterval = 1000; // 1 second
31352
+ const checkConnection = () => {
31353
+ if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
31354
+ resolve();
31355
+ }
31356
+ else {
31357
+ setTimeout(checkConnection, checkInterval);
31358
+ }
31359
+ };
31360
+ checkConnection();
31461
31361
  });
31462
- return () => {
31463
- log(`getInvitations (tmpid: ${timestamp}) > dispose`);
31464
- disposers.forEach(fn => fn());
31465
- };
31466
31362
  };
31363
+ /**
31364
+ * AmityRoomAnalytics provides analytics capabilities for room watch sessions
31365
+ */
31366
+ class AmityRoomAnalytics {
31367
+ constructor(room) {
31368
+ this.storage = getWatchSessionStorage();
31369
+ this.client = getActiveClient();
31370
+ this.room = room;
31371
+ }
31372
+ /**
31373
+ * Create a new watch session for the current room
31374
+ * @param startedAt The timestamp when watching started
31375
+ * @returns Promise<string> sessionId unique identifier for this watch session
31376
+ * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
31377
+ */
31378
+ async createWatchSession(startedAt) {
31379
+ // Validate room status
31380
+ if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
31381
+ throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
31382
+ }
31383
+ // Generate session ID with prefix
31384
+ const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
31385
+ const sessionId = prefix + uuid$1.v4();
31386
+ // Create watch session entity
31387
+ const session = {
31388
+ sessionId,
31389
+ roomId: this.room.roomId,
31390
+ watchSeconds: 0,
31391
+ startTime: startedAt,
31392
+ endTime: null,
31393
+ syncState: 'PENDING',
31394
+ syncedAt: null,
31395
+ retryCount: 0,
31396
+ };
31397
+ // Persist to storage
31398
+ this.storage.addSession(session);
31399
+ return sessionId;
31400
+ }
31401
+ /**
31402
+ * Update an existing watch session with duration
31403
+ * @param sessionId The unique identifier of the watch session
31404
+ * @param duration The total watch duration in seconds
31405
+ * @param endedAt The timestamp when this update occurred
31406
+ * @returns Promise<void> Completion status
31407
+ */
31408
+ async updateWatchSession(sessionId, duration, endedAt) {
31409
+ const session = this.storage.getSession(sessionId);
31410
+ if (!session) {
31411
+ throw new Error(`Watch session ${sessionId} not found`);
31412
+ }
31413
+ // Update session
31414
+ this.storage.updateSession(sessionId, {
31415
+ watchSeconds: duration,
31416
+ endTime: endedAt,
31417
+ });
31418
+ }
31419
+ /**
31420
+ * Sync all pending watch sessions to backend
31421
+ * This function uses jitter delay and handles network resilience
31422
+ */
31423
+ syncPendingWatchSessions() {
31424
+ // Execute with jitter delay (5-30 seconds)
31425
+ const jitterDelay = getJitterDelay();
31426
+ this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
31427
+ setTimeout(async () => {
31428
+ this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
31429
+ try {
31430
+ // Reset any SYNCING sessions back to PENDING
31431
+ const syncingSessions = this.storage.getSyncingSessions();
31432
+ this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
31433
+ syncingSessions.forEach(session => {
31434
+ this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
31435
+ });
31436
+ // Wait for network connection (max 60 seconds)
31437
+ await waitForNetwork(60000);
31438
+ this.client.log('room/RoomAnalytics: Network available');
31439
+ // Sync pending sessions
31440
+ this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
31441
+ await syncWatchSessions();
31442
+ this.client.log('room/RoomAnalytics: syncWatchSessions completed');
31443
+ }
31444
+ catch (error) {
31445
+ // Error is already handled in syncWatchSessions
31446
+ console.error('Failed to sync watch sessions:', error);
31447
+ }
31448
+ }, jitterDelay);
31449
+ }
31450
+ }
31467
31451
 
31468
- const communityLinkedObject = (community) => {
31469
- return Object.assign(Object.assign({}, community), { get categories() {
31452
+ const roomLinkedObject = (room) => {
31453
+ return Object.assign(Object.assign({}, room), { get post() {
31470
31454
  var _a;
31471
- return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
31472
- .map(categoryId => {
31473
- const cacheData = pullFromCache(['category', 'get', categoryId]);
31474
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
31475
- return categoryLinkedObject(cacheData.data);
31476
- return undefined;
31477
- })
31478
- .filter(category => !!category);
31455
+ if (room.referenceType !== 'post')
31456
+ return;
31457
+ return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
31479
31458
  },
31480
- get avatar() {
31459
+ get community() {
31481
31460
  var _a;
31482
- if (!community.avatarFileId)
31483
- return undefined;
31484
- const avatar = (_a = pullFromCache([
31485
- 'file',
31486
- 'get',
31487
- community.avatarFileId,
31488
- ])) === null || _a === void 0 ? void 0 : _a.data;
31489
- return avatar;
31490
- }, createInvitations: async (userIds) => {
31491
- await createInvitations({
31492
- type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
31493
- targetType: 'community',
31494
- targetId: community.communityId,
31495
- userIds,
31496
- });
31497
- }, getMemberInvitations: (params, callback) => {
31498
- return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
31499
- }, getInvitation: async () => {
31461
+ if (room.targetType !== 'community')
31462
+ return;
31463
+ return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
31464
+ },
31465
+ get user() {
31466
+ var _a;
31467
+ const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
31468
+ return user ? userLinkedObject(user) : user;
31469
+ },
31470
+ get childRooms() {
31471
+ if (!room.childRoomIds || room.childRoomIds.length === 0)
31472
+ return [];
31473
+ return room.childRoomIds
31474
+ .map(id => {
31475
+ var _a;
31476
+ const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
31477
+ if (!roomCache)
31478
+ return undefined;
31479
+ return roomLinkedObject(roomCache);
31480
+ })
31481
+ .filter(isNonNullable);
31482
+ }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
31483
+ var _a;
31484
+ const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
31485
+ return user ? userLinkedObject(user) : user;
31486
+ } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
31487
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
31488
+ targetType: 'room',
31489
+ targetId: room.roomId,
31490
+ userIds: [userId],
31491
+ }), getInvitations: async () => {
31500
31492
  const { data } = await getInvitation({
31501
- targetType: 'community',
31502
- targetId: community.communityId,
31493
+ targetId: room.roomId,
31494
+ targetType: 'room',
31495
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
31503
31496
  });
31504
31497
  return data;
31505
- }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
31506
- return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
31507
- }, getMyJoinRequest: async () => {
31508
- const { data } = await getMyJoinRequest(community.communityId);
31509
- return data;
31498
+ }, analytics() {
31499
+ // Use 'this' to avoid creating a new room object
31500
+ return new AmityRoomAnalytics(this);
31510
31501
  } });
31511
31502
  };
31512
31503
 
31504
+ const pollLinkedObject = (poll) => {
31505
+ return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
31506
+ var _a;
31507
+ if (!answer.fileId)
31508
+ return undefined;
31509
+ return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
31510
+ } }))) });
31511
+ };
31512
+
31513
31513
  const productLinkedObject = (product) => {
31514
31514
  const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
31515
31515
  return Object.assign(Object.assign({}, product), { analytics: {