@simplr-ai/react-native 1.1.0 → 1.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.
@@ -1,3 +1,26 @@
1
+ type NetworkSource = "frontend" | "backend";
2
+ interface NetworkLogEntry {
3
+ id: string;
4
+ requestId?: string;
5
+ source: NetworkSource;
6
+ timestamp: string;
7
+ sdk?: string;
8
+ applicationId?: string;
9
+ environment?: string;
10
+ method: string;
11
+ url: string;
12
+ requestHeaders?: Record<string, string>;
13
+ requestBody?: unknown;
14
+ status?: number;
15
+ statusText?: string;
16
+ responseHeaders?: Record<string, string>;
17
+ responseBody?: unknown;
18
+ durationMs?: number;
19
+ ok?: boolean;
20
+ error?: string;
21
+ }
22
+ type NetworkLogger = (entry: NetworkLogEntry) => void;
23
+
1
24
  /**
2
25
  * Shared types mirroring the Simplr API contract (source of truth).
3
26
  * Keep byte-for-byte compatible with the browser/Node/Flutter SDKs.
@@ -332,12 +355,18 @@ interface SimplrProfilesConfig {
332
355
  timeoutMs?: number;
333
356
  /** Override fetch (defaults to the RN/global fetch). */
334
357
  fetchImpl?: typeof fetch;
358
+ onNetworkLog?: NetworkLogger;
359
+ logBodies?: boolean;
360
+ redactFields?: string[];
335
361
  }
336
362
  declare class SimplrProfiles {
337
363
  private apiKey;
338
364
  private baseUrl;
339
365
  private timeoutMs;
340
366
  private fetchImpl?;
367
+ private onNetworkLog?;
368
+ private logBodies?;
369
+ private redactFields?;
341
370
  private collectDeviceSignalsFn?;
342
371
  private configured;
343
372
  constructor(config?: SimplrProfilesConfig);
@@ -456,12 +485,18 @@ interface SimplrAIConfig {
456
485
  baseUrl?: string;
457
486
  timeoutMs?: number;
458
487
  fetchImpl?: typeof fetch;
488
+ onNetworkLog?: NetworkLogger;
489
+ logBodies?: boolean;
490
+ redactFields?: string[];
459
491
  }
460
492
  declare class SimplrAI {
461
493
  private apiKey;
462
494
  private baseUrl;
463
495
  private timeoutMs;
464
496
  private fetchImpl?;
497
+ private onNetworkLog?;
498
+ private logBodies?;
499
+ private redactFields?;
465
500
  private configured;
466
501
  constructor(config?: SimplrAIConfig);
467
502
  configure(config: SimplrAIConfig): this;
@@ -508,6 +543,13 @@ interface SimplrFraudConfig {
508
543
  autoStart?: boolean;
509
544
  /** Override fetch (defaults to the RN/global fetch). */
510
545
  fetchImpl?: typeof fetch;
546
+ onNetworkLog?: NetworkLogger;
547
+ logBodies?: boolean;
548
+ redactFields?: string[];
549
+ shipNetworkLogs?: boolean;
550
+ applicationId?: string;
551
+ environment?: string;
552
+ logSelfCalls?: boolean;
511
553
  }
512
554
  declare class SimplrFraud {
513
555
  private apiKey;
@@ -517,6 +559,10 @@ declare class SimplrFraud {
517
559
  private touchTracker;
518
560
  private formStartTime;
519
561
  private configured;
562
+ private shipper?;
563
+ private onNetworkLog?;
564
+ private logBodies?;
565
+ private redactFields?;
520
566
  /** Anonymous user profiles + order fraud monitoring (shares this client's config). */
521
567
  readonly profiles: SimplrProfiles;
522
568
  /** Real User Monitoring — batched events to /v1/rum/events. */
@@ -528,6 +574,10 @@ declare class SimplrFraud {
528
574
  configure(config: SimplrFraudConfig): this;
529
575
  private requireConfigured;
530
576
  private get httpConfig();
577
+ /** Flush any queued network logs to /v1/network-logs. */
578
+ flushNetworkLogs(): Promise<void>;
579
+ /** Stop the network-log shipper and flush remaining logs. */
580
+ close(): void;
531
581
  /** Start collecting touch biometrics and reset the form timer. */
532
582
  startTracking(): void;
533
583
  stopTracking(): void;
@@ -603,4 +653,4 @@ declare class SimplrFlags {
603
653
  }
604
654
  declare const simplrFlags: SimplrFlags;
605
655
 
606
- export { simplr as A, type BehaviorSignals as B, type CheckInput as C, type DeviceSignals as D, type EvalContext as E, type FlagDefinition as F, simplrAI as G, simplrFlags as H, type IdentifyOptions as I, simplrProfiles as J, simplrRUM as K, type OrderInput as O, type ProfileResult as P, type RUMEvent as R, SimplrFraud as S, TouchTracker as T, type ValidationResult as V, SimplrFlags as a, type SimplrRUMConfig as b, SimplrRUM as c, type SimplrFraudConfig as d, type BindingMode as e, type CheckResult as f, type CollectedSignals as g, type CreateDelegationOptions as h, type DelegationInfo as i, type DelegationResult as j, type DelegationStats as k, type FlagRule as l, type OrderResult as m, type ProfileRiskResult as n, type RUMEventBatch as o, type RUMEventType as p, type RUMLogLevel as q, type RiskLevel as r, SimplrAI as s, type SimplrAIConfig as t, type SimplrFlagsConfig as u, SimplrProfiles as v, type SimplrProfilesConfig as w, type TouchMetrics as x, type TouchSample as y, createTouchTracker as z };
656
+ export { type TouchSample as A, type BehaviorSignals as B, type CheckInput as C, type DeviceSignals as D, type EvalContext as E, type FlagDefinition as F, createTouchTracker as G, simplr as H, type IdentifyOptions as I, simplrAI as J, simplrFlags as K, simplrProfiles as L, simplrRUM as M, type NetworkLogEntry as N, type OrderInput as O, type ProfileResult as P, type RUMEvent as R, SimplrFraud as S, TouchTracker as T, type ValidationResult as V, SimplrFlags as a, type SimplrRUMConfig as b, SimplrRUM as c, type SimplrFraudConfig as d, type BindingMode as e, type CheckResult as f, type CollectedSignals as g, type CreateDelegationOptions as h, type DelegationInfo as i, type DelegationResult as j, type DelegationStats as k, type FlagRule as l, type NetworkLogger as m, type NetworkSource as n, type OrderResult as o, type ProfileRiskResult as p, type RUMEventBatch as q, type RUMEventType as r, type RUMLogLevel as s, type RiskLevel as t, SimplrAI as u, type SimplrAIConfig as v, type SimplrFlagsConfig as w, SimplrProfiles as x, type SimplrProfilesConfig as y, type TouchMetrics as z };
@@ -1,3 +1,26 @@
1
+ type NetworkSource = "frontend" | "backend";
2
+ interface NetworkLogEntry {
3
+ id: string;
4
+ requestId?: string;
5
+ source: NetworkSource;
6
+ timestamp: string;
7
+ sdk?: string;
8
+ applicationId?: string;
9
+ environment?: string;
10
+ method: string;
11
+ url: string;
12
+ requestHeaders?: Record<string, string>;
13
+ requestBody?: unknown;
14
+ status?: number;
15
+ statusText?: string;
16
+ responseHeaders?: Record<string, string>;
17
+ responseBody?: unknown;
18
+ durationMs?: number;
19
+ ok?: boolean;
20
+ error?: string;
21
+ }
22
+ type NetworkLogger = (entry: NetworkLogEntry) => void;
23
+
1
24
  /**
2
25
  * Shared types mirroring the Simplr API contract (source of truth).
3
26
  * Keep byte-for-byte compatible with the browser/Node/Flutter SDKs.
@@ -332,12 +355,18 @@ interface SimplrProfilesConfig {
332
355
  timeoutMs?: number;
333
356
  /** Override fetch (defaults to the RN/global fetch). */
334
357
  fetchImpl?: typeof fetch;
358
+ onNetworkLog?: NetworkLogger;
359
+ logBodies?: boolean;
360
+ redactFields?: string[];
335
361
  }
336
362
  declare class SimplrProfiles {
337
363
  private apiKey;
338
364
  private baseUrl;
339
365
  private timeoutMs;
340
366
  private fetchImpl?;
367
+ private onNetworkLog?;
368
+ private logBodies?;
369
+ private redactFields?;
341
370
  private collectDeviceSignalsFn?;
342
371
  private configured;
343
372
  constructor(config?: SimplrProfilesConfig);
@@ -456,12 +485,18 @@ interface SimplrAIConfig {
456
485
  baseUrl?: string;
457
486
  timeoutMs?: number;
458
487
  fetchImpl?: typeof fetch;
488
+ onNetworkLog?: NetworkLogger;
489
+ logBodies?: boolean;
490
+ redactFields?: string[];
459
491
  }
460
492
  declare class SimplrAI {
461
493
  private apiKey;
462
494
  private baseUrl;
463
495
  private timeoutMs;
464
496
  private fetchImpl?;
497
+ private onNetworkLog?;
498
+ private logBodies?;
499
+ private redactFields?;
465
500
  private configured;
466
501
  constructor(config?: SimplrAIConfig);
467
502
  configure(config: SimplrAIConfig): this;
@@ -508,6 +543,13 @@ interface SimplrFraudConfig {
508
543
  autoStart?: boolean;
509
544
  /** Override fetch (defaults to the RN/global fetch). */
510
545
  fetchImpl?: typeof fetch;
546
+ onNetworkLog?: NetworkLogger;
547
+ logBodies?: boolean;
548
+ redactFields?: string[];
549
+ shipNetworkLogs?: boolean;
550
+ applicationId?: string;
551
+ environment?: string;
552
+ logSelfCalls?: boolean;
511
553
  }
512
554
  declare class SimplrFraud {
513
555
  private apiKey;
@@ -517,6 +559,10 @@ declare class SimplrFraud {
517
559
  private touchTracker;
518
560
  private formStartTime;
519
561
  private configured;
562
+ private shipper?;
563
+ private onNetworkLog?;
564
+ private logBodies?;
565
+ private redactFields?;
520
566
  /** Anonymous user profiles + order fraud monitoring (shares this client's config). */
521
567
  readonly profiles: SimplrProfiles;
522
568
  /** Real User Monitoring — batched events to /v1/rum/events. */
@@ -528,6 +574,10 @@ declare class SimplrFraud {
528
574
  configure(config: SimplrFraudConfig): this;
529
575
  private requireConfigured;
530
576
  private get httpConfig();
577
+ /** Flush any queued network logs to /v1/network-logs. */
578
+ flushNetworkLogs(): Promise<void>;
579
+ /** Stop the network-log shipper and flush remaining logs. */
580
+ close(): void;
531
581
  /** Start collecting touch biometrics and reset the form timer. */
532
582
  startTracking(): void;
533
583
  stopTracking(): void;
@@ -603,4 +653,4 @@ declare class SimplrFlags {
603
653
  }
604
654
  declare const simplrFlags: SimplrFlags;
605
655
 
606
- export { simplr as A, type BehaviorSignals as B, type CheckInput as C, type DeviceSignals as D, type EvalContext as E, type FlagDefinition as F, simplrAI as G, simplrFlags as H, type IdentifyOptions as I, simplrProfiles as J, simplrRUM as K, type OrderInput as O, type ProfileResult as P, type RUMEvent as R, SimplrFraud as S, TouchTracker as T, type ValidationResult as V, SimplrFlags as a, type SimplrRUMConfig as b, SimplrRUM as c, type SimplrFraudConfig as d, type BindingMode as e, type CheckResult as f, type CollectedSignals as g, type CreateDelegationOptions as h, type DelegationInfo as i, type DelegationResult as j, type DelegationStats as k, type FlagRule as l, type OrderResult as m, type ProfileRiskResult as n, type RUMEventBatch as o, type RUMEventType as p, type RUMLogLevel as q, type RiskLevel as r, SimplrAI as s, type SimplrAIConfig as t, type SimplrFlagsConfig as u, SimplrProfiles as v, type SimplrProfilesConfig as w, type TouchMetrics as x, type TouchSample as y, createTouchTracker as z };
656
+ export { type TouchSample as A, type BehaviorSignals as B, type CheckInput as C, type DeviceSignals as D, type EvalContext as E, type FlagDefinition as F, createTouchTracker as G, simplr as H, type IdentifyOptions as I, simplrAI as J, simplrFlags as K, simplrProfiles as L, simplrRUM as M, type NetworkLogEntry as N, type OrderInput as O, type ProfileResult as P, type RUMEvent as R, SimplrFraud as S, TouchTracker as T, type ValidationResult as V, SimplrFlags as a, type SimplrRUMConfig as b, SimplrRUM as c, type SimplrFraudConfig as d, type BindingMode as e, type CheckResult as f, type CollectedSignals as g, type CreateDelegationOptions as h, type DelegationInfo as i, type DelegationResult as j, type DelegationStats as k, type FlagRule as l, type NetworkLogger as m, type NetworkSource as n, type OrderResult as o, type ProfileRiskResult as p, type RUMEventBatch as q, type RUMEventType as r, type RUMLogLevel as s, type RiskLevel as t, SimplrAI as u, type SimplrAIConfig as v, type SimplrFlagsConfig as w, SimplrProfiles as x, type SimplrProfilesConfig as y, type TouchMetrics as z };
@@ -20,6 +20,98 @@ var SimplrError = class _SimplrError extends Error {
20
20
  }
21
21
  };
22
22
 
23
+ // src/network-log.ts
24
+ var SENSITIVE_HEADERS = /* @__PURE__ */ new Set([
25
+ "authorization",
26
+ "cookie",
27
+ "set-cookie",
28
+ "x-api-key",
29
+ "x-auth-token",
30
+ "x-csrf-token",
31
+ "x-xsrf-token"
32
+ ]);
33
+ var SENSITIVE_KEY_PARTS = [
34
+ "password",
35
+ "passwd",
36
+ "secret",
37
+ "token",
38
+ "api_key",
39
+ "apikey",
40
+ "authorization",
41
+ "auth",
42
+ "credential",
43
+ "private_key",
44
+ "card",
45
+ "cardnumber",
46
+ "pan",
47
+ "cvv",
48
+ "cvc",
49
+ "ssn",
50
+ "pin",
51
+ "otp"
52
+ ];
53
+ var MAX_REDACT_DEPTH = 8;
54
+ var MAX_BODY_CHARS = 1e4;
55
+ function isSensitiveKey(key, extraKeys) {
56
+ const lower = key.toLowerCase();
57
+ if (extraKeys.some((k) => lower === k.toLowerCase())) return true;
58
+ return SENSITIVE_KEY_PARTS.some((part) => lower.includes(part));
59
+ }
60
+ function redactDeep(value, extraKeys, depth = 0) {
61
+ if (depth >= MAX_REDACT_DEPTH) return "[truncated]";
62
+ if (Array.isArray(value)) return value.map((v) => redactDeep(v, extraKeys, depth + 1));
63
+ if (value && typeof value === "object") {
64
+ const out = {};
65
+ for (const [key, val] of Object.entries(value)) {
66
+ out[key] = isSensitiveKey(key, extraKeys) ? "[REDACTED]" : redactDeep(val, extraKeys, depth + 1);
67
+ }
68
+ return out;
69
+ }
70
+ return value;
71
+ }
72
+ function redactHeaders(headers) {
73
+ if (!headers) return void 0;
74
+ const out = {};
75
+ const set = (key, value) => {
76
+ out[key] = SENSITIVE_HEADERS.has(key.toLowerCase()) ? "[REDACTED]" : value;
77
+ };
78
+ if (typeof headers.forEach === "function" && !Array.isArray(headers)) {
79
+ headers.forEach((value, key) => set(key, value));
80
+ } else {
81
+ for (const [key, value] of Object.entries(headers)) {
82
+ set(key, String(value));
83
+ }
84
+ }
85
+ return out;
86
+ }
87
+ function previewBody(raw, redactFields = []) {
88
+ if (raw === void 0 || raw === null) return void 0;
89
+ let value = raw;
90
+ if (typeof raw === "string") {
91
+ try {
92
+ value = JSON.parse(raw);
93
+ } catch {
94
+ return raw.length > MAX_BODY_CHARS ? raw.slice(0, MAX_BODY_CHARS) + "\u2026[truncated]" : raw;
95
+ }
96
+ }
97
+ const redacted = redactDeep(value, redactFields);
98
+ let text;
99
+ try {
100
+ text = JSON.stringify(redacted);
101
+ } catch {
102
+ return "[unserializable]";
103
+ }
104
+ if (text.length > MAX_BODY_CHARS) {
105
+ return text.slice(0, MAX_BODY_CHARS) + "\u2026[truncated]";
106
+ }
107
+ return redacted;
108
+ }
109
+ function newLogId() {
110
+ const uuid = globalThis?.crypto?.randomUUID;
111
+ if (typeof uuid === "function") return uuid.call(globalThis.crypto);
112
+ return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
113
+ }
114
+
23
115
  // src/http.ts
24
116
  async function apiRequest(cfg, method, path, body) {
25
117
  const fetchImpl = cfg.fetchImpl ?? globalThis.fetch;
@@ -28,13 +120,32 @@ async function apiRequest(cfg, method, path, body) {
28
120
  }
29
121
  const controller = new AbortController();
30
122
  const timer = setTimeout(() => controller.abort(), cfg.timeoutMs);
123
+ const url = `${cfg.baseUrl}${path}`;
124
+ const requestHeaders = {
125
+ "Content-Type": "application/json",
126
+ ...cfg.authHeaders
127
+ };
128
+ const startedAt = Date.now();
129
+ const log = cfg.onNetworkLog ? {
130
+ id: newLogId(),
131
+ source: "frontend",
132
+ timestamp: new Date(startedAt).toISOString(),
133
+ method,
134
+ url,
135
+ requestHeaders: redactHeaders(requestHeaders),
136
+ requestBody: cfg.logBodies ? previewBody(body, cfg.redactFields) : void 0
137
+ } : null;
138
+ const emit = (extra) => {
139
+ if (!log || !cfg.onNetworkLog) return;
140
+ try {
141
+ cfg.onNetworkLog({ ...log, durationMs: Date.now() - startedAt, ...extra });
142
+ } catch {
143
+ }
144
+ };
31
145
  try {
32
- const res = await fetchImpl(`${cfg.baseUrl}${path}`, {
146
+ const res = await fetchImpl(url, {
33
147
  method,
34
- headers: {
35
- "Content-Type": "application/json",
36
- ...cfg.authHeaders
37
- },
148
+ headers: requestHeaders,
38
149
  body: body !== void 0 ? JSON.stringify(body) : void 0,
39
150
  signal: controller.signal
40
151
  });
@@ -45,6 +156,13 @@ async function apiRequest(cfg, method, path, body) {
45
156
  } catch {
46
157
  parsed = text;
47
158
  }
159
+ emit({
160
+ status: res.status,
161
+ statusText: res.statusText,
162
+ ok: res.ok,
163
+ responseHeaders: redactHeaders(res.headers),
164
+ responseBody: cfg.logBodies ? previewBody(parsed ?? text, cfg.redactFields) : void 0
165
+ });
48
166
  if (!res.ok) {
49
167
  const message = parsed && (parsed.message || parsed.error) || `Simplr API error ${res.status}`;
50
168
  throw new SimplrError(message, res.status, parsed);
@@ -53,8 +171,10 @@ async function apiRequest(cfg, method, path, body) {
53
171
  } catch (err) {
54
172
  if (err instanceof SimplrError) throw err;
55
173
  if (err instanceof Error && err.name === "AbortError") {
174
+ emit({ ok: false, error: `timed out after ${cfg.timeoutMs}ms` });
56
175
  throw new SimplrError(`Request to ${path} timed out after ${cfg.timeoutMs}ms`, 0, null);
57
176
  }
177
+ emit({ ok: false, error: err instanceof Error ? err.message : "Network error" });
58
178
  throw new SimplrError(err instanceof Error ? err.message : "Network error", 0, null);
59
179
  } finally {
60
180
  clearTimeout(timer);
@@ -64,6 +184,57 @@ function normalizeBaseUrl(url) {
64
184
  return url.replace(/\/+$/, "");
65
185
  }
66
186
 
187
+ // src/network-shipper.ts
188
+ var DEFAULT_BATCH = 25;
189
+ var DEFAULT_FLUSH_MS = 5e3;
190
+ var NetworkLogShipper = class {
191
+ constructor(cfg) {
192
+ this.queue = [];
193
+ this.timer = null;
194
+ this.cfg = cfg;
195
+ }
196
+ start() {
197
+ if (this.timer) return;
198
+ const interval = this.cfg.flushIntervalMs ?? DEFAULT_FLUSH_MS;
199
+ this.timer = setInterval(() => {
200
+ void this.flush();
201
+ }, interval);
202
+ this.timer?.unref?.();
203
+ }
204
+ add(entry) {
205
+ this.queue.push({
206
+ ...entry,
207
+ sdk: this.cfg.sdk,
208
+ applicationId: entry.applicationId ?? this.cfg.applicationId,
209
+ environment: entry.environment ?? this.cfg.environment
210
+ });
211
+ if (this.queue.length >= (this.cfg.batchSize ?? DEFAULT_BATCH)) {
212
+ void this.flush();
213
+ }
214
+ }
215
+ async flush() {
216
+ if (this.queue.length === 0) return;
217
+ const logs = this.queue;
218
+ this.queue = [];
219
+ try {
220
+ await this.cfg.fetchImpl(`${this.cfg.baseUrl}/v1/network-logs`, {
221
+ method: "POST",
222
+ headers: {
223
+ "Content-Type": "application/json",
224
+ "X-API-Key": this.cfg.apiKey
225
+ },
226
+ body: JSON.stringify({ logs })
227
+ });
228
+ } catch {
229
+ }
230
+ }
231
+ stop() {
232
+ if (this.timer) clearInterval(this.timer);
233
+ this.timer = null;
234
+ void this.flush();
235
+ }
236
+ };
237
+
67
238
  // src/hash.ts
68
239
  function murmurHash3(input, seed = 0) {
69
240
  let h1 = seed;
@@ -379,6 +550,9 @@ var SimplrProfiles = class {
379
550
  this.baseUrl = config.baseUrl ? normalizeBaseUrl(config.baseUrl) : DEFAULT_BASE_URL;
380
551
  if (config.timeoutMs !== void 0) this.timeoutMs = config.timeoutMs;
381
552
  this.fetchImpl = config.fetchImpl;
553
+ this.onNetworkLog = config.onNetworkLog;
554
+ this.logBodies = config.logBodies;
555
+ this.redactFields = config.redactFields;
382
556
  this.configured = true;
383
557
  return this;
384
558
  }
@@ -399,7 +573,10 @@ var SimplrProfiles = class {
399
573
  authHeaders: { "X-API-Key": this.apiKey },
400
574
  baseUrl: this.baseUrl,
401
575
  timeoutMs: this.timeoutMs,
402
- fetchImpl: this.fetchImpl
576
+ fetchImpl: this.fetchImpl,
577
+ onNetworkLog: this.onNetworkLog,
578
+ logBodies: this.logBodies,
579
+ redactFields: this.redactFields
403
580
  };
404
581
  }
405
582
  /** Create or update an anonymous profile and link the current device. */
@@ -627,6 +804,9 @@ var SimplrAI = class {
627
804
  this.baseUrl = config.baseUrl ? normalizeBaseUrl(config.baseUrl) : DEFAULT_BASE_URL3;
628
805
  if (config.timeoutMs !== void 0) this.timeoutMs = config.timeoutMs;
629
806
  this.fetchImpl = config.fetchImpl;
807
+ this.onNetworkLog = config.onNetworkLog;
808
+ this.logBodies = config.logBodies;
809
+ this.redactFields = config.redactFields;
630
810
  this.configured = true;
631
811
  return this;
632
812
  }
@@ -640,7 +820,10 @@ var SimplrAI = class {
640
820
  authHeaders: { "X-API-Key": this.apiKey },
641
821
  baseUrl: this.baseUrl,
642
822
  timeoutMs: this.timeoutMs,
643
- fetchImpl: this.fetchImpl
823
+ fetchImpl: this.fetchImpl,
824
+ onNetworkLog: this.onNetworkLog,
825
+ logBodies: this.logBodies,
826
+ redactFields: this.redactFields
644
827
  };
645
828
  }
646
829
  /** Create a new AI delegation token for a user. POST /v1/ai/delegations. */
@@ -763,12 +946,37 @@ var SimplrFraud = class {
763
946
  this.baseUrl = config.baseUrl ? normalizeBaseUrl(config.baseUrl) : DEFAULT_BASE_URL4;
764
947
  if (config.timeoutMs !== void 0) this.timeoutMs = config.timeoutMs;
765
948
  this.fetchImpl = config.fetchImpl;
949
+ const logSelf = !!config.logSelfCalls;
950
+ this.logBodies = config.logBodies ?? (config.shipNetworkLogs && logSelf);
951
+ this.redactFields = config.redactFields;
766
952
  this.configured = true;
953
+ this.shipper?.stop();
954
+ this.shipper = void 0;
955
+ if (config.shipNetworkLogs && logSelf) {
956
+ this.shipper = new NetworkLogShipper({
957
+ baseUrl: this.baseUrl,
958
+ apiKey: this.apiKey,
959
+ fetchImpl: this.fetchImpl ?? globalThis.fetch,
960
+ sdk: "react-native",
961
+ applicationId: config.applicationId,
962
+ environment: config.environment
963
+ });
964
+ this.shipper.start();
965
+ }
966
+ const shipper = this.shipper;
967
+ const userLog = config.onNetworkLog;
968
+ this.onNetworkLog = shipper || userLog ? (entry) => {
969
+ shipper?.add(entry);
970
+ userLog?.(entry);
971
+ } : void 0;
767
972
  const sub = {
768
973
  apiKey: this.apiKey,
769
974
  baseUrl: this.baseUrl,
770
975
  timeoutMs: this.timeoutMs,
771
- fetchImpl: this.fetchImpl
976
+ fetchImpl: this.fetchImpl,
977
+ onNetworkLog: this.onNetworkLog,
978
+ logBodies: this.logBodies,
979
+ redactFields: this.redactFields
772
980
  };
773
981
  this.profiles.configure(sub);
774
982
  this.ai.configure(sub);
@@ -787,9 +995,20 @@ var SimplrFraud = class {
787
995
  authHeaders: { "X-API-Key": this.apiKey },
788
996
  baseUrl: this.baseUrl,
789
997
  timeoutMs: this.timeoutMs,
790
- fetchImpl: this.fetchImpl
998
+ fetchImpl: this.fetchImpl,
999
+ onNetworkLog: this.onNetworkLog,
1000
+ logBodies: this.logBodies,
1001
+ redactFields: this.redactFields
791
1002
  };
792
1003
  }
1004
+ /** Flush any queued network logs to /v1/network-logs. */
1005
+ flushNetworkLogs() {
1006
+ return this.shipper?.flush() ?? Promise.resolve();
1007
+ }
1008
+ /** Stop the network-log shipper and flush remaining logs. */
1009
+ close() {
1010
+ this.shipper?.stop();
1011
+ }
793
1012
  // --- Biometrics ---------------------------------------------------------
794
1013
  /** Start collecting touch biometrics and reset the form timer. */
795
1014
  startTracking() {