@amityco/ts-sdk 7.12.1-501d118.0 → 7.12.1-5cb139d3.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.
@@ -3,11 +3,15 @@ declare global {
3
3
  namespace Amity {
4
4
  type UsageDataModel = {
5
5
  sessionId: string;
6
- streamId: string;
6
+ roomId?: string;
7
7
  startTime: string;
8
8
  endTime: string;
9
9
  watchSeconds: number;
10
- resolution: string;
10
+ resolution?: string;
11
+ /**
12
+ * @deprecated Use `roomId` instead.
13
+ */
14
+ streamId?: string;
11
15
  };
12
16
  }
13
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"liveStreamPlayer.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/liveStreamPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC;AAEV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK,CAAC;QACd,KAAK,cAAc,GAAG;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,QAAQ,EAAE,MAAM,CAAC;YACjB,SAAS,EAAE,MAAM,CAAC;YAClB,OAAO,EAAE,MAAM,CAAC;YAChB,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;KACH;CACF"}
1
+ {"version":3,"file":"liveStreamPlayer.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/liveStreamPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC;AAEV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK,CAAC;QACd,KAAK,cAAc,GAAG;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,SAAS,EAAE,MAAM,CAAC;YAClB,OAAO,EAAE,MAAM,CAAC;YAChB,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB;;eAEG;YACH,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH;CACF"}
@@ -66,6 +66,7 @@ declare global {
66
66
  getLiveChat: () => Promise<Amity.Channel<'live'> | undefined>;
67
67
  createInvitation: (userId: string) => Promise<Amity.Cached<Amity.InternalInvitation[]>>;
68
68
  getInvitations: () => Promise<Amity.Invitation | undefined>;
69
+ analytics: () => Amity.RoomAnalytics;
69
70
  };
70
71
  type Room = Omit<InternalRoom, 'participants'> & RoomLinkedObject;
71
72
  type RoomLiveCollection = {
@@ -105,6 +106,34 @@ declare global {
105
106
  invitation?: Amity.Invitation;
106
107
  actorInternalId?: string;
107
108
  };
109
+ enum WatchSessionSyncStateEnum {
110
+ PENDING = "PENDING",
111
+ SYNCING = "SYNCING",
112
+ SYNCED = "SYNCED"
113
+ }
114
+ type WatchSessionSyncState = `${WatchSessionSyncStateEnum}`;
115
+ type WatchSessionEntity = {
116
+ sessionId: string;
117
+ roomId: string;
118
+ watchSeconds: number;
119
+ startTime: Date;
120
+ endTime?: Date | null;
121
+ syncState: WatchSessionSyncState;
122
+ syncedAt?: Date | null;
123
+ retryCount: number;
124
+ };
125
+ type WatchSessionData = {
126
+ sessionId: string;
127
+ roomId: string;
128
+ watchSeconds: number;
129
+ startTime: string;
130
+ endTime?: string;
131
+ };
132
+ interface RoomAnalytics {
133
+ createWatchSession(startedAt: Date): Promise<string>;
134
+ updateWatchSession(sessionId: string, duration: number, endedAt: Date): Promise<void>;
135
+ syncPendingWatchSessions(): void;
136
+ }
108
137
  }
109
138
  }
110
139
  //# sourceMappingURL=room.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/room.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../../src/@types/domains/room.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs.js CHANGED
@@ -10632,12 +10632,15 @@ const blockUser = async (userId) => {
10632
10632
  const { data } = await client.http.post(`/api/v4/me/user-blocks/${userId}`);
10633
10633
  const cachedAt = client.cache && Date.now();
10634
10634
  const { follows, followCounts } = data;
10635
- const followStatus = { follows };
10635
+ const blockedFollowStatus = { follows };
10636
10636
  if (client.cache) {
10637
- ingestInCache(followStatus, { cachedAt });
10637
+ ingestInCache(blockedFollowStatus, { cachedAt });
10638
10638
  upsertInCache(['followInfo', 'get', userId], followCounts[0], { cachedAt });
10639
10639
  }
10640
- const payload = prepareFollowStatusPayload(followStatus);
10640
+ const blockedUnfollowStatus = {
10641
+ follows: follows.map(follow => follow.status === 'blocked' ? Object.assign(Object.assign({}, follow), { to: follow.from, from: follow.to }) : follow),
10642
+ };
10643
+ const payload = prepareFollowStatusPayload(blockedUnfollowStatus);
10641
10644
  fireEvent('local.follow.unfollowed', payload);
10642
10645
  return data;
10643
10646
  };
@@ -12542,6 +12545,414 @@ const getInvitation = async (params) => {
12542
12545
  };
12543
12546
  /* end_public_function */
12544
12547
 
12548
+ /**
12549
+ * WatchSessionStorage manages watch session data in memory
12550
+ * Similar to UsageCollector for stream watch minutes
12551
+ */
12552
+ class WatchSessionStorage {
12553
+ constructor() {
12554
+ this.sessions = new Map();
12555
+ }
12556
+ /**
12557
+ * Add a new watch session
12558
+ */
12559
+ addSession(session) {
12560
+ this.sessions.set(session.sessionId, session);
12561
+ }
12562
+ /**
12563
+ * Get a watch session by sessionId
12564
+ */
12565
+ getSession(sessionId) {
12566
+ return this.sessions.get(sessionId);
12567
+ }
12568
+ /**
12569
+ * Update a watch session
12570
+ */
12571
+ updateSession(sessionId, updates) {
12572
+ const session = this.sessions.get(sessionId);
12573
+ if (session) {
12574
+ this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
12575
+ }
12576
+ }
12577
+ /**
12578
+ * Get all sessions with a specific sync state
12579
+ */
12580
+ getSessionsByState(state) {
12581
+ return Array.from(this.sessions.values()).filter(session => session.syncState === state);
12582
+ }
12583
+ /**
12584
+ * Delete a session
12585
+ */
12586
+ deleteSession(sessionId) {
12587
+ this.sessions.delete(sessionId);
12588
+ }
12589
+ /**
12590
+ * Get all pending sessions
12591
+ */
12592
+ getPendingSessions() {
12593
+ return this.getSessionsByState('PENDING');
12594
+ }
12595
+ /**
12596
+ * Get all syncing sessions
12597
+ */
12598
+ getSyncingSessions() {
12599
+ return this.getSessionsByState('SYNCING');
12600
+ }
12601
+ }
12602
+ // Singleton instance
12603
+ let storageInstance = null;
12604
+ const getWatchSessionStorage = () => {
12605
+ if (!storageInstance) {
12606
+ storageInstance = new WatchSessionStorage();
12607
+ }
12608
+ return storageInstance;
12609
+ };
12610
+
12611
+ 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=";
12612
+ /*
12613
+ * The crypto algorithm used for importing key and signing string
12614
+ */
12615
+ const ALGORITHM = {
12616
+ name: 'RSASSA-PKCS1-v1_5',
12617
+ hash: { name: 'SHA-256' },
12618
+ };
12619
+ /*
12620
+ * IMPORTANT!
12621
+ * If you are recieving key from other platforms use an online tool to convert
12622
+ * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
12623
+ * PKCS1.
12624
+ *
12625
+ * If recieving from the platform, verify if it's already in the expected
12626
+ * format. Otherwise the crypto.subtle.importKey will throw a DOMException
12627
+ */
12628
+ const PRIVATE_KEY_SIGNATURE = 'pkcs8';
12629
+ /*
12630
+ * Ensure that the private key in the .env follows this format
12631
+ */
12632
+ const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
12633
+ const PEM_FOOTER = '-----END PRIVATE KEY-----';
12634
+ /*
12635
+ * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
12636
+ * expects a base64 string. This util helps facilitate that process
12637
+ */
12638
+ function base64FromArrayBuffer(buffer) {
12639
+ const uint8Array = new Uint8Array(buffer);
12640
+ let binary = '';
12641
+ uint8Array.forEach(byte => {
12642
+ binary += String.fromCharCode(byte);
12643
+ });
12644
+ return jsBase64.btoa(binary);
12645
+ }
12646
+ /*
12647
+ * Encode ASN.1 length field
12648
+ */
12649
+ function encodeLength(length) {
12650
+ if (length < 128) {
12651
+ return new Uint8Array([length]);
12652
+ }
12653
+ if (length < 256) {
12654
+ return new Uint8Array([0x81, length]);
12655
+ }
12656
+ // eslint-disable-next-line no-bitwise
12657
+ return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
12658
+ }
12659
+ /*
12660
+ * Convert PKCS1 private key to PKCS8 format
12661
+ * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
12662
+ * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
12663
+ */
12664
+ function pkcs1ToPkcs8(pkcs1) {
12665
+ // Algorithm identifier for RSA
12666
+ const algorithmIdentifier = new Uint8Array([
12667
+ 0x30,
12668
+ 0x0d,
12669
+ 0x06,
12670
+ 0x09,
12671
+ 0x2a,
12672
+ 0x86,
12673
+ 0x48,
12674
+ 0x86,
12675
+ 0xf7,
12676
+ 0x0d,
12677
+ 0x01,
12678
+ 0x01,
12679
+ 0x01,
12680
+ 0x05,
12681
+ 0x00, // NULL
12682
+ ]);
12683
+ // Version (INTEGER 0)
12684
+ const version = new Uint8Array([0x02, 0x01, 0x00]);
12685
+ // OCTET STRING tag + length + pkcs1 data
12686
+ const octetStringTag = 0x04;
12687
+ const octetStringLength = encodeLength(pkcs1.length);
12688
+ // Calculate total content length (version + algorithm + octet string)
12689
+ const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
12690
+ // SEQUENCE tag + length
12691
+ const sequenceTag = 0x30;
12692
+ const sequenceLength = encodeLength(contentLength);
12693
+ // Build the PKCS8 structure
12694
+ const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
12695
+ let offset = 0;
12696
+ pkcs8[offset] = sequenceTag;
12697
+ offset += 1;
12698
+ pkcs8.set(sequenceLength, offset);
12699
+ offset += sequenceLength.length;
12700
+ pkcs8.set(version, offset);
12701
+ offset += version.length;
12702
+ pkcs8.set(algorithmIdentifier, offset);
12703
+ offset += algorithmIdentifier.length;
12704
+ pkcs8[offset] = octetStringTag;
12705
+ offset += 1;
12706
+ pkcs8.set(octetStringLength, offset);
12707
+ offset += octetStringLength.length;
12708
+ pkcs8.set(pkcs1, offset);
12709
+ return pkcs8;
12710
+ }
12711
+ async function importPrivateKey(keyString) {
12712
+ // Remove PEM headers if present and any whitespace
12713
+ let base64Key = keyString;
12714
+ if (keyString.includes(PEM_HEADER)) {
12715
+ base64Key = keyString
12716
+ .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
12717
+ .replace(/\s/g, '');
12718
+ }
12719
+ else {
12720
+ base64Key = keyString.replace(/\s/g, '');
12721
+ }
12722
+ // Base64 decode to get binary data
12723
+ const binaryDerString = jsBase64.atob(base64Key);
12724
+ // Convert to Uint8Array for manipulation
12725
+ const pkcs1 = new Uint8Array(binaryDerString.length);
12726
+ for (let i = 0; i < binaryDerString.length; i += 1) {
12727
+ pkcs1[i] = binaryDerString.charCodeAt(i);
12728
+ }
12729
+ // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
12730
+ const pkcs8 = pkcs1ToPkcs8(pkcs1);
12731
+ // Import the key
12732
+ const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
12733
+ return key;
12734
+ }
12735
+ async function createSignature({ timestamp, rooms, }) {
12736
+ const dataStr = rooms
12737
+ .map(item => Object.keys(item)
12738
+ .sort()
12739
+ .map(key => `${key}=${item[key]}`)
12740
+ .join('&'))
12741
+ .join(';');
12742
+ /*
12743
+ * nonceStr needs to be unique for each request
12744
+ */
12745
+ const nonceStr = uuid__default["default"].v4();
12746
+ const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
12747
+ const encoder = new TextEncoder();
12748
+ const data = encoder.encode(signStr);
12749
+ const key = await importPrivateKey(privateKey);
12750
+ const sign = await crypto.subtle.sign(ALGORITHM, key, data);
12751
+ return { signature: base64FromArrayBuffer(sign), nonceStr };
12752
+ }
12753
+
12754
+ /**
12755
+ * Sync pending watch sessions to backend
12756
+ * This function implements the full sync flow with network resilience
12757
+ */
12758
+ async function syncWatchSessions() {
12759
+ const storage = getWatchSessionStorage();
12760
+ // Get all pending sessions
12761
+ const pendingSessions = storage.getPendingSessions();
12762
+ if (pendingSessions.length === 0) {
12763
+ return true;
12764
+ }
12765
+ try {
12766
+ const timestamp = new Date().toISOString();
12767
+ // Convert sessions to API format - always include all fields like syncUsage does
12768
+ const rooms = pendingSessions.map(session => ({
12769
+ sessionId: session.sessionId,
12770
+ roomId: session.roomId,
12771
+ watchSeconds: session.watchSeconds,
12772
+ startTime: session.startTime.toISOString(),
12773
+ endTime: session.endTime ? session.endTime.toISOString() : '',
12774
+ }));
12775
+ // Create signature (reuse from stream feature) - pass directly like syncUsage
12776
+ const signatureData = await createSignature({
12777
+ timestamp,
12778
+ rooms,
12779
+ });
12780
+ if (!signatureData || !signatureData.signature) {
12781
+ throw new Error('Signature is undefined');
12782
+ }
12783
+ // Update sync state to SYNCING
12784
+ pendingSessions.forEach(session => {
12785
+ storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
12786
+ });
12787
+ const payload = {
12788
+ signature: signatureData.signature,
12789
+ nonceStr: signatureData.nonceStr,
12790
+ timestamp,
12791
+ rooms,
12792
+ };
12793
+ const client = getActiveClient();
12794
+ // Send to backend
12795
+ await client.http.post('/api/v3/user-event/room', payload);
12796
+ // Success - update to SYNCED
12797
+ pendingSessions.forEach(session => {
12798
+ storage.updateSession(session.sessionId, {
12799
+ syncState: 'SYNCED',
12800
+ syncedAt: new Date(),
12801
+ });
12802
+ });
12803
+ return true;
12804
+ }
12805
+ catch (err) {
12806
+ console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
12807
+ // Failure - update back to PENDING and increment retry count
12808
+ pendingSessions.forEach(session => {
12809
+ const currentSession = storage.getSession(session.sessionId);
12810
+ if (currentSession) {
12811
+ const newRetryCount = currentSession.retryCount + 1;
12812
+ if (newRetryCount >= 3) {
12813
+ // Delete session if retry count exceeds 3
12814
+ storage.deleteSession(session.sessionId);
12815
+ }
12816
+ else {
12817
+ // Update to PENDING with incremented retry count
12818
+ storage.updateSession(session.sessionId, {
12819
+ syncState: 'PENDING',
12820
+ retryCount: newRetryCount,
12821
+ });
12822
+ }
12823
+ }
12824
+ });
12825
+ return false;
12826
+ }
12827
+ }
12828
+
12829
+ /**
12830
+ * Room statuses that are considered watchable
12831
+ */
12832
+ const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
12833
+ /**
12834
+ * Generate a random jitter delay between 5 and 30 seconds
12835
+ */
12836
+ const getJitterDelay = () => {
12837
+ const minDelay = 5000; // 5 seconds
12838
+ const maxDelay = 30000; // 30 seconds
12839
+ return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
12840
+ };
12841
+ /**
12842
+ * Wait for network connection with timeout
12843
+ * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
12844
+ * @returns Promise that resolves when network is available or timeout is reached
12845
+ */
12846
+ const waitForNetwork = (maxWaitTime = 60000) => {
12847
+ return new Promise(resolve => {
12848
+ // Simple check - if navigator.onLine is available, use it
12849
+ // Otherwise, assume network is available
12850
+ if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
12851
+ resolve();
12852
+ return;
12853
+ }
12854
+ const startTime = Date.now();
12855
+ const checkInterval = 1000; // 1 second
12856
+ const checkConnection = () => {
12857
+ if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
12858
+ resolve();
12859
+ }
12860
+ else {
12861
+ setTimeout(checkConnection, checkInterval);
12862
+ }
12863
+ };
12864
+ checkConnection();
12865
+ });
12866
+ };
12867
+ /**
12868
+ * AmityRoomAnalytics provides analytics capabilities for room watch sessions
12869
+ */
12870
+ class AmityRoomAnalytics {
12871
+ constructor(room) {
12872
+ this.storage = getWatchSessionStorage();
12873
+ this.client = getActiveClient();
12874
+ this.room = room;
12875
+ }
12876
+ /**
12877
+ * Create a new watch session for the current room
12878
+ * @param startedAt The timestamp when watching started
12879
+ * @returns Promise<string> sessionId unique identifier for this watch session
12880
+ * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
12881
+ */
12882
+ async createWatchSession(startedAt) {
12883
+ // Validate room status
12884
+ if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
12885
+ throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
12886
+ }
12887
+ // Generate session ID with prefix
12888
+ const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
12889
+ const sessionId = prefix + uuid__default["default"].v4();
12890
+ // Create watch session entity
12891
+ const session = {
12892
+ sessionId,
12893
+ roomId: this.room.roomId,
12894
+ watchSeconds: 0,
12895
+ startTime: startedAt,
12896
+ endTime: null,
12897
+ syncState: 'PENDING',
12898
+ syncedAt: null,
12899
+ retryCount: 0,
12900
+ };
12901
+ // Persist to storage
12902
+ this.storage.addSession(session);
12903
+ return sessionId;
12904
+ }
12905
+ /**
12906
+ * Update an existing watch session with duration
12907
+ * @param sessionId The unique identifier of the watch session
12908
+ * @param duration The total watch duration in seconds
12909
+ * @param endedAt The timestamp when this update occurred
12910
+ * @returns Promise<void> Completion status
12911
+ */
12912
+ async updateWatchSession(sessionId, duration, endedAt) {
12913
+ const session = this.storage.getSession(sessionId);
12914
+ if (!session) {
12915
+ throw new Error(`Watch session ${sessionId} not found`);
12916
+ }
12917
+ // Update session
12918
+ this.storage.updateSession(sessionId, {
12919
+ watchSeconds: duration,
12920
+ endTime: endedAt,
12921
+ });
12922
+ }
12923
+ /**
12924
+ * Sync all pending watch sessions to backend
12925
+ * This function uses jitter delay and handles network resilience
12926
+ */
12927
+ syncPendingWatchSessions() {
12928
+ // Execute with jitter delay (5-30 seconds)
12929
+ const jitterDelay = getJitterDelay();
12930
+ this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
12931
+ setTimeout(async () => {
12932
+ this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
12933
+ try {
12934
+ // Reset any SYNCING sessions back to PENDING
12935
+ const syncingSessions = this.storage.getSyncingSessions();
12936
+ this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
12937
+ syncingSessions.forEach(session => {
12938
+ this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
12939
+ });
12940
+ // Wait for network connection (max 60 seconds)
12941
+ await waitForNetwork(60000);
12942
+ this.client.log('room/RoomAnalytics: Network available');
12943
+ // Sync pending sessions
12944
+ this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
12945
+ await syncWatchSessions();
12946
+ this.client.log('room/RoomAnalytics: syncWatchSessions completed');
12947
+ }
12948
+ catch (error) {
12949
+ // Error is already handled in syncWatchSessions
12950
+ console.error('Failed to sync watch sessions:', error);
12951
+ }
12952
+ }, jitterDelay);
12953
+ }
12954
+ }
12955
+
12545
12956
  const roomLinkedObject = (room) => {
12546
12957
  return Object.assign(Object.assign({}, room), { get post() {
12547
12958
  var _a;
@@ -12588,6 +12999,9 @@ const roomLinkedObject = (room) => {
12588
12999
  type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
12589
13000
  });
12590
13001
  return data;
13002
+ }, analytics() {
13003
+ // Use 'this' to avoid creating a new room object
13004
+ return new AmityRoomAnalytics(this);
12591
13005
  } });
12592
13006
  };
12593
13007
 
@@ -28966,6 +29380,10 @@ var index$b = /*#__PURE__*/Object.freeze({
28966
29380
  getRecordedUrl: getRecordedUrl,
28967
29381
  removeParticipant: removeParticipant,
28968
29382
  leaveRoom: leaveRoom,
29383
+ AmityRoomAnalytics: AmityRoomAnalytics,
29384
+ WatchSessionStorage: WatchSessionStorage,
29385
+ getWatchSessionStorage: getWatchSessionStorage,
29386
+ syncWatchSessions: syncWatchSessions,
28969
29387
  onRoomStartBroadcasting: onRoomStartBroadcasting,
28970
29388
  onRoomWaitingReconnect: onRoomWaitingReconnect,
28971
29389
  onRoomEndBroadcasting: onRoomEndBroadcasting,
@@ -30481,85 +30899,6 @@ var index$7 = /*#__PURE__*/Object.freeze({
30481
30899
  getPoll: getPoll
30482
30900
  });
30483
30901
 
30484
- 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-----";
30485
- /*
30486
- * The crypto algorithm used for importing key and signing string
30487
- */
30488
- const ALGORITHM = {
30489
- name: 'RSASSA-PKCS1-v1_5',
30490
- hash: { name: 'SHA-256' },
30491
- };
30492
- /*
30493
- * IMPORTANT!
30494
- * If you are recieving key from other platforms use an online tool to convert
30495
- * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
30496
- * PKCS1.
30497
- *
30498
- * If recieving from the platform, verify if it's already in the expected
30499
- * format. Otherwise the crypto.subtle.importKey will throw a DOMException
30500
- */
30501
- const PRIVATE_KEY_SIGNATURE = 'pkcs8';
30502
- /*
30503
- * Ensure that the private key in the .env follows this format
30504
- */
30505
- const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
30506
- const PEM_FOOTER = '-----END PRIVATE KEY-----';
30507
- /*
30508
- * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
30509
- * expects a base64 string. This util helps facilitate that process
30510
- */
30511
- function base64FromArrayBuffer(buffer) {
30512
- const uint8Array = new Uint8Array(buffer);
30513
- let binary = '';
30514
- uint8Array.forEach(byte => {
30515
- binary += String.fromCharCode(byte);
30516
- });
30517
- return jsBase64.btoa(binary);
30518
- }
30519
- /*
30520
- * Convert a string into an ArrayBuffer
30521
- * from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
30522
- *
30523
- * Solely used by the importPrivateKey method
30524
- */
30525
- function str2ab(str) {
30526
- const buf = new ArrayBuffer(str.length);
30527
- const bufView = new Uint8Array(buf);
30528
- for (let i = 0, strLen = str.length; i < strLen; i += 1) {
30529
- bufView[i] = str.charCodeAt(i);
30530
- }
30531
- return buf;
30532
- }
30533
- function importPrivateKey(pem) {
30534
- // fetch the part of the PEM string between header and footer
30535
- const pemContents = pem.substring(PEM_HEADER.length, pem.length - PEM_FOOTER.length);
30536
- /*
30537
- * base64 decode the string to get the binary data
30538
- */
30539
- const binaryDerString = jsBase64.atob(pemContents);
30540
- // convert from a binary string to an ArrayBuffer
30541
- const binaryDer = str2ab(binaryDerString);
30542
- return crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, binaryDer, ALGORITHM, false, ['sign']);
30543
- }
30544
- async function createSignature({ timestamp, streams, }) {
30545
- const dataStr = streams
30546
- .map(item => Object.keys(item)
30547
- .sort()
30548
- .map(key => `${key}=${item[key]}`)
30549
- .join('&'))
30550
- .join(';');
30551
- /*
30552
- * nonceStr needs to be unique for each request
30553
- */
30554
- const nonceStr = uuid__default["default"].v4();
30555
- const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
30556
- const encoder = new TextEncoder();
30557
- const data = encoder.encode(signStr);
30558
- const key = await importPrivateKey(privateKey);
30559
- const sign = await crypto.subtle.sign(ALGORITHM, key, data);
30560
- return { signature: base64FromArrayBuffer(sign), nonceStr };
30561
- }
30562
-
30563
30902
  async function syncUsage({ bufferCurrentUsage, getActiveStreams, updateUsage, dispose, }) {
30564
30903
  const streams = bufferCurrentUsage();
30565
30904
  if (!streams.length)