@simplr-ai/react-native 1.1.0 → 1.2.0
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/dist/{chunk-FCBLJE3T.js → chunk-AJZHWHYK.js} +230 -12
- package/dist/chunk-AJZHWHYK.js.map +1 -0
- package/dist/{flags-CwhHmaHQ.d.cts → flags-CQpteSek.d.cts} +50 -1
- package/dist/{flags-CwhHmaHQ.d.ts → flags-CQpteSek.d.ts} +50 -1
- package/dist/hooks/index.cjs +227 -9
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/index.cjs +228 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FCBLJE3T.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -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(
|
|
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;
|
|
@@ -391,6 +562,9 @@ var SimplrProfiles = class {
|
|
|
391
562
|
this.baseUrl = config.baseUrl ? normalizeBaseUrl(config.baseUrl) : DEFAULT_BASE_URL;
|
|
392
563
|
if (config.timeoutMs !== void 0) this.timeoutMs = config.timeoutMs;
|
|
393
564
|
this.fetchImpl = config.fetchImpl;
|
|
565
|
+
this.onNetworkLog = config.onNetworkLog;
|
|
566
|
+
this.logBodies = config.logBodies;
|
|
567
|
+
this.redactFields = config.redactFields;
|
|
394
568
|
this.configured = true;
|
|
395
569
|
return this;
|
|
396
570
|
}
|
|
@@ -411,7 +585,10 @@ var SimplrProfiles = class {
|
|
|
411
585
|
authHeaders: { "X-API-Key": this.apiKey },
|
|
412
586
|
baseUrl: this.baseUrl,
|
|
413
587
|
timeoutMs: this.timeoutMs,
|
|
414
|
-
fetchImpl: this.fetchImpl
|
|
588
|
+
fetchImpl: this.fetchImpl,
|
|
589
|
+
onNetworkLog: this.onNetworkLog,
|
|
590
|
+
logBodies: this.logBodies,
|
|
591
|
+
redactFields: this.redactFields
|
|
415
592
|
};
|
|
416
593
|
}
|
|
417
594
|
/** Create or update an anonymous profile and link the current device. */
|
|
@@ -639,6 +816,9 @@ var SimplrAI = class {
|
|
|
639
816
|
this.baseUrl = config.baseUrl ? normalizeBaseUrl(config.baseUrl) : DEFAULT_BASE_URL3;
|
|
640
817
|
if (config.timeoutMs !== void 0) this.timeoutMs = config.timeoutMs;
|
|
641
818
|
this.fetchImpl = config.fetchImpl;
|
|
819
|
+
this.onNetworkLog = config.onNetworkLog;
|
|
820
|
+
this.logBodies = config.logBodies;
|
|
821
|
+
this.redactFields = config.redactFields;
|
|
642
822
|
this.configured = true;
|
|
643
823
|
return this;
|
|
644
824
|
}
|
|
@@ -652,7 +832,10 @@ var SimplrAI = class {
|
|
|
652
832
|
authHeaders: { "X-API-Key": this.apiKey },
|
|
653
833
|
baseUrl: this.baseUrl,
|
|
654
834
|
timeoutMs: this.timeoutMs,
|
|
655
|
-
fetchImpl: this.fetchImpl
|
|
835
|
+
fetchImpl: this.fetchImpl,
|
|
836
|
+
onNetworkLog: this.onNetworkLog,
|
|
837
|
+
logBodies: this.logBodies,
|
|
838
|
+
redactFields: this.redactFields
|
|
656
839
|
};
|
|
657
840
|
}
|
|
658
841
|
/** Create a new AI delegation token for a user. POST /v1/ai/delegations. */
|
|
@@ -775,12 +958,36 @@ var SimplrFraud = class {
|
|
|
775
958
|
this.baseUrl = config.baseUrl ? normalizeBaseUrl(config.baseUrl) : DEFAULT_BASE_URL4;
|
|
776
959
|
if (config.timeoutMs !== void 0) this.timeoutMs = config.timeoutMs;
|
|
777
960
|
this.fetchImpl = config.fetchImpl;
|
|
961
|
+
this.logBodies = config.logBodies ?? config.shipNetworkLogs;
|
|
962
|
+
this.redactFields = config.redactFields;
|
|
778
963
|
this.configured = true;
|
|
964
|
+
this.shipper?.stop();
|
|
965
|
+
this.shipper = void 0;
|
|
966
|
+
if (config.shipNetworkLogs) {
|
|
967
|
+
this.shipper = new NetworkLogShipper({
|
|
968
|
+
baseUrl: this.baseUrl,
|
|
969
|
+
apiKey: this.apiKey,
|
|
970
|
+
fetchImpl: this.fetchImpl ?? globalThis.fetch,
|
|
971
|
+
sdk: "react-native",
|
|
972
|
+
applicationId: config.applicationId,
|
|
973
|
+
environment: config.environment
|
|
974
|
+
});
|
|
975
|
+
this.shipper.start();
|
|
976
|
+
}
|
|
977
|
+
const shipper = this.shipper;
|
|
978
|
+
const userLog = config.onNetworkLog;
|
|
979
|
+
this.onNetworkLog = shipper || userLog ? (entry) => {
|
|
980
|
+
shipper?.add(entry);
|
|
981
|
+
userLog?.(entry);
|
|
982
|
+
} : void 0;
|
|
779
983
|
const sub = {
|
|
780
984
|
apiKey: this.apiKey,
|
|
781
985
|
baseUrl: this.baseUrl,
|
|
782
986
|
timeoutMs: this.timeoutMs,
|
|
783
|
-
fetchImpl: this.fetchImpl
|
|
987
|
+
fetchImpl: this.fetchImpl,
|
|
988
|
+
onNetworkLog: this.onNetworkLog,
|
|
989
|
+
logBodies: this.logBodies,
|
|
990
|
+
redactFields: this.redactFields
|
|
784
991
|
};
|
|
785
992
|
this.profiles.configure(sub);
|
|
786
993
|
this.ai.configure(sub);
|
|
@@ -799,9 +1006,20 @@ var SimplrFraud = class {
|
|
|
799
1006
|
authHeaders: { "X-API-Key": this.apiKey },
|
|
800
1007
|
baseUrl: this.baseUrl,
|
|
801
1008
|
timeoutMs: this.timeoutMs,
|
|
802
|
-
fetchImpl: this.fetchImpl
|
|
1009
|
+
fetchImpl: this.fetchImpl,
|
|
1010
|
+
onNetworkLog: this.onNetworkLog,
|
|
1011
|
+
logBodies: this.logBodies,
|
|
1012
|
+
redactFields: this.redactFields
|
|
803
1013
|
};
|
|
804
1014
|
}
|
|
1015
|
+
/** Flush any queued network logs to /v1/network-logs. */
|
|
1016
|
+
flushNetworkLogs() {
|
|
1017
|
+
return this.shipper?.flush() ?? Promise.resolve();
|
|
1018
|
+
}
|
|
1019
|
+
/** Stop the network-log shipper and flush remaining logs. */
|
|
1020
|
+
close() {
|
|
1021
|
+
this.shipper?.stop();
|
|
1022
|
+
}
|
|
805
1023
|
// --- Biometrics ---------------------------------------------------------
|
|
806
1024
|
/** Start collecting touch biometrics and reset the form timer. */
|
|
807
1025
|
startTracking() {
|
|
@@ -987,6 +1205,7 @@ var simplrFlags = new SimplrFlags();
|
|
|
987
1205
|
// src/index.ts
|
|
988
1206
|
var src_default = SimplrFraud;
|
|
989
1207
|
|
|
1208
|
+
exports.NetworkLogShipper = NetworkLogShipper;
|
|
990
1209
|
exports.SimplrAI = SimplrAI;
|
|
991
1210
|
exports.SimplrError = SimplrError;
|
|
992
1211
|
exports.SimplrFlags = SimplrFlags;
|