@amityco/ts-sdk 7.11.1-fec87c5.0 → 7.12.1-27702e75.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.
Files changed (64) hide show
  1. package/dist/@types/core/events.d.ts +5 -4
  2. package/dist/@types/core/events.d.ts.map +1 -1
  3. package/dist/@types/core/linkPreviewMetadata.d.ts +12 -0
  4. package/dist/@types/core/linkPreviewMetadata.d.ts.map +1 -0
  5. package/dist/@types/domains/community.d.ts +2 -7
  6. package/dist/@types/domains/community.d.ts.map +1 -1
  7. package/dist/@types/domains/liveStreamPlayer.d.ts +6 -2
  8. package/dist/@types/domains/liveStreamPlayer.d.ts.map +1 -1
  9. package/dist/@types/domains/post.d.ts +10 -0
  10. package/dist/@types/domains/post.d.ts.map +1 -1
  11. package/dist/@types/domains/room.d.ts +41 -2
  12. package/dist/@types/domains/room.d.ts.map +1 -1
  13. package/dist/client/api/fetchLinkPreview.d.ts +3 -0
  14. package/dist/client/api/fetchLinkPreview.d.ts.map +1 -1
  15. package/dist/client/api/getLinkPreviewMetadata.d.ts +14 -0
  16. package/dist/client/api/getLinkPreviewMetadata.d.ts.map +1 -0
  17. package/dist/client/api/index.d.ts +1 -0
  18. package/dist/client/api/index.d.ts.map +1 -1
  19. package/dist/core/events.d.ts +3 -3
  20. package/dist/core/events.d.ts.map +1 -1
  21. package/dist/eventRepository/internalApi/getEvent.d.ts.map +1 -1
  22. package/dist/index.cjs.js +922 -430
  23. package/dist/index.esm.js +902 -410
  24. package/dist/index.umd.js +3 -3
  25. package/dist/liveReactionRepository/api/createReaction.d.ts +7 -2
  26. package/dist/liveReactionRepository/api/createReaction.d.ts.map +1 -1
  27. package/dist/liveReactionRepository/internalApi/createLiveReaction.d.ts +3 -2
  28. package/dist/liveReactionRepository/internalApi/createLiveReaction.d.ts.map +1 -1
  29. package/dist/liveReactionRepository/service/ReactionSyncEngine.d.ts +2 -1
  30. package/dist/liveReactionRepository/service/ReactionSyncEngine.d.ts.map +1 -1
  31. package/dist/liveStreamPlayer/utils/cryptoSignatureUtils.d.ts +2 -2
  32. package/dist/liveStreamPlayer/utils/cryptoSignatureUtils.d.ts.map +1 -1
  33. package/dist/postRepository/api/createPost.d.ts +1 -0
  34. package/dist/postRepository/api/createPost.d.ts.map +1 -1
  35. package/dist/postRepository/api/editPost.d.ts +1 -0
  36. package/dist/postRepository/api/editPost.d.ts.map +1 -1
  37. package/dist/roomRepository/api/analytics/AmityRoomAnalytics.d.ts +30 -0
  38. package/dist/roomRepository/api/analytics/AmityRoomAnalytics.d.ts.map +1 -0
  39. package/dist/roomRepository/api/analytics/WatchSessionStorage.d.ts +38 -0
  40. package/dist/roomRepository/api/analytics/WatchSessionStorage.d.ts.map +1 -0
  41. package/dist/roomRepository/api/analytics/index.d.ts +4 -0
  42. package/dist/roomRepository/api/analytics/index.d.ts.map +1 -0
  43. package/dist/roomRepository/api/analytics/syncWatchSessions.d.ts +6 -0
  44. package/dist/roomRepository/api/analytics/syncWatchSessions.d.ts.map +1 -0
  45. package/dist/roomRepository/api/index.d.ts +1 -0
  46. package/dist/roomRepository/api/index.d.ts.map +1 -1
  47. package/dist/roomRepository/events/index.d.ts +2 -0
  48. package/dist/roomRepository/events/index.d.ts.map +1 -1
  49. package/dist/roomRepository/events/onRoomParticipantJoined.d.ts +1 -1
  50. package/dist/roomRepository/events/onRoomParticipantJoined.d.ts.map +1 -1
  51. package/dist/roomRepository/events/onRoomParticipantLeft.d.ts +1 -1
  52. package/dist/roomRepository/events/onRoomParticipantLeft.d.ts.map +1 -1
  53. package/dist/roomRepository/events/onRoomParticipantRemoved.d.ts +1 -1
  54. package/dist/roomRepository/events/onRoomParticipantRemoved.d.ts.map +1 -1
  55. package/dist/roomRepository/events/onRoomParticipantStageJoined.d.ts +17 -0
  56. package/dist/roomRepository/events/onRoomParticipantStageJoined.d.ts.map +1 -0
  57. package/dist/roomRepository/events/onRoomParticipantStageLeft.d.ts +17 -0
  58. package/dist/roomRepository/events/onRoomParticipantStageLeft.d.ts.map +1 -0
  59. package/dist/roomRepository/observers/getRoom.d.ts.map +1 -1
  60. package/dist/roomRepository/observers/getRooms/RoomLiveCollectionController.d.ts.map +1 -1
  61. package/dist/roomRepository/observers/utils.d.ts +1 -0
  62. package/dist/roomRepository/observers/utils.d.ts.map +1 -1
  63. package/dist/utils/linkedObject/roomLinkedObject.d.ts.map +1 -1
  64. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -239,8 +239,8 @@ exports.AmityEventOrderOption = void 0;
239
239
 
240
240
  function getVersion() {
241
241
  try {
242
- // the string ''v7.11.0-cjs'' should be replaced by actual value by @rollup/plugin-replace
243
- return 'v7.11.0-cjs';
242
+ // the string ''v7.12.0-cjs'' should be replaced by actual value by @rollup/plugin-replace
243
+ return 'v7.12.0-cjs';
244
244
  }
245
245
  catch (error) {
246
246
  return '__dev__';
@@ -8530,12 +8530,13 @@ var objectResolverEngineOnLoginHandler = () => {
8530
8530
  * @category Live Reaction API
8531
8531
  * @async
8532
8532
  */
8533
- const createLiveReaction = async ({ reactions, liveStreamId, }) => {
8533
+ const createLiveReaction = async ({ reactions, liveStreamId, roomId, }) => {
8534
8534
  const client = getActiveClient();
8535
8535
  client.log('live_reaction/addReaction', reactions);
8536
8536
  const { data } = await client.http.post(`/api/v1/reactions/live`, {
8537
8537
  liveStreamId,
8538
8538
  reactions,
8539
+ roomId,
8539
8540
  });
8540
8541
  return data;
8541
8542
  };
@@ -8592,19 +8593,23 @@ class LiveReactionSyncEngine {
8592
8593
  // Clear buffer
8593
8594
  this.clearBuffer();
8594
8595
  const payloads = reactions.reduce((prev, curr) => {
8595
- const { roomId } = curr, rest = __rest(curr, ["roomId"]);
8596
- if (!prev[roomId]) {
8596
+ const { roomId, streamId } = curr, rest = __rest(curr, ["roomId", "streamId"]);
8597
+ const referenceType = streamId ? 'liveStream' : 'room';
8598
+ const referenceId = streamId !== null && streamId !== void 0 ? streamId : roomId;
8599
+ if (!prev[referenceId]) {
8597
8600
  // eslint-disable-next-line no-param-reassign
8598
- prev[roomId] = [rest];
8601
+ prev[referenceId] = { referenceType, reactions: [] };
8602
+ prev[referenceId].reactions.push(rest);
8599
8603
  }
8600
8604
  else
8601
- prev[roomId].push(rest);
8605
+ prev[referenceId].reactions.push(rest);
8602
8606
  return prev;
8603
8607
  }, {});
8604
8608
  // Call server api `POST /api/v1/reactions/live` to sync live reactions
8605
- Object.entries(payloads).forEach(([roomId, reactions]) => {
8609
+ Object.entries(payloads).forEach(([referenceId, reactionPayload]) => {
8610
+ const referenceIdName = reactionPayload.referenceType === 'room' ? 'roomId' : 'liveStreamId';
8606
8611
  createLiveReaction({
8607
- liveStreamId: roomId,
8612
+ [referenceIdName]: referenceId,
8608
8613
  reactions,
8609
8614
  });
8610
8615
  });
@@ -9995,6 +10000,9 @@ function setUploadedFileAccessType(accessType) {
9995
10000
  GlobalFileAccessType$1.getInstance().setFileAccessType(accessType);
9996
10001
  }
9997
10002
 
10003
+ /**
10004
+ * @deprecated This function will to be deprecated and use the new getLinkPreviewMetadata
10005
+ */
9998
10006
  /**
9999
10007
  * ```js
10000
10008
  * import { fetchLinkPreview } from '@amityco/ts-sdk'
@@ -10017,6 +10025,24 @@ const fetchLinkPreview = async (url) => {
10017
10025
  return data;
10018
10026
  };
10019
10027
 
10028
+ /**
10029
+ * ```js
10030
+ * import { getLinkPreviewMetadata } from '@amityco/ts-sdk'
10031
+ * const { title, description, imageUrl } = getLinkPreviewMetadata('https://www.example.com/')
10032
+ * ```
10033
+ *
10034
+ *
10035
+ * @param url the url to fetch link preview
10036
+ * @returns A {@link Amity.LinkPreviewMetadata} instance
10037
+ *
10038
+ * @category Client API
10039
+ * */
10040
+ const getLinkPreviewMetadata = async (url) => {
10041
+ const client = getActiveClient();
10042
+ const { data } = await client.http.get(`/api/v1/link-preview?url=${url}`);
10043
+ return data;
10044
+ };
10045
+
10020
10046
  /**
10021
10047
  * ```js
10022
10048
  * import Client from '@amityco/ts-sdk'
@@ -10546,6 +10572,7 @@ var index$r = /*#__PURE__*/Object.freeze({
10546
10572
  enableUnreadCount: enableUnreadCount,
10547
10573
  setUploadedFileAccessType: setUploadedFileAccessType,
10548
10574
  fetchLinkPreview: fetchLinkPreview,
10575
+ getLinkPreviewMetadata: getLinkPreviewMetadata,
10549
10576
  getSocialSettings: getSocialSettings,
10550
10577
  getShareableLinkConfiguration: getShareableLinkConfiguration,
10551
10578
  loginAsVisitor: loginAsVisitor,
@@ -12446,12 +12473,9 @@ const rejectInvitation = async (invitationId) => {
12446
12473
  };
12447
12474
  /* end_public_function */
12448
12475
 
12449
- var InvitationActionsEnum;
12450
- (function (InvitationActionsEnum) {
12451
- InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
12452
- InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
12453
- InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
12454
- })(InvitationActionsEnum || (InvitationActionsEnum = {}));
12476
+ const prepareMyInvitationsPayload = (rawPayload) => {
12477
+ return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), invitations: rawPayload.invitations.map(convertRawInvitationToInternalInvitation) });
12478
+ };
12455
12479
 
12456
12480
  const invitationLinkedObject = (invitation) => {
12457
12481
  return Object.assign(Object.assign({}, invitation), { get user() {
@@ -12485,306 +12509,446 @@ const invitationLinkedObject = (invitation) => {
12485
12509
  } });
12486
12510
  };
12487
12511
 
12488
- class InvitationsPaginationController extends PaginationController {
12489
- async getRequest(queryParams, token) {
12490
- const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
12491
- const options = token ? { token } : { limit };
12492
- const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
12493
- return data;
12494
- }
12495
- }
12496
-
12497
- class InvitationsQueryStreamController extends QueryStreamController {
12498
- constructor(query, cacheKey, notifyChange, preparePayload) {
12499
- super(query, cacheKey);
12500
- this.notifyChange = notifyChange;
12501
- this.preparePayload = preparePayload;
12502
- }
12503
- async saveToMainDB(response) {
12504
- const processedPayload = await this.preparePayload(response);
12505
- const client = getActiveClient();
12506
- const cachedAt = client.cache && Date.now();
12507
- if (client.cache) {
12508
- ingestInCache(processedPayload, { cachedAt });
12509
- }
12510
- }
12511
- appendToQueryStream(response, direction, refresh = false) {
12512
- var _a, _b;
12513
- if (refresh) {
12514
- pushToCache(this.cacheKey, {
12515
- data: response.invitations.map(getResolver('invitation')),
12516
- });
12517
- }
12518
- else {
12519
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
12520
- const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
12521
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
12522
- ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
12523
- ] }));
12524
- }
12525
- }
12526
- reactor(action) {
12527
- return (invitations) => {
12528
- var _a;
12529
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
12530
- if (!collection)
12531
- return;
12532
- if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
12533
- const isExist = collection.data.find(id => id === invitations[0].invitationId);
12534
- if (!isExist)
12535
- return;
12536
- }
12537
- if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
12538
- collection.data = [
12539
- ...new Set([
12540
- ...invitations.map(invitation => invitation.invitationId),
12541
- ...collection.data,
12542
- ]),
12543
- ];
12544
- }
12545
- if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
12546
- collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
12547
- }
12548
- pushToCache(this.cacheKey, collection);
12549
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
12550
- };
12551
- }
12552
- subscribeRTE(createSubscriber) {
12553
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
12554
- }
12555
- }
12556
-
12557
- /**
12558
- * ```js
12559
- * import { onLocalInvitationCreated } from '@amityco/ts-sdk'
12560
- * const dispose = onLocalInvitationCreated(data => {
12561
- * // ...
12562
- * })
12563
- * ```
12564
- *
12565
- * Fired when an {@link Amity.InvitationPayload} has been created
12566
- *
12567
- * @param callback The function to call when the event was fired
12568
- * @returns an {@link Amity.Unsubscriber} function to stop listening
12569
- *
12570
- * @category Invitation Events
12571
- */
12572
- const onLocalInvitationCreated = (callback) => {
12573
- const client = getActiveClient();
12574
- const disposers = [
12575
- createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
12576
- ];
12577
- return () => {
12578
- disposers.forEach(fn => fn());
12579
- };
12580
- };
12581
-
12512
+ /* begin_public_function
12513
+ id: invitation.get
12514
+ */
12582
12515
  /**
12583
12516
  * ```js
12584
- * import { onLocalInvitationUpdated } from '@amityco/ts-sdk'
12585
- * const dispose = onLocalInvitationUpdated(data => {
12586
- * // ...
12587
- * })
12517
+ * import { getInvitation } from '@amityco/ts-sdk'
12518
+ * const { invitation } = await getInvitation(targetType, targetId)
12588
12519
  * ```
12589
12520
  *
12590
- * Fired when an {@link Amity.InvitationPayload} has been updated
12521
+ * Get a {@link Amity.Invitation} object
12591
12522
  *
12592
- * @param callback The function to call when the event was fired
12593
- * @returns an {@link Amity.Unsubscriber} function to stop listening
12523
+ * @param targetType The type of the target of the {@link Amity.Invitation}
12524
+ * @param targetId The ID of the target of the {@link Amity.Invitation}
12525
+ * @returns A {@link Amity.Invitation} object
12594
12526
  *
12595
- * @category Invitation Events
12527
+ * @category Invitation API
12528
+ * @async
12596
12529
  */
12597
- const onLocalInvitationUpdated = (callback) => {
12530
+ const getInvitation = async (params) => {
12598
12531
  const client = getActiveClient();
12599
- const disposers = [
12600
- createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
12601
- ];
12602
- return () => {
12603
- disposers.forEach(fn => fn());
12532
+ client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
12533
+ const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
12534
+ const data = prepareMyInvitationsPayload(payload);
12535
+ const cachedAt = client.cache && Date.now();
12536
+ if (client.cache)
12537
+ ingestInCache(data, { cachedAt });
12538
+ return {
12539
+ data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
12540
+ cachedAt,
12604
12541
  };
12605
12542
  };
12543
+ /* end_public_function */
12606
12544
 
12607
12545
  /**
12608
- * ```js
12609
- * import { onLocalInvitationCanceled } from '@amityco/ts-sdk'
12610
- * const dispose = onLocalInvitationCanceled(data => {
12611
- * // ...
12612
- * })
12613
- * ```
12614
- *
12615
- * Fired when an {@link Amity.InvitationPayload} has been deleted
12616
- *
12617
- * @param callback The function to call when the event was fired
12618
- * @returns an {@link Amity.Unsubscriber} function to stop listening
12619
- *
12620
- * @category Invitation Events
12546
+ * WatchSessionStorage manages watch session data in memory
12547
+ * Similar to UsageCollector for stream watch minutes
12621
12548
  */
12622
- const onLocalInvitationCanceled = (callback) => {
12623
- const client = getActiveClient();
12624
- const disposers = [
12625
- createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
12626
- ];
12627
- return () => {
12628
- disposers.forEach(fn => fn());
12629
- };
12630
- };
12631
-
12632
- class InvitationsLiveCollectionController extends LiveCollectionController {
12633
- constructor(query, callback) {
12634
- const queryStreamId = hash__default["default"](query);
12635
- const cacheKey = ['invitation', 'collection', queryStreamId];
12636
- const paginationController = new InvitationsPaginationController(query);
12637
- super(paginationController, queryStreamId, cacheKey, callback);
12638
- this.query = query;
12639
- this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
12640
- this.callback = callback.bind(this);
12641
- this.loadPage({ initial: true });
12549
+ class WatchSessionStorage {
12550
+ constructor() {
12551
+ this.sessions = new Map();
12642
12552
  }
12643
- setup() {
12644
- var _a;
12645
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
12646
- if (!collection) {
12647
- pushToCache(this.cacheKey, {
12648
- data: [],
12649
- params: this.query,
12650
- });
12553
+ /**
12554
+ * Add a new watch session
12555
+ */
12556
+ addSession(session) {
12557
+ this.sessions.set(session.sessionId, session);
12558
+ }
12559
+ /**
12560
+ * Get a watch session by sessionId
12561
+ */
12562
+ getSession(sessionId) {
12563
+ return this.sessions.get(sessionId);
12564
+ }
12565
+ /**
12566
+ * Update a watch session
12567
+ */
12568
+ updateSession(sessionId, updates) {
12569
+ const session = this.sessions.get(sessionId);
12570
+ if (session) {
12571
+ this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
12651
12572
  }
12652
12573
  }
12653
- async persistModel(queryPayload) {
12654
- await this.queryStreamController.saveToMainDB(queryPayload);
12574
+ /**
12575
+ * Get all sessions with a specific sync state
12576
+ */
12577
+ getSessionsByState(state) {
12578
+ return Array.from(this.sessions.values()).filter(session => session.syncState === state);
12655
12579
  }
12656
- persistQueryStream({ response, direction, refresh, }) {
12657
- this.queryStreamController.appendToQueryStream(response, direction, refresh);
12580
+ /**
12581
+ * Delete a session
12582
+ */
12583
+ deleteSession(sessionId) {
12584
+ this.sessions.delete(sessionId);
12658
12585
  }
12659
- startSubscription() {
12660
- return this.queryStreamController.subscribeRTE([
12661
- {
12662
- fn: onLocalInvitationCreated,
12663
- action: InvitationActionsEnum.OnLocalInvitationCreated,
12664
- },
12665
- {
12666
- fn: onLocalInvitationUpdated,
12667
- action: InvitationActionsEnum.OnLocalInvitationUpdated,
12668
- },
12669
- {
12670
- fn: onLocalInvitationCanceled,
12671
- action: InvitationActionsEnum.OnLocalInvitationCanceled,
12672
- },
12673
- ]);
12586
+ /**
12587
+ * Get all pending sessions
12588
+ */
12589
+ getPendingSessions() {
12590
+ return this.getSessionsByState('PENDING');
12674
12591
  }
12675
- notifyChange({ origin, loading, error }) {
12676
- var _a, _b;
12677
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
12678
- if (!collection)
12679
- return;
12680
- const data = this.applyFilter((_b = collection.data
12681
- .map(id => pullFromCache(['invitation', 'get', id]))
12682
- .filter(isNonNullable)
12683
- .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
12684
- if (!this.shouldNotify(data) && origin === 'event')
12685
- return;
12686
- this.callback({
12687
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
12688
- data,
12689
- hasNextPage: !!this.paginationController.getNextToken(),
12690
- loading,
12691
- error,
12692
- });
12592
+ /**
12593
+ * Get all syncing sessions
12594
+ */
12595
+ getSyncingSessions() {
12596
+ return this.getSessionsByState('SYNCING');
12693
12597
  }
12694
- applyFilter(data) {
12695
- let invitations = data;
12696
- if (this.query.targetId) {
12697
- invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
12698
- }
12699
- if (this.query.statuses) {
12700
- invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
12701
- }
12702
- if (this.query.targetType) {
12703
- invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
12704
- }
12705
- if (this.query.type) {
12706
- invitations = invitations.filter(invitation => invitation.type === this.query.type);
12707
- }
12708
- const sortFn = (() => {
12709
- switch (this.query.sortBy) {
12710
- case 'firstCreated':
12711
- return sortByFirstCreated;
12712
- case 'lastCreated':
12713
- return sortByLastCreated;
12714
- default:
12715
- return sortByLastCreated;
12716
- }
12717
- })();
12718
- invitations = invitations.sort(sortFn);
12719
- return invitations;
12598
+ }
12599
+ // Singleton instance
12600
+ let storageInstance = null;
12601
+ const getWatchSessionStorage = () => {
12602
+ if (!storageInstance) {
12603
+ storageInstance = new WatchSessionStorage();
12720
12604
  }
12605
+ return storageInstance;
12606
+ };
12607
+
12608
+ const privateKey = "MIIEpQIBAAKCAQEAwAEc/oZgYIvKSUG/C3mONYLR4ZPgAjMEX4bJ+xqqakUDRtql\\nNO+eZs2blQ1Ko0DBkqPExyQezvjibH5W2UZBV5RaBTlTcNVKTToMBEGesAfaEcM3\\nqUyQHxdbFYZv6P4sb14dcwxTQ8usmaV8ooiR1Fcaso5ZWYcZ8Hb46FbQ7OoVumsB\\ntPWwfZ4f003o5VCl6AIM6lcLv9UDLlFVYhE+PeXpRHtfWlGqxMvqC9oinlwhL6nW\\nv6VjQXW4nhcib72dPBzfHT7k/PMKto2SxALYdb68ENiAGuJLWi3AUHSyYCJK2w7w\\nIlWfJUAI0v26ub10IpExr6D5QuW2577jjP93iwIDAQABAoIBAFWfqXhwIIatkFY+\\n9Z1+ZcbDQimgsmMIsUiQaX6Lk7e0cxOj6czDlxYtVtaPiNtow2pLkjNkjkCqiP7t\\nEHnwdK9DvylZOTa2R15NJpK3WLcTqVIGhsn/FL5owfvFah6zSsmXZParZm5zY9NZ\\nE03ALZhOB9/cz0e3kf/EbpfeL2mW7MApyiUt5i09ycchroOpcWp73ipIxvgigtZy\\nUGFmsQicWhUs28F0D7w4Qfk76yG3nqXeb+BAMhCaIaa/k/aAxhiZG/ygEQWQrcC8\\ngfe+jyicMAQPDEVS9YuUMGsLjIjKuVLZzp2xirQnhc2i2zVNEIvG6soprPOBEMQu\\ngzrtX5ECgYEA3b7KAbBIbDl1e4ZSCWhHdHkiWVZHaopsR/LhqDDNhXjWjq3AesgV\\n6k0j9EdziMn/HmmOso0bz99GTV3JZf4A9ztTLumJlkHbdVtlgOqSjrFLj12rH9KX\\nTheyIhWSpUmm8+WB1xasFbqpvJaGo7F3pd2Fqj1XR4mp5BO7c/t7LJ0CgYEA3aou\\nEzXQ9THRKYocdfY69EI1Il1t/d/RSqqd9BxEjxBgxkM13ZiYIn/R4WW/nCUrlmhx\\nG44Aa2Gob4Ahfsui2xKTg/g/3Zk/rAxAEGkfOLGoenaJMD41fH4wUq3FRYwkvnaM\\nb9Hd6f/TlBHslIRa2NN58bSBGJCyBP2b59+2+EcCgYEAixDVRXvV37GlYUOa/XVd\\nosk5Zoe6oDGRuQm0xbNdoUBoZvDHDvme7ONWEiQha/8qtVsD+CyQ7awcPfb8kK9c\\n0bBt+bTS6d4BkTcxkEkMgtrkBVR8Nqfu5jXsLH4VCv4G61zbMhZw8+ut+az5YX2y\\nCN7Frj9sFlxapMRPQmzMEe0CgYEAumsAzM8ZqNv4mAK65Mnr0rhLj1cbxcKRdUYA\\nCOgtEFQpzxN/HZnTeFAe5nx3pI3uFlRHq3DFEYnT6dHMWaJQmAULYpVIwMi9L6gt\\nyJ9fzoI6uqMtxRDMUqKdaSsTGOY/kJ6KhQ/unXi1K3XXjR+yd1+C0q+HUm1+CYxv\\nrZYLfskCgYEArsEy+IQOiqniJ0NE2vVUF+UK/IRZaic9YKcpov5Ot7Vvzm/MnnW4\\nN1ljVskocETBWMmPUvNSExVjPebi+rxd8fa5kY8BJScPTzMFbunZn/wjtGdcM10q\\ndlVQ9doG61A/9P3ezFKCfS4AvF/H/59LcSx2Bh28fp3/efiVIOpVd4Y=";
12609
+ /*
12610
+ * The crypto algorithm used for importing key and signing string
12611
+ */
12612
+ const ALGORITHM = {
12613
+ name: 'RSASSA-PKCS1-v1_5',
12614
+ hash: { name: 'SHA-256' },
12615
+ };
12616
+ /*
12617
+ * IMPORTANT!
12618
+ * If you are recieving key from other platforms use an online tool to convert
12619
+ * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
12620
+ * PKCS1.
12621
+ *
12622
+ * If recieving from the platform, verify if it's already in the expected
12623
+ * format. Otherwise the crypto.subtle.importKey will throw a DOMException
12624
+ */
12625
+ const PRIVATE_KEY_SIGNATURE = 'pkcs8';
12626
+ /*
12627
+ * Ensure that the private key in the .env follows this format
12628
+ */
12629
+ const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
12630
+ const PEM_FOOTER = '-----END PRIVATE KEY-----';
12631
+ /*
12632
+ * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
12633
+ * expects a base64 string. This util helps facilitate that process
12634
+ */
12635
+ function base64FromArrayBuffer(buffer) {
12636
+ const uint8Array = new Uint8Array(buffer);
12637
+ let binary = '';
12638
+ uint8Array.forEach(byte => {
12639
+ binary += String.fromCharCode(byte);
12640
+ });
12641
+ return jsBase64.btoa(binary);
12642
+ }
12643
+ /*
12644
+ * Encode ASN.1 length field
12645
+ */
12646
+ function encodeLength(length) {
12647
+ if (length < 128) {
12648
+ return new Uint8Array([length]);
12649
+ }
12650
+ if (length < 256) {
12651
+ return new Uint8Array([0x81, length]);
12652
+ }
12653
+ // eslint-disable-next-line no-bitwise
12654
+ return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
12655
+ }
12656
+ /*
12657
+ * Convert PKCS1 private key to PKCS8 format
12658
+ * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
12659
+ * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
12660
+ */
12661
+ function pkcs1ToPkcs8(pkcs1) {
12662
+ // Algorithm identifier for RSA
12663
+ const algorithmIdentifier = new Uint8Array([
12664
+ 0x30,
12665
+ 0x0d,
12666
+ 0x06,
12667
+ 0x09,
12668
+ 0x2a,
12669
+ 0x86,
12670
+ 0x48,
12671
+ 0x86,
12672
+ 0xf7,
12673
+ 0x0d,
12674
+ 0x01,
12675
+ 0x01,
12676
+ 0x01,
12677
+ 0x05,
12678
+ 0x00, // NULL
12679
+ ]);
12680
+ // Version (INTEGER 0)
12681
+ const version = new Uint8Array([0x02, 0x01, 0x00]);
12682
+ // OCTET STRING tag + length + pkcs1 data
12683
+ const octetStringTag = 0x04;
12684
+ const octetStringLength = encodeLength(pkcs1.length);
12685
+ // Calculate total content length (version + algorithm + octet string)
12686
+ const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
12687
+ // SEQUENCE tag + length
12688
+ const sequenceTag = 0x30;
12689
+ const sequenceLength = encodeLength(contentLength);
12690
+ // Build the PKCS8 structure
12691
+ const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
12692
+ let offset = 0;
12693
+ pkcs8[offset] = sequenceTag;
12694
+ offset += 1;
12695
+ pkcs8.set(sequenceLength, offset);
12696
+ offset += sequenceLength.length;
12697
+ pkcs8.set(version, offset);
12698
+ offset += version.length;
12699
+ pkcs8.set(algorithmIdentifier, offset);
12700
+ offset += algorithmIdentifier.length;
12701
+ pkcs8[offset] = octetStringTag;
12702
+ offset += 1;
12703
+ pkcs8.set(octetStringLength, offset);
12704
+ offset += octetStringLength.length;
12705
+ pkcs8.set(pkcs1, offset);
12706
+ return pkcs8;
12707
+ }
12708
+ async function importPrivateKey(keyString) {
12709
+ // Remove PEM headers if present and any whitespace
12710
+ let base64Key = keyString;
12711
+ if (keyString.includes(PEM_HEADER)) {
12712
+ base64Key = keyString
12713
+ .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
12714
+ .replace(/\s/g, '');
12715
+ }
12716
+ else {
12717
+ base64Key = keyString.replace(/\s/g, '');
12718
+ }
12719
+ // Base64 decode to get binary data
12720
+ const binaryDerString = jsBase64.atob(base64Key);
12721
+ // Convert to Uint8Array for manipulation
12722
+ const pkcs1 = new Uint8Array(binaryDerString.length);
12723
+ for (let i = 0; i < binaryDerString.length; i += 1) {
12724
+ pkcs1[i] = binaryDerString.charCodeAt(i);
12725
+ }
12726
+ // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
12727
+ const pkcs8 = pkcs1ToPkcs8(pkcs1);
12728
+ // Import the key
12729
+ const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
12730
+ return key;
12731
+ }
12732
+ async function createSignature({ timestamp, rooms, }) {
12733
+ const dataStr = rooms
12734
+ .map(item => Object.keys(item)
12735
+ .sort()
12736
+ .map(key => `${key}=${item[key]}`)
12737
+ .join('&'))
12738
+ .join(';');
12739
+ /*
12740
+ * nonceStr needs to be unique for each request
12741
+ */
12742
+ const nonceStr = uuid__default["default"].v4();
12743
+ const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
12744
+ const encoder = new TextEncoder();
12745
+ const data = encoder.encode(signStr);
12746
+ const key = await importPrivateKey(privateKey);
12747
+ const sign = await crypto.subtle.sign(ALGORITHM, key, data);
12748
+ return { signature: base64FromArrayBuffer(sign), nonceStr };
12721
12749
  }
12722
12750
 
12723
12751
  /**
12724
- * Get invitations
12725
- *
12726
- * @param params the query parameters
12727
- * @param callback the callback to be called when the invitations are updated
12728
- * @returns invitations
12729
- *
12730
- * @category Invitation Live Collection
12731
- *
12752
+ * Sync pending watch sessions to backend
12753
+ * This function implements the full sync flow with network resilience
12732
12754
  */
12733
- const getInvitations$1 = (params, callback, config) => {
12734
- const { log, cache } = getActiveClient();
12735
- if (!cache) {
12736
- console.log(ENABLE_CACHE_MESSAGE);
12755
+ async function syncWatchSessions() {
12756
+ const storage = getWatchSessionStorage();
12757
+ // Get all pending sessions
12758
+ const pendingSessions = storage.getPendingSessions();
12759
+ if (pendingSessions.length === 0) {
12760
+ return true;
12737
12761
  }
12738
- const timestamp = Date.now();
12739
- log(`getInvitations: (tmpid: ${timestamp}) > listen`);
12740
- const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
12741
- const disposers = invitationsLiveCollection.startSubscription();
12742
- const cacheKey = invitationsLiveCollection.getCacheKey();
12743
- disposers.push(() => {
12744
- dropFromCache(cacheKey);
12745
- });
12746
- return () => {
12747
- log(`getInvitations (tmpid: ${timestamp}) > dispose`);
12748
- disposers.forEach(fn => fn());
12749
- };
12750
- };
12762
+ try {
12763
+ const timestamp = new Date().toISOString();
12764
+ // Convert sessions to API format - always include all fields like syncUsage does
12765
+ const rooms = pendingSessions.map(session => ({
12766
+ sessionId: session.sessionId,
12767
+ roomId: session.roomId,
12768
+ watchSeconds: session.watchSeconds,
12769
+ startTime: session.startTime.toISOString(),
12770
+ endTime: session.endTime ? session.endTime.toISOString() : '',
12771
+ }));
12772
+ // Create signature (reuse from stream feature) - pass directly like syncUsage
12773
+ const signatureData = await createSignature({
12774
+ timestamp,
12775
+ rooms,
12776
+ });
12777
+ if (!signatureData || !signatureData.signature) {
12778
+ throw new Error('Signature is undefined');
12779
+ }
12780
+ // Update sync state to SYNCING
12781
+ pendingSessions.forEach(session => {
12782
+ storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
12783
+ });
12784
+ const payload = {
12785
+ signature: signatureData.signature,
12786
+ nonceStr: signatureData.nonceStr,
12787
+ timestamp,
12788
+ rooms,
12789
+ };
12790
+ const client = getActiveClient();
12791
+ // Send to backend
12792
+ await client.http.post('/api/v3/user-event/room', payload);
12793
+ // Success - update to SYNCED
12794
+ pendingSessions.forEach(session => {
12795
+ storage.updateSession(session.sessionId, {
12796
+ syncState: 'SYNCED',
12797
+ syncedAt: new Date(),
12798
+ });
12799
+ });
12800
+ return true;
12801
+ }
12802
+ catch (err) {
12803
+ console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
12804
+ // Failure - update back to PENDING and increment retry count
12805
+ pendingSessions.forEach(session => {
12806
+ const currentSession = storage.getSession(session.sessionId);
12807
+ if (currentSession) {
12808
+ const newRetryCount = currentSession.retryCount + 1;
12809
+ if (newRetryCount >= 3) {
12810
+ // Delete session if retry count exceeds 3
12811
+ storage.deleteSession(session.sessionId);
12812
+ }
12813
+ else {
12814
+ // Update to PENDING with incremented retry count
12815
+ storage.updateSession(session.sessionId, {
12816
+ syncState: 'PENDING',
12817
+ retryCount: newRetryCount,
12818
+ });
12819
+ }
12820
+ }
12821
+ });
12822
+ return false;
12823
+ }
12824
+ }
12751
12825
 
12752
- const prepareMyInvitationsPayload = (rawPayload) => {
12753
- return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), invitations: rawPayload.invitations.map(convertRawInvitationToInternalInvitation) });
12826
+ /**
12827
+ * Room statuses that are considered watchable
12828
+ */
12829
+ const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
12830
+ /**
12831
+ * Generate a random jitter delay between 5 and 30 seconds
12832
+ */
12833
+ const getJitterDelay = () => {
12834
+ const minDelay = 5000; // 5 seconds
12835
+ const maxDelay = 30000; // 30 seconds
12836
+ return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
12754
12837
  };
12755
-
12756
- /* begin_public_function
12757
- id: invitation.get
12758
- */
12759
12838
  /**
12760
- * ```js
12761
- * import { getInvitation } from '@amityco/ts-sdk'
12762
- * const { invitation } = await getInvitation(targetType, targetId)
12763
- * ```
12764
- *
12765
- * Get a {@link Amity.Invitation} object
12766
- *
12767
- * @param targetType The type of the target of the {@link Amity.Invitation}
12768
- * @param targetId The ID of the target of the {@link Amity.Invitation}
12769
- * @returns A {@link Amity.Invitation} object
12770
- *
12771
- * @category Invitation API
12772
- * @async
12839
+ * Wait for network connection with timeout
12840
+ * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
12841
+ * @returns Promise that resolves when network is available or timeout is reached
12773
12842
  */
12774
- const getInvitation = async (params) => {
12775
- const client = getActiveClient();
12776
- client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
12777
- const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
12778
- const data = prepareMyInvitationsPayload(payload);
12779
- const cachedAt = client.cache && Date.now();
12780
- if (client.cache)
12781
- ingestInCache(data, { cachedAt });
12782
- return {
12783
- data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
12784
- cachedAt,
12785
- };
12843
+ const waitForNetwork = (maxWaitTime = 60000) => {
12844
+ return new Promise(resolve => {
12845
+ // Simple check - if navigator.onLine is available, use it
12846
+ // Otherwise, assume network is available
12847
+ if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
12848
+ resolve();
12849
+ return;
12850
+ }
12851
+ const startTime = Date.now();
12852
+ const checkInterval = 1000; // 1 second
12853
+ const checkConnection = () => {
12854
+ if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
12855
+ resolve();
12856
+ }
12857
+ else {
12858
+ setTimeout(checkConnection, checkInterval);
12859
+ }
12860
+ };
12861
+ checkConnection();
12862
+ });
12786
12863
  };
12787
- /* end_public_function */
12864
+ /**
12865
+ * AmityRoomAnalytics provides analytics capabilities for room watch sessions
12866
+ */
12867
+ class AmityRoomAnalytics {
12868
+ constructor(room) {
12869
+ this.storage = getWatchSessionStorage();
12870
+ this.client = getActiveClient();
12871
+ this.room = room;
12872
+ }
12873
+ /**
12874
+ * Create a new watch session for the current room
12875
+ * @param startedAt The timestamp when watching started
12876
+ * @returns Promise<string> sessionId unique identifier for this watch session
12877
+ * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
12878
+ */
12879
+ async createWatchSession(startedAt) {
12880
+ // Validate room status
12881
+ if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
12882
+ throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
12883
+ }
12884
+ // Generate session ID with prefix
12885
+ const prefix = this.room.status === 'live' ? 'live_' : 'playback_';
12886
+ const sessionId = prefix + uuid__default["default"].v4();
12887
+ // Create watch session entity
12888
+ const session = {
12889
+ sessionId,
12890
+ roomId: this.room.roomId,
12891
+ watchSeconds: 0,
12892
+ startTime: startedAt,
12893
+ endTime: null,
12894
+ syncState: 'PENDING',
12895
+ syncedAt: null,
12896
+ retryCount: 0,
12897
+ };
12898
+ // Persist to storage
12899
+ this.storage.addSession(session);
12900
+ return sessionId;
12901
+ }
12902
+ /**
12903
+ * Update an existing watch session with duration
12904
+ * @param sessionId The unique identifier of the watch session
12905
+ * @param duration The total watch duration in seconds
12906
+ * @param endedAt The timestamp when this update occurred
12907
+ * @returns Promise<void> Completion status
12908
+ */
12909
+ async updateWatchSession(sessionId, duration, endedAt) {
12910
+ const session = this.storage.getSession(sessionId);
12911
+ if (!session) {
12912
+ throw new Error(`Watch session ${sessionId} not found`);
12913
+ }
12914
+ // Update session
12915
+ this.storage.updateSession(sessionId, {
12916
+ watchSeconds: duration,
12917
+ endTime: endedAt,
12918
+ });
12919
+ }
12920
+ /**
12921
+ * Sync all pending watch sessions to backend
12922
+ * This function uses jitter delay and handles network resilience
12923
+ */
12924
+ syncPendingWatchSessions() {
12925
+ // Execute with jitter delay (5-30 seconds)
12926
+ const jitterDelay = getJitterDelay();
12927
+ this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
12928
+ setTimeout(async () => {
12929
+ this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
12930
+ try {
12931
+ // Reset any SYNCING sessions back to PENDING
12932
+ const syncingSessions = this.storage.getSyncingSessions();
12933
+ this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
12934
+ syncingSessions.forEach(session => {
12935
+ this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
12936
+ });
12937
+ // Wait for network connection (max 60 seconds)
12938
+ await waitForNetwork(60000);
12939
+ this.client.log('room/RoomAnalytics: Network available');
12940
+ // Sync pending sessions
12941
+ this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
12942
+ await syncWatchSessions();
12943
+ this.client.log('room/RoomAnalytics: syncWatchSessions completed');
12944
+ }
12945
+ catch (error) {
12946
+ // Error is already handled in syncWatchSessions
12947
+ console.error('Failed to sync watch sessions:', error);
12948
+ }
12949
+ }, jitterDelay);
12950
+ }
12951
+ }
12788
12952
 
12789
12953
  const roomLinkedObject = (room) => {
12790
12954
  return Object.assign(Object.assign({}, room), { get post() {
@@ -12825,13 +12989,16 @@ const roomLinkedObject = (room) => {
12825
12989
  targetType: 'room',
12826
12990
  targetId: room.roomId,
12827
12991
  userIds: [userId],
12828
- }), getInvitations: (params, callback) => getInvitations$1(Object.assign(Object.assign({}, params), { targetId: room.roomId, targetType: 'room', type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */ }), callback), getMyInvitation: async () => {
12992
+ }), getInvitations: async () => {
12829
12993
  const { data } = await getInvitation({
12830
12994
  targetId: room.roomId,
12831
12995
  targetType: 'room',
12832
12996
  type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
12833
12997
  });
12834
12998
  return data;
12999
+ }, analytics() {
13000
+ // Use 'this' to avoid creating a new room object
13001
+ return new AmityRoomAnalytics(this);
12835
13002
  } });
12836
13003
  };
12837
13004
 
@@ -13336,11 +13503,273 @@ class JoinRequestsLiveCollectionController extends LiveCollectionController {
13336
13503
  const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13337
13504
  if (!collection)
13338
13505
  return;
13339
- const data = this.applyFilter(collection.data
13340
- .map(id => pullFromCache(['joinRequest', 'get', id]))
13506
+ const data = this.applyFilter(collection.data
13507
+ .map(id => pullFromCache(['joinRequest', 'get', id]))
13508
+ .filter(isNonNullable)
13509
+ .map(({ data }) => data)
13510
+ .map(joinRequestLinkedObject));
13511
+ if (!this.shouldNotify(data) && origin === 'event')
13512
+ return;
13513
+ this.callback({
13514
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
13515
+ data,
13516
+ hasNextPage: !!this.paginationController.getNextToken(),
13517
+ loading,
13518
+ error,
13519
+ });
13520
+ }
13521
+ applyFilter(data) {
13522
+ let joinRequest = data;
13523
+ if (this.query.status) {
13524
+ joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
13525
+ }
13526
+ const sortFn = (() => {
13527
+ switch (this.query.sortBy) {
13528
+ case 'firstCreated':
13529
+ return sortByFirstCreated;
13530
+ case 'lastCreated':
13531
+ return sortByLastCreated;
13532
+ default:
13533
+ return sortByLastCreated;
13534
+ }
13535
+ })();
13536
+ joinRequest = joinRequest.sort(sortFn);
13537
+ return joinRequest;
13538
+ }
13539
+ }
13540
+
13541
+ /**
13542
+ * Get Join Requests
13543
+ *
13544
+ * @param params the query parameters
13545
+ * @param callback the callback to be called when the join request are updated
13546
+ * @returns joinRequests
13547
+ *
13548
+ * @category joinRequest Live Collection
13549
+ *
13550
+ */
13551
+ const getJoinRequests = (params, callback, config) => {
13552
+ const { log, cache } = getActiveClient();
13553
+ if (!cache) {
13554
+ console.log(ENABLE_CACHE_MESSAGE);
13555
+ }
13556
+ const timestamp = Date.now();
13557
+ log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
13558
+ const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
13559
+ const disposers = joinRequestLiveCollection.startSubscription();
13560
+ const cacheKey = joinRequestLiveCollection.getCacheKey();
13561
+ disposers.push(() => {
13562
+ dropFromCache(cacheKey);
13563
+ });
13564
+ return () => {
13565
+ log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
13566
+ disposers.forEach(fn => fn());
13567
+ };
13568
+ };
13569
+
13570
+ var InvitationActionsEnum;
13571
+ (function (InvitationActionsEnum) {
13572
+ InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
13573
+ InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
13574
+ InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
13575
+ })(InvitationActionsEnum || (InvitationActionsEnum = {}));
13576
+
13577
+ class InvitationsPaginationController extends PaginationController {
13578
+ async getRequest(queryParams, token) {
13579
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
13580
+ const options = token ? { token } : { limit };
13581
+ const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
13582
+ return data;
13583
+ }
13584
+ }
13585
+
13586
+ class InvitationsQueryStreamController extends QueryStreamController {
13587
+ constructor(query, cacheKey, notifyChange, preparePayload) {
13588
+ super(query, cacheKey);
13589
+ this.notifyChange = notifyChange;
13590
+ this.preparePayload = preparePayload;
13591
+ }
13592
+ async saveToMainDB(response) {
13593
+ const processedPayload = await this.preparePayload(response);
13594
+ const client = getActiveClient();
13595
+ const cachedAt = client.cache && Date.now();
13596
+ if (client.cache) {
13597
+ ingestInCache(processedPayload, { cachedAt });
13598
+ }
13599
+ }
13600
+ appendToQueryStream(response, direction, refresh = false) {
13601
+ var _a, _b;
13602
+ if (refresh) {
13603
+ pushToCache(this.cacheKey, {
13604
+ data: response.invitations.map(getResolver('invitation')),
13605
+ });
13606
+ }
13607
+ else {
13608
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13609
+ const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
13610
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
13611
+ ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
13612
+ ] }));
13613
+ }
13614
+ }
13615
+ reactor(action) {
13616
+ return (invitations) => {
13617
+ var _a;
13618
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13619
+ if (!collection)
13620
+ return;
13621
+ if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
13622
+ const isExist = collection.data.find(id => id === invitations[0].invitationId);
13623
+ if (!isExist)
13624
+ return;
13625
+ }
13626
+ if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
13627
+ collection.data = [
13628
+ ...new Set([
13629
+ ...invitations.map(invitation => invitation.invitationId),
13630
+ ...collection.data,
13631
+ ]),
13632
+ ];
13633
+ }
13634
+ if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
13635
+ collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
13636
+ }
13637
+ pushToCache(this.cacheKey, collection);
13638
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
13639
+ };
13640
+ }
13641
+ subscribeRTE(createSubscriber) {
13642
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
13643
+ }
13644
+ }
13645
+
13646
+ /**
13647
+ * ```js
13648
+ * import { onLocalInvitationCreated } from '@amityco/ts-sdk'
13649
+ * const dispose = onLocalInvitationCreated(data => {
13650
+ * // ...
13651
+ * })
13652
+ * ```
13653
+ *
13654
+ * Fired when an {@link Amity.InvitationPayload} has been created
13655
+ *
13656
+ * @param callback The function to call when the event was fired
13657
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13658
+ *
13659
+ * @category Invitation Events
13660
+ */
13661
+ const onLocalInvitationCreated = (callback) => {
13662
+ const client = getActiveClient();
13663
+ const disposers = [
13664
+ createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
13665
+ ];
13666
+ return () => {
13667
+ disposers.forEach(fn => fn());
13668
+ };
13669
+ };
13670
+
13671
+ /**
13672
+ * ```js
13673
+ * import { onLocalInvitationUpdated } from '@amityco/ts-sdk'
13674
+ * const dispose = onLocalInvitationUpdated(data => {
13675
+ * // ...
13676
+ * })
13677
+ * ```
13678
+ *
13679
+ * Fired when an {@link Amity.InvitationPayload} has been updated
13680
+ *
13681
+ * @param callback The function to call when the event was fired
13682
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13683
+ *
13684
+ * @category Invitation Events
13685
+ */
13686
+ const onLocalInvitationUpdated = (callback) => {
13687
+ const client = getActiveClient();
13688
+ const disposers = [
13689
+ createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
13690
+ ];
13691
+ return () => {
13692
+ disposers.forEach(fn => fn());
13693
+ };
13694
+ };
13695
+
13696
+ /**
13697
+ * ```js
13698
+ * import { onLocalInvitationCanceled } from '@amityco/ts-sdk'
13699
+ * const dispose = onLocalInvitationCanceled(data => {
13700
+ * // ...
13701
+ * })
13702
+ * ```
13703
+ *
13704
+ * Fired when an {@link Amity.InvitationPayload} has been deleted
13705
+ *
13706
+ * @param callback The function to call when the event was fired
13707
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13708
+ *
13709
+ * @category Invitation Events
13710
+ */
13711
+ const onLocalInvitationCanceled = (callback) => {
13712
+ const client = getActiveClient();
13713
+ const disposers = [
13714
+ createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
13715
+ ];
13716
+ return () => {
13717
+ disposers.forEach(fn => fn());
13718
+ };
13719
+ };
13720
+
13721
+ class InvitationsLiveCollectionController extends LiveCollectionController {
13722
+ constructor(query, callback) {
13723
+ const queryStreamId = hash__default["default"](query);
13724
+ const cacheKey = ['invitation', 'collection', queryStreamId];
13725
+ const paginationController = new InvitationsPaginationController(query);
13726
+ super(paginationController, queryStreamId, cacheKey, callback);
13727
+ this.query = query;
13728
+ this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
13729
+ this.callback = callback.bind(this);
13730
+ this.loadPage({ initial: true });
13731
+ }
13732
+ setup() {
13733
+ var _a;
13734
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13735
+ if (!collection) {
13736
+ pushToCache(this.cacheKey, {
13737
+ data: [],
13738
+ params: this.query,
13739
+ });
13740
+ }
13741
+ }
13742
+ async persistModel(queryPayload) {
13743
+ await this.queryStreamController.saveToMainDB(queryPayload);
13744
+ }
13745
+ persistQueryStream({ response, direction, refresh, }) {
13746
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
13747
+ }
13748
+ startSubscription() {
13749
+ return this.queryStreamController.subscribeRTE([
13750
+ {
13751
+ fn: onLocalInvitationCreated,
13752
+ action: InvitationActionsEnum.OnLocalInvitationCreated,
13753
+ },
13754
+ {
13755
+ fn: onLocalInvitationUpdated,
13756
+ action: InvitationActionsEnum.OnLocalInvitationUpdated,
13757
+ },
13758
+ {
13759
+ fn: onLocalInvitationCanceled,
13760
+ action: InvitationActionsEnum.OnLocalInvitationCanceled,
13761
+ },
13762
+ ]);
13763
+ }
13764
+ notifyChange({ origin, loading, error }) {
13765
+ var _a, _b;
13766
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13767
+ if (!collection)
13768
+ return;
13769
+ const data = this.applyFilter((_b = collection.data
13770
+ .map(id => pullFromCache(['invitation', 'get', id]))
13341
13771
  .filter(isNonNullable)
13342
- .map(({ data }) => data)
13343
- .map(joinRequestLinkedObject));
13772
+ .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
13344
13773
  if (!this.shouldNotify(data) && origin === 'event')
13345
13774
  return;
13346
13775
  this.callback({
@@ -13352,9 +13781,18 @@ class JoinRequestsLiveCollectionController extends LiveCollectionController {
13352
13781
  });
13353
13782
  }
13354
13783
  applyFilter(data) {
13355
- let joinRequest = data;
13356
- if (this.query.status) {
13357
- joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
13784
+ let invitations = data;
13785
+ if (this.query.targetId) {
13786
+ invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
13787
+ }
13788
+ if (this.query.statuses) {
13789
+ invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
13790
+ }
13791
+ if (this.query.targetType) {
13792
+ invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
13793
+ }
13794
+ if (this.query.type) {
13795
+ invitations = invitations.filter(invitation => invitation.type === this.query.type);
13358
13796
  }
13359
13797
  const sortFn = (() => {
13360
13798
  switch (this.query.sortBy) {
@@ -13366,36 +13804,36 @@ class JoinRequestsLiveCollectionController extends LiveCollectionController {
13366
13804
  return sortByLastCreated;
13367
13805
  }
13368
13806
  })();
13369
- joinRequest = joinRequest.sort(sortFn);
13370
- return joinRequest;
13807
+ invitations = invitations.sort(sortFn);
13808
+ return invitations;
13371
13809
  }
13372
13810
  }
13373
13811
 
13374
13812
  /**
13375
- * Get Join Requests
13813
+ * Get invitations
13376
13814
  *
13377
13815
  * @param params the query parameters
13378
- * @param callback the callback to be called when the join request are updated
13379
- * @returns joinRequests
13816
+ * @param callback the callback to be called when the invitations are updated
13817
+ * @returns invitations
13380
13818
  *
13381
- * @category joinRequest Live Collection
13819
+ * @category Invitation Live Collection
13382
13820
  *
13383
13821
  */
13384
- const getJoinRequests = (params, callback, config) => {
13822
+ const getInvitations$1 = (params, callback, config) => {
13385
13823
  const { log, cache } = getActiveClient();
13386
13824
  if (!cache) {
13387
13825
  console.log(ENABLE_CACHE_MESSAGE);
13388
13826
  }
13389
13827
  const timestamp = Date.now();
13390
- log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
13391
- const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
13392
- const disposers = joinRequestLiveCollection.startSubscription();
13393
- const cacheKey = joinRequestLiveCollection.getCacheKey();
13828
+ log(`getInvitations: (tmpid: ${timestamp}) > listen`);
13829
+ const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
13830
+ const disposers = invitationsLiveCollection.startSubscription();
13831
+ const cacheKey = invitationsLiveCollection.getCacheKey();
13394
13832
  disposers.push(() => {
13395
13833
  dropFromCache(cacheKey);
13396
13834
  });
13397
13835
  return () => {
13398
- log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
13836
+ log(`getInvitations (tmpid: ${timestamp}) > dispose`);
13399
13837
  disposers.forEach(fn => fn());
13400
13838
  };
13401
13839
  };
@@ -28371,8 +28809,12 @@ const onRoomCoHostInviteCanceled = (callback) => {
28371
28809
  const onRoomParticipantJoined = (callback) => {
28372
28810
  const client = getActiveClient();
28373
28811
  const filter = (payload) => {
28374
- ingestInCache(payload);
28375
- callback(payload.rooms[0]);
28812
+ const { rooms, users } = payload;
28813
+ ingestInCache({ rooms, users });
28814
+ callback({
28815
+ room: roomLinkedObject(rooms[0]),
28816
+ actorInternalId: payload.eventActor.userInternalId,
28817
+ });
28376
28818
  };
28377
28819
  return createEventSubscriber(client, 'room/onRoomParticipantJoined', 'room.participantJoined', filter);
28378
28820
  };
@@ -28395,12 +28837,72 @@ const onRoomParticipantJoined = (callback) => {
28395
28837
  const onRoomParticipantLeft = (callback) => {
28396
28838
  const client = getActiveClient();
28397
28839
  const filter = (payload) => {
28398
- ingestInCache(payload);
28399
- callback(payload.rooms[0]);
28840
+ const { rooms, users } = payload;
28841
+ ingestInCache({ rooms, users });
28842
+ callback({
28843
+ room: roomLinkedObject(rooms[0]),
28844
+ actorInternalId: payload.eventActor.userInternalId,
28845
+ });
28400
28846
  };
28401
28847
  return createEventSubscriber(client, 'room/onRoomParticipantLeft', 'room.participantLeft', filter);
28402
28848
  };
28403
28849
 
28850
+ /**
28851
+ * ```js
28852
+ * import { onRoomParticipantStageLeft } from '@amityco/ts-sdk'
28853
+ * const dispose = onRoomParticipantStageLeft(room => {
28854
+ * // ...
28855
+ * })
28856
+ * ```
28857
+ *
28858
+ * Fired when a participant has left the stage of a {@link Amity.Room}
28859
+ *
28860
+ * @param callback The function to call when the event was fired
28861
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
28862
+ *
28863
+ * @category Room Events
28864
+ */
28865
+ const onRoomParticipantStageLeft = (callback) => {
28866
+ const client = getActiveClient();
28867
+ const filter = (payload) => {
28868
+ const { rooms, users } = payload;
28869
+ ingestInCache({ rooms, users });
28870
+ callback({
28871
+ room: roomLinkedObject(rooms[0]),
28872
+ actorInternalId: payload.eventActor.userInternalId,
28873
+ });
28874
+ };
28875
+ return createEventSubscriber(client, 'room/onRoomParticipantStageLeft', 'room.participantStageLeft', filter);
28876
+ };
28877
+
28878
+ /**
28879
+ * ```js
28880
+ * import { onRoomParticipantStageJoined } from '@amityco/ts-sdk'
28881
+ * const dispose = onRoomParticipantStageJoined(room => {
28882
+ * // ...
28883
+ * })
28884
+ * ```
28885
+ *
28886
+ * Fired when a participant has joined the stage of a {@link Amity.Room}
28887
+ *
28888
+ * @param callback The function to call when the event was fired
28889
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
28890
+ *
28891
+ * @category Room Events
28892
+ */
28893
+ const onRoomParticipantStageJoined = (callback) => {
28894
+ const client = getActiveClient();
28895
+ const filter = (payload) => {
28896
+ const { rooms, users } = payload;
28897
+ ingestInCache({ rooms, users });
28898
+ callback({
28899
+ room: roomLinkedObject(rooms[0]),
28900
+ actorInternalId: payload.eventActor.userInternalId,
28901
+ });
28902
+ };
28903
+ return createEventSubscriber(client, 'room/onRoomParticipantStageJoined', 'room.participantStageJoined', filter);
28904
+ };
28905
+
28404
28906
  /**
28405
28907
  * ```js
28406
28908
  * import { onRoomTerminated } from '@amityco/ts-sdk'
@@ -28539,8 +29041,12 @@ const onRoomStopped = (callback) => {
28539
29041
  const onRoomParticipantRemoved = (callback) => {
28540
29042
  const client = getActiveClient();
28541
29043
  const filter = (payload) => {
28542
- ingestInCache(payload);
28543
- callback(payload.rooms[0]);
29044
+ const { rooms, users } = payload;
29045
+ ingestInCache({ rooms, users });
29046
+ callback({
29047
+ room: roomLinkedObject(rooms[0]),
29048
+ actorInternalId: payload.eventActor.userInternalId,
29049
+ });
28544
29050
  };
28545
29051
  return createEventSubscriber(client, 'room/onRoomParticipantRemoved', 'room.participantRemoved', filter);
28546
29052
  };
@@ -28593,6 +29099,68 @@ const onRoomParticipantRemovedLocal = (callback) => {
28593
29099
  return createEventSubscriber(client, 'room/onRoomParticipantRemoved', 'local.room.participantRemoved', filter);
28594
29100
  };
28595
29101
 
29102
+ var EnumRoomActions;
29103
+ (function (EnumRoomActions) {
29104
+ EnumRoomActions["OnRoomCreated"] = "OnRoomCreated";
29105
+ EnumRoomActions["OnRoomUpdated"] = "OnRoomUpdated";
29106
+ EnumRoomActions["OnRoomDeleted"] = "OnRoomDeleted";
29107
+ EnumRoomActions["OnRoomStartBroadcasting"] = "OnRoomStartBroadcasting";
29108
+ EnumRoomActions["OnRoomEndBroadcasting"] = "OnRoomEndBroadcasting";
29109
+ EnumRoomActions["OnRoomParticipantJoined"] = "OnRoomParticipantJoined";
29110
+ EnumRoomActions["OnRoomParticipantLeft"] = "OnRoomParticipantLeft";
29111
+ })(EnumRoomActions || (EnumRoomActions = {}));
29112
+
29113
+ const convertToRoomEventPayload = (eventHandler) => (callback) => eventHandler((payload) => {
29114
+ callback(payload.room);
29115
+ });
29116
+ // TODO: confirm related events
29117
+ const getRoomSubscription = () => [
29118
+ {
29119
+ fn: onRoomStartBroadcasting,
29120
+ action: EnumRoomActions.OnRoomStartBroadcasting,
29121
+ },
29122
+ {
29123
+ fn: onRoomEndBroadcasting,
29124
+ action: EnumRoomActions.OnRoomEndBroadcasting,
29125
+ },
29126
+ {
29127
+ fn: onRoomRecordedAvailable,
29128
+ action: EnumRoomActions.OnRoomUpdated,
29129
+ },
29130
+ {
29131
+ fn: onRoomWaitingReconnect,
29132
+ action: EnumRoomActions.OnRoomUpdated,
29133
+ },
29134
+ {
29135
+ fn: onRoomTerminated,
29136
+ action: EnumRoomActions.OnRoomUpdated,
29137
+ },
29138
+ {
29139
+ fn: convertToRoomEventPayload(onRoomParticipantJoined),
29140
+ action: EnumRoomActions.OnRoomUpdated,
29141
+ },
29142
+ {
29143
+ fn: convertToRoomEventPayload(onRoomParticipantLeft),
29144
+ action: EnumRoomActions.OnRoomUpdated,
29145
+ },
29146
+ {
29147
+ fn: convertToRoomEventPayload(onRoomParticipantRemoved),
29148
+ action: EnumRoomActions.OnRoomUpdated,
29149
+ },
29150
+ {
29151
+ fn: onRoomParticipantRemovedLocal,
29152
+ action: EnumRoomActions.OnRoomUpdated,
29153
+ },
29154
+ {
29155
+ fn: convertToRoomEventPayload(onRoomParticipantStageJoined),
29156
+ action: EnumRoomActions.OnRoomUpdated,
29157
+ },
29158
+ {
29159
+ fn: convertEventPayload(onRoomCoHostInviteAccepted, 'targetId', 'room'),
29160
+ action: EnumRoomActions.OnRoomUpdated,
29161
+ },
29162
+ ];
29163
+
28596
29164
  const getRoom = (roomId, callback) => {
28597
29165
  // TODO: add callbackDataSelector if there are linked object fields
28598
29166
  return liveObject(roomId, callback, '_id', getRoomById, [
@@ -28601,10 +29169,11 @@ const getRoom = (roomId, callback) => {
28601
29169
  onRoomWaitingReconnect,
28602
29170
  onRoomTerminated,
28603
29171
  onRoomRecordedAvailable,
28604
- onRoomParticipantJoined,
28605
- onRoomParticipantLeft,
28606
- onRoomParticipantRemoved,
29172
+ convertToRoomEventPayload(onRoomParticipantJoined),
29173
+ convertToRoomEventPayload(onRoomParticipantLeft),
29174
+ convertToRoomEventPayload(onRoomParticipantRemoved),
28607
29175
  onRoomParticipantRemovedLocal,
29176
+ convertToRoomEventPayload(onRoomParticipantStageJoined),
28608
29177
  convertEventPayload(onRoomCoHostInviteAccepted, 'targetId', 'room'),
28609
29178
  ], {
28610
29179
  callbackDataSelector: (data) => {
@@ -28629,17 +29198,6 @@ class RoomPaginationController extends PaginationController {
28629
29198
  }
28630
29199
  }
28631
29200
 
28632
- var EnumRoomActions;
28633
- (function (EnumRoomActions) {
28634
- EnumRoomActions["OnRoomCreated"] = "OnRoomCreated";
28635
- EnumRoomActions["OnRoomUpdated"] = "OnRoomUpdated";
28636
- EnumRoomActions["OnRoomDeleted"] = "OnRoomDeleted";
28637
- EnumRoomActions["OnRoomStartBroadcasting"] = "OnRoomStartBroadcasting";
28638
- EnumRoomActions["OnRoomEndBroadcasting"] = "OnRoomEndBroadcasting";
28639
- EnumRoomActions["OnRoomParticipantJoined"] = "OnRoomParticipantJoined";
28640
- EnumRoomActions["OnRoomParticipantLeft"] = "OnRoomParticipantLeft";
28641
- })(EnumRoomActions || (EnumRoomActions = {}));
28642
-
28643
29201
  class RoomQueryStreamController extends QueryStreamController {
28644
29202
  constructor(query, cacheKey, notifyChange, preparePayload) {
28645
29203
  super(query, cacheKey);
@@ -28688,22 +29246,6 @@ class RoomQueryStreamController extends QueryStreamController {
28688
29246
  }
28689
29247
  }
28690
29248
 
28691
- // TODO: confirm related events
28692
- const getRoomSubscription = () => [
28693
- {
28694
- fn: onRoomStartBroadcasting,
28695
- action: EnumRoomActions.OnRoomStartBroadcasting,
28696
- },
28697
- {
28698
- fn: onRoomEndBroadcasting,
28699
- action: EnumRoomActions.OnRoomEndBroadcasting,
28700
- },
28701
- {
28702
- fn: onRoomRecordedAvailable,
28703
- action: EnumRoomActions.OnRoomUpdated,
28704
- },
28705
- ];
28706
-
28707
29249
  class RoomLiveCollectionController extends LiveCollectionController {
28708
29250
  constructor(query, callback) {
28709
29251
  const queryStreamId = hash__default["default"](query);
@@ -28742,7 +29284,7 @@ class RoomLiveCollectionController extends LiveCollectionController {
28742
29284
  const data = this.applyFilter((_b = collection.data
28743
29285
  .map(id => pullFromCache(['room', 'get', id]))
28744
29286
  .filter(isNonNullable)
28745
- .map(({ data }) => data)) !== null && _b !== void 0 ? _b : []).map(room => room); // Since Room is same as InternalRoom, no transformation needed
29287
+ .map(({ data }) => data)) !== null && _b !== void 0 ? _b : []).map(roomLinkedObject);
28746
29288
  if (!this.shouldNotify(data) && origin === 'event')
28747
29289
  return;
28748
29290
  this.callback({
@@ -28835,6 +29377,10 @@ var index$b = /*#__PURE__*/Object.freeze({
28835
29377
  getRecordedUrl: getRecordedUrl,
28836
29378
  removeParticipant: removeParticipant,
28837
29379
  leaveRoom: leaveRoom,
29380
+ AmityRoomAnalytics: AmityRoomAnalytics,
29381
+ WatchSessionStorage: WatchSessionStorage,
29382
+ getWatchSessionStorage: getWatchSessionStorage,
29383
+ syncWatchSessions: syncWatchSessions,
28838
29384
  onRoomStartBroadcasting: onRoomStartBroadcasting,
28839
29385
  onRoomWaitingReconnect: onRoomWaitingReconnect,
28840
29386
  onRoomEndBroadcasting: onRoomEndBroadcasting,
@@ -28845,6 +29391,8 @@ var index$b = /*#__PURE__*/Object.freeze({
28845
29391
  onRoomCoHostInviteCanceled: onRoomCoHostInviteCanceled,
28846
29392
  onRoomParticipantJoined: onRoomParticipantJoined,
28847
29393
  onRoomParticipantLeft: onRoomParticipantLeft,
29394
+ onRoomParticipantStageLeft: onRoomParticipantStageLeft,
29395
+ onRoomParticipantStageJoined: onRoomParticipantStageJoined,
28848
29396
  onRoomTerminated: onRoomTerminated,
28849
29397
  onRoomCreated: onRoomCreated,
28850
29398
  onRoomUpdated: onRoomUpdated,
@@ -30348,85 +30896,6 @@ var index$7 = /*#__PURE__*/Object.freeze({
30348
30896
  getPoll: getPoll
30349
30897
  });
30350
30898
 
30351
- const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAARz+hmBgi8pJ\nQb8LeY41gtHhk+ACMwRfhsn7GqpqRQNG2qU0755mzZuVDUqjQMGSo8THJB7O+OJs\nflbZRkFXlFoFOVNw1UpNOgwEQZ6wB9oRwzepTJAfF1sVhm/o/ixvXh1zDFNDy6yZ\npXyiiJHUVxqyjllZhxnwdvjoVtDs6hW6awG09bB9nh/TTejlUKXoAgzqVwu/1QMu\nUVViET495elEe19aUarEy+oL2iKeXCEvqda/pWNBdbieFyJvvZ08HN8dPuT88wq2\njZLEAth1vrwQ2IAa4ktaLcBQdLJgIkrbDvAiVZ8lQAjS/bq5vXQikTGvoPlC5bbn\nvuOM/3eLAgMBAAECggEAVZ+peHAghq2QVj71nX5lxsNCKaCyYwixSJBpfouTt7Rz\nE6PpzMOXFi1W1o+I22jDakuSM2SOQKqI/u0QefB0r0O/KVk5NrZHXk0mkrdYtxOp\nUgaGyf8UvmjB+8VqHrNKyZdk9qtmbnNj01kTTcAtmE4H39zPR7eR/8Rul94vaZbs\nwCnKJS3mLT3JxyGug6lxanveKkjG+CKC1nJQYWaxCJxaFSzbwXQPvDhB+TvrIbee\npd5v4EAyEJohpr+T9oDGGJkb/KARBZCtwLyB976PKJwwBA8MRVL1i5QwawuMiMq5\nUtnOnbGKtCeFzaLbNU0Qi8bqyims84EQxC6DOu1fkQKBgQDdvsoBsEhsOXV7hlIJ\naEd0eSJZVkdqimxH8uGoMM2FeNaOrcB6yBXqTSP0R3OIyf8eaY6yjRvP30ZNXcll\n/gD3O1Mu6YmWQdt1W2WA6pKOsUuPXasf0pdOF7IiFZKlSabz5YHXFqwVuqm8loaj\nsXel3YWqPVdHiankE7tz+3ssnQKBgQDdqi4TNdD1MdEpihx19jr0QjUiXW3939FK\nqp30HESPEGDGQzXdmJgif9HhZb+cJSuWaHEbjgBrYahvgCF+y6LbEpOD+D/dmT+s\nDEAQaR84sah6dokwPjV8fjBSrcVFjCS+doxv0d3p/9OUEeyUhFrY03nxtIEYkLIE\n/Zvn37b4RwKBgQCLENVFe9XfsaVhQ5r9dV2iyTlmh7qgMZG5CbTFs12hQGhm8McO\n+Z7s41YSJCFr/yq1WwP4LJDtrBw99vyQr1zRsG35tNLp3gGRNzGQSQyC2uQFVHw2\np+7mNewsfhUK/gbrXNsyFnDz6635rPlhfbII3sWuP2wWXFqkxE9CbMwR7QKBgQC6\nawDMzxmo2/iYArrkyevSuEuPVxvFwpF1RgAI6C0QVCnPE38dmdN4UB7mfHekje4W\nVEercMURidPp0cxZolCYBQtilUjAyL0vqC3In1/Ogjq6oy3FEMxSop1pKxMY5j+Q\nnoqFD+6deLUrddeNH7J3X4LSr4dSbX4JjG+tlgt+yQKBgQCuwTL4hA6KqeInQ0Ta\n9VQX5Qr8hFlqJz1gpymi/k63tW/Ob8yedbg3WWNWyShwRMFYyY9S81ITFWM95uL6\nvF3x9rmRjwElJw9PMwVu6dmf/CO0Z1wzXSp2VVD12gbrUD/0/d7MUoJ9LgC8X8f/\nn0txLHYGHbx+nf95+JUg6lV3hg==\n-----END PRIVATE KEY-----";
30352
- /*
30353
- * The crypto algorithm used for importing key and signing string
30354
- */
30355
- const ALGORITHM = {
30356
- name: 'RSASSA-PKCS1-v1_5',
30357
- hash: { name: 'SHA-256' },
30358
- };
30359
- /*
30360
- * IMPORTANT!
30361
- * If you are recieving key from other platforms use an online tool to convert
30362
- * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
30363
- * PKCS1.
30364
- *
30365
- * If recieving from the platform, verify if it's already in the expected
30366
- * format. Otherwise the crypto.subtle.importKey will throw a DOMException
30367
- */
30368
- const PRIVATE_KEY_SIGNATURE = 'pkcs8';
30369
- /*
30370
- * Ensure that the private key in the .env follows this format
30371
- */
30372
- const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
30373
- const PEM_FOOTER = '-----END PRIVATE KEY-----';
30374
- /*
30375
- * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
30376
- * expects a base64 string. This util helps facilitate that process
30377
- */
30378
- function base64FromArrayBuffer(buffer) {
30379
- const uint8Array = new Uint8Array(buffer);
30380
- let binary = '';
30381
- uint8Array.forEach(byte => {
30382
- binary += String.fromCharCode(byte);
30383
- });
30384
- return jsBase64.btoa(binary);
30385
- }
30386
- /*
30387
- * Convert a string into an ArrayBuffer
30388
- * from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
30389
- *
30390
- * Solely used by the importPrivateKey method
30391
- */
30392
- function str2ab(str) {
30393
- const buf = new ArrayBuffer(str.length);
30394
- const bufView = new Uint8Array(buf);
30395
- for (let i = 0, strLen = str.length; i < strLen; i += 1) {
30396
- bufView[i] = str.charCodeAt(i);
30397
- }
30398
- return buf;
30399
- }
30400
- function importPrivateKey(pem) {
30401
- // fetch the part of the PEM string between header and footer
30402
- const pemContents = pem.substring(PEM_HEADER.length, pem.length - PEM_FOOTER.length);
30403
- /*
30404
- * base64 decode the string to get the binary data
30405
- */
30406
- const binaryDerString = jsBase64.atob(pemContents);
30407
- // convert from a binary string to an ArrayBuffer
30408
- const binaryDer = str2ab(binaryDerString);
30409
- return crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, binaryDer, ALGORITHM, false, ['sign']);
30410
- }
30411
- async function createSignature({ timestamp, streams, }) {
30412
- const dataStr = streams
30413
- .map(item => Object.keys(item)
30414
- .sort()
30415
- .map(key => `${key}=${item[key]}`)
30416
- .join('&'))
30417
- .join(';');
30418
- /*
30419
- * nonceStr needs to be unique for each request
30420
- */
30421
- const nonceStr = uuid__default["default"].v4();
30422
- const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
30423
- const encoder = new TextEncoder();
30424
- const data = encoder.encode(signStr);
30425
- const key = await importPrivateKey(privateKey);
30426
- const sign = await crypto.subtle.sign(ALGORITHM, key, data);
30427
- return { signature: base64FromArrayBuffer(sign), nonceStr };
30428
- }
30429
-
30430
30899
  async function syncUsage({ bufferCurrentUsage, getActiveStreams, updateUsage, dispose, }) {
30431
30900
  const streams = bufferCurrentUsage();
30432
30901
  if (!streams.length)
@@ -32648,24 +33117,30 @@ var index$2 = /*#__PURE__*/Object.freeze({
32648
33117
  * @param referenceType should be 'post'
32649
33118
  * @param reactionName that is the reaction name
32650
33119
  * @param streamId stream id
33120
+ * @param roomId room id
32651
33121
  * @returns a success boolean if the reaction was added
32652
33122
  *
32653
33123
  * @category Live Reaction API
32654
33124
  * @async
32655
33125
  */
32656
- const createReaction = async ({ referenceId, referenceType, reactionName, roomId, }) => {
33126
+ const createReaction = async ({ referenceId, referenceType, reactionName, streamId, roomId, }) => {
32657
33127
  const client = getActiveClient();
32658
33128
  client.log('live_reaction/createReaction', {
32659
33129
  referenceId,
32660
33130
  referenceType,
32661
33131
  reactionName,
33132
+ streamId,
33133
+ roomId,
32662
33134
  });
33135
+ if (!streamId && !roomId)
33136
+ throw new ASCError('You have to specify either streamId or roomId', 800110 /* Amity.ClientError.INVALID_PARAMETERS */, "error" /* Amity.ErrorLevel.ERROR */);
32663
33137
  const reactionSynceEngine = ReactionSyncEngine.getInstance();
32664
33138
  const reaction = {
32665
33139
  reactionName,
32666
33140
  referencePublicId: referenceId,
32667
33141
  referenceType,
32668
33142
  roomId,
33143
+ streamId,
32669
33144
  occurredAt: new Date().toISOString(),
32670
33145
  };
32671
33146
  reactionSynceEngine.createLiveReaction(reaction);
@@ -32855,15 +33330,32 @@ const updateEvent = async (eventId, bundle) => {
32855
33330
  const getEvent$1 = async (eventId) => {
32856
33331
  const client = getActiveClient();
32857
33332
  client.log('event/getEvent', eventId);
32858
- const { data: payload } = await client.http.get(`/api/v1/events/${eventId}`);
32859
- const data = prepareEventPayload(payload);
32860
- const cachedAt = client.cache && Date.now();
32861
- if (client.cache)
32862
- ingestInCache(data, { cachedAt });
32863
- return {
32864
- data: data.events.find(event => event.eventId === eventId),
32865
- cachedAt,
32866
- };
33333
+ try {
33334
+ const { data: payload } = await client.http.get(`/api/v1/events/${eventId}`);
33335
+ const data = prepareEventPayload(payload);
33336
+ const cachedAt = client.cache && Date.now();
33337
+ if (client.cache)
33338
+ ingestInCache(data, { cachedAt });
33339
+ return {
33340
+ data: data.events.find(event => event.eventId === eventId),
33341
+ cachedAt,
33342
+ };
33343
+ }
33344
+ catch (error) {
33345
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
33346
+ const event = getEvent$1.locally(eventId);
33347
+ if (!event)
33348
+ throw error;
33349
+ const deletedEvent = Object.assign(Object.assign({}, event === null || event === void 0 ? void 0 : event.data), { isDeleted: true });
33350
+ upsertInCache(['event', 'get', eventId], deletedEvent);
33351
+ const cachedAt = client.cache && Date.now();
33352
+ return {
33353
+ data: deletedEvent,
33354
+ cachedAt,
33355
+ };
33356
+ }
33357
+ throw error;
33358
+ }
32867
33359
  };
32868
33360
  /* end_public_function */
32869
33361
  /**