@finatic/client 0.0.141 → 0.0.142

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.
@@ -16,6 +16,8 @@ export declare class ApiClient {
16
16
  private tradingContext;
17
17
  private companyId;
18
18
  private csrfToken;
19
+ private readonly logger;
20
+ private buildLoggerExtra;
19
21
  constructor(baseUrl: string, deviceInfo?: DeviceInfo);
20
22
  /**
21
23
  * Set session context (session ID, company ID, CSRF token)
@@ -27,6 +27,8 @@ export declare class FinaticConnect extends EventEmitter {
27
27
  private readonly SESSION_VALIDATION_TIMEOUT;
28
28
  private readonly SESSION_REFRESH_BUFFER_HOURS;
29
29
  private sessionStartTime;
30
+ private readonly logger;
31
+ private buildLoggerExtra;
30
32
  constructor(options: FinaticConnectOptions, deviceInfo?: DeviceInfo);
31
33
  private linkUserToSession;
32
34
  /**
@@ -6,7 +6,9 @@ export declare class PortalUI {
6
6
  private portalOrigin;
7
7
  private options?;
8
8
  private originalBodyStyle;
9
+ private readonly logger;
9
10
  constructor(portalUrl: string);
11
+ private buildLoggerExtra;
10
12
  private createContainer;
11
13
  /**
12
14
  * Lock background scrolling by setting overflow: hidden on body
@@ -8,4 +8,5 @@ export { PaginatedResult } from './types/common/pagination';
8
8
  export * from './utils/errors';
9
9
  export * from './utils/events';
10
10
  export * from './utils/themeUtils';
11
+ export * from './lib/logger';
11
12
  export { portalThemePresets } from './themes/portalPresets';
@@ -0,0 +1,2 @@
1
+ export * from './logger';
2
+ export * from './logger.types';
@@ -0,0 +1,4 @@
1
+ import { Logger, LoggerExtra, LoggerMetadata, LoggerOptions, LogLevel } from './logger.types';
2
+ export declare const setupLogger: (nameOrOptions: string | LoggerOptions, level?: LogLevel, defaultMetadata?: LoggerMetadata) => Logger;
3
+ export declare const buildLoggerExtra: (metadata: LoggerMetadata) => LoggerExtra;
4
+ export declare const logStartEnd: (logger: Logger) => <Args extends unknown[], ReturnType>(fn: (...args: Args) => ReturnType | Promise<ReturnType>) => (...args: Args) => Promise<ReturnType>;
@@ -0,0 +1,28 @@
1
+ export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
2
+ export interface LoggerMetadata {
3
+ [key: string]: unknown;
4
+ }
5
+ export interface LoggerExtra {
6
+ metadata?: LoggerMetadata;
7
+ module?: string;
8
+ function?: string;
9
+ event?: string;
10
+ duration_ms?: number;
11
+ error?: unknown;
12
+ [key: string]: unknown;
13
+ }
14
+ export interface LoggerOptions {
15
+ name: string;
16
+ level?: LogLevel;
17
+ defaultMetadata?: LoggerMetadata;
18
+ }
19
+ export interface Logger {
20
+ getLevel: () => LogLevel;
21
+ setLevel: (level: LogLevel) => void;
22
+ debug: (message: string, extra?: LoggerExtra) => void;
23
+ info: (message: string, extra?: LoggerExtra) => void;
24
+ warn: (message: string, extra?: LoggerExtra) => void;
25
+ error: (message: string, extra?: LoggerExtra) => void;
26
+ exception: (message: string, error: unknown, extra?: LoggerExtra) => void;
27
+ }
28
+ export type LogVerbosity = 0 | 1 | 2 | 3;
@@ -19,6 +19,8 @@ export declare class MockApiClient {
19
19
  private csrfToken;
20
20
  private mockDataProvider;
21
21
  private readonly mockApiOnly;
22
+ private readonly logger;
23
+ private buildLoggerExtra;
22
24
  constructor(baseUrl: string, deviceInfo?: DeviceInfo, mockConfig?: MockConfig);
23
25
  /**
24
26
  * Store tokens after successful authentication
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finatic/client",
3
- "version": "0.0.141",
3
+ "version": "0.0.142",
4
4
  "description": "Finatic Client SDK for browser integration",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -31,6 +31,7 @@ import { TradingContext } from '../../types/api/orders';
31
31
  import { ApiPaginationInfo, PaginatedResult } from '../../types/common/pagination';
32
32
  import { ApiResponse } from '../../types/api/core';
33
33
  import { PortalUrlResponse } from '../../types/api/core';
34
+ import { setupLogger, buildLoggerExtra, LoggerExtra } from '../../lib/logger';
34
35
  import {
35
36
  DeviceInfo,
36
37
  SessionState,
@@ -70,6 +71,17 @@ export class ApiClient {
70
71
  // Session and company context
71
72
  private companyId: string | null = null;
72
73
  private csrfToken: string | null = null;
74
+ private readonly logger = setupLogger('FinaticClientSDK.ApiClient', undefined, {
75
+ codebase: 'FinaticClientSDK',
76
+ });
77
+
78
+ private buildLoggerExtra(functionName: string, metadata?: Record<string, unknown>): LoggerExtra {
79
+ return {
80
+ module: 'ApiClient',
81
+ function: functionName,
82
+ ...(metadata ? buildLoggerExtra(metadata) : {}),
83
+ };
84
+ }
73
85
 
74
86
  constructor(baseUrl: string, deviceInfo?: DeviceInfo) {
75
87
  this.baseUrl = baseUrl;
@@ -223,15 +235,11 @@ export class ApiClient {
223
235
  }
224
236
  });
225
237
 
226
- // Debug logging for development
227
- if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
228
- console.log('Request to:', url.toString());
229
- console.log('Safari-safe headers:', safariSafeHeaders);
230
- console.log('Browser:', navigator.userAgent);
231
- console.log('Session ID:', this.currentSessionId);
232
- console.log('Company ID:', this.companyId);
233
- console.log('CSRF Token:', this.csrfToken);
234
- }
238
+ this.logger.debug('Dispatching API request', this.buildLoggerExtra('request', {
239
+ url: url.toString(),
240
+ method: options.method,
241
+ has_body: Boolean(options.body),
242
+ }));
235
243
 
236
244
  const response = await fetch(url.toString(), {
237
245
  method: options.method,
@@ -239,16 +247,19 @@ export class ApiClient {
239
247
  body: options.body ? JSON.stringify(options.body) : undefined,
240
248
  });
241
249
 
242
- // Debug logging for response
243
- if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
244
- console.log('Response status:', response.status);
245
- console.log('Response headers:', Object.fromEntries(response.headers.entries()));
246
- console.log('Request was made with headers:', safariSafeHeaders);
247
- }
250
+ this.logger.debug('Received API response', this.buildLoggerExtra('request', {
251
+ url: url.toString(),
252
+ status: response.status,
253
+ }));
248
254
 
249
255
  if (!response.ok) {
250
256
  const error = await response.json();
251
- throw this.handleError(response.status, error);
257
+ const apiError = this.handleError(response.status, error);
258
+ this.logger.exception('API request failed', apiError, this.buildLoggerExtra('request', {
259
+ url: url.toString(),
260
+ status: response.status,
261
+ }));
262
+ throw apiError;
252
263
  }
253
264
 
254
265
  const data = await response.json();
@@ -261,12 +272,22 @@ export class ApiClient {
261
272
  // Add context that this is an order-related error
262
273
  data._isOrderError = true;
263
274
  }
264
- throw this.handleError(data.status_code || 500, data);
275
+ const apiError = this.handleError(data.status_code || 500, data);
276
+ this.logger.exception('API response indicated failure', apiError, this.buildLoggerExtra('request', {
277
+ url: url.toString(),
278
+ status: data.status_code || 500,
279
+ }));
280
+ throw apiError;
265
281
  }
266
282
 
267
283
  // Check if the response has a status_code field indicating an error (4xx or 5xx)
268
284
  if (data && typeof data === 'object' && 'status_code' in data && data.status_code >= 400) {
269
- throw this.handleError(data.status_code, data);
285
+ const apiError = this.handleError(data.status_code, data);
286
+ this.logger.exception('API status code error', apiError, this.buildLoggerExtra('request', {
287
+ url: url.toString(),
288
+ status: data.status_code,
289
+ }));
290
+ throw apiError;
270
291
  }
271
292
 
272
293
  // Check if the response has errors field with content
@@ -278,7 +299,12 @@ export class ApiClient {
278
299
  Array.isArray(data.errors) &&
279
300
  data.errors.length > 0
280
301
  ) {
281
- throw this.handleError(data.status_code || 500, data);
302
+ const apiError = this.handleError(data.status_code || 500, data);
303
+ this.logger.exception('API response contained errors', apiError, this.buildLoggerExtra('request', {
304
+ url: url.toString(),
305
+ status: data.status_code || 500,
306
+ }));
307
+ throw apiError;
282
308
  }
283
309
 
284
310
  return data;
@@ -27,6 +27,17 @@ import {
27
27
  import { FinaticConnectOptions, PortalOptions } from '../../types/connect';
28
28
  import { appendThemeToURL } from '../../utils/themeUtils';
29
29
  import { appendBrokerFilterToURL } from '../../utils/brokerUtils';
30
+ import { setupLogger, buildLoggerExtra, LoggerExtra } from '../../lib/logger';
31
+
32
+ const finaticConnectLogger = setupLogger('FinaticClientSDK.FinaticConnect', undefined, {
33
+ codebase: 'FinaticClientSDK',
34
+ });
35
+
36
+ const makeFinaticConnectExtra = (functionName: string, metadata?: Record<string, unknown>): LoggerExtra => ({
37
+ module: 'FinaticConnect',
38
+ function: functionName,
39
+ ...(metadata ? buildLoggerExtra(metadata) : {}),
40
+ });
30
41
  // Supabase import removed - SDK no longer depends on Supabase
31
42
 
32
43
  interface DeviceInfo {
@@ -57,6 +68,16 @@ export class FinaticConnect extends EventEmitter {
57
68
  private readonly SESSION_REFRESH_BUFFER_HOURS = 16; // Refresh session at 16 hours
58
69
  private sessionStartTime: number | null = null;
59
70
 
71
+ private readonly logger = finaticConnectLogger;
72
+
73
+ private buildLoggerExtra(functionName: string, metadata?: Record<string, unknown>): LoggerExtra {
74
+ return {
75
+ module: 'FinaticConnect',
76
+ function: functionName,
77
+ ...(metadata ? buildLoggerExtra(metadata) : {}),
78
+ };
79
+ }
80
+
60
81
  constructor(options: FinaticConnectOptions, deviceInfo?: DeviceInfo) {
61
82
  super();
62
83
  this.options = options;
@@ -112,7 +133,7 @@ export class FinaticConnect extends EventEmitter {
112
133
  private async linkUserToSession(userId: string): Promise<boolean> {
113
134
  try {
114
135
  if (!this.sessionId) {
115
- console.error('No session ID available for user linking');
136
+ this.logger.error('No session ID available for user linking', this.buildLoggerExtra('linkUserToSession'));
116
137
  return false;
117
138
  }
118
139
 
@@ -126,14 +147,20 @@ export class FinaticConnect extends EventEmitter {
126
147
  });
127
148
 
128
149
  if (response.error) {
129
- console.error('Failed to link user to session:', response.error);
150
+ this.logger.error('Failed to link user to session', {
151
+ ...this.buildLoggerExtra('linkUserToSession', {
152
+ session_id: this.sessionId,
153
+ user_id: userId,
154
+ }),
155
+ error: response.error,
156
+ });
130
157
  return false;
131
158
  }
132
159
 
133
- console.log('User linked to session successfully');
160
+ this.logger.info('User linked to session successfully', this.buildLoggerExtra('linkUserToSession', { session_id: this.sessionId, user_id: userId }));
134
161
  return true;
135
162
  } catch (error) {
136
- console.error('Error linking user to session:', error);
163
+ this.logger.exception('Error linking user to session', error, this.buildLoggerExtra('linkUserToSession', { session_id: this.sessionId, user_id: userId }));
137
164
  return false;
138
165
  }
139
166
  }
@@ -322,7 +349,7 @@ export class FinaticConnect extends EventEmitter {
322
349
  // Safari-specific fix: Clear instance if it exists but has no valid session
323
350
  // This prevents stale instances from interfering with new requests
324
351
  if (FinaticConnect.instance && !FinaticConnect.instance.sessionId) {
325
- console.log('[FinaticConnect] Clearing stale instance for Safari compatibility');
352
+ finaticConnectLogger.debug('Clearing stale instance for Safari compatibility', makeFinaticConnectExtra('init'));
326
353
  FinaticConnect.instance = null;
327
354
  }
328
355
 
@@ -390,7 +417,7 @@ export class FinaticConnect extends EventEmitter {
390
417
  // Emit success event
391
418
  FinaticConnect.instance.emit('success', normalizedUserId);
392
419
  } else {
393
- console.warn('Failed to link user to session during initialization');
420
+ finaticConnectLogger.warn('Failed to link user to session during initialization', makeFinaticConnectExtra('init', { user_id: normalizedUserId }));
394
421
  }
395
422
  } catch (error) {
396
423
  FinaticConnect.instance.emit('error', error as Error);
@@ -423,7 +450,7 @@ export class FinaticConnect extends EventEmitter {
423
450
  // Try to link user to session
424
451
  const linked = await this.linkUserToSession(userId);
425
452
  if (!linked) {
426
- console.warn('Failed to link user to session during initialization');
453
+ this.logger.warn('Failed to link user to session during initialization', this.buildLoggerExtra('initializeWithUser', { user_id: userId }));
427
454
  // Don't throw error, just continue without authentication
428
455
  return;
429
456
  }
@@ -537,7 +564,7 @@ export class FinaticConnect extends EventEmitter {
537
564
  // Try to link user to session via API
538
565
  const linked = await this.linkUserToSession(userId);
539
566
  if (!linked) {
540
- console.warn('Failed to link user to session, but continuing with authentication');
567
+ this.logger.warn('Failed to link user to session, continuing with authentication', this.buildLoggerExtra('openPortal.onSuccess', { user_id: userId }));
541
568
  }
542
569
 
543
570
  // Emit portal success event
@@ -573,7 +600,13 @@ export class FinaticConnect extends EventEmitter {
573
600
  options?.onClose?.();
574
601
  },
575
602
  onEvent: (type: string, data: any) => {
576
- console.log('[FinaticConnect] Portal event received:', type, data);
603
+ this.logger.debug('Portal event received', {
604
+ ...this.buildLoggerExtra('openPortal.onEvent', {
605
+ event_type: type,
606
+ payload_present: Boolean(data),
607
+ }),
608
+ event: 'portal-event',
609
+ });
577
610
 
578
611
  // Emit generic event
579
612
  this.emit('event', type, data);
@@ -1293,7 +1326,7 @@ export class FinaticConnect extends EventEmitter {
1293
1326
  this.validateSessionKeepAlive();
1294
1327
  }, this.SESSION_KEEP_ALIVE_INTERVAL);
1295
1328
 
1296
- console.log('[FinaticConnect] Session keep-alive started (5-minute intervals)');
1329
+ this.logger.debug('Session keep-alive started', this.buildLoggerExtra('startSessionKeepAlive', { interval_ms: this.SESSION_KEEP_ALIVE_INTERVAL }));
1297
1330
  }
1298
1331
 
1299
1332
  /**
@@ -1303,7 +1336,7 @@ export class FinaticConnect extends EventEmitter {
1303
1336
  if (this.sessionKeepAliveInterval) {
1304
1337
  clearInterval(this.sessionKeepAliveInterval);
1305
1338
  this.sessionKeepAliveInterval = null;
1306
- console.log('[FinaticConnect] Session keep-alive stopped');
1339
+ this.logger.debug('Session keep-alive stopped', this.buildLoggerExtra('stopSessionKeepAlive'));
1307
1340
  }
1308
1341
  }
1309
1342
 
@@ -1312,12 +1345,12 @@ export class FinaticConnect extends EventEmitter {
1312
1345
  */
1313
1346
  private async validateSessionKeepAlive(): Promise<void> {
1314
1347
  if (!this.sessionId || !(await this.isAuthenticated())) {
1315
- console.log('[FinaticConnect] Session keep-alive skipped - no active session');
1348
+ this.logger.debug('Session keep-alive skipped - no active session', this.buildLoggerExtra('validateSessionKeepAlive'));
1316
1349
  return;
1317
1350
  }
1318
1351
 
1319
1352
  try {
1320
- console.log('[FinaticConnect] Validating session for keep-alive...');
1353
+ this.logger.debug('Validating session for keep-alive', this.buildLoggerExtra('validateSessionKeepAlive', { session_id: this.sessionId }));
1321
1354
 
1322
1355
  // Check if we need to refresh the session (at 16 hours)
1323
1356
  if (this.shouldRefreshSession()) {
@@ -1326,10 +1359,10 @@ export class FinaticConnect extends EventEmitter {
1326
1359
  }
1327
1360
 
1328
1361
  // Session keep-alive - assume session is active if we have a session ID
1329
- console.log('[FinaticConnect] Session keep-alive successful');
1362
+ this.logger.debug('Session keep-alive successful', this.buildLoggerExtra('validateSessionKeepAlive', { session_id: this.sessionId }));
1330
1363
  this.currentSessionState = 'active';
1331
1364
  } catch (error) {
1332
- console.warn('[FinaticConnect] Session keep-alive error:', error);
1365
+ this.logger.exception('Session keep-alive error', error, this.buildLoggerExtra('validateSessionKeepAlive', { session_id: this.sessionId }));
1333
1366
  // Don't throw errors during keep-alive - just log them
1334
1367
  }
1335
1368
  }
@@ -1346,15 +1379,17 @@ export class FinaticConnect extends EventEmitter {
1346
1379
  const hoursUntilRefresh = this.SESSION_REFRESH_BUFFER_HOURS - sessionAgeHours;
1347
1380
 
1348
1381
  if (hoursUntilRefresh <= 0) {
1349
- console.log(
1350
- `[FinaticConnect] Session is ${sessionAgeHours.toFixed(1)} hours old - triggering refresh`
1351
- );
1382
+ this.logger.info('Session age threshold exceeded - triggering refresh', this.buildLoggerExtra('shouldRefreshSession', {
1383
+ session_age_hours: Number(sessionAgeHours.toFixed(1)),
1384
+ }));
1352
1385
  return true;
1353
1386
  }
1354
1387
 
1355
1388
  // Log when refresh will occur (every 5 minutes during keep-alive)
1356
1389
  if (hoursUntilRefresh <= 1) {
1357
- console.log(`[FinaticConnect] Session will refresh in ${hoursUntilRefresh.toFixed(1)} hours`);
1390
+ this.logger.debug('Session refresh scheduled', this.buildLoggerExtra('shouldRefreshSession', {
1391
+ hours_until_refresh: Number(hoursUntilRefresh.toFixed(1)),
1392
+ }));
1358
1393
  }
1359
1394
 
1360
1395
  return false;
@@ -1365,26 +1400,35 @@ export class FinaticConnect extends EventEmitter {
1365
1400
  */
1366
1401
  private async refreshSessionAutomatically(): Promise<void> {
1367
1402
  if (!this.sessionId) {
1368
- console.warn('[FinaticConnect] Cannot refresh session - no session ID');
1403
+ this.logger.warn('Cannot refresh session - missing session ID', this.buildLoggerExtra('refreshSessionAutomatically'));
1369
1404
  return;
1370
1405
  }
1371
1406
 
1372
1407
  try {
1373
- console.log('[FinaticConnect] Automatically refreshing session (16+ hours old)...');
1408
+ this.logger.info('Automatically refreshing session', this.buildLoggerExtra('refreshSessionAutomatically', {
1409
+ session_id: this.sessionId,
1410
+ }));
1374
1411
  const response = await this.apiClient.refreshSession();
1375
1412
 
1376
1413
  if (response.success) {
1377
- console.log('[FinaticConnect] Session automatically refreshed successfully');
1378
- console.log('[FinaticConnect] New session expires at:', response.response_data.expires_at);
1414
+ this.logger.info('Session automatically refreshed successfully', this.buildLoggerExtra('refreshSessionAutomatically', {
1415
+ session_id: this.sessionId,
1416
+ status: response.response_data.status,
1417
+ expires_at: response.response_data.expires_at,
1418
+ }));
1379
1419
  this.currentSessionState = response.response_data.status;
1380
1420
 
1381
1421
  // Update session start time to prevent immediate re-refresh
1382
1422
  this.sessionStartTime = Date.now();
1383
1423
  } else {
1384
- console.warn('[FinaticConnect] Automatic session refresh failed');
1424
+ this.logger.warn('Automatic session refresh failed', this.buildLoggerExtra('refreshSessionAutomatically', {
1425
+ session_id: this.sessionId,
1426
+ }));
1385
1427
  }
1386
1428
  } catch (error) {
1387
- console.warn('[FinaticConnect] Automatic session refresh error:', error);
1429
+ this.logger.exception('Automatic session refresh error', error, this.buildLoggerExtra('refreshSessionAutomatically', {
1430
+ session_id: this.sessionId,
1431
+ }));
1388
1432
  // Don't throw errors during automatic refresh - just log them
1389
1433
  }
1390
1434
  }
@@ -1406,7 +1450,9 @@ export class FinaticConnect extends EventEmitter {
1406
1450
  private async handleVisibilityChange(): Promise<void> {
1407
1451
  // For 24-hour sessions, we don't want to complete sessions on visibility changes
1408
1452
  // This prevents sessions from being closed when users switch tabs or apps
1409
- console.log('[FinaticConnect] Page visibility changed to:', document.visibilityState);
1453
+ this.logger.debug('Page visibility changed', this.buildLoggerExtra('handleVisibilityChange', {
1454
+ visibility_state: document.visibilityState,
1455
+ }));
1410
1456
 
1411
1457
  // Only pause keep-alive when hidden, but don't complete the session
1412
1458
  if (document.visibilityState === 'hidden') {
@@ -1431,7 +1477,7 @@ export class FinaticConnect extends EventEmitter {
1431
1477
 
1432
1478
  if (isMockMode) {
1433
1479
  // Mock the completion response
1434
- console.log('[FinaticConnect] Mock session completion for session:', sessionId);
1480
+ this.logger.debug('Mock session completion', this.buildLoggerExtra('completeSession', { session_id: sessionId }));
1435
1481
  return;
1436
1482
  }
1437
1483
 
@@ -1444,13 +1490,16 @@ export class FinaticConnect extends EventEmitter {
1444
1490
  });
1445
1491
 
1446
1492
  if (response.ok) {
1447
- console.log('[FinaticConnect] Session completed successfully');
1493
+ this.logger.info('Session completed successfully', this.buildLoggerExtra('completeSession', { session_id: sessionId }));
1448
1494
  } else {
1449
- console.warn('[FinaticConnect] Failed to complete session:', response.status);
1495
+ this.logger.warn('Failed to complete session', this.buildLoggerExtra('completeSession', {
1496
+ session_id: sessionId,
1497
+ response_status: response.status,
1498
+ }));
1450
1499
  }
1451
1500
  } catch (error) {
1452
1501
  // Silent failure - don't throw errors during cleanup
1453
- console.warn('[FinaticConnect] Session cleanup failed:', error);
1502
+ this.logger.exception('Session cleanup failed', error, this.buildLoggerExtra('completeSession', { session_id: sessionId }));
1454
1503
  }
1455
1504
  }
1456
1505
 
@@ -1,3 +1,9 @@
1
+ import { setupLogger, buildLoggerExtra, LoggerExtra } from '../../lib/logger';
2
+
3
+ const portalLogger = setupLogger('FinaticClientSDK.PortalUI', undefined, {
4
+ codebase: 'FinaticClientSDK',
5
+ });
6
+
1
7
  export class PortalUI {
2
8
  private iframe: HTMLIFrameElement | null = null;
3
9
  private container: HTMLDivElement | null = null;
@@ -12,12 +18,22 @@ export class PortalUI {
12
18
  };
13
19
  private originalBodyStyle: string | null = null;
14
20
 
21
+ private readonly logger = portalLogger;
22
+
15
23
  constructor(portalUrl: string) {
16
24
  this.createContainer();
17
25
  }
18
26
 
27
+ private buildLoggerExtra(functionName: string, metadata?: Record<string, unknown>): LoggerExtra {
28
+ return {
29
+ module: 'PortalUI',
30
+ function: functionName,
31
+ ...(metadata ? buildLoggerExtra(metadata) : {}),
32
+ };
33
+ }
34
+
19
35
  private createContainer(): void {
20
- console.debug('[PortalUI] Creating container and iframe');
36
+ this.logger.debug('Creating portal container and iframe', this.buildLoggerExtra('createContainer'));
21
37
  this.container = document.createElement('div');
22
38
  this.container.style.cssText = `
23
39
  position: fixed;
@@ -74,7 +90,7 @@ export class PortalUI {
74
90
 
75
91
  this.container.appendChild(this.iframe);
76
92
  document.body.appendChild(this.container);
77
- console.debug('[PortalUI] Container and iframe created successfully');
93
+ this.logger.debug('Portal container and iframe created successfully', this.buildLoggerExtra('createContainer'));
78
94
  }
79
95
 
80
96
  /**
@@ -91,7 +107,7 @@ export class PortalUI {
91
107
  document.body.style.width = '100%';
92
108
  document.body.style.top = `-${window.scrollY}px`;
93
109
 
94
- console.debug('[PortalUI] Background scroll locked');
110
+ this.logger.debug('Background scroll locked', this.buildLoggerExtra('lockScroll'));
95
111
  }
96
112
  }
97
113
 
@@ -110,7 +126,7 @@ export class PortalUI {
110
126
  window.scrollTo(0, parseInt(scrollY || '0') * -1);
111
127
 
112
128
  this.originalBodyStyle = null;
113
- console.debug('[PortalUI] Background scroll unlocked');
129
+ this.logger.debug('Background scroll unlocked', this.buildLoggerExtra('unlockScroll'));
114
130
  }
115
131
  }
116
132
 
@@ -168,17 +184,18 @@ export class PortalUI {
168
184
  private handleMessage(event: MessageEvent): void {
169
185
  // Verify origin matches the portal URL
170
186
  if (!this.portalOrigin || event.origin !== this.portalOrigin) {
171
- console.warn(
172
- '[PortalUI] Received message from unauthorized origin:',
173
- event.origin,
174
- 'Expected:',
175
- this.portalOrigin
176
- );
187
+ this.logger.warn('Received message from unauthorized origin', this.buildLoggerExtra('handleMessage', {
188
+ received_origin: event.origin,
189
+ expected_origin: this.portalOrigin || 'unknown',
190
+ }));
177
191
  return;
178
192
  }
179
193
 
180
194
  const { type, userId, access_token, refresh_token, error, height, data } = event.data;
181
- console.log('[PortalUI] Received message:', event.data);
195
+ this.logger.debug('Received portal message', this.buildLoggerExtra('handleMessage', {
196
+ message_type: type,
197
+ has_data: Boolean(data),
198
+ }));
182
199
 
183
200
  switch (type) {
184
201
  case 'portal-success': {
@@ -225,19 +242,26 @@ export class PortalUI {
225
242
  break;
226
243
 
227
244
  default:
228
- console.warn('[PortalUI] Received unhandled message type:', type);
245
+ this.logger.warn('Received unhandled message type', this.buildLoggerExtra('handleMessage', {
246
+ message_type: type,
247
+ }));
229
248
  }
230
249
  }
231
250
 
232
251
  private handlePortalSuccess(userId: string, tokens?: { access_token?: string; refresh_token?: string }): void {
233
252
  if (!userId) {
234
- console.error('[PortalUI] Missing userId in portal-success message');
253
+ this.logger.error('Missing userId in portal-success message', this.buildLoggerExtra('handlePortalSuccess'));
235
254
  return;
236
255
  }
237
256
 
238
- console.log('[PortalUI] Portal success - User connected:', userId);
257
+ this.logger.info('Portal success - user connected', this.buildLoggerExtra('handlePortalSuccess', {
258
+ user_id_present: Boolean(userId),
259
+ tokens_provided: Boolean(tokens?.access_token && tokens?.refresh_token),
260
+ }));
239
261
  if (tokens?.access_token && tokens?.refresh_token) {
240
- console.log('[PortalUI] Tokens received for user:', userId);
262
+ this.logger.debug('Tokens received for user', this.buildLoggerExtra('handlePortalSuccess', {
263
+ tokens_provided: true,
264
+ }));
241
265
  }
242
266
 
243
267
  // Pass userId to parent (SDK will handle tokens internally)
@@ -245,23 +269,30 @@ export class PortalUI {
245
269
  }
246
270
 
247
271
  private handlePortalError(error: string): void {
248
- console.error('[PortalUI] Portal error:', error);
272
+ this.logger.error('Portal error received', this.buildLoggerExtra('handlePortalError', {
273
+ error_message: error,
274
+ }));
249
275
  this.options?.onError?.(new Error(error || 'Unknown portal error'));
250
276
  }
251
277
 
252
278
  private handlePortalClose(): void {
253
- console.log('[PortalUI] Portal closed by user');
279
+ this.logger.info('Portal closed by user', this.buildLoggerExtra('handlePortalClose'));
254
280
  this.options?.onClose?.();
255
281
  this.hide();
256
282
  }
257
283
 
258
284
  private handleGenericEvent(data: any): void {
259
285
  if (!data || !data.type) {
260
- console.warn('[PortalUI] Invalid event data:', data);
286
+ this.logger.warn('Invalid event data received', this.buildLoggerExtra('handleGenericEvent', {
287
+ has_type: Boolean(data?.type),
288
+ }));
261
289
  return;
262
290
  }
263
291
 
264
- console.log('[PortalUI] Generic event received:', data.type, data.data);
292
+ this.logger.debug('Generic event received', this.buildLoggerExtra('handleGenericEvent', {
293
+ event_type: data.type,
294
+ payload_present: Boolean(data.data),
295
+ }));
265
296
 
266
297
  // Emit the event to be handled by the SDK
267
298
  // This will be implemented in FinaticConnect
@@ -272,7 +303,7 @@ export class PortalUI {
272
303
 
273
304
  private handleSuccess(userId: string): void {
274
305
  if (!userId) {
275
- console.error('[PortalUI] Missing required fields in success message');
306
+ this.logger.error('Missing required fields in success message', this.buildLoggerExtra('handleSuccess'));
276
307
  return;
277
308
  }
278
309
 
@@ -281,19 +312,23 @@ export class PortalUI {
281
312
  }
282
313
 
283
314
  private handleError(error: string): void {
284
- console.error('[PortalUI] Received error:', error);
315
+ this.logger.error('Received portal error message', this.buildLoggerExtra('handleError', {
316
+ error_message: error,
317
+ }));
285
318
  this.options?.onError?.(new Error(error || 'Unknown error'));
286
319
  }
287
320
 
288
321
  private handleClose(): void {
289
- console.log('[PortalUI] Received close message');
322
+ this.logger.debug('Received close message', this.buildLoggerExtra('handleClose'));
290
323
  this.options?.onClose?.();
291
324
  this.hide();
292
325
  }
293
326
 
294
327
  private handleResize(height: number): void {
295
328
  if (height && this.iframe) {
296
- console.log('[PortalUI] Received resize message:', height);
329
+ this.logger.debug('Received resize message', this.buildLoggerExtra('handleResize', {
330
+ height,
331
+ }));
297
332
  this.iframe.style.height = `${height}px`;
298
333
  }
299
334
  }