clintplay-react-native 0.1.0 → 0.2.1

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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Session capture SDK for React Native / Expo apps — companion to [`clintplay-sdk`](../sdk) (web). Captures lifecycle, screen dimensions, navigation, JS errors, network requests (Fetch & XHR/Axios), console output, touches (screen-relative & target-relative), and native visual wireframe replay on iOS and Android.
4
4
 
5
- > **Status:** `0.1.0` — Production-ready JS runtime and Native TurboModule. Supports native view hierarchy traversal on iOS (`ios/ClintplayRN.mm`) and Android (`android/.../ClintplayRNModule.kt`), visual wireframe session replay, network interception for `fetch` and `XMLHttpRequest`/Axios, automatic navigation tracking, and intelligent auto-masking for sensitive fields.
5
+ > **Status:** `0.2.1` — Production-ready JS runtime and Native TurboModule. Supports native view hierarchy traversal on iOS (`ios/ClintplayRN.mm`) and Android (`android/.../ClintplayRNModule.kt`), visual wireframe session replay, network interception for `fetch` and `XMLHttpRequest`/Axios, automatic navigation tracking, and intelligent auto-masking for sensitive fields.
6
6
 
7
7
  ## Install
8
8
 
@@ -81,7 +81,7 @@ export default function RootLayout() {
81
81
  | `enabled` | `boolean` | `true` | Master killswitch. Set to `false` to disable all telemetry. |
82
82
  | `sampleRate` | `number` | `1.0` | Probabilistic sampling rate between `0.0` and `1.0`. |
83
83
  | `captureWireframe` | `boolean` | `false` | Enable native view-hierarchy visual wireframe capture for session replay. |
84
- | `wireframeIntervalMs` | `number` | `1000` | Wireframe snapshot interval in milliseconds. |
84
+ | `wireframeIntervalMs` | `number` | `1000` | Wireframe snapshot interval in milliseconds. A snapshot identical to the previous one is not re-sent (an unchanged screen is re-sent every 30 s), and a snapshot is also taken ~400 ms after every touch end and navigation, so screens visited for less than the interval still reach the replay. |
85
85
  | `captureNetwork` | `boolean` | `true` | Intercept `globalThis.fetch` and `XMLHttpRequest` (including Axios) requests. |
86
86
  | `captureConsole` | `boolean` | `false` | Intercept `console.warn` and `console.error` logs. |
87
87
  | `captureConsoleLog` | `boolean` | `false` | Intercept `console.log` logs when `captureConsole: true`. |
@@ -104,7 +104,7 @@ export default function RootLayout() {
104
104
  | `network` | `fetch` & `XMLHttpRequest` / Axios | **On** | HTTP method, URL (sanitized), status code, duration, and errors. Protected against double-counting. |
105
105
  | `navigation` | Navigation Trackers & `trackScreen` | **On (Tracker)** | Screen path changes (`to`, `from`). Automatic via `<ClintplayNavigationTracker />` or React Navigation listener. |
106
106
  | `touch` | `<ClintplayCaptureProvider>` | **Provider** | Tap / touch gestures with both screen-relative coordinates (`screenX`, `screenY`) and target-relative coordinates (`x`, `y`). |
107
- | `wireframe` | Native TurboModule | **Opt-in** | Visual UI hierarchy snapshots (view rects, styles, text, masking) across iOS and Android. |
107
+ | `wireframe` | Native TurboModule | **Opt-in** | Visual UI hierarchy snapshots (view rects, background colors, text with font size, color and alignment — plus weight on iOS, and bold on Android —, masking) across iOS and Android. Sent on change, after interactions, and every 30 s while unchanged. |
108
108
  | `log` | Console Interceptor | **Opt-in** | Console output (`warn`, `error`, and optional `log`). |
109
109
  | `identify` | `Clintplay.identify()` | **Manual** | Associating sessions with authenticated users and custom traits. |
110
110
 
@@ -2,13 +2,19 @@ package digital.clint.clintplay
2
2
 
3
3
  import android.app.Activity
4
4
  import android.content.Context
5
+ import android.graphics.Typeface
5
6
  import android.graphics.drawable.ColorDrawable
6
7
  import android.graphics.drawable.Drawable
7
8
  import android.os.Build
8
9
  import android.os.Handler
9
10
  import android.os.Looper
10
11
  import android.text.InputType
12
+ import android.text.Spanned
11
13
  import android.text.method.PasswordTransformationMethod
14
+ import android.text.style.AbsoluteSizeSpan
15
+ import android.text.style.ForegroundColorSpan
16
+ import android.text.style.StyleSpan
17
+ import android.view.Gravity
12
18
  import android.view.View
13
19
  import android.view.ViewGroup
14
20
  import android.view.WindowManager
@@ -112,6 +118,45 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
112
118
  return false
113
119
  }
114
120
 
121
+ // React Native sets size and colour as spans on the text, so the spans at the first
122
+ // character win over the TextView's own defaults. Weight is only sent when bold is
123
+ // actually detected: RN carries it in its own CustomStyleSpan, which this does not read,
124
+ // and a guessed 400 would look measured. Best effort: the text alone already makes the
125
+ // replay readable.
126
+ private fun putTextStyle(node: JSONObject, view: TextView, density: Float) {
127
+ try {
128
+ val text = view.text
129
+ val safeDensity = if (density > 0f) density else 1f
130
+ var sizePx = view.textSize
131
+ var color = view.currentTextColor
132
+ var bold = view.typeface?.isBold == true
133
+ if (text is Spanned && text.isNotEmpty()) {
134
+ text.getSpans(0, 1, AbsoluteSizeSpan::class.java).lastOrNull()?.let { span ->
135
+ sizePx = if (span.dip) span.size * safeDensity else span.size.toFloat()
136
+ }
137
+ text.getSpans(0, 1, ForegroundColorSpan::class.java).lastOrNull()?.let { span ->
138
+ color = span.foregroundColor
139
+ }
140
+ if (text.getSpans(0, 1, StyleSpan::class.java).any { (it.style and Typeface.BOLD) != 0 }) {
141
+ bold = true
142
+ }
143
+ }
144
+ node.put("fontSize", round(sizePx / safeDensity * 10.0) / 10.0)
145
+ if (bold) node.put("fontWeight", 700)
146
+ node.put("color", formatColor(color))
147
+ val horizontal = Gravity.getAbsoluteGravity(view.gravity, view.layoutDirection) and
148
+ Gravity.HORIZONTAL_GRAVITY_MASK
149
+ node.put(
150
+ "textAlign",
151
+ when (horizontal) {
152
+ Gravity.CENTER_HORIZONTAL -> "center"
153
+ Gravity.RIGHT -> "right"
154
+ else -> "left"
155
+ },
156
+ )
157
+ } catch (_: Throwable) {}
158
+ }
159
+
115
160
  private fun serializeView(
116
161
  view: View?,
117
162
  nodeCounter: AtomicInteger,
@@ -206,6 +251,9 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
206
251
  var extractedText: String? = null
207
252
  if (view is TextView) {
208
253
  extractedText = view.text?.toString()
254
+ if (!isMasked && !extractedText.isNullOrEmpty()) {
255
+ putTextStyle(nodeObj, view, density)
256
+ }
209
257
  }
210
258
 
211
259
  if (extractedText != null) {
@@ -328,7 +376,7 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
328
376
 
329
377
  companion object {
330
378
  const val NAME = "ClintplayRN"
331
- private const val VERSION = "0.1.0"
379
+ private const val VERSION = "0.2.1"
332
380
  private const val FALLBACK_JSON = "{\"version\":1,\"nodes\":[]}"
333
381
 
334
382
  private val NO_METHOD_SENTINEL = Any()
package/dist/index.d.mts CHANGED
@@ -2,6 +2,25 @@ import React from 'react';
2
2
  import { ViewProps, View, TextInputProps, TextInput, ImageProps, Image, StyleProp, ViewStyle } from 'react-native';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
+ interface SessionState {
6
+ sessionId: string;
7
+ startedAt: number;
8
+ lastActivity: number;
9
+ userId: string | null;
10
+ }
11
+ declare class SessionManager {
12
+ private state;
13
+ private readonly now;
14
+ constructor(now?: () => number);
15
+ private create;
16
+ current(): SessionState;
17
+ touch(): void;
18
+ setUser(userId: string | null): boolean;
19
+ isStale(): boolean;
20
+ rotateIfStale(): boolean;
21
+ reset(): void;
22
+ }
23
+
5
24
  type EventType = 'meta' | 'screen' | 'lifecycle' | 'navigation' | 'touch' | 'error' | 'log' | 'identify' | 'network' | 'wireframe';
6
25
  interface DeviceInfo {
7
26
  platform: 'ios' | 'android' | 'web';
@@ -59,8 +78,10 @@ interface LogEvent {
59
78
  interface IdentifyEvent {
60
79
  type: 'identify';
61
80
  ts: number;
62
- userId: string | null;
63
- traits?: Record<string, unknown>;
81
+ data: {
82
+ userId: string | null;
83
+ traits?: Record<string, unknown>;
84
+ };
64
85
  }
65
86
  interface NetworkEvent {
66
87
  type: 'network';
@@ -112,7 +133,8 @@ interface ReplayBatch {
112
133
  sdkVersion?: string;
113
134
  }
114
135
  interface ClintplayReactNativeConfig {
115
- apiUrl: string;
136
+ apiUrl?: string;
137
+ endpoint?: string;
116
138
  apiKey?: string;
117
139
  projectId?: string;
118
140
  anonId?: string;
@@ -139,6 +161,111 @@ interface AsyncStorageLike {
139
161
  multiRemove(keys: readonly string[]): Promise<void>;
140
162
  }
141
163
 
164
+ interface TransportConfig {
165
+ apiUrl: string;
166
+ apiKey?: string;
167
+ projectId?: string;
168
+ maxRetries?: number;
169
+ timeoutMs?: number;
170
+ backoffMs?: (attempt: number) => number;
171
+ }
172
+ interface TransportResult {
173
+ ok: boolean;
174
+ status?: number;
175
+ retryable?: boolean;
176
+ }
177
+ declare class Transport {
178
+ private readonly cfg;
179
+ constructor(cfg: TransportConfig);
180
+ sendDetailed(batch: ReplayBatch): Promise<TransportResult>;
181
+ send(batch: ReplayBatch): Promise<boolean>;
182
+ private headers;
183
+ }
184
+
185
+ interface Recorder {
186
+ start(): void;
187
+ stop(): void;
188
+ takeWireframeSnapshot(): void;
189
+ /** Captura depois que a interação assenta (toque, navegação). Chamadas próximas viram uma. */
190
+ scheduleWireframeSnapshot(): void;
191
+ /** A próxima captura é enviada mesmo igual à anterior (sessão nova precisa da tela). */
192
+ resetWireframeBaseline(): void;
193
+ }
194
+
195
+ interface NetworkInterceptorDeps {
196
+ onEvent: (event: ReplayEvent) => void;
197
+ now: () => number;
198
+ sanitizeUrl?: (url: string) => string;
199
+ apiUrl?: string;
200
+ }
201
+ declare class NetworkInterceptor {
202
+ private readonly deps;
203
+ private originalFetch;
204
+ private wrappedFetch;
205
+ private originalXHROpen;
206
+ private wrappedXHROpen;
207
+ private originalXHRSend;
208
+ private wrappedXHRSend;
209
+ private started;
210
+ private isCallingFetchSync;
211
+ private readonly sanitize;
212
+ private readonly ingestOrigin;
213
+ private readonly ingestPath;
214
+ constructor(deps: NetworkInterceptorDeps);
215
+ private isSelfIngestUrl;
216
+ start(): void;
217
+ stop(): void;
218
+ private extractUrl;
219
+ private extractMethod;
220
+ }
221
+
222
+ interface ConsoleInterceptorDeps {
223
+ onEvent: (event: ReplayEvent) => void;
224
+ now: () => number;
225
+ maxMessageLength?: number;
226
+ captureConsoleLog?: boolean;
227
+ }
228
+ declare class ConsoleInterceptor {
229
+ private readonly deps;
230
+ private readonly originals;
231
+ private readonly wrapped;
232
+ private started;
233
+ private isEmitting;
234
+ private readonly maxLength;
235
+ constructor(deps: ConsoleInterceptorDeps);
236
+ start(): void;
237
+ private wrapMethod;
238
+ stop(): void;
239
+ private formatMessage;
240
+ }
241
+
242
+ type SendBatchResult = boolean | {
243
+ ok: boolean;
244
+ status?: number;
245
+ retryable?: boolean;
246
+ };
247
+ interface OfflineQueueDeps {
248
+ storage: AsyncStorageLike;
249
+ send: (batch: ReplayBatch) => Promise<SendBatchResult>;
250
+ maxBytes?: number;
251
+ keyPrefix?: string;
252
+ debug?: (msg: string) => void;
253
+ }
254
+ declare class OfflineQueue {
255
+ private readonly deps;
256
+ private currentBytes;
257
+ private seq;
258
+ private readonly prefix;
259
+ private readonly maxBytes;
260
+ private hydrationPromise;
261
+ constructor(deps: OfflineQueueDeps);
262
+ hydrate(force?: boolean): Promise<void>;
263
+ persist(batch: ReplayBatch): Promise<void>;
264
+ drain(): Promise<number>;
265
+ clear(): Promise<void>;
266
+ private evictUntilFits;
267
+ }
268
+
142
269
  declare const CLINTPLAY_MASK_ID = "clintplay-mask";
143
270
  interface ClintplayMaskViewProps extends ViewProps {
144
271
  children?: React.ReactNode;
@@ -252,9 +379,20 @@ declare function _resetLastTrackedRoute(): void;
252
379
  declare function useClintplayNavigationTracking(routeNameOrPath?: string, options?: UseClintplayNavigationOptions): UseClintplayNavigationResult;
253
380
 
254
381
  declare const SDK_VERSION: string;
382
+ interface InternalConfig {
383
+ apiUrl: string;
384
+ apiKey?: string;
385
+ projectId: string;
386
+ anonId?: string;
387
+ flushIntervalMs: number;
388
+ flushSize: number;
389
+ maxBufferSize: number;
390
+ debug: boolean;
391
+ captureWireframe: boolean;
392
+ }
255
393
  declare function formatEventForBatch(event: ReplayEvent | BackendEvent, defaultSessionId: string): BackendEvent;
256
- declare function init(rawConfig: ClintplayReactNativeConfig): void;
257
- declare function identify(userId: string | null, traits?: Record<string, unknown>): void;
394
+ declare function init(rawConfig: ClintplayReactNativeConfig): typeof Clintplay;
395
+ declare function identify(userId: string | number | null, traits?: Record<string, unknown>): void;
258
396
  declare function reset(options?: {
259
397
  clearOfflineQueue?: boolean;
260
398
  }): void;
@@ -266,6 +404,19 @@ declare function current(): {
266
404
  sessionId: string;
267
405
  userId: string | null;
268
406
  } | null;
407
+ declare function _getState(): {
408
+ buffer: readonly ReplayEvent[];
409
+ config: InternalConfig;
410
+ session: SessionManager;
411
+ transport: Transport;
412
+ recorder: Recorder;
413
+ networkInterceptor: NetworkInterceptor | null;
414
+ consoleInterceptor: ConsoleInterceptor | null;
415
+ offlineQueue: OfflineQueue | null;
416
+ flushTimer: ReturnType<typeof setInterval> | null;
417
+ excluded: ReadonlySet<EventType>;
418
+ active: boolean;
419
+ } | null;
269
420
  declare const Clintplay: {
270
421
  init: typeof init;
271
422
  identify: typeof identify;
@@ -275,6 +426,7 @@ declare const Clintplay: {
275
426
  flush: typeof flush;
276
427
  stop: typeof stop;
277
428
  current: typeof current;
429
+ _getState: typeof _getState;
278
430
  };
279
431
 
280
- export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, sanitizeRoute, useClintplayNavigationTracking };
432
+ export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeRoute, useClintplayNavigationTracking };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,25 @@ import React from 'react';
2
2
  import { ViewProps, View, TextInputProps, TextInput, ImageProps, Image, StyleProp, ViewStyle } from 'react-native';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
+ interface SessionState {
6
+ sessionId: string;
7
+ startedAt: number;
8
+ lastActivity: number;
9
+ userId: string | null;
10
+ }
11
+ declare class SessionManager {
12
+ private state;
13
+ private readonly now;
14
+ constructor(now?: () => number);
15
+ private create;
16
+ current(): SessionState;
17
+ touch(): void;
18
+ setUser(userId: string | null): boolean;
19
+ isStale(): boolean;
20
+ rotateIfStale(): boolean;
21
+ reset(): void;
22
+ }
23
+
5
24
  type EventType = 'meta' | 'screen' | 'lifecycle' | 'navigation' | 'touch' | 'error' | 'log' | 'identify' | 'network' | 'wireframe';
6
25
  interface DeviceInfo {
7
26
  platform: 'ios' | 'android' | 'web';
@@ -59,8 +78,10 @@ interface LogEvent {
59
78
  interface IdentifyEvent {
60
79
  type: 'identify';
61
80
  ts: number;
62
- userId: string | null;
63
- traits?: Record<string, unknown>;
81
+ data: {
82
+ userId: string | null;
83
+ traits?: Record<string, unknown>;
84
+ };
64
85
  }
65
86
  interface NetworkEvent {
66
87
  type: 'network';
@@ -112,7 +133,8 @@ interface ReplayBatch {
112
133
  sdkVersion?: string;
113
134
  }
114
135
  interface ClintplayReactNativeConfig {
115
- apiUrl: string;
136
+ apiUrl?: string;
137
+ endpoint?: string;
116
138
  apiKey?: string;
117
139
  projectId?: string;
118
140
  anonId?: string;
@@ -139,6 +161,111 @@ interface AsyncStorageLike {
139
161
  multiRemove(keys: readonly string[]): Promise<void>;
140
162
  }
141
163
 
164
+ interface TransportConfig {
165
+ apiUrl: string;
166
+ apiKey?: string;
167
+ projectId?: string;
168
+ maxRetries?: number;
169
+ timeoutMs?: number;
170
+ backoffMs?: (attempt: number) => number;
171
+ }
172
+ interface TransportResult {
173
+ ok: boolean;
174
+ status?: number;
175
+ retryable?: boolean;
176
+ }
177
+ declare class Transport {
178
+ private readonly cfg;
179
+ constructor(cfg: TransportConfig);
180
+ sendDetailed(batch: ReplayBatch): Promise<TransportResult>;
181
+ send(batch: ReplayBatch): Promise<boolean>;
182
+ private headers;
183
+ }
184
+
185
+ interface Recorder {
186
+ start(): void;
187
+ stop(): void;
188
+ takeWireframeSnapshot(): void;
189
+ /** Captura depois que a interação assenta (toque, navegação). Chamadas próximas viram uma. */
190
+ scheduleWireframeSnapshot(): void;
191
+ /** A próxima captura é enviada mesmo igual à anterior (sessão nova precisa da tela). */
192
+ resetWireframeBaseline(): void;
193
+ }
194
+
195
+ interface NetworkInterceptorDeps {
196
+ onEvent: (event: ReplayEvent) => void;
197
+ now: () => number;
198
+ sanitizeUrl?: (url: string) => string;
199
+ apiUrl?: string;
200
+ }
201
+ declare class NetworkInterceptor {
202
+ private readonly deps;
203
+ private originalFetch;
204
+ private wrappedFetch;
205
+ private originalXHROpen;
206
+ private wrappedXHROpen;
207
+ private originalXHRSend;
208
+ private wrappedXHRSend;
209
+ private started;
210
+ private isCallingFetchSync;
211
+ private readonly sanitize;
212
+ private readonly ingestOrigin;
213
+ private readonly ingestPath;
214
+ constructor(deps: NetworkInterceptorDeps);
215
+ private isSelfIngestUrl;
216
+ start(): void;
217
+ stop(): void;
218
+ private extractUrl;
219
+ private extractMethod;
220
+ }
221
+
222
+ interface ConsoleInterceptorDeps {
223
+ onEvent: (event: ReplayEvent) => void;
224
+ now: () => number;
225
+ maxMessageLength?: number;
226
+ captureConsoleLog?: boolean;
227
+ }
228
+ declare class ConsoleInterceptor {
229
+ private readonly deps;
230
+ private readonly originals;
231
+ private readonly wrapped;
232
+ private started;
233
+ private isEmitting;
234
+ private readonly maxLength;
235
+ constructor(deps: ConsoleInterceptorDeps);
236
+ start(): void;
237
+ private wrapMethod;
238
+ stop(): void;
239
+ private formatMessage;
240
+ }
241
+
242
+ type SendBatchResult = boolean | {
243
+ ok: boolean;
244
+ status?: number;
245
+ retryable?: boolean;
246
+ };
247
+ interface OfflineQueueDeps {
248
+ storage: AsyncStorageLike;
249
+ send: (batch: ReplayBatch) => Promise<SendBatchResult>;
250
+ maxBytes?: number;
251
+ keyPrefix?: string;
252
+ debug?: (msg: string) => void;
253
+ }
254
+ declare class OfflineQueue {
255
+ private readonly deps;
256
+ private currentBytes;
257
+ private seq;
258
+ private readonly prefix;
259
+ private readonly maxBytes;
260
+ private hydrationPromise;
261
+ constructor(deps: OfflineQueueDeps);
262
+ hydrate(force?: boolean): Promise<void>;
263
+ persist(batch: ReplayBatch): Promise<void>;
264
+ drain(): Promise<number>;
265
+ clear(): Promise<void>;
266
+ private evictUntilFits;
267
+ }
268
+
142
269
  declare const CLINTPLAY_MASK_ID = "clintplay-mask";
143
270
  interface ClintplayMaskViewProps extends ViewProps {
144
271
  children?: React.ReactNode;
@@ -252,9 +379,20 @@ declare function _resetLastTrackedRoute(): void;
252
379
  declare function useClintplayNavigationTracking(routeNameOrPath?: string, options?: UseClintplayNavigationOptions): UseClintplayNavigationResult;
253
380
 
254
381
  declare const SDK_VERSION: string;
382
+ interface InternalConfig {
383
+ apiUrl: string;
384
+ apiKey?: string;
385
+ projectId: string;
386
+ anonId?: string;
387
+ flushIntervalMs: number;
388
+ flushSize: number;
389
+ maxBufferSize: number;
390
+ debug: boolean;
391
+ captureWireframe: boolean;
392
+ }
255
393
  declare function formatEventForBatch(event: ReplayEvent | BackendEvent, defaultSessionId: string): BackendEvent;
256
- declare function init(rawConfig: ClintplayReactNativeConfig): void;
257
- declare function identify(userId: string | null, traits?: Record<string, unknown>): void;
394
+ declare function init(rawConfig: ClintplayReactNativeConfig): typeof Clintplay;
395
+ declare function identify(userId: string | number | null, traits?: Record<string, unknown>): void;
258
396
  declare function reset(options?: {
259
397
  clearOfflineQueue?: boolean;
260
398
  }): void;
@@ -266,6 +404,19 @@ declare function current(): {
266
404
  sessionId: string;
267
405
  userId: string | null;
268
406
  } | null;
407
+ declare function _getState(): {
408
+ buffer: readonly ReplayEvent[];
409
+ config: InternalConfig;
410
+ session: SessionManager;
411
+ transport: Transport;
412
+ recorder: Recorder;
413
+ networkInterceptor: NetworkInterceptor | null;
414
+ consoleInterceptor: ConsoleInterceptor | null;
415
+ offlineQueue: OfflineQueue | null;
416
+ flushTimer: ReturnType<typeof setInterval> | null;
417
+ excluded: ReadonlySet<EventType>;
418
+ active: boolean;
419
+ } | null;
269
420
  declare const Clintplay: {
270
421
  init: typeof init;
271
422
  identify: typeof identify;
@@ -275,6 +426,7 @@ declare const Clintplay: {
275
426
  flush: typeof flush;
276
427
  stop: typeof stop;
277
428
  current: typeof current;
429
+ _getState: typeof _getState;
278
430
  };
279
431
 
280
- export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, sanitizeRoute, useClintplayNavigationTracking };
432
+ export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeRoute, useClintplayNavigationTracking };