@keverdjs/fraud-sdk-angular 1.1.0 → 1.1.2
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/index.d.mts +29 -7
- package/dist/index.d.ts +29 -7
- package/dist/index.js +459 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +459 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2803,11 +2803,19 @@ var PageInteractionCollector = class {
|
|
|
2803
2803
|
};
|
|
2804
2804
|
|
|
2805
2805
|
// ../fraud-sdk/src/core/sdk.ts
|
|
2806
|
+
var DEFAULT_ENDPOINT = "https://api.keverd.com";
|
|
2806
2807
|
var KeverdSDK = class {
|
|
2808
|
+
// Maximum 10 minutes of collection
|
|
2807
2809
|
constructor() {
|
|
2808
2810
|
this.config = null;
|
|
2809
2811
|
this.isInitialized = false;
|
|
2810
2812
|
this.sessionId = null;
|
|
2813
|
+
this.ghostInterval = null;
|
|
2814
|
+
this.ghostStartTime = null;
|
|
2815
|
+
this.ghostSignalCount = 0;
|
|
2816
|
+
this.MIN_GHOST_SIGNALS = 10;
|
|
2817
|
+
// Collect at least 10 signals (5 minutes of data)
|
|
2818
|
+
this.MAX_GHOST_COLLECTION_TIME = 10 * 60 * 1e3;
|
|
2811
2819
|
this.deviceCollector = new DeviceCollector();
|
|
2812
2820
|
this.behavioralCollector = new BehavioralCollector();
|
|
2813
2821
|
this.fingerprintManager = new FingerprintManager();
|
|
@@ -2830,12 +2838,10 @@ var KeverdSDK = class {
|
|
|
2830
2838
|
if (typeof config === "string") {
|
|
2831
2839
|
this.config = {
|
|
2832
2840
|
apiKey: config,
|
|
2833
|
-
endpoint: "https://api.keverd.com",
|
|
2834
2841
|
debug: false
|
|
2835
2842
|
};
|
|
2836
2843
|
} else {
|
|
2837
2844
|
this.config = {
|
|
2838
|
-
endpoint: "https://api.keverd.com",
|
|
2839
2845
|
debug: false,
|
|
2840
2846
|
...config
|
|
2841
2847
|
};
|
|
@@ -2846,10 +2852,122 @@ var KeverdSDK = class {
|
|
|
2846
2852
|
this.sessionId = this.generateSessionId();
|
|
2847
2853
|
this.isInitialized = true;
|
|
2848
2854
|
if (this.config.debug) {
|
|
2849
|
-
console.log("[Keverd SDK] Initialized successfully"
|
|
2850
|
-
|
|
2855
|
+
console.log("[Keverd SDK] Initialized successfully");
|
|
2856
|
+
}
|
|
2857
|
+
this.startSession().catch(() => {
|
|
2858
|
+
});
|
|
2859
|
+
this.startGhostSignalCollection();
|
|
2860
|
+
}
|
|
2861
|
+
startGhostSignalCollection() {
|
|
2862
|
+
if (this.ghostInterval) return;
|
|
2863
|
+
if (!this.config) return;
|
|
2864
|
+
this.ghostStartTime = Date.now();
|
|
2865
|
+
this.ghostSignalCount = 0;
|
|
2866
|
+
const intervalMs = 3e4;
|
|
2867
|
+
const sendGhostSignal = () => {
|
|
2868
|
+
const now = Date.now();
|
|
2869
|
+
const totalCollectionTime = this.ghostStartTime ? now - this.ghostStartTime : 0;
|
|
2870
|
+
const hasEnoughSignals = this.ghostSignalCount >= this.MIN_GHOST_SIGNALS;
|
|
2871
|
+
const exceededMaxTime = totalCollectionTime >= this.MAX_GHOST_COLLECTION_TIME;
|
|
2872
|
+
if (hasEnoughSignals || exceededMaxTime) {
|
|
2873
|
+
if (this.config?.debug) {
|
|
2874
|
+
console.log(`[Keverd SDK] Ghost collection complete: ${this.ghostSignalCount} signals, ${Math.round(totalCollectionTime / 1e3)}s elapsed`);
|
|
2875
|
+
}
|
|
2876
|
+
this.stopGhostSignalCollection();
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2879
|
+
const durationMs = this.ghostStartTime ? now - this.ghostStartTime : intervalMs;
|
|
2880
|
+
this.sendGhostSignals(durationMs).catch((err) => {
|
|
2881
|
+
if (this.config?.debug) {
|
|
2882
|
+
console.debug("[Keverd SDK] Ghost signals upload failed:", err);
|
|
2883
|
+
}
|
|
2851
2884
|
});
|
|
2885
|
+
this.ghostSignalCount++;
|
|
2886
|
+
this.ghostStartTime = now;
|
|
2887
|
+
};
|
|
2888
|
+
setTimeout(() => {
|
|
2889
|
+
sendGhostSignal();
|
|
2890
|
+
this.ghostInterval = setInterval(() => {
|
|
2891
|
+
sendGhostSignal();
|
|
2892
|
+
}, intervalMs);
|
|
2893
|
+
}, intervalMs);
|
|
2894
|
+
}
|
|
2895
|
+
stopGhostSignalCollection() {
|
|
2896
|
+
if (this.ghostInterval) {
|
|
2897
|
+
clearInterval(this.ghostInterval);
|
|
2898
|
+
this.ghostInterval = null;
|
|
2899
|
+
this.ghostStartTime = null;
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
async sendGhostSignals(durationMs) {
|
|
2903
|
+
if (!this.isInitialized || !this.config) return;
|
|
2904
|
+
const deviceInfo = this.deviceCollector.collect();
|
|
2905
|
+
const behavioralData = this.behavioralCollector.getData();
|
|
2906
|
+
const fingerprintData = await this.fingerprintManager.collect();
|
|
2907
|
+
const fingerprintjsData = {
|
|
2908
|
+
visitorId: fingerprintData.visitorId,
|
|
2909
|
+
confidence: fingerprintData.confidence,
|
|
2910
|
+
components: fingerprintData.components
|
|
2911
|
+
};
|
|
2912
|
+
const privacySignals = this.privacySignalCollector.collect();
|
|
2913
|
+
const browserCapabilities = this.browserCapabilityCollector.collect();
|
|
2914
|
+
const hardwareSignals = this.hardwareSignalCollector.collect();
|
|
2915
|
+
const formInteractions = this.formInteractionCollector.getData();
|
|
2916
|
+
const mouseSignals = this.behavioralCollector.getMouseSignals();
|
|
2917
|
+
const keyboardSignals = this.behavioralCollector.getKeyboardSignals();
|
|
2918
|
+
const pageInteractions = this.pageInteractionCollector.getData();
|
|
2919
|
+
const networkSignals = {
|
|
2920
|
+
connectionType: hardwareSignals.connectionType || void 0,
|
|
2921
|
+
effectiveType: hardwareSignals.effectiveType || void 0,
|
|
2922
|
+
downlink: hardwareSignals.downlink || void 0,
|
|
2923
|
+
rtt: hardwareSignals.rtt || void 0,
|
|
2924
|
+
saveData: hardwareSignals.saveData || void 0
|
|
2925
|
+
};
|
|
2926
|
+
const sessionInfo = {
|
|
2927
|
+
sessionId: this.sessionId || void 0,
|
|
2928
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2929
|
+
};
|
|
2930
|
+
const request = {
|
|
2931
|
+
userId: this.config.userId,
|
|
2932
|
+
device: deviceInfo,
|
|
2933
|
+
session: sessionInfo,
|
|
2934
|
+
behavioral: behavioralData,
|
|
2935
|
+
duration_ms: durationMs,
|
|
2936
|
+
fingerprintjs: fingerprintjsData || void 0,
|
|
2937
|
+
privacySignals,
|
|
2938
|
+
browserCapabilities,
|
|
2939
|
+
hardwareSignals,
|
|
2940
|
+
formInteractions,
|
|
2941
|
+
mouseSignals,
|
|
2942
|
+
keyboardSignals,
|
|
2943
|
+
pageInteractions,
|
|
2944
|
+
networkSignals,
|
|
2945
|
+
useCase: "ghost"
|
|
2946
|
+
};
|
|
2947
|
+
const url = `${DEFAULT_ENDPOINT}/fingerprint/ghost`;
|
|
2948
|
+
const headers = {
|
|
2949
|
+
"Content-Type": "application/json",
|
|
2950
|
+
"X-SDK-Source": "javascript"
|
|
2951
|
+
};
|
|
2952
|
+
const { origin, referrer } = this.getOriginHeaders();
|
|
2953
|
+
if (origin) {
|
|
2954
|
+
headers["X-Origin-URL"] = origin;
|
|
2955
|
+
}
|
|
2956
|
+
if (referrer) {
|
|
2957
|
+
headers["X-Referrer-URL"] = referrer;
|
|
2958
|
+
}
|
|
2959
|
+
const apiKey = this.config.apiKey;
|
|
2960
|
+
if (apiKey) {
|
|
2961
|
+
headers["x-keverd-key"] = apiKey;
|
|
2962
|
+
headers["X-API-KEY"] = apiKey;
|
|
2963
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
2852
2964
|
}
|
|
2965
|
+
await fetch(url, {
|
|
2966
|
+
method: "POST",
|
|
2967
|
+
headers,
|
|
2968
|
+
body: JSON.stringify(request)
|
|
2969
|
+
}).catch(() => {
|
|
2970
|
+
});
|
|
2853
2971
|
}
|
|
2854
2972
|
/**
|
|
2855
2973
|
* Get visitor data (fingerprint and risk assessment)
|
|
@@ -3035,12 +3153,18 @@ var KeverdSDK = class {
|
|
|
3035
3153
|
if (options.changeType) {
|
|
3036
3154
|
request.changeType = options.changeType;
|
|
3037
3155
|
}
|
|
3038
|
-
const
|
|
3039
|
-
const url = `${endpoint}/fingerprint/verify/${useCase}`;
|
|
3156
|
+
const url = `${DEFAULT_ENDPOINT}/fingerprint/verify/${useCase}`;
|
|
3040
3157
|
const headers = {
|
|
3041
3158
|
"Content-Type": "application/json",
|
|
3042
3159
|
"X-SDK-Source": "javascript"
|
|
3043
3160
|
};
|
|
3161
|
+
const { origin, referrer } = this.getOriginHeaders();
|
|
3162
|
+
if (origin) {
|
|
3163
|
+
headers["X-Origin-URL"] = origin;
|
|
3164
|
+
}
|
|
3165
|
+
if (referrer) {
|
|
3166
|
+
headers["X-Referrer-URL"] = referrer;
|
|
3167
|
+
}
|
|
3044
3168
|
const apiKey = this.config.apiKey;
|
|
3045
3169
|
if (apiKey) {
|
|
3046
3170
|
headers["x-keverd-key"] = apiKey;
|
|
@@ -3059,6 +3183,17 @@ var KeverdSDK = class {
|
|
|
3059
3183
|
const data = await response.json();
|
|
3060
3184
|
return data;
|
|
3061
3185
|
}
|
|
3186
|
+
/**
|
|
3187
|
+
* Extract origin and referrer from browser
|
|
3188
|
+
*/
|
|
3189
|
+
getOriginHeaders() {
|
|
3190
|
+
if (typeof window === "undefined") {
|
|
3191
|
+
return {};
|
|
3192
|
+
}
|
|
3193
|
+
const origin = window.location.origin || void 0;
|
|
3194
|
+
const referrer = document.referrer || void 0;
|
|
3195
|
+
return { origin, referrer };
|
|
3196
|
+
}
|
|
3062
3197
|
/**
|
|
3063
3198
|
* Send fingerprint request to backend
|
|
3064
3199
|
*/
|
|
@@ -3066,13 +3201,19 @@ var KeverdSDK = class {
|
|
|
3066
3201
|
if (!this.config) {
|
|
3067
3202
|
throw new Error("SDK not initialized");
|
|
3068
3203
|
}
|
|
3069
|
-
const
|
|
3070
|
-
const url = `${endpoint}/fingerprint/score`;
|
|
3204
|
+
const url = `${DEFAULT_ENDPOINT}/fingerprint/score`;
|
|
3071
3205
|
const headers = {
|
|
3072
3206
|
"Content-Type": "application/json",
|
|
3073
3207
|
"X-SDK-Source": "javascript"
|
|
3074
3208
|
// Identify SDK source for backend analytics
|
|
3075
3209
|
};
|
|
3210
|
+
const { origin, referrer } = this.getOriginHeaders();
|
|
3211
|
+
if (origin) {
|
|
3212
|
+
headers["X-Origin-URL"] = origin;
|
|
3213
|
+
}
|
|
3214
|
+
if (referrer) {
|
|
3215
|
+
headers["X-Referrer-URL"] = referrer;
|
|
3216
|
+
}
|
|
3076
3217
|
const apiKey = this.config.apiKey;
|
|
3077
3218
|
if (apiKey) {
|
|
3078
3219
|
headers["x-keverd-key"] = apiKey;
|
|
@@ -3097,15 +3238,222 @@ var KeverdSDK = class {
|
|
|
3097
3238
|
generateSessionId() {
|
|
3098
3239
|
return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
3099
3240
|
}
|
|
3241
|
+
/**
|
|
3242
|
+
* Detect browser name from user agent
|
|
3243
|
+
*/
|
|
3244
|
+
_detectBrowser() {
|
|
3245
|
+
const ua = navigator.userAgent;
|
|
3246
|
+
if (ua.includes("Chrome")) return "Chrome";
|
|
3247
|
+
if (ua.includes("Firefox")) return "Firefox";
|
|
3248
|
+
if (ua.includes("Safari") && !ua.includes("Chrome")) return "Safari";
|
|
3249
|
+
if (ua.includes("Edge")) return "Edge";
|
|
3250
|
+
if (ua.includes("Opera")) return "Opera";
|
|
3251
|
+
return void 0;
|
|
3252
|
+
}
|
|
3253
|
+
/**
|
|
3254
|
+
* Detect OS from user agent
|
|
3255
|
+
*/
|
|
3256
|
+
_detectOS() {
|
|
3257
|
+
const ua = navigator.userAgent;
|
|
3258
|
+
if (ua.includes("Windows")) return "Windows";
|
|
3259
|
+
if (ua.includes("Mac OS")) return "macOS";
|
|
3260
|
+
if (ua.includes("Linux")) return "Linux";
|
|
3261
|
+
if (ua.includes("Android")) return "Android";
|
|
3262
|
+
if (ua.includes("iOS") || ua.includes("iPhone") || ua.includes("iPad")) return "iOS";
|
|
3263
|
+
return void 0;
|
|
3264
|
+
}
|
|
3265
|
+
/**
|
|
3266
|
+
* Start a new session (called automatically on init, but can be called manually)
|
|
3267
|
+
*/
|
|
3268
|
+
async startSession(userId, deviceHash, metadata) {
|
|
3269
|
+
if (!this.isInitialized || !this.config) {
|
|
3270
|
+
throw new Error("Keverd SDK not initialized. Call init() first.");
|
|
3271
|
+
}
|
|
3272
|
+
if (!this.sessionId) {
|
|
3273
|
+
this.sessionId = this.generateSessionId();
|
|
3274
|
+
}
|
|
3275
|
+
try {
|
|
3276
|
+
const url = `${DEFAULT_ENDPOINT}/dashboard/sessions/start`;
|
|
3277
|
+
const headers = {
|
|
3278
|
+
"Content-Type": "application/json"
|
|
3279
|
+
};
|
|
3280
|
+
const { origin, referrer } = this.getOriginHeaders();
|
|
3281
|
+
if (origin) {
|
|
3282
|
+
headers["X-Origin-URL"] = origin;
|
|
3283
|
+
}
|
|
3284
|
+
if (referrer) {
|
|
3285
|
+
headers["X-Referrer-URL"] = referrer;
|
|
3286
|
+
}
|
|
3287
|
+
const apiKey = this.config.apiKey;
|
|
3288
|
+
if (apiKey) {
|
|
3289
|
+
headers["x-keverd-key"] = apiKey;
|
|
3290
|
+
headers["X-API-KEY"] = apiKey;
|
|
3291
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
3292
|
+
}
|
|
3293
|
+
const deviceInfo = this.deviceCollector.collect();
|
|
3294
|
+
await fetch(url, {
|
|
3295
|
+
method: "POST",
|
|
3296
|
+
headers,
|
|
3297
|
+
body: JSON.stringify({
|
|
3298
|
+
session_id: this.sessionId,
|
|
3299
|
+
user_id: userId || this.config.userId,
|
|
3300
|
+
device_hash: deviceHash || deviceInfo.fingerprint,
|
|
3301
|
+
metadata: metadata || {},
|
|
3302
|
+
user_agent: navigator.userAgent,
|
|
3303
|
+
browser: this._detectBrowser(),
|
|
3304
|
+
os: this._detectOS(),
|
|
3305
|
+
platform: "web",
|
|
3306
|
+
sdk_type: "web",
|
|
3307
|
+
sdk_source: "javascript"
|
|
3308
|
+
})
|
|
3309
|
+
});
|
|
3310
|
+
if (this.config.debug) {
|
|
3311
|
+
console.log(`[Keverd SDK] Session started: ${this.sessionId}`);
|
|
3312
|
+
}
|
|
3313
|
+
} catch (error) {
|
|
3314
|
+
if (this.config.debug) {
|
|
3315
|
+
console.warn("[Keverd SDK] Failed to start session on server:", error);
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
/**
|
|
3320
|
+
* End the current session
|
|
3321
|
+
*/
|
|
3322
|
+
async endSession() {
|
|
3323
|
+
if (!this.isInitialized || !this.config || !this.sessionId) {
|
|
3324
|
+
return;
|
|
3325
|
+
}
|
|
3326
|
+
try {
|
|
3327
|
+
const url = `${DEFAULT_ENDPOINT}/dashboard/sessions/${this.sessionId}/end`;
|
|
3328
|
+
const headers = {
|
|
3329
|
+
"Content-Type": "application/json"
|
|
3330
|
+
};
|
|
3331
|
+
const apiKey = this.config.apiKey;
|
|
3332
|
+
if (apiKey) {
|
|
3333
|
+
headers["x-keverd-key"] = apiKey;
|
|
3334
|
+
headers["X-API-KEY"] = apiKey;
|
|
3335
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
3336
|
+
}
|
|
3337
|
+
await fetch(url, {
|
|
3338
|
+
method: "POST",
|
|
3339
|
+
headers
|
|
3340
|
+
});
|
|
3341
|
+
if (this.config.debug) {
|
|
3342
|
+
console.log(`[Keverd SDK] Session ended: ${this.sessionId}`);
|
|
3343
|
+
}
|
|
3344
|
+
} catch (error) {
|
|
3345
|
+
if (this.config.debug) {
|
|
3346
|
+
console.warn("[Keverd SDK] Failed to end session on server:", error);
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
/**
|
|
3351
|
+
* Pause the current session (e.g., when app goes to background)
|
|
3352
|
+
*/
|
|
3353
|
+
async pauseSession() {
|
|
3354
|
+
if (!this.isInitialized || !this.config || !this.sessionId) {
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3357
|
+
try {
|
|
3358
|
+
const url = `${DEFAULT_ENDPOINT}/dashboard/sessions/${this.sessionId}/pause`;
|
|
3359
|
+
const headers = {
|
|
3360
|
+
"Content-Type": "application/json"
|
|
3361
|
+
};
|
|
3362
|
+
const apiKey = this.config.apiKey;
|
|
3363
|
+
if (apiKey) {
|
|
3364
|
+
headers["x-keverd-key"] = apiKey;
|
|
3365
|
+
headers["X-API-KEY"] = apiKey;
|
|
3366
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
3367
|
+
}
|
|
3368
|
+
await fetch(url, {
|
|
3369
|
+
method: "POST",
|
|
3370
|
+
headers
|
|
3371
|
+
});
|
|
3372
|
+
if (this.config.debug) {
|
|
3373
|
+
console.log(`[Keverd SDK] Session paused: ${this.sessionId}`);
|
|
3374
|
+
}
|
|
3375
|
+
} catch (error) {
|
|
3376
|
+
if (this.config.debug) {
|
|
3377
|
+
console.warn("[Keverd SDK] Failed to pause session on server:", error);
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3380
|
+
}
|
|
3381
|
+
/**
|
|
3382
|
+
* Resume a paused session (e.g., when app comes to foreground)
|
|
3383
|
+
*/
|
|
3384
|
+
async resumeSession() {
|
|
3385
|
+
if (!this.isInitialized || !this.config || !this.sessionId) {
|
|
3386
|
+
return;
|
|
3387
|
+
}
|
|
3388
|
+
try {
|
|
3389
|
+
const url = `${DEFAULT_ENDPOINT}/dashboard/sessions/${this.sessionId}/resume`;
|
|
3390
|
+
const headers = {
|
|
3391
|
+
"Content-Type": "application/json"
|
|
3392
|
+
};
|
|
3393
|
+
const apiKey = this.config.apiKey;
|
|
3394
|
+
if (apiKey) {
|
|
3395
|
+
headers["x-keverd-key"] = apiKey;
|
|
3396
|
+
headers["X-API-KEY"] = apiKey;
|
|
3397
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
3398
|
+
}
|
|
3399
|
+
await fetch(url, {
|
|
3400
|
+
method: "POST",
|
|
3401
|
+
headers
|
|
3402
|
+
});
|
|
3403
|
+
if (this.config.debug) {
|
|
3404
|
+
console.log(`[Keverd SDK] Session resumed: ${this.sessionId}`);
|
|
3405
|
+
}
|
|
3406
|
+
} catch (error) {
|
|
3407
|
+
if (this.config.debug) {
|
|
3408
|
+
console.warn("[Keverd SDK] Failed to resume session on server:", error);
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* Get current session status
|
|
3414
|
+
*/
|
|
3415
|
+
async getSessionStatus() {
|
|
3416
|
+
if (!this.isInitialized || !this.config || !this.sessionId) {
|
|
3417
|
+
return null;
|
|
3418
|
+
}
|
|
3419
|
+
try {
|
|
3420
|
+
const url = `${DEFAULT_ENDPOINT}/dashboard/sessions/${this.sessionId}/status`;
|
|
3421
|
+
const headers = {};
|
|
3422
|
+
const apiKey = this.config.apiKey;
|
|
3423
|
+
if (apiKey) {
|
|
3424
|
+
headers["x-keverd-key"] = apiKey;
|
|
3425
|
+
headers["X-API-KEY"] = apiKey;
|
|
3426
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
3427
|
+
}
|
|
3428
|
+
const response = await fetch(url, {
|
|
3429
|
+
method: "GET",
|
|
3430
|
+
headers
|
|
3431
|
+
});
|
|
3432
|
+
if (!response.ok) {
|
|
3433
|
+
return null;
|
|
3434
|
+
}
|
|
3435
|
+
return await response.json();
|
|
3436
|
+
} catch (error) {
|
|
3437
|
+
if (this.config.debug) {
|
|
3438
|
+
console.warn("[Keverd SDK] Failed to get session status:", error);
|
|
3439
|
+
}
|
|
3440
|
+
return null;
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3100
3443
|
/**
|
|
3101
3444
|
* Destroy the SDK instance
|
|
3102
3445
|
*/
|
|
3103
|
-
destroy() {
|
|
3446
|
+
async destroy() {
|
|
3447
|
+
if (this.sessionId) {
|
|
3448
|
+
await this.endSession();
|
|
3449
|
+
}
|
|
3104
3450
|
this.behavioralCollector.stop();
|
|
3105
3451
|
this.formInteractionCollector.stop();
|
|
3106
3452
|
this.pageInteractionCollector.stop();
|
|
3107
3453
|
this.fingerprintManager.clearCache();
|
|
3108
3454
|
this.isInitialized = false;
|
|
3455
|
+
this.stopGhostSignalCollection();
|
|
3456
|
+
this.ghostSignalCount = 0;
|
|
3109
3457
|
if (this.config?.debug) {
|
|
3110
3458
|
console.log("[Keverd SDK] Destroyed");
|
|
3111
3459
|
}
|
|
@@ -3145,22 +3493,20 @@ exports.KeverdService = class KeverdService {
|
|
|
3145
3493
|
throw new Error("Keverd SDK: apiKey is required");
|
|
3146
3494
|
}
|
|
3147
3495
|
this.config = {
|
|
3148
|
-
endpoint: config.endpoint || this.getDefaultEndpoint(),
|
|
3149
3496
|
debug: false,
|
|
3150
3497
|
...config
|
|
3151
3498
|
};
|
|
3152
3499
|
Keverd.init({
|
|
3153
3500
|
apiKey: this.config.apiKey,
|
|
3154
|
-
endpoint: this.config.endpoint,
|
|
3155
3501
|
userId: this.config.userId,
|
|
3156
3502
|
debug: this.config.debug || false
|
|
3157
3503
|
});
|
|
3158
3504
|
this.isInitialized = true;
|
|
3159
3505
|
if (this.config.debug) {
|
|
3160
|
-
console.log("[Keverd SDK] Initialized successfully"
|
|
3161
|
-
endpoint: this.config.endpoint
|
|
3162
|
-
});
|
|
3506
|
+
console.log("[Keverd SDK] Initialized successfully");
|
|
3163
3507
|
}
|
|
3508
|
+
Keverd.startSession().catch(() => {
|
|
3509
|
+
});
|
|
3164
3510
|
}
|
|
3165
3511
|
/**
|
|
3166
3512
|
* Get visitor data (fingerprint and risk assessment)
|
|
@@ -3225,22 +3571,115 @@ exports.KeverdService = class KeverdService {
|
|
|
3225
3571
|
recommendedAction: response.recommended_action
|
|
3226
3572
|
};
|
|
3227
3573
|
}
|
|
3228
|
-
/**
|
|
3229
|
-
* Get default endpoint
|
|
3230
|
-
*/
|
|
3231
|
-
getDefaultEndpoint() {
|
|
3232
|
-
return "https://api.keverd.com";
|
|
3233
|
-
}
|
|
3234
3574
|
/**
|
|
3235
3575
|
* Generate a session ID
|
|
3236
3576
|
*/
|
|
3237
3577
|
generateSessionId() {
|
|
3238
3578
|
return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
3239
3579
|
}
|
|
3580
|
+
/**
|
|
3581
|
+
* Start a new session (called automatically on init, but can be called manually)
|
|
3582
|
+
*/
|
|
3583
|
+
startSession(userId, deviceHash, metadata) {
|
|
3584
|
+
if (!this.isInitialized || !this.config) {
|
|
3585
|
+
return rxjs.throwError(() => ({
|
|
3586
|
+
message: "Keverd SDK not initialized. Call init() first.",
|
|
3587
|
+
code: "SDK_NOT_INITIALIZED"
|
|
3588
|
+
}));
|
|
3589
|
+
}
|
|
3590
|
+
return rxjs.from(Keverd.startSession(userId, deviceHash, metadata)).pipe(
|
|
3591
|
+
operators.catchError((error) => {
|
|
3592
|
+
if (this.config?.debug) {
|
|
3593
|
+
console.warn("[Keverd SDK] Failed to start session:", error);
|
|
3594
|
+
}
|
|
3595
|
+
return rxjs.throwError(() => error);
|
|
3596
|
+
})
|
|
3597
|
+
);
|
|
3598
|
+
}
|
|
3599
|
+
/**
|
|
3600
|
+
* End the current session
|
|
3601
|
+
*/
|
|
3602
|
+
endSession() {
|
|
3603
|
+
if (!this.isInitialized || !this.config) {
|
|
3604
|
+
return rxjs.throwError(() => ({
|
|
3605
|
+
message: "Keverd SDK not initialized. Call init() first.",
|
|
3606
|
+
code: "SDK_NOT_INITIALIZED"
|
|
3607
|
+
}));
|
|
3608
|
+
}
|
|
3609
|
+
return rxjs.from(Keverd.endSession()).pipe(
|
|
3610
|
+
operators.catchError((error) => {
|
|
3611
|
+
if (this.config?.debug) {
|
|
3612
|
+
console.warn("[Keverd SDK] Failed to end session:", error);
|
|
3613
|
+
}
|
|
3614
|
+
return rxjs.throwError(() => error);
|
|
3615
|
+
})
|
|
3616
|
+
);
|
|
3617
|
+
}
|
|
3618
|
+
/**
|
|
3619
|
+
* Pause the current session (e.g., when app goes to background)
|
|
3620
|
+
*/
|
|
3621
|
+
pauseSession() {
|
|
3622
|
+
if (!this.isInitialized || !this.config) {
|
|
3623
|
+
return rxjs.throwError(() => ({
|
|
3624
|
+
message: "Keverd SDK not initialized. Call init() first.",
|
|
3625
|
+
code: "SDK_NOT_INITIALIZED"
|
|
3626
|
+
}));
|
|
3627
|
+
}
|
|
3628
|
+
return rxjs.from(Keverd.pauseSession()).pipe(
|
|
3629
|
+
operators.catchError((error) => {
|
|
3630
|
+
if (this.config?.debug) {
|
|
3631
|
+
console.warn("[Keverd SDK] Failed to pause session:", error);
|
|
3632
|
+
}
|
|
3633
|
+
return rxjs.throwError(() => error);
|
|
3634
|
+
})
|
|
3635
|
+
);
|
|
3636
|
+
}
|
|
3637
|
+
/**
|
|
3638
|
+
* Resume a paused session (e.g., when app comes to foreground)
|
|
3639
|
+
*/
|
|
3640
|
+
resumeSession() {
|
|
3641
|
+
if (!this.isInitialized || !this.config) {
|
|
3642
|
+
return rxjs.throwError(() => ({
|
|
3643
|
+
message: "Keverd SDK not initialized. Call init() first.",
|
|
3644
|
+
code: "SDK_NOT_INITIALIZED"
|
|
3645
|
+
}));
|
|
3646
|
+
}
|
|
3647
|
+
return rxjs.from(Keverd.resumeSession()).pipe(
|
|
3648
|
+
operators.catchError((error) => {
|
|
3649
|
+
if (this.config?.debug) {
|
|
3650
|
+
console.warn("[Keverd SDK] Failed to resume session:", error);
|
|
3651
|
+
}
|
|
3652
|
+
return rxjs.throwError(() => error);
|
|
3653
|
+
})
|
|
3654
|
+
);
|
|
3655
|
+
}
|
|
3656
|
+
/**
|
|
3657
|
+
* Get current session status
|
|
3658
|
+
*/
|
|
3659
|
+
getSessionStatus() {
|
|
3660
|
+
if (!this.isInitialized || !this.config) {
|
|
3661
|
+
return rxjs.throwError(() => ({
|
|
3662
|
+
message: "Keverd SDK not initialized. Call init() first.",
|
|
3663
|
+
code: "SDK_NOT_INITIALIZED"
|
|
3664
|
+
}));
|
|
3665
|
+
}
|
|
3666
|
+
return rxjs.from(Keverd.getSessionStatus()).pipe(
|
|
3667
|
+
operators.catchError((error) => {
|
|
3668
|
+
if (this.config?.debug) {
|
|
3669
|
+
console.warn("[Keverd SDK] Failed to get session status:", error);
|
|
3670
|
+
}
|
|
3671
|
+
return rxjs.throwError(() => error);
|
|
3672
|
+
})
|
|
3673
|
+
);
|
|
3674
|
+
}
|
|
3240
3675
|
/**
|
|
3241
3676
|
* Destroy the SDK instance
|
|
3242
3677
|
*/
|
|
3243
3678
|
destroy() {
|
|
3679
|
+
if (this.isInitialized) {
|
|
3680
|
+
Keverd.endSession().catch(() => {
|
|
3681
|
+
});
|
|
3682
|
+
}
|
|
3244
3683
|
Keverd.destroy();
|
|
3245
3684
|
this.isInitialized = false;
|
|
3246
3685
|
this.config = null;
|
|
@@ -3276,7 +3715,6 @@ exports.KeverdModule = class KeverdModule {
|
|
|
3276
3715
|
* imports: [
|
|
3277
3716
|
* KeverdModule.forRoot({
|
|
3278
3717
|
* apiKey: 'your-api-key',
|
|
3279
|
-
* endpoint: 'https://api.keverd.com'
|
|
3280
3718
|
* })
|
|
3281
3719
|
* ]
|
|
3282
3720
|
* })
|