@axeptio/behavior-detection 1.0.2 → 1.0.3

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/package.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
2
  "name": "@axeptio/behavior-detection",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Lightweight behavior detection library to assess human likelihood of user sessions",
5
- "main": "./dist/cjs/index.js",
5
+ "type": "module",
6
+ "main": "./dist/cjs/index.cjs",
6
7
  "module": "./dist/esm/index.js",
7
8
  "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
11
  "types": "./dist/index.d.ts",
11
12
  "import": "./dist/esm/index.js",
12
- "require": "./dist/cjs/index.js"
13
+ "require": "./dist/cjs/index.cjs"
13
14
  }
14
15
  },
15
16
  "files": [
16
17
  "dist"
17
18
  ],
18
19
  "scripts": {
19
- "build": "npm run build:cjs && npm run build:esm && npm run build:types",
20
- "build:cjs": "tsc --module commonjs --outDir dist/cjs",
20
+ "build": "npm run build:esm && npm run build:cjs && npm run build:types",
21
+ "build:cjs": "esbuild dist/esm/index.js --bundle --format=cjs --platform=node --target=es2017 --outfile=dist/cjs/index.cjs",
21
22
  "build:esm": "tsc --module es2015 --outDir dist/esm",
22
23
  "build:types": "tsc --declaration --emitDeclarationOnly --outDir dist",
23
24
  "build:bundle": "npm run build:esm && esbuild dist/esm/index.js --bundle --minify --sourcemap --target=es2020 --tree-shaking=true --outfile=dist/behavior-detection.esm.min.js",
@@ -25,19 +26,19 @@
25
26
  "build:browser:dev": "npm run build:esm && esbuild dist/esm/browser.js --bundle --minify --sourcemap --format=iife --global-name=BehaviorDetector --target=es2020 --tree-shaking=true --outfile=dist/behavior-detection.min.js",
26
27
  "build:all": "npm run build && npm run build:bundle && npm run build:browser",
27
28
  "clean": "rm -rf dist",
28
- "deploy": "node scripts/deploy.js",
29
+ "deploy": "node scripts/deploy.cjs",
29
30
  "release:patch": "npm version patch && git push && git push --tags",
30
31
  "release:minor": "npm version minor && git push && git push --tags",
31
32
  "release:major": "npm version major && git push && git push --tags",
32
- "tryme": "npm run build && node scripts/serve.js",
33
- "test": "npm run build && node tests/adversarial/run-tests.js",
34
- "test:adversarial": "npm run build && node tests/adversarial/run-all.js",
35
- "test:playwright": "npm run build && node tests/adversarial/playwright-test.js",
36
- "test:selenium": "npm run build && node tests/adversarial/selenium-test.js",
37
- "test:puppeteer": "npm run build && node tests/adversarial/puppeteer-test.js",
38
- "test:stress": "npm run build && node tests/adversarial/detector-stress-test.js",
39
- "test:stress:quick": "npm run build && node tests/adversarial/detector-stress-test.js --cycles=3 --duration=5000",
40
- "test:stress:intense": "npm run build && node tests/adversarial/detector-stress-test.js --cycles=10 --duration=20000"
33
+ "tryme": "npm run build && node scripts/serve.cjs",
34
+ "test": "npm run build && node tests/adversarial/run-tests.cjs",
35
+ "test:adversarial": "npm run build && node tests/adversarial/run-all.cjs",
36
+ "test:playwright": "npm run build && node tests/adversarial/playwright-test.cjs",
37
+ "test:selenium": "npm run build && node tests/adversarial/selenium-test.cjs",
38
+ "test:puppeteer": "npm run build && node tests/adversarial/puppeteer-test.cjs",
39
+ "test:stress": "npm run build && node tests/adversarial/detector-stress-test.cjs",
40
+ "test:stress:quick": "npm run build && node tests/adversarial/detector-stress-test.cjs --cycles=3 --duration=5000",
41
+ "test:stress:intense": "npm run build && node tests/adversarial/detector-stress-test.cjs --cycles=10 --duration=20000"
41
42
  },
42
43
  "keywords": [
43
44
  "behavior-detection",
@@ -1,102 +0,0 @@
1
- import type { ScoreOptions, ScoreResult } from './types.js';
2
- import type { DetectionStrategy, StrategyConfig, TickOptions } from './strategy.js';
3
- /**
4
- * Main class for behavior detection
5
- * Uses modular strategy pattern for tree-shakeable, autonomous detection modules
6
- */
7
- export declare class BehaviorDetector {
8
- private strategies;
9
- private isTracking;
10
- private isPausedByVisibility;
11
- private tickInterval;
12
- private tickIntervalMs;
13
- private pauseOnHidden;
14
- private visibilityChangeHandler;
15
- private confidenceScore;
16
- private readonly CONFIDENCE_TARGET;
17
- private readonly CONFIDENCE_DECAY;
18
- constructor(tickOptions?: TickOptions);
19
- /**
20
- * Add a detection strategy
21
- */
22
- addStrategy(strategy: DetectionStrategy, weight?: number): this;
23
- /**
24
- * Handle event from strategy - update confidence
25
- */
26
- private onStrategyEvent;
27
- /**
28
- * Remove a detection strategy
29
- */
30
- removeStrategy(name: string): this;
31
- /**
32
- * Enable/disable a strategy
33
- */
34
- setStrategyEnabled(name: string, enabled: boolean): this;
35
- /**
36
- * Get all registered strategies
37
- */
38
- getStrategies(): ReadonlyMap<string, StrategyConfig>;
39
- /**
40
- * Start tracking
41
- */
42
- start(): void;
43
- /**
44
- * Stop tracking
45
- */
46
- stop(): void;
47
- /**
48
- * Reset all data
49
- */
50
- reset(): void;
51
- /**
52
- * Calculate human likelihood score
53
- */
54
- score(options?: ScoreOptions): Promise<ScoreResult>;
55
- /**
56
- * Check if currently tracking
57
- */
58
- isActive(): boolean;
59
- /**
60
- * Check if currently paused due to tab visibility
61
- */
62
- isPaused(): boolean;
63
- /**
64
- * Get event count from all strategies
65
- */
66
- getEventCount(): Record<string, number>;
67
- /**
68
- * Get debug info from all strategies
69
- */
70
- getStrategyDebugInfo(): Record<string, any>;
71
- /**
72
- * Get current confidence score (0-1)
73
- * Represents how much interaction data we've collected
74
- * Higher confidence = more reliable classification
75
- */
76
- getConfidence(): number;
77
- /**
78
- * Check if confidence is above threshold for reliable classification
79
- * @param threshold - Minimum confidence (0-1), default 0.3
80
- */
81
- hasConfidentData(threshold?: number): boolean;
82
- /**
83
- * Cleanup resources
84
- */
85
- destroy(): void;
86
- /**
87
- * Handle visibility change events
88
- */
89
- private handleVisibilityChange;
90
- /**
91
- * Start tick mechanism for strategies
92
- */
93
- private startTick;
94
- /**
95
- * Stop tick mechanism
96
- */
97
- private stopTick;
98
- /**
99
- * Calculate score using strategies
100
- */
101
- private calculateStrategyScore;
102
- }
@@ -1,315 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BehaviorDetector = void 0;
4
- /**
5
- * Main class for behavior detection
6
- * Uses modular strategy pattern for tree-shakeable, autonomous detection modules
7
- */
8
- class BehaviorDetector {
9
- constructor(tickOptions) {
10
- // Strategy mode
11
- this.strategies = new Map();
12
- this.isTracking = false;
13
- this.isPausedByVisibility = false;
14
- this.tickInterval = null;
15
- this.tickIntervalMs = 1000; // Default: 1 second
16
- this.pauseOnHidden = true;
17
- this.visibilityChangeHandler = null;
18
- // Confidence tracking
19
- this.confidenceScore = 0;
20
- this.CONFIDENCE_TARGET = 1.0; // Target confidence for reliable classification
21
- this.CONFIDENCE_DECAY = 0.95; // Per event decay to prevent infinite growth
22
- if (tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.interval) {
23
- this.tickIntervalMs = tickOptions.interval;
24
- }
25
- if ((tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.pauseOnHidden) !== undefined) {
26
- this.pauseOnHidden = tickOptions.pauseOnHidden;
27
- }
28
- }
29
- /**
30
- * Add a detection strategy
31
- */
32
- addStrategy(strategy, weight) {
33
- const config = {
34
- strategy,
35
- weight: weight !== null && weight !== void 0 ? weight : strategy.defaultWeight,
36
- enabled: true,
37
- };
38
- this.strategies.set(strategy.name, config);
39
- // Set up event callback for confidence tracking
40
- if (strategy.setEventCallback) {
41
- strategy.setEventCallback((event) => {
42
- this.onStrategyEvent(event, config.weight);
43
- });
44
- }
45
- // If already tracking, start this strategy immediately
46
- if (this.isTracking) {
47
- strategy.start();
48
- }
49
- return this;
50
- }
51
- /**
52
- * Handle event from strategy - update confidence
53
- */
54
- onStrategyEvent(event, strategyWeight) {
55
- // Apply decay to existing confidence to prevent infinite growth
56
- this.confidenceScore *= this.CONFIDENCE_DECAY;
57
- // Add weighted contribution from this event
58
- // eventWeight (0-1) * strategyWeight (e.g. 0.3 for mouse) = contribution
59
- const contribution = event.weight * strategyWeight;
60
- this.confidenceScore = Math.min(this.CONFIDENCE_TARGET, this.confidenceScore + contribution);
61
- }
62
- /**
63
- * Remove a detection strategy
64
- */
65
- removeStrategy(name) {
66
- const config = this.strategies.get(name);
67
- if (config) {
68
- if (this.isTracking) {
69
- config.strategy.stop();
70
- }
71
- this.strategies.delete(name);
72
- }
73
- return this;
74
- }
75
- /**
76
- * Enable/disable a strategy
77
- */
78
- setStrategyEnabled(name, enabled) {
79
- const config = this.strategies.get(name);
80
- if (config) {
81
- config.enabled = enabled;
82
- // If tracking and being disabled, stop it
83
- if (!enabled && this.isTracking) {
84
- config.strategy.stop();
85
- }
86
- // If tracking and being enabled, start it
87
- if (enabled && this.isTracking) {
88
- config.strategy.start();
89
- }
90
- }
91
- return this;
92
- }
93
- /**
94
- * Get all registered strategies
95
- */
96
- getStrategies() {
97
- return this.strategies;
98
- }
99
- /**
100
- * Start tracking
101
- */
102
- start() {
103
- if (this.isTracking)
104
- return;
105
- this.isTracking = true;
106
- // Set up visibility change listener
107
- if (this.pauseOnHidden && typeof document !== 'undefined') {
108
- this.visibilityChangeHandler = this.handleVisibilityChange.bind(this);
109
- document.addEventListener('visibilitychange', this.visibilityChangeHandler);
110
- // Check initial visibility state
111
- if (document.hidden) {
112
- this.isPausedByVisibility = true;
113
- return; // Don't start strategies if already hidden
114
- }
115
- }
116
- // Start all enabled strategies
117
- for (const [_, config] of this.strategies) {
118
- if (config.enabled) {
119
- config.strategy.start();
120
- }
121
- }
122
- // Start tick mechanism
123
- this.startTick();
124
- }
125
- /**
126
- * Stop tracking
127
- */
128
- stop() {
129
- if (!this.isTracking)
130
- return;
131
- this.isTracking = false;
132
- this.isPausedByVisibility = false;
133
- // Remove visibility change listener
134
- if (this.visibilityChangeHandler && typeof document !== 'undefined') {
135
- document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
136
- this.visibilityChangeHandler = null;
137
- }
138
- // Stop all strategies
139
- for (const [_, config] of this.strategies) {
140
- config.strategy.stop();
141
- }
142
- // Stop tick
143
- this.stopTick();
144
- }
145
- /**
146
- * Reset all data
147
- */
148
- reset() {
149
- this.confidenceScore = 0;
150
- for (const [_, config] of this.strategies) {
151
- config.strategy.reset();
152
- }
153
- }
154
- /**
155
- * Calculate human likelihood score
156
- */
157
- async score(options = {}) {
158
- const breakdown = this.calculateStrategyScore();
159
- const result = {
160
- score: breakdown.overall,
161
- };
162
- if (options.breakdown) {
163
- result.breakdown = breakdown;
164
- }
165
- // Note: auditTrail not available in strategy mode
166
- // Each strategy manages its own data independently
167
- return result;
168
- }
169
- /**
170
- * Check if currently tracking
171
- */
172
- isActive() {
173
- return this.isTracking;
174
- }
175
- /**
176
- * Check if currently paused due to tab visibility
177
- */
178
- isPaused() {
179
- return this.isPausedByVisibility;
180
- }
181
- /**
182
- * Get event count from all strategies
183
- */
184
- getEventCount() {
185
- var _a, _b;
186
- const counts = {};
187
- for (const [name, config] of this.strategies) {
188
- const debug = (_b = (_a = config.strategy).getDebugInfo) === null || _b === void 0 ? void 0 : _b.call(_a);
189
- if ((debug === null || debug === void 0 ? void 0 : debug.eventCount) !== undefined) {
190
- counts[name] = debug.eventCount;
191
- }
192
- }
193
- return counts;
194
- }
195
- /**
196
- * Get debug info from all strategies
197
- */
198
- getStrategyDebugInfo() {
199
- const debug = {};
200
- for (const [name, config] of this.strategies) {
201
- if (config.strategy.getDebugInfo) {
202
- debug[name] = config.strategy.getDebugInfo();
203
- }
204
- }
205
- return debug;
206
- }
207
- /**
208
- * Get current confidence score (0-1)
209
- * Represents how much interaction data we've collected
210
- * Higher confidence = more reliable classification
211
- */
212
- getConfidence() {
213
- return Math.min(1, this.confidenceScore);
214
- }
215
- /**
216
- * Check if confidence is above threshold for reliable classification
217
- * @param threshold - Minimum confidence (0-1), default 0.3
218
- */
219
- hasConfidentData(threshold = 0.3) {
220
- return this.getConfidence() >= threshold;
221
- }
222
- /**
223
- * Cleanup resources
224
- */
225
- destroy() {
226
- this.stop();
227
- this.strategies.clear();
228
- }
229
- /**
230
- * Handle visibility change events
231
- */
232
- handleVisibilityChange() {
233
- if (!this.isTracking)
234
- return;
235
- if (document.hidden) {
236
- // Tab became hidden - pause detection
237
- if (!this.isPausedByVisibility) {
238
- this.isPausedByVisibility = true;
239
- // Stop all strategies
240
- for (const [_, config] of this.strategies) {
241
- if (config.enabled) {
242
- config.strategy.stop();
243
- }
244
- }
245
- // Stop tick
246
- this.stopTick();
247
- }
248
- }
249
- else {
250
- // Tab became visible - resume detection
251
- if (this.isPausedByVisibility) {
252
- this.isPausedByVisibility = false;
253
- // Restart all enabled strategies
254
- for (const [_, config] of this.strategies) {
255
- if (config.enabled) {
256
- config.strategy.start();
257
- }
258
- }
259
- // Restart tick
260
- this.startTick();
261
- }
262
- }
263
- }
264
- /**
265
- * Start tick mechanism for strategies
266
- */
267
- startTick() {
268
- if (this.tickInterval !== null)
269
- return;
270
- this.tickInterval = window.setInterval(() => {
271
- const now = Date.now();
272
- for (const [_, config] of this.strategies) {
273
- if (config.enabled && config.strategy.onTick) {
274
- config.strategy.onTick(now);
275
- }
276
- }
277
- }, this.tickIntervalMs);
278
- }
279
- /**
280
- * Stop tick mechanism
281
- */
282
- stopTick() {
283
- if (this.tickInterval !== null) {
284
- clearInterval(this.tickInterval);
285
- this.tickInterval = null;
286
- }
287
- }
288
- /**
289
- * Calculate score using strategies
290
- */
291
- calculateStrategyScore() {
292
- const factors = {};
293
- const weights = {};
294
- let totalWeight = 0;
295
- let weightedSum = 0;
296
- for (const [name, config] of this.strategies) {
297
- if (!config.enabled)
298
- continue;
299
- const score = config.strategy.score();
300
- factors[name] = score;
301
- weights[name] = config.weight;
302
- if (score !== undefined && score !== null) {
303
- totalWeight += config.weight;
304
- weightedSum += score * config.weight;
305
- }
306
- }
307
- const overall = totalWeight > 0 ? weightedSum / totalWeight : 0.5;
308
- return {
309
- overall: Math.max(0, Math.min(1, overall)),
310
- factors,
311
- weights,
312
- };
313
- }
314
- }
315
- exports.BehaviorDetector = BehaviorDetector;
@@ -1,33 +0,0 @@
1
- /**
2
- * Browser Build - Auto-initializing standalone bundle for CDN usage
3
- *
4
- * Usage:
5
- * <script src="https://cdn.../behavior-detector.js"></script>
6
- * <script>
7
- * window.bdSettings = {
8
- * strategies: {
9
- * mouse: { weight: 0.3 },
10
- * scroll: { weight: 0.15 },
11
- * click: { weight: 0.3 },
12
- * keyboard: { weight: 0.1 },
13
- * environment: { weight: 0.08 },
14
- * resize: { weight: 0.02 }
15
- * },
16
- * autoStart: true,
17
- * checkMs: 2000,
18
- * pauseOnHidden: true, // Auto-pause when tab hidden (default: true)
19
- * onScore: (result) => {
20
- * console.log('Human likelihood:', result.score);
21
- * if (result.score < 0.3) {
22
- * // Likely bot
23
- * }
24
- * },
25
- * ifBot: (result) => {
26
- * // Called when score < threshold
27
- * console.warn('Bot detected:', result);
28
- * },
29
- * botThreshold: 0.3
30
- * }
31
- * </script>
32
- */
33
- export {};