@ianmenethil/zp-devicefp 0.1.0-alpha.0 → 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 +235 -80
- package/dist/cdn/zp.dfp.manifest.json +8 -8
- package/dist/cdn/zp.dfp.obf.js +1 -1
- package/docs/api-reference.md +472 -0
- package/docs/signals.md +383 -0
- package/package.json +75 -72
package/docs/signals.md
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# Signal Reference
|
|
2
|
+
|
|
3
|
+
Every signal collected by the library, including its name, tier, sync support, description, and the shape of its `value` when `status` is `'ok'`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Signal overview
|
|
8
|
+
|
|
9
|
+
| # | Signal | Tier | Sync | Description |
|
|
10
|
+
|---|--------|------|------|-------------|
|
|
11
|
+
| 1 | `ua` | core | yes | Legacy `navigator.userAgent` and related properties |
|
|
12
|
+
| 2 | `uaHints` | core | no | User-Agent Client Hints (brands, platform, high-entropy values) |
|
|
13
|
+
| 3 | `locale` | core | yes | Language, locale, calendar, time zone, number/date formatting |
|
|
14
|
+
| 4 | `screen` | core | yes | Screen dimensions, color depth, orientation, DPR, media queries |
|
|
15
|
+
| 5 | `hardware` | core | yes | Hardware concurrency, device memory, platform |
|
|
16
|
+
| 6 | `storage` | core | yes | localStorage, sessionStorage, IndexedDB, Web SQL availability |
|
|
17
|
+
| 7 | `fonts` | core | yes | Installed font detection via DOM measurement |
|
|
18
|
+
| 8 | `canvas` | core | yes | Canvas 2D rendering fingerprint (GPU+driver signature) |
|
|
19
|
+
| 9 | `webgl` | core | yes | WebGL renderer, vendor, extensions, GPU capabilities |
|
|
20
|
+
| 10 | `audio` | core | no | OfflineAudioContext oscillator+compressor signature |
|
|
21
|
+
| 11 | `mediaDevices` | extended | no | Media device kind enumeration (counts only, no labels) |
|
|
22
|
+
| 12 | `permissions` | extended | no | Permissions API state for geolocation, notifications, camera, microphone |
|
|
23
|
+
| 13 | `webrtc` | extended | no | RTCPeerConnection codec and extmap capability hash |
|
|
24
|
+
| 14 | `frameInfo` | extended | yes | Iframe context: count, domains, top-level check |
|
|
25
|
+
| 15 | `networkInfo` | extended | yes | NetworkInformation API: effective type, downlink, RTT, saveData |
|
|
26
|
+
| 16 | `paymentSupport` | extended | yes | PaymentRequest API availability |
|
|
27
|
+
| 17 | `referrerInfo` | extended | yes | `document.referrer` |
|
|
28
|
+
| 18 | `navigationInfo` | extended | yes | PerformanceNavigationTiming type (navigate/reload/back_forward/prerender) |
|
|
29
|
+
| 19 | `riskSignals` | extended | no | Bot/headless detection: 9 heuristics |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Core signals
|
|
34
|
+
|
|
35
|
+
### `ua` — User-Agent string
|
|
36
|
+
|
|
37
|
+
**Tier:** core | **Sync:** yes | **APIs used:** `navigator`
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
// value shape:
|
|
41
|
+
{
|
|
42
|
+
userAgent: string; // navigator.userAgent
|
|
43
|
+
appVersion: string; // navigator.appVersion
|
|
44
|
+
vendor: string; // navigator.vendor
|
|
45
|
+
platform: string; // navigator.platform
|
|
46
|
+
webdriver: boolean; // navigator.webdriver
|
|
47
|
+
maxTouchPoints: number; // navigator.maxTouchPoints
|
|
48
|
+
cookieEnabled: boolean; // navigator.cookieEnabled
|
|
49
|
+
vendorSub: string; // navigator.vendorSub
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Returns `'unsupported'` if `navigator` is not available.
|
|
54
|
+
|
|
55
|
+
### `uaHints` — User-Agent Client Hints
|
|
56
|
+
|
|
57
|
+
**Tier:** core | **Sync:** no | **APIs used:** `navigator.userAgentData`
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
// value shape:
|
|
61
|
+
{
|
|
62
|
+
brands: { brand: string; version: string }[]; // low-entropy brands
|
|
63
|
+
mobile: boolean; // userAgentData.mobile
|
|
64
|
+
platform: string; // userAgentData.platform
|
|
65
|
+
architecture?: string; // high-entropy: CPU architecture
|
|
66
|
+
bitness?: string; // high-entropy: 32/64
|
|
67
|
+
formFactors?: string[]; // high-entropy: device form factors
|
|
68
|
+
fullVersionList?: { brand: string; version: string }[]; // high-entropy: full versions
|
|
69
|
+
model?: string; // high-entropy: device model
|
|
70
|
+
platformVersion?: string; // high-entropy: OS version
|
|
71
|
+
wow64?: boolean; // high-entropy: 32-bit on 64-bit
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Returns `'unsupported'` if `navigator.userAgentData` is not available. Returns `'blocked'` if `getHighEntropyValues` throws.
|
|
76
|
+
|
|
77
|
+
### `locale` — Language and internationalization
|
|
78
|
+
|
|
79
|
+
**Tier:** core | **Sync:** yes | **APIs used:** `navigator`, `Intl`
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
// value shape:
|
|
83
|
+
{
|
|
84
|
+
language: string; // navigator.language
|
|
85
|
+
languages: readonly string[]; // navigator.languages
|
|
86
|
+
locale: string; // Intl.DateTimeFormat resolved locale
|
|
87
|
+
calendar: string; // e.g. "gregory", "iso8601"
|
|
88
|
+
numberingSystem: string; // e.g. "latn", "arab"
|
|
89
|
+
timeZone: string; // IANA timezone e.g. "America/New_York"
|
|
90
|
+
hourCycle: string; // e.g. "h12", "h23"
|
|
91
|
+
timeZoneOffsetMinutes: number; // UTC offset in minutes
|
|
92
|
+
formattedNumber: string; // Intl.NumberFormat sample: "123,456.789"
|
|
93
|
+
formattedDate: string; // Intl.DateTimeFormat sample for Jan 2, 2024
|
|
94
|
+
formattedRelativeDay: string | undefined; // Intl.RelativeTimeFormat: "yesterday" etc.
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Returns `'unsupported'` if `navigator` or `Intl` is not available.
|
|
99
|
+
|
|
100
|
+
### `screen` — Screen and display
|
|
101
|
+
|
|
102
|
+
**Tier:** core | **Sync:** yes | **APIs used:** `screen`, `navigator`, `matchMedia`, `devicePixelRatio`
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
// value shape:
|
|
106
|
+
{
|
|
107
|
+
width: number; // screen.width
|
|
108
|
+
height: number; // screen.height
|
|
109
|
+
availWidth: number; // screen.availWidth
|
|
110
|
+
availHeight: number; // screen.availHeight
|
|
111
|
+
colorDepth: number; // screen.colorDepth
|
|
112
|
+
pixelDepth: number; // screen.pixelDepth
|
|
113
|
+
orientationType: string; // screen.orientation.type
|
|
114
|
+
orientationAngle: number; // screen.orientation.angle
|
|
115
|
+
maxTouchPoints: number; // navigator.maxTouchPoints (0 if missing)
|
|
116
|
+
devicePixelRatio: number | undefined; // window.devicePixelRatio
|
|
117
|
+
colorGamutP3: boolean | 'unsupported'; // (color-gamut: p3) media query
|
|
118
|
+
prefersReducedMotion: boolean | 'unsupported'; // (prefers-reduced-motion: reduce)
|
|
119
|
+
prefersContrastMore: boolean | 'unsupported'; // (prefers-contrast: more)
|
|
120
|
+
forcedColorsActive: boolean | 'unsupported'; // (forced-colors: active)
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Returns `'unsupported'` if `screen` is not available.
|
|
125
|
+
|
|
126
|
+
### `hardware` — Hardware properties
|
|
127
|
+
|
|
128
|
+
**Tier:** core | **Sync:** yes | **APIs used:** `navigator`
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// value shape:
|
|
132
|
+
{
|
|
133
|
+
hardwareConcurrency: number; // navigator.hardwareConcurrency (logical CPU cores)
|
|
134
|
+
deviceMemory: number | undefined; // navigator.deviceMemory (GB, may be undefined)
|
|
135
|
+
platform: string; // navigator.platform
|
|
136
|
+
maxTouchPoints: number; // navigator.maxTouchPoints
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Returns `'unsupported'` if `navigator` is not available.
|
|
141
|
+
|
|
142
|
+
### `storage` — Storage API availability
|
|
143
|
+
|
|
144
|
+
**Tier:** core | **Sync:** yes | **APIs used:** `localStorage`, `sessionStorage`, `indexedDB`, `openDatabase`, `navigator`
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
// value shape:
|
|
148
|
+
{
|
|
149
|
+
cookiesEnabled: boolean; // navigator.cookieEnabled
|
|
150
|
+
localStorage: 'available' | 'blocked' | 'unsupported'; // write-read-delete probe
|
|
151
|
+
sessionStorage: 'available' | 'blocked' | 'unsupported'; // write-read-delete probe
|
|
152
|
+
indexedDb: 'available' | 'unsupported'; // typeof indexedDB check
|
|
153
|
+
openDatabase: 'available' | 'unsupported'; // typeof openDatabase check (Web SQL)
|
|
154
|
+
pdfViewerEnabled: boolean; // navigator.pdfViewerEnabled
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `fonts` — Font detection
|
|
159
|
+
|
|
160
|
+
**Tier:** core | **Sync:** yes | **APIs used:** DOM (`document.createElement`, `offsetWidth`)
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
// value shape:
|
|
164
|
+
{
|
|
165
|
+
detectedFonts: string[]; // sorted list of detected font family names
|
|
166
|
+
fontCount: number; // count of detected fonts
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Tests 10 fonts against 3 generic families (monospace, sans-serif, serif) by rendering hidden `<span>` elements and measuring width differences. Returns `'unsupported'` if the DOM is not available.
|
|
171
|
+
|
|
172
|
+
**Fonts probed:** `Arial`, `Helvetica Neue`, `Times New Roman`, `Georgia`, `Courier New`, `Trebuchet MS`, `Verdana`, `Tahoma`, `Impact`, `Comic Sans MS`
|
|
173
|
+
|
|
174
|
+
### `canvas` — Canvas 2D fingerprint
|
|
175
|
+
|
|
176
|
+
**Tier:** core | **Sync:** yes | **APIs used:** Canvas 2D (`getContext('2d')`)
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// value shape:
|
|
180
|
+
{
|
|
181
|
+
dataUrl: string; // canvas.toDataURL() — base64 PNG of rendered pattern
|
|
182
|
+
winding: boolean; // ctx.isPointInPath(1, 1, 'evenodd')
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Renders a 280×80 canvas with a filled rectangle (#f60), text ("Browser FP"), and an arc. Differences in GPU, driver, and browser anti-aliasing produce distinct fingerprints.
|
|
187
|
+
|
|
188
|
+
Returns `'unsupported'` if the canvas 2D context is unavailable. Returns `'error'` if rendering throws.
|
|
189
|
+
|
|
190
|
+
### `webgl` — WebGL fingerprint
|
|
191
|
+
|
|
192
|
+
**Tier:** core | **Sync:** yes | **APIs used:** WebGL (`getContext('webgl')`, `WEBGL_debug_renderer_info`)
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
// value shape:
|
|
196
|
+
{
|
|
197
|
+
vendor: string; // UNMASKED_VENDOR_WEBGL or VENDOR
|
|
198
|
+
renderer: string; // UNMASKED_RENDERER_WEBGL or RENDERER
|
|
199
|
+
version: string; // WebGL version string
|
|
200
|
+
shadingLanguageVersion: string; // GLSL version string
|
|
201
|
+
maxTextureSize: number; // MAX_TEXTURE_SIZE
|
|
202
|
+
maxViewportDims: Int32Array; // MAX_VIEWPORT_DIMS
|
|
203
|
+
extensions: string[]; // getSupportedExtensions() sorted
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Attempts `webgl` context first, falls back to `experimental-webgl`. Uses `WEBGL_debug_renderer_info` for unmasked GPU strings when available.
|
|
208
|
+
|
|
209
|
+
Returns `'unsupported'` if canvas/WebGL is not available.
|
|
210
|
+
|
|
211
|
+
### `audio` — AudioContext fingerprint
|
|
212
|
+
|
|
213
|
+
**Tier:** core | **Sync:** no | **APIs used:** `OfflineAudioContext`, `OscillatorNode`, `DynamicsCompressorNode`
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
// value shape:
|
|
217
|
+
{
|
|
218
|
+
sampleRate: number; // rendered.sampleRate
|
|
219
|
+
length: number; // rendered.length (number of sample frames)
|
|
220
|
+
signalValue: number; // sum of absolute channel data values (6 decimal places)
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Creates an OfflineAudioContext (1 channel, 5000 samples, 44100 Hz), plays a 10 kHz triangle wave through a DynamicsCompressor with tuned parameters, then sums the absolute values of the rendered output. Different audio hardware/drivers produce distinct values.
|
|
225
|
+
|
|
226
|
+
Returns `'unsupported'` if `OfflineAudioContext` (or `webkitOfflineAudioContext`) is not available. Returns `'blocked'` if rendering throws.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Extended signals
|
|
231
|
+
|
|
232
|
+
### `mediaDevices` — Media device enumeration
|
|
233
|
+
|
|
234
|
+
**Tier:** extended | **Sync:** no | **APIs used:** `navigator.mediaDevices.enumerateDevices`
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
// value shape — an object keyed by MediaDeviceKind:
|
|
238
|
+
{
|
|
239
|
+
audioinput: number; // count of audio input devices
|
|
240
|
+
audiooutput: number; // count of audio output devices
|
|
241
|
+
videoinput: number; // count of video input devices
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Only device counts and kinds are collected — no device labels or IDs. Requires a secure context (HTTPS) and a visible document.
|
|
246
|
+
|
|
247
|
+
Returns `'blocked'` if not in a secure context, if document is not visible, or if `enumerateDevices` throws. Returns `'unsupported'` if `mediaDevices` is not available.
|
|
248
|
+
|
|
249
|
+
### `permissions` — Permissions API state
|
|
250
|
+
|
|
251
|
+
**Tier:** extended | **Sync:** no | **APIs used:** `navigator.permissions.query`
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
// value shape:
|
|
255
|
+
{
|
|
256
|
+
geolocation: 'granted' | 'denied' | 'prompt' | 'unsupported';
|
|
257
|
+
notifications: 'granted' | 'denied' | 'prompt' | 'unsupported';
|
|
258
|
+
camera: 'granted' | 'denied' | 'prompt' | 'unsupported';
|
|
259
|
+
microphone: 'granted' | 'denied' | 'prompt' | 'unsupported';
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Queries 4 permission names in parallel. Each individual query that fails returns `'unsupported'` for that key.
|
|
264
|
+
|
|
265
|
+
Returns `'unsupported'` if `navigator.permissions` is not available. Returns `'blocked'` if all queries fail together.
|
|
266
|
+
|
|
267
|
+
### `webrtc` — WebRTC codec capability
|
|
268
|
+
|
|
269
|
+
**Tier:** extended | **Sync:** no | **APIs used:** `RTCPeerConnection`
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
// value shape:
|
|
273
|
+
{
|
|
274
|
+
codecs: string[]; // sorted audio/video codec names from SDP rtpmap lines
|
|
275
|
+
extmaps: string[]; // sorted extmap IDs from SDP
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Creates an RTCPeerConnection, opens a data channel, generates an SDP offer, and parses supported codecs and extmap entries. The peer connection is closed after collection.
|
|
280
|
+
|
|
281
|
+
Returns `'unsupported'` if `RTCPeerConnection` (or `webkitRTCPeerConnection`) is not available. Returns `'blocked'` if SDP negotiation throws.
|
|
282
|
+
|
|
283
|
+
### `frameInfo` — Iframe context
|
|
284
|
+
|
|
285
|
+
**Tier:** extended | **Sync:** yes | **APIs used:** DOM, `window.top`
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
// value shape:
|
|
289
|
+
{
|
|
290
|
+
iframesCount: number; // count of <iframe> elements in the document
|
|
291
|
+
isTopLevel: boolean; // whether window === window.top
|
|
292
|
+
iframeDomains: string[]; // hostnames extracted from iframe src URLs
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Returns `'unsupported'` if `document` is not available. Returns `'error'` if enumeration throws.
|
|
297
|
+
|
|
298
|
+
### `networkInfo` — Network Information
|
|
299
|
+
|
|
300
|
+
**Tier:** extended | **Sync:** yes | **APIs used:** `navigator.connection` (vendor-prefixed)
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
// value shape:
|
|
304
|
+
{
|
|
305
|
+
effectiveType: string | null; // 'slow-2g' | '2g' | '3g' | '4g' | null
|
|
306
|
+
downlink: number | null; // estimated downlink speed in Mbps
|
|
307
|
+
rtt: number | null; // estimated round-trip time in ms
|
|
308
|
+
saveData: boolean | null; // data-saver mode
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Checks `navigator.connection`, `navigator.mozConnection`, and `navigator.webkitConnection` for the NetworkInformation API (Chrome, Firefox, older WebKit).
|
|
313
|
+
|
|
314
|
+
Returns `'unsupported'` if `navigator` or the connection API is not available.
|
|
315
|
+
|
|
316
|
+
### `paymentSupport` — PaymentRequest API
|
|
317
|
+
|
|
318
|
+
**Tier:** extended | **Sync:** yes | **APIs used:** `window.PaymentRequest`
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
// value shape:
|
|
322
|
+
{
|
|
323
|
+
paymentRequest: boolean; // whether PaymentRequest constructor exists
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### `referrerInfo` — Document referrer
|
|
328
|
+
|
|
329
|
+
**Tier:** extended | **Sync:** yes | **APIs used:** `document.referrer`
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
// value shape:
|
|
333
|
+
{
|
|
334
|
+
referrer: string; // document.referrer (empty string if no referrer)
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Returns `'unsupported'` if `document` is not available.
|
|
339
|
+
|
|
340
|
+
### `navigationInfo` — Navigation type
|
|
341
|
+
|
|
342
|
+
**Tier:** extended | **Sync:** yes | **APIs used:** `PerformanceNavigationTiming`
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
// value shape:
|
|
346
|
+
{
|
|
347
|
+
navigationType: string | number | null;
|
|
348
|
+
// 'navigate' | 'reload' | 'back_forward' | 'prerender' (modern)
|
|
349
|
+
// 0 | 1 | 2 | 255 (legacy performance.navigation.type)
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Prefers `PerformanceNavigationTiming.type`. Falls back to deprecated `performance.navigation.type` in older browsers.
|
|
354
|
+
|
|
355
|
+
Returns `'unsupported'` if `performance` is not available. Returns `'error'` if probing throws.
|
|
356
|
+
|
|
357
|
+
### `riskSignals` — Bot and headless detection
|
|
358
|
+
|
|
359
|
+
**Tier:** extended | **Sync:** no | **APIs used:** `navigator`, `Notification`, `Permissions`, `Performance`
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
// value shape:
|
|
363
|
+
{
|
|
364
|
+
webdriver: boolean | null; // navigator.webdriver flag
|
|
365
|
+
headlessHints: string[]; // detected headless indicators
|
|
366
|
+
uaConsistency: boolean | null; // UA platform vs UA-CH consistency
|
|
367
|
+
notificationPermission: string | null; // Notification.permission
|
|
368
|
+
permissionsHeadlessHint: boolean | null; // denied+default mismatch
|
|
369
|
+
timeToCaptureMs: number | null; // ms since navigation start
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### Headless hints checked
|
|
374
|
+
|
|
375
|
+
| Hint code | Trigger |
|
|
376
|
+
|-----------|---------|
|
|
377
|
+
| `headless-ua` | UA contains `"HeadlessChrome"` |
|
|
378
|
+
| `missing-chrome-object` | Chrome UA but `window.chrome` is not an object |
|
|
379
|
+
| `zero-outer-dimensions` | `outerWidth === 0` or `outerHeight === 0` |
|
|
380
|
+
| `no-plugins-on-desktop-chrome` | Chrome UA (non-mobile) but `navigator.plugins` is empty |
|
|
381
|
+
| `empty-languages` | `navigator.languages` is an empty array |
|
|
382
|
+
|
|
383
|
+
Returns `'unsupported'` if `navigator` is not available. Returns `'blocked'` if collection throws.
|
package/package.json
CHANGED
|
@@ -1,75 +1,78 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"files": [
|
|
19
|
-
"dist",
|
|
20
|
-
"README.md",
|
|
21
|
-
"LICENSE",
|
|
22
|
-
"docs"
|
|
23
|
-
],
|
|
24
|
-
"packageManager": "bun@1.3.9",
|
|
25
|
-
"engines": {
|
|
26
|
-
"bun": ">=1.3.0",
|
|
27
|
-
"node": ">=22"
|
|
28
|
-
},
|
|
29
|
-
"prepublishOnly": "bun run build",
|
|
30
|
-
"scripts": {
|
|
31
|
-
"build": "bun run check && bun run test:coverage && bun -e \"await import('./.scripts/build.ts')\"",
|
|
32
|
-
"test": "bun test",
|
|
33
|
-
"test:coverage": "bun test --coverage",
|
|
34
|
-
"release": "sh -c 'V=$(npm version \"${1:-minor}\" -m \"chore: release %s\" | tail -1 | sed s/v//) && bun publish --access public && mkdir -p \"F:/_ZP-Main/apps/CDN-server/public/devicefp/$V\" && cp -r dist/cdn/* \"F:/_ZP-Main/apps/CDN-server/public/devicefp/$V/\" && mkdir -p \"F:/_ZP-Main/apps/CDN-server/public/devicefp/latest\" && cp -r dist/cdn/* \"F:/_ZP-Main/apps/CDN-server/public/devicefp/latest/\" && git push --follow-tags' --",
|
|
35
|
-
"smoke": "bun run scripts/smoke.mjs",
|
|
36
|
-
"check": "bun run lint && bun run typecheck && bun run knip && bun run jscpd",
|
|
37
|
-
"lint": "eslint . --config eslint.config.js",
|
|
38
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
39
|
-
"knip": "knip --config knip.json",
|
|
40
|
-
"jscpd": "jscpd --config .jscpd.json",
|
|
41
|
-
"format": "prettier --write .",
|
|
42
|
-
"format:check": "prettier --check ."
|
|
43
|
-
},
|
|
44
|
-
"keywords": [
|
|
45
|
-
"browser",
|
|
46
|
-
"device",
|
|
47
|
-
"fingerprint",
|
|
48
|
-
"typescript",
|
|
49
|
-
"fraud",
|
|
50
|
-
"risk"
|
|
51
|
-
],
|
|
52
|
-
"author": "Ian / Zenith Payments",
|
|
53
|
-
"license": "MIT",
|
|
54
|
-
"homepage": "https://github.com/ianmenethil/zp-devicefp#readme",
|
|
55
|
-
"repository": {
|
|
56
|
-
"type": "git",
|
|
57
|
-
"url": "git+https://github.com/ianmenethil/zp-devicefp.git"
|
|
58
|
-
},
|
|
59
|
-
"bugs": {
|
|
60
|
-
"url": "https://github.com/ianmenethil/zp-devicefp/issues"
|
|
61
|
-
},
|
|
62
|
-
"devDependencies": {
|
|
63
|
-
"@eslint/js": "^10.0.1",
|
|
64
|
-
"esbuild": "^0.28.0",
|
|
65
|
-
"eslint": "^10.3.0",
|
|
66
|
-
"eslint-plugin-tsdoc": "^0.5.2",
|
|
67
|
-
"javascript-obfuscator": "^5.4.2",
|
|
68
|
-
"jscpd": "^4.1.1",
|
|
69
|
-
"knip": "^6.13.1",
|
|
70
|
-
"lefthook": "^2.1.6",
|
|
71
|
-
"prettier": "^3.8.3",
|
|
72
|
-
"typescript": "~6.0.3",
|
|
73
|
-
"typescript-eslint": "^8.59.3"
|
|
2
|
+
"name": "@ianmenethil/zp-devicefp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Async-first browser and device fingerprinting library with explainable signals and anomaly scoring.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/npm/index.cjs",
|
|
7
|
+
"module": "./dist/npm/index.mjs",
|
|
8
|
+
"types": "./dist/npm/index.d.ts",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/npm/index.d.ts",
|
|
13
|
+
"import": "./dist/npm/index.mjs",
|
|
14
|
+
"require": "./dist/npm/index.cjs",
|
|
15
|
+
"default": "./dist/npm/index.mjs"
|
|
74
16
|
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"docs"
|
|
23
|
+
],
|
|
24
|
+
"packageManager": "bun@1.3.9",
|
|
25
|
+
"engines": {
|
|
26
|
+
"bun": ">=1.3.0",
|
|
27
|
+
"node": ">=22"
|
|
28
|
+
},
|
|
29
|
+
"prepublishOnly": "bun run build",
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "bun run check && bun run test:coverage && bun -e \"await import('./.scripts/build.ts')\"",
|
|
32
|
+
"test": "bun test",
|
|
33
|
+
"test:coverage": "bun test --coverage",
|
|
34
|
+
"release": "sh -c 'V=$(npm version \"${1:-minor}\" -m \"chore: release %s\" | tail -1 | sed s/v//) && bun publish --access public && rm -rf \"F:/_ZP-Main/apps/CDN-server/public/devicefp\" && mkdir -p \"F:/_ZP-Main/apps/CDN-server/public/devicefp/$V\" && cp -r dist/cdn/* \"F:/_ZP-Main/apps/CDN-server/public/devicefp/$V/\" && mkdir -p \"F:/_ZP-Main/apps/CDN-server/public/devicefp/latest\" && cp -r dist/cdn/* \"F:/_ZP-Main/apps/CDN-server/public/devicefp/latest/\" && git push --follow-tags' --",
|
|
35
|
+
"release:minor": "bun run release minor",
|
|
36
|
+
"release:patch": "bun run release patch",
|
|
37
|
+
"release:major": "bun run release major",
|
|
38
|
+
"smoke": "bun run scripts/smoke.mjs",
|
|
39
|
+
"check": "bun run lint && bun run typecheck && bun run knip && bun run jscpd",
|
|
40
|
+
"lint": "eslint . --config eslint.config.js",
|
|
41
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
42
|
+
"knip": "knip --config knip.json",
|
|
43
|
+
"jscpd": "jscpd --config .jscpd.json",
|
|
44
|
+
"format": "prettier --write .",
|
|
45
|
+
"format:check": "prettier --check ."
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"browser",
|
|
49
|
+
"device",
|
|
50
|
+
"fingerprint",
|
|
51
|
+
"typescript",
|
|
52
|
+
"fraud",
|
|
53
|
+
"risk"
|
|
54
|
+
],
|
|
55
|
+
"author": "Ian / Zenith Payments",
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"homepage": "https://github.com/ianmenethil/zp-devicefp#readme",
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/ianmenethil/zp-devicefp.git"
|
|
61
|
+
},
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/ianmenethil/zp-devicefp/issues"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@eslint/js": "^10.0.1",
|
|
67
|
+
"esbuild": "^0.28.0",
|
|
68
|
+
"eslint": "^10.3.0",
|
|
69
|
+
"eslint-plugin-tsdoc": "^0.5.2",
|
|
70
|
+
"javascript-obfuscator": "^5.4.2",
|
|
71
|
+
"jscpd": "^4.2.0",
|
|
72
|
+
"knip": "^6.13.1",
|
|
73
|
+
"lefthook": "^2.1.6",
|
|
74
|
+
"prettier": "^3.8.3",
|
|
75
|
+
"typescript": "~6.0.3",
|
|
76
|
+
"typescript-eslint": "^8.59.3"
|
|
77
|
+
}
|
|
75
78
|
}
|