@sanctum-key/react-native-sdk 1.0.57 → 1.0.58

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.
@@ -1,6 +1,13 @@
1
1
  import { Platform, AppState, AppStateStatus } from 'react-native';
2
- import axios from 'axios';
3
- import KYCConfig from '../config/KYCConfig';
2
+ import PostHog from 'posthog-react-native';
3
+
4
+ const posthogClient = new PostHog('phc_qjCHjCgkdVniammXrrfLrmNPoPH5uAmkzoQMhrEhGaYR', {
5
+ host: 'https://eu.i.posthog.com',
6
+ disabled: false,
7
+ captureAppLifecycleEvents: false,
8
+ flushAt: 1,
9
+ flushInterval: 1000, // Backup: flush automatically every 1 second
10
+ });
4
11
 
5
12
  const isProduction = (): boolean => {
6
13
  if (typeof __DEV__ !== 'undefined') {
@@ -11,7 +18,6 @@ const isProduction = (): boolean => {
11
18
  }
12
19
  return false;
13
20
  };
14
-
15
21
  const IS_PROD = isProduction();
16
22
 
17
23
  export const logger = {
@@ -23,32 +29,16 @@ export const logger = {
23
29
  };
24
30
 
25
31
  // ==========================================
26
- // 2. SDK TELEMETRY LOGGER (REMOTE)
32
+ // 2. SDK TELEMETRY LOGGER (POSTHOG ONLY)
27
33
  // ==========================================
28
- // 🚨 FIX 1: Changed 'warn' to 'warning' to match backend enums
29
- type LogLevel = 'info' | 'warning' | 'error' | 'debug';
30
-
31
- interface LogEntry {
32
- level: LogLevel;
33
- message: string;
34
- timestamp: string;
35
- session_id?: string;
36
- metadata?: any;
37
- }
34
+ type LogLevel = 'info' | 'warning' | 'error' | 'debug';
38
35
 
39
36
  class SDKTelemetryLogger {
40
- private queue: LogEntry[] = [];
41
- private isFlushing = false;
42
- private maxQueueSize = 3;
43
- private flushIntervalMs = 3000;
44
37
  private sessionId: string | undefined;
45
- private apiKey: string | undefined;
46
- private timerId?: ReturnType<typeof setInterval>;
47
38
  private appStateSubscription: any;
48
39
 
49
40
  constructor() {
50
- this.timerId = setInterval(() => this.flush(), this.flushIntervalMs);
51
-
41
+ // Flush PostHog when the app goes into the background
52
42
  if (Platform.OS !== 'web') {
53
43
  this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);
54
44
  }
@@ -62,29 +52,33 @@ class SDKTelemetryLogger {
62
52
 
63
53
  public setSessionId(id: string) {
64
54
  this.sessionId = id;
65
-
66
- this.queue = this.queue.map(log => {
67
- if (!log.session_id) {
68
- return { ...log, session_id: id };
69
- }
70
- return log;
55
+ posthogClient.identify(id, {
56
+ kyc_session_id: id,
71
57
  });
72
-
73
- this.flush();
74
58
  }
75
59
 
76
60
  public clearSessionId() {
77
61
  this.sessionId = undefined;
62
+ posthogClient.reset(); // Clears identity
78
63
  }
79
64
 
80
- public setApiKey(key: string) {
81
- this.apiKey = key;
65
+ // Kept as a no-op just in case your SDK still calls this somewhere
66
+ public setApiKey(_key: string) {
67
+ // No longer needed for PostHog
68
+ }
69
+
70
+ public track(eventName: string, properties?: Record<string, any>) {
71
+ posthogClient.capture(`[SanctumKey] ${eventName}`, {
72
+ session_id: this.sessionId || null,
73
+ os: Platform.OS,
74
+ osVersion: Platform.Version,
75
+ ...properties,
76
+ });
82
77
  }
83
78
 
84
79
  private parseArgs(args: any[]): { message: string, metadata: any } {
85
80
  let message = '';
86
81
  let metadata: any = {};
87
-
88
82
  args.forEach(arg => {
89
83
  if (typeof arg === 'string') {
90
84
  message += (message ? ' ' : '') + arg;
@@ -97,7 +91,6 @@ class SDKTelemetryLogger {
97
91
  message += (message ? ' ' : '') + String(arg);
98
92
  }
99
93
  });
100
-
101
94
  return { message: message || 'No message provided', metadata };
102
95
  }
103
96
 
@@ -107,77 +100,33 @@ class SDKTelemetryLogger {
107
100
  if (!IS_PROD) {
108
101
  const devPrefix = `[SDK_TELEMETRY_${level.toUpperCase()}]`;
109
102
  if (level === 'error') console.error(devPrefix, message, metadata);
110
- else if (level === 'warning') console.warn(devPrefix, message, metadata); // Match updated level
103
+ else if (level === 'warning') console.warn(devPrefix, message, metadata);
111
104
  else console.log(devPrefix, message, metadata);
112
105
  }
113
106
 
114
- const entry: LogEntry = {
115
- level,
116
- message: message.substring(0, 500),
117
- timestamp: new Date().toISOString(),
118
- session_id: this.sessionId,
119
- metadata: {
120
- ...metadata,
121
- os: Platform.OS,
122
- osVersion: Platform.Version,
123
- }
107
+ const payloadMetadata = {
108
+ ...metadata,
109
+ os: Platform.OS,
110
+ osVersion: Platform.Version,
124
111
  };
125
112
 
126
- this.queue.push(entry);
127
-
128
- const isError = level === 'error';
129
- const hitLimit = this.queue.length >= this.maxQueueSize;
113
+ const levelLabel = level.toUpperCase();
114
+ posthogClient.capture(`[SanctumKey] ${message}`, {
115
+ session_id: this.sessionId || null,
116
+ log_level: levelLabel,
117
+ ...payloadMetadata,
118
+ });
130
119
 
131
- if (isError || (this.sessionId && hitLimit)) {
120
+ if (level === 'error') {
132
121
  this.flush();
133
122
  }
134
123
  }
135
124
 
136
125
  public async flush() {
137
- if (this.queue.length === 0 || this.isFlushing) return;
138
-
139
- const batch = this.queue.map(log => ({
140
- ...log,
141
- session_id: log.session_id || 'pre-session-startup'
142
- }));
143
-
144
- this.isFlushing = true;
145
- this.queue = [];
146
-
147
- try {
148
- const url = `${KYCConfig.getBackendUrl()}/core/sdk/logs/`;
149
-
150
- const headers: Record<string, string> = { 'Content-Type': 'application/json' };
151
- if (this.apiKey) {
152
- headers['Authorization'] = `ApiKey ${this.apiKey}`;
153
- }
154
-
155
- await axios.post(url, { logs: batch }, {
156
- headers,
157
- timeout: 5000
158
- });
159
- } catch (error: any) {
160
- // 🚨 FIX 2: Stop Infinite Loops
161
- // If the backend actively rejects our payload (400-499 error code), do NOT requeue it.
162
- const isClientError = error.response && error.response.status >= 400 && error.response.status < 500;
163
-
164
- if (!isClientError) {
165
- // Only retry if it's a network failure or a 5xx Server Error
166
- if (this.queue.length < 50) {
167
- this.queue = [...batch, ...this.queue].slice(0, 50);
168
- }
169
- } else {
170
- if (!IS_PROD) {
171
- console.error("[SDK_TELEMETRY] Backend rejected log payload. Dropping batch to prevent infinite loop.", error.response.data);
172
- }
173
- }
174
- } finally {
175
- this.isFlushing = false;
176
- }
126
+ await posthogClient.flush();
177
127
  }
178
128
 
179
129
  public destroy() {
180
- if (this.timerId) clearInterval(this.timerId);
181
130
  if (this.appStateSubscription) this.appStateSubscription.remove();
182
131
  this.flush();
183
132
  }
@@ -192,10 +141,10 @@ export const sdkLogger = {
192
141
  destroy: () => telemetryInstance.destroy(),
193
142
  setApiKey: (key: string) => telemetryInstance.setApiKey(key),
194
143
 
144
+ track: (eventName: string, properties?: Record<string, any>) => telemetryInstance.track(eventName, properties),
195
145
  log: (...args: any[]) => telemetryInstance.processLog('info', ...args),
196
146
  info: (...args: any[]) => telemetryInstance.processLog('info', ...args),
197
- // 🚨 FIX 1 (Continued): Map warn() function to send 'warning' to backend
198
- warn: (...args: any[]) => telemetryInstance.processLog('warning', ...args),
147
+ warn: (...args: any[]) => telemetryInstance.processLog('warning', ...args),
199
148
  error: (...args: any[]) => telemetryInstance.processLog('error', ...args),
200
149
  debug: (...args: any[]) => telemetryInstance.processLog('debug', ...args),
201
150
  };
@@ -42,7 +42,6 @@ interface VerificationSteps {
42
42
  liveness_checked?: boolean;
43
43
  }
44
44
 
45
- // 🚨 MODIFIED: Accepts the webhook secret to generate the signature
46
45
  const postWebhook = async (url: string, payload: unknown, secret?: string, timeoutMs: number = 5000) => {
47
46
  const body = JSON.stringify(payload);
48
47
 
@@ -50,7 +49,6 @@ const postWebhook = async (url: string, payload: unknown, secret?: string, timeo
50
49
  'Content-Type': 'application/json',
51
50
  };
52
51
 
53
- // 🚨 Generate HMAC SHA-256 Signature if secret is provided
54
52
  if (secret) {
55
53
  const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);
56
54
  headers['x-sanctumkey-signature'] = signature;