@multiplayer-app/session-recorder-react-native 1.2.37 → 1.3.2

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 (54) hide show
  1. package/lib/module/config/constants.js +3 -0
  2. package/lib/module/config/constants.js.map +1 -1
  3. package/lib/module/config/defaults.js +2 -1
  4. package/lib/module/config/defaults.js.map +1 -1
  5. package/lib/module/config/session-recorder.js +2 -1
  6. package/lib/module/config/session-recorder.js.map +1 -1
  7. package/lib/module/recorder/index.js +7 -18
  8. package/lib/module/recorder/index.js.map +1 -1
  9. package/lib/module/services/api.service.js +2 -2
  10. package/lib/module/services/api.service.js.map +1 -1
  11. package/lib/module/services/socket.service.js +176 -0
  12. package/lib/module/services/socket.service.js.map +1 -0
  13. package/lib/module/session-recorder.js +67 -11
  14. package/lib/module/session-recorder.js.map +1 -1
  15. package/lib/module/types/session-recorder.js.map +1 -1
  16. package/lib/module/types/session.js.map +1 -1
  17. package/lib/module/utils/logger.js +1 -1
  18. package/lib/typescript/src/config/constants.d.ts +3 -0
  19. package/lib/typescript/src/config/constants.d.ts.map +1 -1
  20. package/lib/typescript/src/config/defaults.d.ts.map +1 -1
  21. package/lib/typescript/src/config/session-recorder.d.ts.map +1 -1
  22. package/lib/typescript/src/recorder/index.d.ts +3 -4
  23. package/lib/typescript/src/recorder/index.d.ts.map +1 -1
  24. package/lib/typescript/src/services/api.service.d.ts +10 -4
  25. package/lib/typescript/src/services/api.service.d.ts.map +1 -1
  26. package/lib/typescript/src/services/socket.service.d.ts +39 -0
  27. package/lib/typescript/src/services/socket.service.d.ts.map +1 -0
  28. package/lib/typescript/src/session-recorder.d.ts +17 -1
  29. package/lib/typescript/src/session-recorder.d.ts.map +1 -1
  30. package/lib/typescript/src/types/session-recorder.d.ts +12 -1
  31. package/lib/typescript/src/types/session-recorder.d.ts.map +1 -1
  32. package/lib/typescript/src/types/session.d.ts +1 -2
  33. package/lib/typescript/src/types/session.d.ts.map +1 -1
  34. package/package.json +2 -2
  35. package/src/config/constants.ts +6 -0
  36. package/src/config/defaults.ts +29 -27
  37. package/src/config/session-recorder.ts +2 -0
  38. package/src/recorder/index.ts +8 -21
  39. package/src/services/api.service.ts +15 -6
  40. package/src/services/socket.service.ts +225 -0
  41. package/src/session-recorder.ts +71 -11
  42. package/src/types/session-recorder.ts +14 -1
  43. package/src/types/session.ts +3 -2
  44. package/src/utils/logger.ts +1 -1
  45. package/lib/module/recorder/eventExporter.js +0 -130
  46. package/lib/module/recorder/eventExporter.js.map +0 -1
  47. package/lib/module/types/client-type.enum.js +0 -9
  48. package/lib/module/types/client-type.enum.js.map +0 -1
  49. package/lib/typescript/src/recorder/eventExporter.d.ts +0 -25
  50. package/lib/typescript/src/recorder/eventExporter.d.ts.map +0 -1
  51. package/lib/typescript/src/types/client-type.enum.d.ts +0 -6
  52. package/lib/typescript/src/types/client-type.enum.d.ts.map +0 -1
  53. package/src/recorder/eventExporter.ts +0 -150
  54. package/src/types/client-type.enum.ts +0 -5
@@ -2,6 +2,7 @@ import {
2
2
  type IResourceAttributes,
3
3
  type ISessionAttributes,
4
4
  type ApiServiceConfig,
5
+ type IUserAttributes,
5
6
  } from '../types';
6
7
 
7
8
  export interface StartSessionRequest {
@@ -9,6 +10,7 @@ export interface StartSessionRequest {
9
10
  stoppedAt?: string | number;
10
11
  sessionAttributes?: ISessionAttributes;
11
12
  resourceAttributes?: IResourceAttributes;
13
+ userAttributes?: IUserAttributes;
12
14
  debugSessionData?: Record<string, any>;
13
15
  tags?: { key?: string; value: string }[];
14
16
  }
@@ -18,6 +20,13 @@ export interface StopSessionRequest {
18
20
  stoppedAt: string | number;
19
21
  }
20
22
 
23
+
24
+ export interface CheckRemoteSessionRequest {
25
+ sessionAttributes?: ISessionAttributes
26
+ resourceAttributes?: IResourceAttributes
27
+ userAttributes?: IUserAttributes
28
+ }
29
+
21
30
  export class ApiService {
22
31
  private config?: ApiServiceConfig;
23
32
  private baseUrl: string = 'https://api.multiplayer.app';
@@ -200,17 +209,17 @@ export class ApiService {
200
209
  }
201
210
 
202
211
  /**
203
- * Check debug session should be started remotely
204
- */
212
+ * Check debug session should be started remotely
213
+ */
205
214
  async checkRemoteSession(
206
- requestBody: StartSessionRequest,
207
- signal?: AbortSignal
215
+ requestBody: CheckRemoteSessionRequest,
216
+ signal?: AbortSignal,
208
217
  ): Promise<{ state: 'START' | 'STOP' }> {
209
218
  return this.makeRequest(
210
219
  '/remote-debug-session/check',
211
220
  'POST',
212
221
  requestBody,
213
- signal
214
- );
222
+ signal,
223
+ )
215
224
  }
216
225
  }
@@ -0,0 +1,225 @@
1
+ import io, { Socket } from 'socket.io-client';
2
+ import { Observable } from 'lib0/observable';
3
+
4
+ import { type ISession, type IUserAttributes } from '../types';
5
+ import { logger } from '../utils';
6
+
7
+ import {
8
+ SESSION_ADD_EVENT,
9
+ SESSION_AUTO_CREATED,
10
+ SESSION_STOPPED_EVENT,
11
+ SESSION_SUBSCRIBE_EVENT,
12
+ SESSION_UNSUBSCRIBE_EVENT,
13
+ SOCKET_SET_USER_EVENT,
14
+ REMOTE_SESSION_RECORDING_START,
15
+ REMOTE_SESSION_RECORDING_STOP,
16
+ SESSION_STARTED_EVENT,
17
+ } from '../config';
18
+
19
+ const MAX_RECONNECTION_ATTEMPTS = 2;
20
+
21
+ export type SocketServiceEvents =
22
+ | typeof SESSION_STOPPED_EVENT
23
+ | typeof SESSION_AUTO_CREATED
24
+ | typeof REMOTE_SESSION_RECORDING_START
25
+ | typeof REMOTE_SESSION_RECORDING_STOP;
26
+
27
+ export interface SocketServiceOptions {
28
+ apiKey: string;
29
+ socketUrl: string;
30
+ keepAlive?: boolean;
31
+ }
32
+
33
+ export class SocketService extends Observable<SocketServiceEvents> {
34
+ private socket: Socket | null = null;
35
+ private queue: any[] = [];
36
+ private isConnecting: boolean = false;
37
+ private isConnected: boolean = false;
38
+ private attempts: number = 0;
39
+ private sessionId: string | null = null;
40
+ private options: SocketServiceOptions;
41
+
42
+ constructor() {
43
+ super();
44
+ this.options = {
45
+ apiKey: '',
46
+ socketUrl: '',
47
+ keepAlive: false,
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Initialize the socket service
53
+ * @param config - Socket service configuration
54
+ */
55
+ public init(config: SocketServiceOptions): void {
56
+ this.options = {
57
+ ...this.options,
58
+ ...config,
59
+ };
60
+ if (
61
+ this.options.keepAlive &&
62
+ this.options.socketUrl &&
63
+ this.options.apiKey
64
+ ) {
65
+ this._initConnection();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Update the socket service configuration
71
+ * @param config - Partial configuration to update
72
+ */
73
+ public updateConfigs(config: Partial<SocketServiceOptions>): void {
74
+ // If any config changed, reconnect if connected
75
+ const hasChanges = Object.keys(config).some(
76
+ (key) => {
77
+ const typedKey = key as keyof SocketServiceOptions;
78
+ return (
79
+ config[typedKey] !== undefined &&
80
+ config[typedKey] !== this.options[typedKey]
81
+ );
82
+ }
83
+ );
84
+
85
+ if (hasChanges) {
86
+ this.options = { ...this.options, ...config };
87
+ if (this.socket?.connected) {
88
+ this.close().then(() => {
89
+ if (
90
+ this.options.keepAlive &&
91
+ this.options.socketUrl &&
92
+ this.options.apiKey
93
+ ) {
94
+ this._initConnection();
95
+ }
96
+ });
97
+ }
98
+ }
99
+ }
100
+
101
+ private _initConnection(): void {
102
+ if (this.isConnecting || this.isConnected) return;
103
+ this.attempts++;
104
+ this.isConnecting = true;
105
+ this.socket = io(this.options.socketUrl, {
106
+ path: '/v0/radar/ws',
107
+ auth: {
108
+ 'x-api-key': this.options.apiKey,
109
+ },
110
+ reconnectionAttempts: 2,
111
+ transports: ['websocket'],
112
+ });
113
+
114
+ this.socket.on('ready', () => {
115
+ this.isConnecting = false;
116
+ this.isConnected = true;
117
+ logger.info('SocketService', 'Connected to server');
118
+ this.flushQueue();
119
+ });
120
+
121
+ this.socket.on('disconnect', (_err: any) => {
122
+ this.isConnecting = false;
123
+ this.isConnected = false;
124
+ logger.info('SocketService', 'Disconnected from server');
125
+ });
126
+
127
+ this.socket.on('connect_error', (err: any) => {
128
+ this.isConnecting = false;
129
+ this.isConnected = false;
130
+ this.checkReconnectionAttempts();
131
+ logger.error('SocketService', 'Error connecting to server', err);
132
+ });
133
+
134
+ this.socket.on(SESSION_STOPPED_EVENT, (data: any) => {
135
+ this.emit(SESSION_STOPPED_EVENT, [data]);
136
+ });
137
+
138
+ this.socket.on(SESSION_AUTO_CREATED, (data: any) => {
139
+ this.emit(SESSION_AUTO_CREATED, [data]);
140
+ });
141
+
142
+ this.socket.on(REMOTE_SESSION_RECORDING_START, (data: any) => {
143
+ this.emit(REMOTE_SESSION_RECORDING_START, [data]);
144
+ });
145
+
146
+ this.socket.on(REMOTE_SESSION_RECORDING_STOP, (data: any) => {
147
+ this.emit(REMOTE_SESSION_RECORDING_STOP, [data]);
148
+ });
149
+ }
150
+
151
+ private checkReconnectionAttempts(): void {
152
+ if (this.attempts >= MAX_RECONNECTION_ATTEMPTS) {
153
+ this.flushQueue();
154
+ }
155
+ }
156
+
157
+ private emitSocketEvent(name: string, data: any): void {
158
+ if (this.socket?.connected) {
159
+ this.socket.emit(name, data)
160
+ } else {
161
+ this.queue.push({ data, name })
162
+ this._initConnection()
163
+ }
164
+ }
165
+
166
+ private flushQueue(): void {
167
+ while (this.queue.length > 0 && this.socket?.connected) {
168
+ const event = this.queue.shift();
169
+ if (!event) continue;
170
+
171
+ if (this.socket?.connected) {
172
+ this.socket.emit(event.name, event.data);
173
+ }
174
+ }
175
+ }
176
+
177
+
178
+ public send(event: any): void {
179
+ this.emitSocketEvent(SESSION_ADD_EVENT, event)
180
+ }
181
+
182
+
183
+ public subscribeToSession(session: ISession): void {
184
+ this.sessionId = session.shortId || session._id;
185
+ const payload = {
186
+ projectId: session.project,
187
+ workspaceId: session.workspace,
188
+ debugSessionId: this.sessionId,
189
+ sessionType: session.creationType,
190
+ };
191
+ this.emitSocketEvent(SESSION_SUBSCRIBE_EVENT, payload)
192
+ this.emitSocketEvent(SESSION_STARTED_EVENT, { debugSessionId: this.sessionId })
193
+ }
194
+
195
+ public unsubscribeFromSession(stopSession?: boolean) {
196
+ if (this.sessionId) {
197
+ this.emitSocketEvent(SESSION_UNSUBSCRIBE_EVENT, { debugSessionId: this.sessionId })
198
+ if (stopSession) {
199
+ this.emitSocketEvent(SESSION_STOPPED_EVENT, {})
200
+ }
201
+ }
202
+ }
203
+
204
+ public setUser(userAttributes: IUserAttributes | undefined): void {
205
+ this.emitSocketEvent(SOCKET_SET_USER_EVENT, userAttributes)
206
+ }
207
+
208
+ public close(): Promise<void> {
209
+ return new Promise((resolve) => {
210
+ if (this.socket?.connected) {
211
+ setTimeout(() => {
212
+ this.unsubscribeFromSession();
213
+ this.attempts = 0;
214
+ this.isConnected = false;
215
+ this.isConnecting = false;
216
+ this.socket?.disconnect();
217
+ this.socket = null;
218
+ resolve();
219
+ }, 500);
220
+ } else {
221
+ resolve();
222
+ }
223
+ });
224
+ }
225
+ }
@@ -13,7 +13,13 @@ import {
13
13
  type SessionRecorderConfigs,
14
14
  type SessionRecorderOptions,
15
15
  type EventRecorder,
16
+ type IUserAttributes,
16
17
  } from './types';
18
+ import {
19
+ SESSION_STOPPED_EVENT,
20
+ REMOTE_SESSION_RECORDING_START,
21
+ REMOTE_SESSION_RECORDING_STOP
22
+ } from './config';
17
23
  import { getFormattedDate, isSessionActive, getNavigatorInfo } from './utils';
18
24
  import {
19
25
  setShouldRecordHttpData,
@@ -28,6 +34,7 @@ import {
28
34
  type StartSessionRequest,
29
35
  type StopSessionRequest,
30
36
  } from './services/api.service';
37
+ import { SocketService } from './services/socket.service';
31
38
 
32
39
  type SessionRecorderEvents = 'state-change' | 'init';
33
40
 
@@ -36,6 +43,7 @@ class SessionRecorder
36
43
  implements ISessionRecorder, EventRecorder {
37
44
  private _configs: SessionRecorderConfigs;
38
45
  private _apiService = new ApiService();
46
+ private _socketService = new SocketService();
39
47
  private _tracer = new TracerReactNativeSDK();
40
48
  private _recorder = new RecorderReactNativeSDK();
41
49
  private _storageService = StorageService.getInstance();
@@ -110,6 +118,8 @@ class SessionRecorder
110
118
  this._sessionAttributes = attributes;
111
119
  }
112
120
 
121
+ private _userAttributes: IUserAttributes | undefined = undefined;
122
+
113
123
  /**
114
124
  * Error message getter and setter
115
125
  */
@@ -200,10 +210,16 @@ class SessionRecorder
200
210
  );
201
211
 
202
212
  this._tracer.init(this._configs);
203
- this._recorder.init(this._configs);
204
213
  this._apiService.init(this._configs);
214
+ this._socketService.init({
215
+ apiKey: this._configs.apiKey,
216
+ socketUrl: this._configs.apiBaseUrl,
217
+ keepAlive: this._configs.useWebsocket
218
+ });
219
+ this._recorder.init(this._configs, this._socketService);
205
220
  await this._networkService.init();
206
221
  this._setupNetworkCallbacks();
222
+ this._registerSocketServiceListeners();
207
223
 
208
224
  if (
209
225
  this.sessionId &&
@@ -215,6 +231,30 @@ class SessionRecorder
215
231
  this.emit('init', []);
216
232
  }
217
233
 
234
+ /**
235
+ * Register socket service event listeners
236
+ */
237
+ private _registerSocketServiceListeners(): void {
238
+ this._socketService.on(SESSION_STOPPED_EVENT, () => {
239
+ this._stop();
240
+ this._clearSession();
241
+ });
242
+
243
+ this._socketService.on(REMOTE_SESSION_RECORDING_START, (payload: any) => {
244
+ logger.info('SessionRecorder', 'Remote session recording started', payload);
245
+ if (this.sessionState === SessionState.stopped) {
246
+ this.start();
247
+ }
248
+ });
249
+
250
+ this._socketService.on(REMOTE_SESSION_RECORDING_STOP, (payload: any) => {
251
+ logger.info('SessionRecorder', 'Remote session recording stopped', payload);
252
+ if (this.sessionState !== SessionState.stopped) {
253
+ this.stop();
254
+ }
255
+ });
256
+ }
257
+
218
258
  /**
219
259
  * Setup network state change callbacks
220
260
  */
@@ -361,13 +401,9 @@ class SessionRecorder
361
401
  {
362
402
  sessionAttributes: this.sessionAttributes,
363
403
  resourceAttributes: getNavigatorInfo(),
404
+ userAttributes: this._userAttributes,
364
405
  stoppedAt: Date.now(),
365
- name: this.sessionAttributes.userName
366
- ? `${this.sessionAttributes.userName}'s session on ${getFormattedDate(
367
- Date.now(),
368
- { month: 'short', day: 'numeric' }
369
- )}`
370
- : `Session on ${getFormattedDate(Date.now())}`,
406
+ name: this._getSessionName()
371
407
  }
372
408
  );
373
409
 
@@ -385,6 +421,15 @@ class SessionRecorder
385
421
  this._sessionAttributes = attributes;
386
422
  }
387
423
 
424
+ /**
425
+ * Set the user attributes
426
+ * @param userAttributes - the user attributes to set
427
+ */
428
+ public setUserAttributes(userAttributes: IUserAttributes | undefined): void {
429
+ this._userAttributes = userAttributes;
430
+ this._socketService.setUser(this._userAttributes);
431
+ }
432
+
388
433
  /**
389
434
  * @description Check if session should be started/stopped automatically
390
435
  * @param {ISession} [sessionPayload]
@@ -406,6 +451,7 @@ class SessionRecorder
406
451
  ...getNavigatorInfo(),
407
452
  ...(sessionPayload?.resourceAttributes || {}),
408
453
  },
454
+ userAttributes: this._userAttributes,
409
455
  };
410
456
 
411
457
  const { state } = await this._apiService.checkRemoteSession(payload);
@@ -430,9 +476,8 @@ class SessionRecorder
430
476
  const payload = {
431
477
  sessionAttributes: this.sessionAttributes,
432
478
  resourceAttributes: getNavigatorInfo(),
433
- name: this.sessionAttributes.userName
434
- ? `${this.sessionAttributes.userName}'s session on ${getFormattedDate(Date.now(), { month: 'short', day: 'numeric' })}`
435
- : `Session on ${getFormattedDate(Date.now())}`,
479
+ userAttributes: this._userAttributes,
480
+ name: this._getSessionName()
436
481
  };
437
482
  const request: StartSessionRequest = !this.continuousRecording
438
483
  ? payload
@@ -467,6 +512,9 @@ class SessionRecorder
467
512
  if (this.sessionId) {
468
513
  this._tracer.start(this.sessionId, this.sessionType);
469
514
  this._recorder.start(this.sessionId, this.sessionType);
515
+ if (this.session) {
516
+ this._socketService.subscribeToSession(this.session);
517
+ }
470
518
  }
471
519
  }
472
520
 
@@ -475,6 +523,7 @@ class SessionRecorder
475
523
  */
476
524
  private _stop(): void {
477
525
  this.sessionState = SessionState.stopped;
526
+ this._socketService.unsubscribeFromSession(true);
478
527
  this._tracer.shutdown();
479
528
  this._recorder.stop();
480
529
  }
@@ -506,8 +555,8 @@ class SessionRecorder
506
555
  if (configureExporters && session.tempApiKey) {
507
556
  this._configs.apiKey = session.tempApiKey;
508
557
  this._tracer.setApiKey(session.tempApiKey);
509
- this._recorder.setApiKey(session.tempApiKey);
510
558
  this._apiService.setApiKey(session.tempApiKey);
559
+ this._socketService.updateConfigs({ apiKey: session.tempApiKey });
511
560
  }
512
561
 
513
562
  this._setSession(session);
@@ -685,6 +734,17 @@ class SessionRecorder
685
734
  return { errorInfo: String(errorInfo) }
686
735
  }
687
736
  }
737
+
738
+ /**
739
+ * Get the session name
740
+ * @returns the session name
741
+ */
742
+ private _getSessionName(date: Date = new Date()): string {
743
+ const userName = this.sessionAttributes?.userName || this._userAttributes?.userName || this._userAttributes?.name || '';
744
+ return userName
745
+ ? `${userName}'s session on ${getFormattedDate(date, { month: 'short', day: 'numeric' })}`
746
+ : `Session on ${getFormattedDate(date)}`;
747
+ }
688
748
  }
689
749
 
690
750
  export default new SessionRecorder();
@@ -1,7 +1,7 @@
1
1
  import { type Span } from '@opentelemetry/api';
2
2
  import { SessionType } from '@multiplayer-app/session-recorder-common';
3
3
  import { type PropagateTraceHeaderCorsUrls } from '@opentelemetry/sdk-trace-web';
4
- import type { ISession } from './session';
4
+ import type { ISession, IUserAttributes } from './session';
5
5
 
6
6
  // WidgetButtonPlacement moved to configs.ts
7
7
 
@@ -155,6 +155,13 @@ export interface SessionRecorderOptions {
155
155
  level?: number;
156
156
  enabled?: boolean;
157
157
  };
158
+
159
+ /**
160
+ * @description
161
+ * If true, webSocket will be used to manage remote recording sessions.
162
+ * @default true
163
+ */
164
+ useWebsocket?: boolean
158
165
  }
159
166
 
160
167
  /**
@@ -332,6 +339,12 @@ export interface ISessionRecorder {
332
339
  */
333
340
  setSessionAttributes(attributes: Record<string, any>): void;
334
341
 
342
+ /**
343
+ * Set the user attributes
344
+ * @param userAttributes - the user attributes to set
345
+ */
346
+ setUserAttributes(userAttributes: IUserAttributes | undefined): void;
347
+
335
348
  /**
336
349
  * Capture an exception and send it as an error trace
337
350
  */
@@ -1,5 +1,6 @@
1
- import { SessionType } from '@multiplayer-app/session-recorder-common';
2
- import type { UserType } from './client-type.enum';
1
+ import { SessionType, UserType } from '@multiplayer-app/session-recorder-common';
2
+
3
+
3
4
 
4
5
  export interface IResourceAttributes {
5
6
  browserInfo?: string;
@@ -24,7 +24,7 @@ class Logger {
24
24
  ['ScreenRecorder', '📸'],
25
25
  ['NativeGestureRecorder', '👆'],
26
26
  ['SessionRecorderContext', '🎯'],
27
- ['EventExporter', '📤'],
27
+ ['SocketService', '📤'],
28
28
  ['NavigationTracker', '📸'],
29
29
  ['RecorderReactNativeSDK', '📤'],
30
30
  ['DEBUGGER_LIB', '🔍'],
@@ -1,130 +0,0 @@
1
- "use strict";
2
-
3
- import io from 'socket.io-client';
4
- import { logger } from "../utils/index.js";
5
- import { SESSION_ADD_EVENT, SESSION_AUTO_CREATED, SESSION_STOPPED_EVENT, SESSION_SUBSCRIBE_EVENT, SESSION_UNSUBSCRIBE_EVENT } from "../config/index.js";
6
- const MAX_RECONNECTION_ATTEMPTS = 2;
7
- export class EventExporter {
8
- socket = null;
9
- queue = [];
10
- isConnecting = false;
11
- isConnected = false;
12
- attempts = 0;
13
- sessionId = null;
14
- constructor(options) {
15
- this.socketUrl = options.socketUrl;
16
- this.apiKey = options.apiKey;
17
- }
18
- init() {
19
- if (this.isConnecting || this.isConnected) return;
20
- this.attempts++;
21
- this.isConnecting = true;
22
- this.socket = io(this.socketUrl, {
23
- path: '/v0/radar/ws',
24
- auth: {
25
- 'x-api-key': this.apiKey
26
- },
27
- reconnectionAttempts: 2,
28
- transports: ['websocket']
29
- });
30
-
31
- // this.socket.on('connect', () => {
32
- // this.isConnecting = false
33
- // this.isConnected = true
34
- // this.usePostMessage = false
35
- // this.flushQueue()
36
- // })
37
-
38
- this.socket.on('ready', () => {
39
- this.isConnecting = false;
40
- this.isConnected = true;
41
- logger.info('EventExporter', 'Connected to server');
42
- this.flushQueue();
43
- });
44
- this.socket.on('disconnect', _err => {
45
- this.isConnecting = false;
46
- this.isConnected = false;
47
- logger.info('EventExporter', 'Disconnected from server');
48
- });
49
- this.socket.on('connect_error', err => {
50
- this.isConnecting = false;
51
- this.isConnected = false;
52
- this.checkReconnectionAttempts();
53
- logger.error('EventExporter', 'Error connecting to server', err);
54
- });
55
- this.socket.on(SESSION_STOPPED_EVENT, _ => {
56
- this.unsubscribeFromSession();
57
- });
58
- this.socket.on(SESSION_AUTO_CREATED, _ => {});
59
- }
60
- setApiKey(apiKey) {
61
- this.apiKey = apiKey;
62
- }
63
- setSocketUrl(socketUrl) {
64
- this.socketUrl = socketUrl;
65
- }
66
- checkReconnectionAttempts() {
67
- if (this.attempts >= MAX_RECONNECTION_ATTEMPTS) {
68
- this.flushQueue();
69
- }
70
- }
71
- flushQueue() {
72
- while (this.queue.length > 0 && this.socket?.connected) {
73
- const event = this.queue.shift();
74
- if (!event) continue;
75
- if (this.socket?.connected) {
76
- this.socket.emit(event.name, event.data);
77
- }
78
- }
79
- }
80
- unsubscribeFromSession() {
81
- const payload = {
82
- debugSessionId: this.sessionId
83
- };
84
- if (this.socket?.connected) {
85
- this.socket.emit(SESSION_UNSUBSCRIBE_EVENT, payload);
86
- }
87
- }
88
- send(event) {
89
- if (this.socket?.connected) {
90
- this.socket.emit(SESSION_ADD_EVENT, event);
91
- } else {
92
- this.queue.push({
93
- data: event,
94
- name: SESSION_ADD_EVENT
95
- });
96
- this.init();
97
- }
98
- }
99
- subscribeToSession(session) {
100
- this.sessionId = session.shortId || session._id;
101
- const payload = {
102
- projectId: session.project,
103
- workspaceId: session.workspace,
104
- debugSessionId: this.sessionId,
105
- sessionType: session.creationType
106
- };
107
- if (this.socket?.connected) {
108
- this.socket.emit(SESSION_SUBSCRIBE_EVENT, payload);
109
- } else {
110
- this.queue.push({
111
- data: payload,
112
- name: SESSION_SUBSCRIBE_EVENT
113
- });
114
- this.init();
115
- }
116
- }
117
- close() {
118
- if (this.socket?.connected) {
119
- setTimeout(() => {
120
- this.unsubscribeFromSession();
121
- this.attempts = 0;
122
- this.isConnected = false;
123
- this.isConnecting = false;
124
- this.socket?.disconnect();
125
- this.socket = null;
126
- }, 500);
127
- }
128
- }
129
- }
130
- //# sourceMappingURL=eventExporter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["io","logger","SESSION_ADD_EVENT","SESSION_AUTO_CREATED","SESSION_STOPPED_EVENT","SESSION_SUBSCRIBE_EVENT","SESSION_UNSUBSCRIBE_EVENT","MAX_RECONNECTION_ATTEMPTS","EventExporter","socket","queue","isConnecting","isConnected","attempts","sessionId","constructor","options","socketUrl","apiKey","init","path","auth","reconnectionAttempts","transports","on","info","flushQueue","_err","err","checkReconnectionAttempts","error","_","unsubscribeFromSession","setApiKey","setSocketUrl","length","connected","event","shift","emit","name","data","payload","debugSessionId","send","push","subscribeToSession","session","shortId","_id","projectId","project","workspaceId","workspace","sessionType","creationType","close","setTimeout","disconnect"],"sourceRoot":"../../../src","sources":["recorder/eventExporter.ts"],"mappings":";;AAAA,OAAOA,EAAE,MAAkB,kBAAkB;AAG7C,SAASC,MAAM,QAAQ,mBAAU;AAEjC,SACEC,iBAAiB,EACjBC,oBAAoB,EACpBC,qBAAqB,EACrBC,uBAAuB,EACvBC,yBAAyB,QACpB,oBAAW;AAElB,MAAMC,yBAAyB,GAAG,CAAC;AAEnC,OAAO,MAAMC,aAAa,CAAC;EACjBC,MAAM,GAAkB,IAAI;EAC5BC,KAAK,GAAU,EAAE;EACjBC,YAAY,GAAY,KAAK;EAC7BC,WAAW,GAAY,KAAK;EAC5BC,QAAQ,GAAW,CAAC;EACpBC,SAAS,GAAkB,IAAI;EAKvCC,WAAWA,CAACC,OAA8C,EAAE;IAC1D,IAAI,CAACC,SAAS,GAAGD,OAAO,CAACC,SAAS;IAClC,IAAI,CAACC,MAAM,GAAGF,OAAO,CAACE,MAAM;EAC9B;EAEQC,IAAIA,CAAA,EAAS;IACnB,IAAI,IAAI,CAACR,YAAY,IAAI,IAAI,CAACC,WAAW,EAAE;IAC3C,IAAI,CAACC,QAAQ,EAAE;IACf,IAAI,CAACF,YAAY,GAAG,IAAI;IACxB,IAAI,CAACF,MAAM,GAAGT,EAAE,CAAC,IAAI,CAACiB,SAAS,EAAE;MAC/BG,IAAI,EAAE,cAAc;MACpBC,IAAI,EAAE;QACJ,WAAW,EAAE,IAAI,CAACH;MACpB,CAAC;MACDI,oBAAoB,EAAE,CAAC;MACvBC,UAAU,EAAE,CAAC,WAAW;IAC1B,CAAC,CAAC;;IAEF;IACA;IACA;IACA;IACA;IACA;;IAEA,IAAI,CAACd,MAAM,CAACe,EAAE,CAAC,OAAO,EAAE,MAAM;MAC5B,IAAI,CAACb,YAAY,GAAG,KAAK;MACzB,IAAI,CAACC,WAAW,GAAG,IAAI;MACvBX,MAAM,CAACwB,IAAI,CAAC,eAAe,EAAE,qBAAqB,CAAC;MACnD,IAAI,CAACC,UAAU,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,IAAI,CAACjB,MAAM,CAACe,EAAE,CAAC,YAAY,EAAGG,IAAS,IAAK;MAC1C,IAAI,CAAChB,YAAY,GAAG,KAAK;MACzB,IAAI,CAACC,WAAW,GAAG,KAAK;MACxBX,MAAM,CAACwB,IAAI,CAAC,eAAe,EAAE,0BAA0B,CAAC;IAC1D,CAAC,CAAC;IAEF,IAAI,CAAChB,MAAM,CAACe,EAAE,CAAC,eAAe,EAAGI,GAAQ,IAAK;MAC5C,IAAI,CAACjB,YAAY,GAAG,KAAK;MACzB,IAAI,CAACC,WAAW,GAAG,KAAK;MACxB,IAAI,CAACiB,yBAAyB,CAAC,CAAC;MAChC5B,MAAM,CAAC6B,KAAK,CAAC,eAAe,EAAE,4BAA4B,EAAEF,GAAG,CAAC;IAClE,CAAC,CAAC;IAEF,IAAI,CAACnB,MAAM,CAACe,EAAE,CAACpB,qBAAqB,EAAG2B,CAAM,IAAK;MAChD,IAAI,CAACC,sBAAsB,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,IAAI,CAACvB,MAAM,CAACe,EAAE,CAACrB,oBAAoB,EAAG4B,CAAM,IAAK,CAAC,CAAC,CAAC;EACtD;EAEAE,SAASA,CAACf,MAAc,EAAQ;IAC9B,IAAI,CAACA,MAAM,GAAGA,MAAM;EACtB;EAEAgB,YAAYA,CAACjB,SAAiB,EAAQ;IACpC,IAAI,CAACA,SAAS,GAAGA,SAAS;EAC5B;EAEQY,yBAAyBA,CAAA,EAAS;IACxC,IAAI,IAAI,CAAChB,QAAQ,IAAIN,yBAAyB,EAAE;MAC9C,IAAI,CAACmB,UAAU,CAAC,CAAC;IACnB;EACF;EAEQA,UAAUA,CAAA,EAAS;IACzB,OAAO,IAAI,CAAChB,KAAK,CAACyB,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC1B,MAAM,EAAE2B,SAAS,EAAE;MACtD,MAAMC,KAAK,GAAG,IAAI,CAAC3B,KAAK,CAAC4B,KAAK,CAAC,CAAC;MAChC,IAAI,CAACD,KAAK,EAAE;MAEZ,IAAI,IAAI,CAAC5B,MAAM,EAAE2B,SAAS,EAAE;QAC1B,IAAI,CAAC3B,MAAM,CAAC8B,IAAI,CAACF,KAAK,CAACG,IAAI,EAAEH,KAAK,CAACI,IAAI,CAAC;MAC1C;IACF;EACF;EAEQT,sBAAsBA,CAAA,EAAG;IAC/B,MAAMU,OAAO,GAAG;MACdC,cAAc,EAAE,IAAI,CAAC7B;IACvB,CAAC;IACD,IAAI,IAAI,CAACL,MAAM,EAAE2B,SAAS,EAAE;MAC1B,IAAI,CAAC3B,MAAM,CAAC8B,IAAI,CAACjC,yBAAyB,EAAEoC,OAAO,CAAC;IACtD;EACF;EAEOE,IAAIA,CAACP,KAAU,EAAQ;IAC5B,IAAI,IAAI,CAAC5B,MAAM,EAAE2B,SAAS,EAAE;MAC1B,IAAI,CAAC3B,MAAM,CAAC8B,IAAI,CAACrC,iBAAiB,EAAEmC,KAAK,CAAC;IAC5C,CAAC,MAAM;MACL,IAAI,CAAC3B,KAAK,CAACmC,IAAI,CAAC;QAAEJ,IAAI,EAAEJ,KAAK;QAAEG,IAAI,EAAEtC;MAAkB,CAAC,CAAC;MACzD,IAAI,CAACiB,IAAI,CAAC,CAAC;IACb;EACF;EAEO2B,kBAAkBA,CAACC,OAAiB,EAAQ;IACjD,IAAI,CAACjC,SAAS,GAAGiC,OAAO,CAACC,OAAO,IAAID,OAAO,CAACE,GAAG;IAC/C,MAAMP,OAAO,GAAG;MACdQ,SAAS,EAAEH,OAAO,CAACI,OAAO;MAC1BC,WAAW,EAAEL,OAAO,CAACM,SAAS;MAC9BV,cAAc,EAAE,IAAI,CAAC7B,SAAS;MAC9BwC,WAAW,EAAEP,OAAO,CAACQ;IACvB,CAAC;IACD,IAAI,IAAI,CAAC9C,MAAM,EAAE2B,SAAS,EAAE;MAC1B,IAAI,CAAC3B,MAAM,CAAC8B,IAAI,CAAClC,uBAAuB,EAAEqC,OAAO,CAAC;IACpD,CAAC,MAAM;MACL,IAAI,CAAChC,KAAK,CAACmC,IAAI,CAAC;QAAEJ,IAAI,EAAEC,OAAO;QAAEF,IAAI,EAAEnC;MAAwB,CAAC,CAAC;MACjE,IAAI,CAACc,IAAI,CAAC,CAAC;IACb;EACF;EAEOqC,KAAKA,CAAA,EAAS;IACnB,IAAI,IAAI,CAAC/C,MAAM,EAAE2B,SAAS,EAAE;MAC1BqB,UAAU,CAAC,MAAM;QACf,IAAI,CAACzB,sBAAsB,CAAC,CAAC;QAC7B,IAAI,CAACnB,QAAQ,GAAG,CAAC;QACjB,IAAI,CAACD,WAAW,GAAG,KAAK;QACxB,IAAI,CAACD,YAAY,GAAG,KAAK;QACzB,IAAI,CAACF,MAAM,EAAEiD,UAAU,CAAC,CAAC;QACzB,IAAI,CAACjD,MAAM,GAAG,IAAI;MACpB,CAAC,EAAE,GAAG,CAAC;IACT;EACF;AACF","ignoreList":[]}
@@ -1,9 +0,0 @@
1
- "use strict";
2
-
3
- export let UserType = /*#__PURE__*/function (UserType) {
4
- UserType["USER"] = "USER";
5
- UserType["VISITOR"] = "VISITOR";
6
- UserType["API_CLIENT"] = "API_CLIENT";
7
- return UserType;
8
- }({});
9
- //# sourceMappingURL=client-type.enum.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["UserType"],"sourceRoot":"../../../src","sources":["types/client-type.enum.ts"],"mappings":";;AAAA,WAAYA,QAAQ,0BAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAAA,OAARA,QAAQ;AAAA","ignoreList":[]}
@@ -1,25 +0,0 @@
1
- import { type ISession } from '../types';
2
- export declare class EventExporter {
3
- private socket;
4
- private queue;
5
- private isConnecting;
6
- private isConnected;
7
- private attempts;
8
- private sessionId;
9
- private socketUrl;
10
- private apiKey;
11
- constructor(options: {
12
- socketUrl: string;
13
- apiKey: string;
14
- });
15
- private init;
16
- setApiKey(apiKey: string): void;
17
- setSocketUrl(socketUrl: string): void;
18
- private checkReconnectionAttempts;
19
- private flushQueue;
20
- private unsubscribeFromSession;
21
- send(event: any): void;
22
- subscribeToSession(session: ISession): void;
23
- close(): void;
24
- }
25
- //# sourceMappingURL=eventExporter.d.ts.map