@arirocha/openrisk-client 0.1.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/README.md +21 -0
- package/dist/client.d.ts +11 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/fingerprint/index.d.ts +8 -0
- package/dist/fingerprint/index.d.ts.map +1 -0
- package/dist/fingerprint/raw.d.ts +4 -0
- package/dist/fingerprint/raw.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +407 -0
- package/dist/lifecycle/interaction.d.ts +4 -0
- package/dist/lifecycle/interaction.d.ts.map +1 -0
- package/dist/lifecycle/page.d.ts +3 -0
- package/dist/lifecycle/page.d.ts.map +1 -0
- package/dist/lifecycle/scroll.d.ts +4 -0
- package/dist/lifecycle/scroll.d.ts.map +1 -0
- package/dist/lifecycle/unload.d.ts +3 -0
- package/dist/lifecycle/unload.d.ts.map +1 -0
- package/dist/lifecycle/visibility.d.ts +3 -0
- package/dist/lifecycle/visibility.d.ts.map +1 -0
- package/dist/openrisk.js +375 -0
- package/dist/payload.d.ts +10 -0
- package/dist/payload.d.ts.map +1 -0
- package/dist/signals/behavior.d.ts +10 -0
- package/dist/signals/behavior.d.ts.map +1 -0
- package/dist/signals/cadence.d.ts +12 -0
- package/dist/signals/cadence.d.ts.map +1 -0
- package/dist/signals/device.d.ts +20 -0
- package/dist/signals/device.d.ts.map +1 -0
- package/dist/signals/environment.d.ts +6 -0
- package/dist/signals/environment.d.ts.map +1 -0
- package/dist/signals/features.d.ts +8 -0
- package/dist/signals/features.d.ts.map +1 -0
- package/dist/signals/integrity.d.ts +7 -0
- package/dist/signals/integrity.d.ts.map +1 -0
- package/dist/signals/multitabs.d.ts +5 -0
- package/dist/signals/multitabs.d.ts.map +1 -0
- package/dist/signals/navigation.d.ts +6 -0
- package/dist/signals/navigation.d.ts.map +1 -0
- package/dist/signals/session.d.ts +7 -0
- package/dist/signals/session.d.ts.map +1 -0
- package/dist/signals/timing.d.ts +6 -0
- package/dist/signals/timing.d.ts.map +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# openrisk-client
|
|
2
|
+
|
|
3
|
+
To install dependencies:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
To run tests:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun test
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
To build:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun run build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This project was created using `bun init` in bun v1.3.1. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RiskClientOptions } from "./types";
|
|
2
|
+
export declare class OpenRiskClient {
|
|
3
|
+
private readonly options;
|
|
4
|
+
constructor(options: RiskClientOptions);
|
|
5
|
+
emit(eventName: string, extra?: Record<string, unknown>): void;
|
|
6
|
+
track(eventName: string, extra?: Record<string, unknown>): void;
|
|
7
|
+
private send;
|
|
8
|
+
}
|
|
9
|
+
export declare class RiskClient extends OpenRiskClient {
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAiBjD,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,iBAAiB;IAmBvD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIvD,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAmBxD,OAAO,CAAC,IAAI;CAmBb;AAGD,qBAAa,UAAW,SAAQ,cAAc;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fingerprint/index.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB;;;;;;EAMjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/fingerprint/raw.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB;;EAepC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtD,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
6
|
+
var __toCommonJS = (from) => {
|
|
7
|
+
var entry = __moduleCache.get(from), desc;
|
|
8
|
+
if (entry)
|
|
9
|
+
return entry;
|
|
10
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
12
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
13
|
+
get: () => from[key],
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
}));
|
|
16
|
+
__moduleCache.set(from, entry);
|
|
17
|
+
return entry;
|
|
18
|
+
};
|
|
19
|
+
var __export = (target, all) => {
|
|
20
|
+
for (var name in all)
|
|
21
|
+
__defProp(target, name, {
|
|
22
|
+
get: all[name],
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
set: (newValue) => all[name] = () => newValue
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/index.ts
|
|
30
|
+
var exports_src = {};
|
|
31
|
+
__export(exports_src, {
|
|
32
|
+
RiskClient: () => RiskClient,
|
|
33
|
+
OpenRiskClient: () => OpenRiskClient
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(exports_src);
|
|
36
|
+
|
|
37
|
+
// src/signals/behavior.ts
|
|
38
|
+
var mouseMoves = 0;
|
|
39
|
+
var lastMove = 0;
|
|
40
|
+
var deltas = [];
|
|
41
|
+
window.addEventListener("mousemove", () => {
|
|
42
|
+
const now = performance.now();
|
|
43
|
+
if (lastMove)
|
|
44
|
+
deltas.push(now - lastMove);
|
|
45
|
+
lastMove = now;
|
|
46
|
+
mouseMoves++;
|
|
47
|
+
});
|
|
48
|
+
function collectBehavior() {
|
|
49
|
+
if (!deltas.length) {
|
|
50
|
+
return {
|
|
51
|
+
mouse_entropy: null
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const avg = deltas.reduce((a, b) => a + b, 0) / deltas.length;
|
|
55
|
+
return {
|
|
56
|
+
mouse_entropy: Math.min(1, mouseMoves / 50),
|
|
57
|
+
avg_mouse_interval_ms: Math.round(avg)
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/signals/cadence.ts
|
|
62
|
+
var timestamps = [];
|
|
63
|
+
var WINDOW_MS = 60000;
|
|
64
|
+
var STRUCTURAL_EVENTS = new Set([
|
|
65
|
+
"session_start",
|
|
66
|
+
"page_view",
|
|
67
|
+
"page_loaded"
|
|
68
|
+
]);
|
|
69
|
+
function recordEventTimestamp(eventName) {
|
|
70
|
+
if (STRUCTURAL_EVENTS.has(eventName))
|
|
71
|
+
return;
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
timestamps.push(now);
|
|
74
|
+
while (timestamps.length > 0) {
|
|
75
|
+
const oldest = timestamps[0];
|
|
76
|
+
if (oldest !== undefined && now - oldest > WINDOW_MS) {
|
|
77
|
+
timestamps.shift();
|
|
78
|
+
} else {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function collectCadence() {
|
|
84
|
+
if (timestamps.length < 2) {
|
|
85
|
+
return {
|
|
86
|
+
events_per_minute: timestamps.length,
|
|
87
|
+
avg_event_interval_ms: null,
|
|
88
|
+
burst_detected: false
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const intervals = [];
|
|
92
|
+
for (let i = 1;i < timestamps.length; i++) {
|
|
93
|
+
intervals.push(timestamps[i] - timestamps[i - 1]);
|
|
94
|
+
}
|
|
95
|
+
const avg = intervals.reduce((a, b) => a + b, 0) / intervals.length;
|
|
96
|
+
const burst = intervals.some((i) => i < 50);
|
|
97
|
+
return {
|
|
98
|
+
events_per_minute: timestamps.length,
|
|
99
|
+
avg_event_interval_ms: Math.round(avg),
|
|
100
|
+
burst_detected: burst
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/fingerprint/raw.ts
|
|
105
|
+
function collectRawFingerprint() {
|
|
106
|
+
const canvas = document.createElement("canvas");
|
|
107
|
+
const ctx = canvas.getContext("2d");
|
|
108
|
+
let canvas_fp = null;
|
|
109
|
+
if (ctx) {
|
|
110
|
+
ctx.textBaseline = "top";
|
|
111
|
+
ctx.font = "14px Arial";
|
|
112
|
+
ctx.fillText("openrisk-fp", 2, 2);
|
|
113
|
+
canvas_fp = canvas.toDataURL();
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
canvas_fp
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/fingerprint/index.ts
|
|
121
|
+
function collectFingerprint() {
|
|
122
|
+
return {
|
|
123
|
+
mode: "raw",
|
|
124
|
+
version: "fp_raw_v1",
|
|
125
|
+
data: collectRawFingerprint()
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/signals/device.ts
|
|
130
|
+
function collectDevice() {
|
|
131
|
+
const screen = window.screen;
|
|
132
|
+
return {
|
|
133
|
+
platform: navigator.platform || "unknown",
|
|
134
|
+
user_agent: navigator.userAgent || "unknown",
|
|
135
|
+
cpu_cores: navigator.hardwareConcurrency ?? null,
|
|
136
|
+
memory_gb: navigator.deviceMemory ?? null,
|
|
137
|
+
touch_support: "ontouchstart" in window,
|
|
138
|
+
screen: {
|
|
139
|
+
width: screen?.width ?? null,
|
|
140
|
+
height: screen?.height ?? null,
|
|
141
|
+
pixel_ratio: window.devicePixelRatio ?? 1
|
|
142
|
+
},
|
|
143
|
+
fingerprint: collectFingerprint()
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/signals/environment.ts
|
|
148
|
+
function collectEnvironment() {
|
|
149
|
+
return {
|
|
150
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
151
|
+
locale: navigator.language,
|
|
152
|
+
languages: navigator.languages
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/signals/features.ts
|
|
157
|
+
function collectFeatures() {
|
|
158
|
+
return {
|
|
159
|
+
webdriver: navigator.webdriver === true,
|
|
160
|
+
plugins_count: navigator.plugins?.length ?? null,
|
|
161
|
+
languages_count: navigator.languages?.length ?? null,
|
|
162
|
+
permissions_api: "permissions" in navigator,
|
|
163
|
+
hardware_concurrency_present: typeof navigator.hardwareConcurrency === "number"
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/signals/integrity.ts
|
|
168
|
+
function collectIntegrity() {
|
|
169
|
+
return {
|
|
170
|
+
sdk_version: "__SDK_VERSION__",
|
|
171
|
+
schema_version: "1.0",
|
|
172
|
+
timestamp_skew_ms: Math.abs(Date.now() - performance.timeOrigin),
|
|
173
|
+
telemetry_blocked: false
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/signals/multitabs.ts
|
|
178
|
+
var TAB_ID = crypto.randomUUID();
|
|
179
|
+
var channel = new BroadcastChannel("openrisk_tabs");
|
|
180
|
+
var peers = new Set;
|
|
181
|
+
peers.add(TAB_ID);
|
|
182
|
+
channel.onmessage = (event) => {
|
|
183
|
+
const msg = event.data;
|
|
184
|
+
if (!msg || msg.tabId === TAB_ID)
|
|
185
|
+
return;
|
|
186
|
+
if (msg.type === "hello") {
|
|
187
|
+
peers.add(msg.tabId);
|
|
188
|
+
channel.postMessage({
|
|
189
|
+
type: "hello_ack",
|
|
190
|
+
tabId: TAB_ID
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (msg.type === "hello_ack") {
|
|
194
|
+
peers.add(msg.tabId);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
setTimeout(() => {
|
|
198
|
+
channel.postMessage({
|
|
199
|
+
type: "hello",
|
|
200
|
+
tabId: TAB_ID
|
|
201
|
+
});
|
|
202
|
+
}, 50);
|
|
203
|
+
function collectMultiTabs() {
|
|
204
|
+
return {
|
|
205
|
+
concurrent_tabs_estimate: peers.size,
|
|
206
|
+
multiple_tabs_detected: peers.size > 1
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/signals/navigation.ts
|
|
211
|
+
function collectNavigation() {
|
|
212
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
213
|
+
return {
|
|
214
|
+
entry_type: nav?.type ?? "unknown",
|
|
215
|
+
referrer_type: document.referrer ? "external" : "direct",
|
|
216
|
+
path_depth: location.pathname.split("/").filter(Boolean).length
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/signals/session.ts
|
|
221
|
+
var sessionStart = Date.now();
|
|
222
|
+
var eventCount = 0;
|
|
223
|
+
var pageCount = 1;
|
|
224
|
+
var visibilityChanges = 0;
|
|
225
|
+
document.addEventListener("visibilitychange", () => {
|
|
226
|
+
visibilityChanges++;
|
|
227
|
+
});
|
|
228
|
+
function collectSession() {
|
|
229
|
+
eventCount++;
|
|
230
|
+
return {
|
|
231
|
+
session_age_ms: Date.now() - sessionStart,
|
|
232
|
+
event_count: eventCount,
|
|
233
|
+
page_count: pageCount,
|
|
234
|
+
tab_visibility_changes: visibilityChanges
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/signals/timing.ts
|
|
239
|
+
function collectTiming() {
|
|
240
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
241
|
+
const pageLoad = nav && nav.domComplete > 0 ? Math.round(nav.domComplete - nav.startTime) : null;
|
|
242
|
+
const domInteractive = nav && nav.domInteractive > 0 ? Math.round(nav.domInteractive - nav.startTime) : null;
|
|
243
|
+
return {
|
|
244
|
+
page_load_ms: pageLoad,
|
|
245
|
+
dom_interactive_ms: domInteractive,
|
|
246
|
+
network_rtt_estimate_ms: navigator.connection?.rtt ?? null
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/payload.ts
|
|
251
|
+
function buildPayload(eventName, extra, signalsOverride) {
|
|
252
|
+
const signals = signalsOverride || {
|
|
253
|
+
environment: collectEnvironment(),
|
|
254
|
+
device: collectDevice(),
|
|
255
|
+
session: collectSession(),
|
|
256
|
+
navigation: collectNavigation(),
|
|
257
|
+
timing: collectTiming(),
|
|
258
|
+
behavior: collectBehavior(),
|
|
259
|
+
cadence: collectCadence(),
|
|
260
|
+
features: collectFeatures(),
|
|
261
|
+
multitabs: collectMultiTabs(),
|
|
262
|
+
integrity: collectIntegrity()
|
|
263
|
+
};
|
|
264
|
+
return {
|
|
265
|
+
event: {
|
|
266
|
+
name: eventName,
|
|
267
|
+
timestamp: new Date().toISOString(),
|
|
268
|
+
event_id: crypto.randomUUID()
|
|
269
|
+
},
|
|
270
|
+
signals,
|
|
271
|
+
extra
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// src/lifecycle/interaction.ts
|
|
276
|
+
var interacted = false;
|
|
277
|
+
function setupInteraction(client) {
|
|
278
|
+
const markInteraction = (type) => {
|
|
279
|
+
if (interacted)
|
|
280
|
+
return;
|
|
281
|
+
interacted = true;
|
|
282
|
+
client.emit("first_interaction", {
|
|
283
|
+
interaction_type: type
|
|
284
|
+
});
|
|
285
|
+
cleanup();
|
|
286
|
+
};
|
|
287
|
+
const cleanup = () => {
|
|
288
|
+
window.removeEventListener("mousemove", onMouse);
|
|
289
|
+
window.removeEventListener("keydown", onKey);
|
|
290
|
+
window.removeEventListener("touchstart", onTouch);
|
|
291
|
+
};
|
|
292
|
+
const onMouse = () => markInteraction("mouse");
|
|
293
|
+
const onKey = () => markInteraction("keyboard");
|
|
294
|
+
const onTouch = () => markInteraction("touch");
|
|
295
|
+
window.addEventListener("mousemove", onMouse, { passive: true });
|
|
296
|
+
window.addEventListener("keydown", onKey);
|
|
297
|
+
window.addEventListener("touchstart", onTouch, { passive: true });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/lifecycle/page.ts
|
|
301
|
+
function setupPageLifecycle(client) {
|
|
302
|
+
client.emit("page_view");
|
|
303
|
+
window.addEventListener("load", () => {
|
|
304
|
+
client.emit("page_loaded");
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// src/lifecycle/scroll.ts
|
|
309
|
+
var maxScroll = 0;
|
|
310
|
+
var thresholds = [25, 50, 75, 100];
|
|
311
|
+
var sent = new Set;
|
|
312
|
+
function setupScroll(client) {
|
|
313
|
+
window.addEventListener("scroll", () => {
|
|
314
|
+
const scrollTop = window.scrollY;
|
|
315
|
+
const height = document.documentElement.scrollHeight - window.innerHeight;
|
|
316
|
+
if (height <= 0)
|
|
317
|
+
return;
|
|
318
|
+
const percent = Math.round(scrollTop / height * 100);
|
|
319
|
+
maxScroll = Math.max(maxScroll, percent);
|
|
320
|
+
for (const t of thresholds) {
|
|
321
|
+
if (percent >= t && !sent.has(t)) {
|
|
322
|
+
sent.add(t);
|
|
323
|
+
client.emit("scroll_depth", { percent: t });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}, { passive: true });
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/lifecycle/unload.ts
|
|
330
|
+
function setupUnload(client) {
|
|
331
|
+
window.addEventListener("beforeunload", () => {
|
|
332
|
+
client.emit("session_end");
|
|
333
|
+
});
|
|
334
|
+
window.addEventListener("pagehide", () => {
|
|
335
|
+
client.emit("session_end");
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/lifecycle/visibility.ts
|
|
340
|
+
function setupVisibility(client) {
|
|
341
|
+
document.addEventListener("visibilitychange", () => {
|
|
342
|
+
if (document.visibilityState === "hidden") {
|
|
343
|
+
client.emit("page_hidden");
|
|
344
|
+
} else if (document.visibilityState === "visible") {
|
|
345
|
+
client.emit("page_visible");
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/client.ts
|
|
351
|
+
function emitDebug(payload) {
|
|
352
|
+
window.dispatchEvent(new CustomEvent("openrisk:debug", {
|
|
353
|
+
detail: payload
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
class OpenRiskClient {
|
|
358
|
+
options;
|
|
359
|
+
constructor(options) {
|
|
360
|
+
this.options = options;
|
|
361
|
+
this.emit("session_start");
|
|
362
|
+
const setupPageLifecycleFn = this.options.setupPageLifecycle || setupPageLifecycle;
|
|
363
|
+
const setupVisibilityFn = this.options.setupVisibility || setupVisibility;
|
|
364
|
+
const setupInteractionFn = this.options.setupInteraction || setupInteraction;
|
|
365
|
+
const setupScrollFn = this.options.setupScroll || setupScroll;
|
|
366
|
+
const setupUnloadFn = this.options.setupUnload || setupUnload;
|
|
367
|
+
setupPageLifecycleFn(this);
|
|
368
|
+
setupVisibilityFn(this);
|
|
369
|
+
setupInteractionFn(this);
|
|
370
|
+
setupScrollFn(this);
|
|
371
|
+
setupUnloadFn(this);
|
|
372
|
+
}
|
|
373
|
+
emit(eventName, extra) {
|
|
374
|
+
this.track(eventName, extra);
|
|
375
|
+
}
|
|
376
|
+
track(eventName, extra) {
|
|
377
|
+
recordEventTimestamp(eventName);
|
|
378
|
+
const payload = buildPayload(eventName, extra, this.options.signalsOverride);
|
|
379
|
+
if (this.options.debug) {
|
|
380
|
+
emitDebug({
|
|
381
|
+
event: eventName,
|
|
382
|
+
payload
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
this.send(payload);
|
|
386
|
+
}
|
|
387
|
+
send(payload) {
|
|
388
|
+
try {
|
|
389
|
+
const body = JSON.stringify(payload);
|
|
390
|
+
if (navigator.sendBeacon) {
|
|
391
|
+
navigator.sendBeacon(this.options.endpoint, body);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
fetch(this.options.endpoint, {
|
|
395
|
+
method: "POST",
|
|
396
|
+
headers: {
|
|
397
|
+
"content-type": "application/json"
|
|
398
|
+
},
|
|
399
|
+
body,
|
|
400
|
+
keepalive: true
|
|
401
|
+
}).catch(() => {});
|
|
402
|
+
} catch {}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
class RiskClient extends OpenRiskClient {
|
|
407
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction.d.ts","sourceRoot":"","sources":["../../src/lifecycle/interaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAI5C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,QAyBlD;AAGD,wBAAgB,qBAAqB,SAEpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/lifecycle/page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,QAMpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../src/lifecycle/scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAM5C,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,QAqB7C;AAGD,wBAAgB,gBAAgB,SAG/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unload.d.ts","sourceRoot":"","sources":["../../src/lifecycle/unload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,QAQ7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../src/lifecycle/visibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,QAQjD"}
|
package/dist/openrisk.js
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
// src/signals/behavior.ts
|
|
2
|
+
var mouseMoves = 0;
|
|
3
|
+
var lastMove = 0;
|
|
4
|
+
var deltas = [];
|
|
5
|
+
window.addEventListener("mousemove", () => {
|
|
6
|
+
const now = performance.now();
|
|
7
|
+
if (lastMove)
|
|
8
|
+
deltas.push(now - lastMove);
|
|
9
|
+
lastMove = now;
|
|
10
|
+
mouseMoves++;
|
|
11
|
+
});
|
|
12
|
+
function collectBehavior() {
|
|
13
|
+
if (!deltas.length) {
|
|
14
|
+
return {
|
|
15
|
+
mouse_entropy: null
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const avg = deltas.reduce((a, b) => a + b, 0) / deltas.length;
|
|
19
|
+
return {
|
|
20
|
+
mouse_entropy: Math.min(1, mouseMoves / 50),
|
|
21
|
+
avg_mouse_interval_ms: Math.round(avg)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/signals/cadence.ts
|
|
26
|
+
var timestamps = [];
|
|
27
|
+
var WINDOW_MS = 60000;
|
|
28
|
+
var STRUCTURAL_EVENTS = new Set([
|
|
29
|
+
"session_start",
|
|
30
|
+
"page_view",
|
|
31
|
+
"page_loaded"
|
|
32
|
+
]);
|
|
33
|
+
function recordEventTimestamp(eventName) {
|
|
34
|
+
if (STRUCTURAL_EVENTS.has(eventName))
|
|
35
|
+
return;
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
timestamps.push(now);
|
|
38
|
+
while (timestamps.length > 0) {
|
|
39
|
+
const oldest = timestamps[0];
|
|
40
|
+
if (oldest !== undefined && now - oldest > WINDOW_MS) {
|
|
41
|
+
timestamps.shift();
|
|
42
|
+
} else {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function collectCadence() {
|
|
48
|
+
if (timestamps.length < 2) {
|
|
49
|
+
return {
|
|
50
|
+
events_per_minute: timestamps.length,
|
|
51
|
+
avg_event_interval_ms: null,
|
|
52
|
+
burst_detected: false
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const intervals = [];
|
|
56
|
+
for (let i = 1;i < timestamps.length; i++) {
|
|
57
|
+
intervals.push(timestamps[i] - timestamps[i - 1]);
|
|
58
|
+
}
|
|
59
|
+
const avg = intervals.reduce((a, b) => a + b, 0) / intervals.length;
|
|
60
|
+
const burst = intervals.some((i) => i < 50);
|
|
61
|
+
return {
|
|
62
|
+
events_per_minute: timestamps.length,
|
|
63
|
+
avg_event_interval_ms: Math.round(avg),
|
|
64
|
+
burst_detected: burst
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/fingerprint/raw.ts
|
|
69
|
+
function collectRawFingerprint() {
|
|
70
|
+
const canvas = document.createElement("canvas");
|
|
71
|
+
const ctx = canvas.getContext("2d");
|
|
72
|
+
let canvas_fp = null;
|
|
73
|
+
if (ctx) {
|
|
74
|
+
ctx.textBaseline = "top";
|
|
75
|
+
ctx.font = "14px Arial";
|
|
76
|
+
ctx.fillText("openrisk-fp", 2, 2);
|
|
77
|
+
canvas_fp = canvas.toDataURL();
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
canvas_fp
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/fingerprint/index.ts
|
|
85
|
+
function collectFingerprint() {
|
|
86
|
+
return {
|
|
87
|
+
mode: "raw",
|
|
88
|
+
version: "fp_raw_v1",
|
|
89
|
+
data: collectRawFingerprint()
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/signals/device.ts
|
|
94
|
+
function collectDevice() {
|
|
95
|
+
const screen = window.screen;
|
|
96
|
+
return {
|
|
97
|
+
platform: navigator.platform || "unknown",
|
|
98
|
+
user_agent: navigator.userAgent || "unknown",
|
|
99
|
+
cpu_cores: navigator.hardwareConcurrency ?? null,
|
|
100
|
+
memory_gb: navigator.deviceMemory ?? null,
|
|
101
|
+
touch_support: "ontouchstart" in window,
|
|
102
|
+
screen: {
|
|
103
|
+
width: screen?.width ?? null,
|
|
104
|
+
height: screen?.height ?? null,
|
|
105
|
+
pixel_ratio: window.devicePixelRatio ?? 1
|
|
106
|
+
},
|
|
107
|
+
fingerprint: collectFingerprint()
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/signals/environment.ts
|
|
112
|
+
function collectEnvironment() {
|
|
113
|
+
return {
|
|
114
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
115
|
+
locale: navigator.language,
|
|
116
|
+
languages: navigator.languages
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/signals/features.ts
|
|
121
|
+
function collectFeatures() {
|
|
122
|
+
return {
|
|
123
|
+
webdriver: navigator.webdriver === true,
|
|
124
|
+
plugins_count: navigator.plugins?.length ?? null,
|
|
125
|
+
languages_count: navigator.languages?.length ?? null,
|
|
126
|
+
permissions_api: "permissions" in navigator,
|
|
127
|
+
hardware_concurrency_present: typeof navigator.hardwareConcurrency === "number"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/signals/integrity.ts
|
|
132
|
+
function collectIntegrity() {
|
|
133
|
+
return {
|
|
134
|
+
sdk_version: "__SDK_VERSION__",
|
|
135
|
+
schema_version: "1.0",
|
|
136
|
+
timestamp_skew_ms: Math.abs(Date.now() - performance.timeOrigin),
|
|
137
|
+
telemetry_blocked: false
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/signals/multitabs.ts
|
|
142
|
+
var TAB_ID = crypto.randomUUID();
|
|
143
|
+
var channel = new BroadcastChannel("openrisk_tabs");
|
|
144
|
+
var peers = new Set;
|
|
145
|
+
peers.add(TAB_ID);
|
|
146
|
+
channel.onmessage = (event) => {
|
|
147
|
+
const msg = event.data;
|
|
148
|
+
if (!msg || msg.tabId === TAB_ID)
|
|
149
|
+
return;
|
|
150
|
+
if (msg.type === "hello") {
|
|
151
|
+
peers.add(msg.tabId);
|
|
152
|
+
channel.postMessage({
|
|
153
|
+
type: "hello_ack",
|
|
154
|
+
tabId: TAB_ID
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (msg.type === "hello_ack") {
|
|
158
|
+
peers.add(msg.tabId);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
channel.postMessage({
|
|
163
|
+
type: "hello",
|
|
164
|
+
tabId: TAB_ID
|
|
165
|
+
});
|
|
166
|
+
}, 50);
|
|
167
|
+
function collectMultiTabs() {
|
|
168
|
+
return {
|
|
169
|
+
concurrent_tabs_estimate: peers.size,
|
|
170
|
+
multiple_tabs_detected: peers.size > 1
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/signals/navigation.ts
|
|
175
|
+
function collectNavigation() {
|
|
176
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
177
|
+
return {
|
|
178
|
+
entry_type: nav?.type ?? "unknown",
|
|
179
|
+
referrer_type: document.referrer ? "external" : "direct",
|
|
180
|
+
path_depth: location.pathname.split("/").filter(Boolean).length
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/signals/session.ts
|
|
185
|
+
var sessionStart = Date.now();
|
|
186
|
+
var eventCount = 0;
|
|
187
|
+
var pageCount = 1;
|
|
188
|
+
var visibilityChanges = 0;
|
|
189
|
+
document.addEventListener("visibilitychange", () => {
|
|
190
|
+
visibilityChanges++;
|
|
191
|
+
});
|
|
192
|
+
function collectSession() {
|
|
193
|
+
eventCount++;
|
|
194
|
+
return {
|
|
195
|
+
session_age_ms: Date.now() - sessionStart,
|
|
196
|
+
event_count: eventCount,
|
|
197
|
+
page_count: pageCount,
|
|
198
|
+
tab_visibility_changes: visibilityChanges
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/signals/timing.ts
|
|
203
|
+
function collectTiming() {
|
|
204
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
205
|
+
const pageLoad = nav && nav.domComplete > 0 ? Math.round(nav.domComplete - nav.startTime) : null;
|
|
206
|
+
const domInteractive = nav && nav.domInteractive > 0 ? Math.round(nav.domInteractive - nav.startTime) : null;
|
|
207
|
+
return {
|
|
208
|
+
page_load_ms: pageLoad,
|
|
209
|
+
dom_interactive_ms: domInteractive,
|
|
210
|
+
network_rtt_estimate_ms: navigator.connection?.rtt ?? null
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/payload.ts
|
|
215
|
+
function buildPayload(eventName, extra, signalsOverride) {
|
|
216
|
+
const signals = signalsOverride || {
|
|
217
|
+
environment: collectEnvironment(),
|
|
218
|
+
device: collectDevice(),
|
|
219
|
+
session: collectSession(),
|
|
220
|
+
navigation: collectNavigation(),
|
|
221
|
+
timing: collectTiming(),
|
|
222
|
+
behavior: collectBehavior(),
|
|
223
|
+
cadence: collectCadence(),
|
|
224
|
+
features: collectFeatures(),
|
|
225
|
+
multitabs: collectMultiTabs(),
|
|
226
|
+
integrity: collectIntegrity()
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
event: {
|
|
230
|
+
name: eventName,
|
|
231
|
+
timestamp: new Date().toISOString(),
|
|
232
|
+
event_id: crypto.randomUUID()
|
|
233
|
+
},
|
|
234
|
+
signals,
|
|
235
|
+
extra
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/lifecycle/interaction.ts
|
|
240
|
+
var interacted = false;
|
|
241
|
+
function setupInteraction(client) {
|
|
242
|
+
const markInteraction = (type) => {
|
|
243
|
+
if (interacted)
|
|
244
|
+
return;
|
|
245
|
+
interacted = true;
|
|
246
|
+
client.emit("first_interaction", {
|
|
247
|
+
interaction_type: type
|
|
248
|
+
});
|
|
249
|
+
cleanup();
|
|
250
|
+
};
|
|
251
|
+
const cleanup = () => {
|
|
252
|
+
window.removeEventListener("mousemove", onMouse);
|
|
253
|
+
window.removeEventListener("keydown", onKey);
|
|
254
|
+
window.removeEventListener("touchstart", onTouch);
|
|
255
|
+
};
|
|
256
|
+
const onMouse = () => markInteraction("mouse");
|
|
257
|
+
const onKey = () => markInteraction("keyboard");
|
|
258
|
+
const onTouch = () => markInteraction("touch");
|
|
259
|
+
window.addEventListener("mousemove", onMouse, { passive: true });
|
|
260
|
+
window.addEventListener("keydown", onKey);
|
|
261
|
+
window.addEventListener("touchstart", onTouch, { passive: true });
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/lifecycle/page.ts
|
|
265
|
+
function setupPageLifecycle(client) {
|
|
266
|
+
client.emit("page_view");
|
|
267
|
+
window.addEventListener("load", () => {
|
|
268
|
+
client.emit("page_loaded");
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/lifecycle/scroll.ts
|
|
273
|
+
var maxScroll = 0;
|
|
274
|
+
var thresholds = [25, 50, 75, 100];
|
|
275
|
+
var sent = new Set;
|
|
276
|
+
function setupScroll(client) {
|
|
277
|
+
window.addEventListener("scroll", () => {
|
|
278
|
+
const scrollTop = window.scrollY;
|
|
279
|
+
const height = document.documentElement.scrollHeight - window.innerHeight;
|
|
280
|
+
if (height <= 0)
|
|
281
|
+
return;
|
|
282
|
+
const percent = Math.round(scrollTop / height * 100);
|
|
283
|
+
maxScroll = Math.max(maxScroll, percent);
|
|
284
|
+
for (const t of thresholds) {
|
|
285
|
+
if (percent >= t && !sent.has(t)) {
|
|
286
|
+
sent.add(t);
|
|
287
|
+
client.emit("scroll_depth", { percent: t });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}, { passive: true });
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/lifecycle/unload.ts
|
|
294
|
+
function setupUnload(client) {
|
|
295
|
+
window.addEventListener("beforeunload", () => {
|
|
296
|
+
client.emit("session_end");
|
|
297
|
+
});
|
|
298
|
+
window.addEventListener("pagehide", () => {
|
|
299
|
+
client.emit("session_end");
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/lifecycle/visibility.ts
|
|
304
|
+
function setupVisibility(client) {
|
|
305
|
+
document.addEventListener("visibilitychange", () => {
|
|
306
|
+
if (document.visibilityState === "hidden") {
|
|
307
|
+
client.emit("page_hidden");
|
|
308
|
+
} else if (document.visibilityState === "visible") {
|
|
309
|
+
client.emit("page_visible");
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/client.ts
|
|
315
|
+
function emitDebug(payload) {
|
|
316
|
+
window.dispatchEvent(new CustomEvent("openrisk:debug", {
|
|
317
|
+
detail: payload
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
class OpenRiskClient {
|
|
322
|
+
options;
|
|
323
|
+
constructor(options) {
|
|
324
|
+
this.options = options;
|
|
325
|
+
this.emit("session_start");
|
|
326
|
+
const setupPageLifecycleFn = this.options.setupPageLifecycle || setupPageLifecycle;
|
|
327
|
+
const setupVisibilityFn = this.options.setupVisibility || setupVisibility;
|
|
328
|
+
const setupInteractionFn = this.options.setupInteraction || setupInteraction;
|
|
329
|
+
const setupScrollFn = this.options.setupScroll || setupScroll;
|
|
330
|
+
const setupUnloadFn = this.options.setupUnload || setupUnload;
|
|
331
|
+
setupPageLifecycleFn(this);
|
|
332
|
+
setupVisibilityFn(this);
|
|
333
|
+
setupInteractionFn(this);
|
|
334
|
+
setupScrollFn(this);
|
|
335
|
+
setupUnloadFn(this);
|
|
336
|
+
}
|
|
337
|
+
emit(eventName, extra) {
|
|
338
|
+
this.track(eventName, extra);
|
|
339
|
+
}
|
|
340
|
+
track(eventName, extra) {
|
|
341
|
+
recordEventTimestamp(eventName);
|
|
342
|
+
const payload = buildPayload(eventName, extra, this.options.signalsOverride);
|
|
343
|
+
if (this.options.debug) {
|
|
344
|
+
emitDebug({
|
|
345
|
+
event: eventName,
|
|
346
|
+
payload
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
this.send(payload);
|
|
350
|
+
}
|
|
351
|
+
send(payload) {
|
|
352
|
+
try {
|
|
353
|
+
const body = JSON.stringify(payload);
|
|
354
|
+
if (navigator.sendBeacon) {
|
|
355
|
+
navigator.sendBeacon(this.options.endpoint, body);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
fetch(this.options.endpoint, {
|
|
359
|
+
method: "POST",
|
|
360
|
+
headers: {
|
|
361
|
+
"content-type": "application/json"
|
|
362
|
+
},
|
|
363
|
+
body,
|
|
364
|
+
keepalive: true
|
|
365
|
+
}).catch(() => {});
|
|
366
|
+
} catch {}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
class RiskClient extends OpenRiskClient {
|
|
371
|
+
}
|
|
372
|
+
export {
|
|
373
|
+
RiskClient,
|
|
374
|
+
OpenRiskClient
|
|
375
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function buildPayload(eventName: string, extra?: Record<string, unknown>, signalsOverride?: Record<string, unknown>): {
|
|
2
|
+
event: {
|
|
3
|
+
name: string;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
event_id: `${string}-${string}-${string}-${string}-${string}`;
|
|
6
|
+
};
|
|
7
|
+
signals: Record<string, unknown>;
|
|
8
|
+
extra: Record<string, unknown> | undefined;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../src/payload.ts"],"names":[],"mappings":"AAWA,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;EA0B1C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function collectBehavior(): {
|
|
2
|
+
mouse_entropy: null;
|
|
3
|
+
avg_mouse_interval_ms?: undefined;
|
|
4
|
+
} | {
|
|
5
|
+
mouse_entropy: number;
|
|
6
|
+
avg_mouse_interval_ms: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function simulateMouseMove(): void;
|
|
9
|
+
export declare function resetBehaviorState(): void;
|
|
10
|
+
//# sourceMappingURL=behavior.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavior.d.ts","sourceRoot":"","sources":["../../src/signals/behavior.ts"],"names":[],"mappings":"AAWA,wBAAgB,eAAe;;;;;;EAa9B;AAGD,wBAAgB,iBAAiB,SAKhC;AAGD,wBAAgB,kBAAkB,SAIjC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function recordEventTimestamp(eventName: string): void;
|
|
2
|
+
export declare function collectCadence(): {
|
|
3
|
+
events_per_minute: number;
|
|
4
|
+
avg_event_interval_ms: null;
|
|
5
|
+
burst_detected: boolean;
|
|
6
|
+
} | {
|
|
7
|
+
events_per_minute: number;
|
|
8
|
+
avg_event_interval_ms: number;
|
|
9
|
+
burst_detected: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function resetCadenceTimestamps(): void;
|
|
12
|
+
//# sourceMappingURL=cadence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cadence.d.ts","sourceRoot":"","sources":["../../src/signals/cadence.ts"],"names":[],"mappings":"AASA,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,QAcrD;AAED,wBAAgB,cAAc;;;;;;;;EAuB7B;AAGD,wBAAgB,sBAAsB,SAErC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function collectDevice(): {
|
|
2
|
+
platform: "MacIntel" | "Win32" | "Linux x86_64";
|
|
3
|
+
user_agent: string;
|
|
4
|
+
cpu_cores: number;
|
|
5
|
+
memory_gb: any;
|
|
6
|
+
touch_support: boolean;
|
|
7
|
+
screen: {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
pixel_ratio: number;
|
|
11
|
+
};
|
|
12
|
+
fingerprint: {
|
|
13
|
+
mode: string;
|
|
14
|
+
version: string;
|
|
15
|
+
data: {
|
|
16
|
+
canvas_fp: string | null;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=device.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/signals/device.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa;;;;;;;;;;;;;;;;;;EAmB5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/signals/environment.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB;;;;EAMjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/signals/features.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe;;;;;;EAS9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/signals/integrity.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB;;;;;EAO/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multitabs.d.ts","sourceRoot":"","sources":["../../src/signals/multitabs.ts"],"names":[],"mappings":"AA+BA,wBAAgB,gBAAgB;;;EAK/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/signals/navigation.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB;;;;EAUhC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/signals/session.ts"],"names":[],"mappings":"AASA,wBAAgB,cAAc;;;;;EAS7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/signals/timing.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa;;;;EAoB5B"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type RiskEventName = string;
|
|
2
|
+
export interface RiskEvent {
|
|
3
|
+
name: RiskEventName;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
event_id: string;
|
|
6
|
+
correlation_id?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RiskPayload {
|
|
9
|
+
event: RiskEvent;
|
|
10
|
+
signals: Record<string, unknown>;
|
|
11
|
+
custom?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
export type RiskClientOptions = {
|
|
14
|
+
projectKey: string;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
setupPageLifecycle?: (client: any) => void;
|
|
18
|
+
setupVisibility?: (client: any) => void;
|
|
19
|
+
setupInteraction?: (client: any) => void;
|
|
20
|
+
setupScroll?: (client: any) => void;
|
|
21
|
+
setupUnload?: (client: any) => void;
|
|
22
|
+
signalsOverride?: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IAEjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAGhB,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACxC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAGpC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arirocha/openrisk-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
},
|
|
14
|
+
"./browser": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/openrisk.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"private": false,
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/bun": "latest",
|
|
29
|
+
"@playwright/test": "^1.58.0",
|
|
30
|
+
"jsdom": "^27.4.0",
|
|
31
|
+
"typescript": "^5.5.4"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"dev": "bun build src/index.ts --outfile=../dist/openrisk.js --target=browser --format=esm --watch",
|
|
35
|
+
"build:esm": "bun build src/index.ts --outdir=dist --target=browser --format=esm",
|
|
36
|
+
"build:cjs": "bun build src/index.ts --outdir=dist --target=browser --format=cjs",
|
|
37
|
+
"build:browser": "bun build src/index.ts --outfile=dist/openrisk.js --target=browser --format=esm",
|
|
38
|
+
"build:types": "bunx tsc -p tsconfig.json --emitDeclarationOnly",
|
|
39
|
+
"build": "bun run build:esm && bun run build:cjs && bun run build:browser && bun run build:types",
|
|
40
|
+
"test": "bun test",
|
|
41
|
+
"test:e2e": "npm run build && playwright test",
|
|
42
|
+
"test:e2e:ui": "playwright test --ui",
|
|
43
|
+
"test:e2e:headed": "playwright test --headed",
|
|
44
|
+
"test:e2e:debug": "playwright test --debug"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"typescript": "^5"
|
|
48
|
+
}
|
|
49
|
+
}
|