@tracetail/js 2.3.14 → 2.3.15
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/compliance.d.ts +66 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tracetail/js — Client-side compliance helper
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ IMPORTANT — READ THIS:
|
|
5
|
+
* The values returned by `getComplianceContext()` are CLIENT-SIDE HEURISTICS,
|
|
6
|
+
* NOT authoritative geolocation. They are derived from browser-exposed signals
|
|
7
|
+
* (timezone, locale, Global Privacy Control, Do Not Track), every one of which
|
|
8
|
+
* can be spoofed, proxied, or absent. Server-side IP geolocation is far more
|
|
9
|
+
* accurate for determining a visitor's actual jurisdiction.
|
|
10
|
+
*
|
|
11
|
+
* This helper does NOT gate, block, or alter fingerprint collection. It simply
|
|
12
|
+
* EXPOSES signals so the *merchant* can decide whether to obtain consent or
|
|
13
|
+
* suppress collection.
|
|
14
|
+
*
|
|
15
|
+
* Consent for fingerprinting (EU ePrivacy Directive / GDPR, UK PECR, etc.) is
|
|
16
|
+
* the MERCHANT's legal responsibility — not TraceTail's. `likelyRequiresConsent`
|
|
17
|
+
* is a conservative hint only and is not legal advice.
|
|
18
|
+
*
|
|
19
|
+
* The module is fully SSR-safe: when `navigator` / `window` / `Intl` are
|
|
20
|
+
* undefined or throw, every accessor falls back to a safe default and the
|
|
21
|
+
* function still returns a complete, well-typed `ComplianceContext`.
|
|
22
|
+
*/
|
|
23
|
+
/** Coarse region inferred from client-side signals (timezone + locale). */
|
|
24
|
+
export type ComplianceRegion = 'EU' | 'EEA' | 'UK' | 'US' | 'OTHER';
|
|
25
|
+
/**
|
|
26
|
+
* Client-side privacy / region signals a merchant can use to decide whether to
|
|
27
|
+
* obtain consent or suppress collection. All fields are best-effort heuristics.
|
|
28
|
+
*/
|
|
29
|
+
export interface ComplianceContext {
|
|
30
|
+
/** Global Privacy Control: `navigator.globalPrivacyControl === true`. */
|
|
31
|
+
gpcEnabled: boolean;
|
|
32
|
+
/** Do Not Track: `navigator.doNotTrack === '1'` (and legacy window/ms variants). */
|
|
33
|
+
doNotTrack: boolean;
|
|
34
|
+
/** IANA timezone, e.g. `Europe/Berlin`. Empty string if undeterminable. */
|
|
35
|
+
timezone: string;
|
|
36
|
+
/** BCP-47 locale, e.g. `de-DE`. Empty string if undeterminable. */
|
|
37
|
+
locale: string;
|
|
38
|
+
/** Coarse region inferred from timezone + locale. */
|
|
39
|
+
region: ComplianceRegion;
|
|
40
|
+
/** True when the inferred region is in the EU. */
|
|
41
|
+
isEU: boolean;
|
|
42
|
+
/** True when the inferred region is in the EEA (EU + IS/LI/NO). */
|
|
43
|
+
isEEA: boolean;
|
|
44
|
+
/** True when the inferred region is the UK. */
|
|
45
|
+
isUK: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Conservative hint: true if `isEEA || isUK || gpcEnabled || doNotTrack`.
|
|
48
|
+
* NOT legal advice — the merchant decides whether consent is actually required.
|
|
49
|
+
*/
|
|
50
|
+
likelyRequiresConsent: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Infer a coarse region from timezone (primary) and locale (fallback).
|
|
54
|
+
* Timezone is preferred because it is more specific than language.
|
|
55
|
+
*/
|
|
56
|
+
export declare function inferRegion(timezone: string, locale: string): ComplianceRegion;
|
|
57
|
+
/**
|
|
58
|
+
* Compute client-side privacy / region signals for compliance decisions.
|
|
59
|
+
*
|
|
60
|
+
* Safe to call anywhere, including during server-side rendering: when browser
|
|
61
|
+
* globals are unavailable, it returns conservative defaults
|
|
62
|
+
* (`region: 'OTHER'`, all booleans `false`, empty strings).
|
|
63
|
+
*
|
|
64
|
+
* @returns A fully-populated {@link ComplianceContext}.
|
|
65
|
+
*/
|
|
66
|
+
export declare function getComplianceContext(): ComplianceContext;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Produces the SAME visitor ID as the script-tag SDK.
|
|
7
7
|
*/
|
|
8
8
|
import { type CoreComponents } from './core';
|
|
9
|
+
import { getComplianceContext, type ComplianceContext, type ComplianceRegion } from './compliance';
|
|
9
10
|
export interface FingerprintOptions {
|
|
10
11
|
/** API key for server-enhanced, keyed fingerprints. Omit to run in keyless free mode
|
|
11
12
|
* (client-only, `free_fp2_`-prefixed IDs) — matching the CDN script-tag SDK. */
|
|
@@ -28,6 +29,8 @@ export interface FingerprintResult {
|
|
|
28
29
|
components?: CoreComponents;
|
|
29
30
|
}
|
|
30
31
|
export { CoreComponents as ComponentData };
|
|
32
|
+
export { getComplianceContext };
|
|
33
|
+
export type { ComplianceContext, ComplianceRegion };
|
|
31
34
|
/**
|
|
32
35
|
* TraceTail SDK - Enterprise Browser Fingerprinting
|
|
33
36
|
*
|
|
@@ -58,6 +61,17 @@ export declare class TraceTail {
|
|
|
58
61
|
*/
|
|
59
62
|
private sendToServer;
|
|
60
63
|
static getVersion(): string;
|
|
64
|
+
/**
|
|
65
|
+
* Return client-side privacy / region compliance signals (GPC, DNT, timezone,
|
|
66
|
+
* locale, inferred region, and a conservative `likelyRequiresConsent` hint).
|
|
67
|
+
*
|
|
68
|
+
* These are CLIENT-SIDE HEURISTICS, not authoritative geolocation, and do NOT
|
|
69
|
+
* gate or alter fingerprint collection. Obtaining consent where required (EU
|
|
70
|
+
* ePrivacy/GDPR, UK PECR, etc.) is the merchant's responsibility.
|
|
71
|
+
*/
|
|
72
|
+
static getComplianceContext(): ComplianceContext;
|
|
73
|
+
/** Instance accessor for {@link TraceTail.getComplianceContext}. */
|
|
74
|
+
getComplianceContext(): ComplianceContext;
|
|
61
75
|
static validateApiKey(apiKey: string): boolean;
|
|
62
76
|
/**
|
|
63
77
|
* Calculate confidence based on actual signal entropy and environment stability.
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";function e(e){let t=0;const r=e.length;if(0===r)return"0";for(let n=0;n<r;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return Math.abs(t).toString(36)}function t(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(t);const r={},n=Object.keys(e).sort();for(const o of n)r[o]=t(e[o]);return r}Object.defineProperty(exports,"__esModule",{value:!0});const r=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function n(e){if(!e||"object"!=typeof e)return!1;if(!(e.error||e.unavailable||e.disabled))return!1;const t=Object.keys(e),r=new Set(["error","unavailable","disabled","id","timestamp"]);return 0===t.filter(e=>!r.has(e)).length}const o=new Set(["canvas","webgl","audio","fonts"]),a={unavailable:!0};function i(t,r){switch(t){case"canvas":return function(t){if(!t||"object"!=typeof t)return t;const r={...t};if(delete r.error,delete r.unavailable,delete r.disabled,delete r.id,delete r.renderTime,delete r.timestamp,Array.isArray(r.samples)){const t=32,n=r.samples.map(e=>Number.isFinite(e)?Math.round(e/t):0);r.canvasHash=e(n.join(",")),delete r.samples,delete r.hash}r.basic&&"string"==typeof r.basic&&(r.basic=s(r.basic));r.advanced&&"string"==typeof r.advanced&&(r.advanced=s(r.advanced));r.textMetrics&&"object"==typeof r.textMetrics&&(r.textMetrics=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(100*t[e])/100)}),t}(r.textMetrics));return r}(r);case"webgl":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,t.vendor&&(t.vendor=c(t.vendor));t.renderer&&(t.renderer=c(t.renderer));t.unmaskedVendor&&(t.unmaskedVendor=c(t.unmaskedVendor));t.unmaskedRenderer&&(t.unmaskedRenderer=c(t.unmaskedRenderer));t.parameters&&"object"==typeof t.parameters&&(t.parameters=function(e){if(!e||"object"!=typeof e)return e;const t={};return["MAX_TEXTURE_SIZE","MAX_VERTEX_ATTRIBS","MAX_FRAGMENT_UNIFORM_VECTORS","MAX_VARYING_VECTORS","MAX_VERTEX_UNIFORM_VECTORS","SHADING_LANGUAGE_VERSION","VERSION","VENDOR","RENDERER"].forEach(r=>{void 0!==e[r]&&(t[r]=e[r])}),t}(t.parameters));for(const e of["renderTests","renderVariance","renderHash","precisionTest","geometryCount","shadingLanguageVersion","maxTextureSize","maxViewportDims","maxVertexAttribs","extensions","contextCreationTime","shaderCompileTime"])delete t[e];return t}(r);case"audio":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};if(delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.baseLatency,delete t.contextState,delete t.audioFingerprint,t.context&&"object"==typeof t.context){const e={...t.context};delete e.currentTime,delete e.baseLatency,delete e.outputLatency,t.context=e}t.frequencyData&&Array.isArray(t.frequencyData)&&(t.frequencyData=function(e){return Array.isArray(e)?e.map(e=>5*Math.round(e/5)):e}(t.frequencyData));t.dynamicsCompressor&&"object"==typeof t.dynamicsCompressor&&(t.dynamicsCompressor=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(1e3*t[e])/1e3)}),t}(t.dynamicsCompressor));return t}(r);case"fonts":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,Array.isArray(t.detected)&&(t.detected=[...new Set(t.detected)].sort(),t.count=t.detected.length,delete t.hash);t.measurements&&"object"==typeof t.measurements&&(t.measurements=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(10*t[e])/10)}),t}(t.measurements));t.available&&Array.isArray(t.available)&&(t.available=[...new Set(t.available)].sort());t.systemFonts&&Array.isArray(t.systemFonts)&&(t.systemFonts=[...new Set(t.systemFonts)].sort());return delete t.detectionTime,delete t.loadingTime,t}(r);case"webAssembly":case"webassembly":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.id,delete t.cpuTimings,delete t.advancedCPUTimings,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.compilationFingerprint,delete t.executionContextFingerprint,delete t.memoryPatternHash,delete t.advancedDistinction,delete t.browserSpecificBehaviors;const r={wasmSupported:t.wasmSupported||!1,memoryGrowSupported:t.memoryGrowSupported||!1};if(t.apiImplementationSignature&&"string"==typeof t.apiImplementationSignature){const e=(n=t.apiImplementationSignature)&&"string"==typeof n?n.replace(/v\d+\.\d+\.\d+/g,"VERSION").replace(/\d{13,}/g,"TIMESTAMP"):n;e.includes("0.")||e.includes("1.")||e.includes("2.")||(r.apiImplementationSignature=e)}var n;return r}(r);case"hardware":case"basic":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,"string"==typeof t.userAgent&&(t.userAgent=function(e){var t;if(!e)return"";let r="unknown",n="";const o=[["edge",/Edg(?:e|A|iOS)?\/(\d+)/],["opera",/OPR\/(\d+)/],["samsung",/SamsungBrowser\/(\d+)/],["firefox",/Firefox\/(\d+)/],["chrome",/Chrome\/(\d+)/],["safari",/Version\/(\d+)[.\d]*\s+.*Safari/]];for(const[a,i]of o){const o=e.match(i);if(o){r=a,n=null!==(t=o[1])&&void 0!==t?t:"";break}}let a="unknown";/Windows NT/.test(e)?a="windows":/CrOS/.test(e)?a="chromeos":/(iPhone|iPad|iPod)/.test(e)?a="ios":/Android/.test(e)?a="android":/Mac OS X|Macintosh/.test(e)?a="macos":/Linux/.test(e)&&(a="linux");return`${r}/${n}|${a}`}(t.userAgent));delete t.timezoneOffset,t.screen&&"object"==typeof t.screen&&(t.screen=function(e){if(!e||"object"!=typeof e)return e;const t={...e};t.width&&t.height&&(t.aspectRatio=Math.round(t.width/t.height*100)/100);return t}(t.screen));t.memory&&"object"==typeof t.memory&&(t.memory=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&t[e]>1e6&&(t[e]=1073741824*Math.round(t[e]/1073741824))}),t}(t.memory));return delete t.performanceTiming,delete t.networkTiming,t}(r);default:return l(r)}}function s(e){try{let t=e.replace(/\d{13,}/g,"TIMESTAMP");return t=t.replace(/\d+\.\d{6,}/g,e=>parseFloat(e).toFixed(3)),t}catch(t){return e}}function c(e){if(!e||"string"!=typeof e)return e;let t=e.replace(/\b\d+\.\d+\.\d+\.\d+\b/g,"VERSION");return t=t.replace(/\b(Direct3D|OpenGL)\s+\d+\.\d+/g,"$1 API"),t}function l(e){if(!e||"object"!=typeof e)return e;const t={...e};return delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.timestamp,delete t.renderTime,delete t.detectionTime,delete t.loadingTime,delete t.currentTime,delete t.baseLatency,delete t.outputLatency,delete t.contextCreationTime,delete t.shaderCompileTime,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.performanceTiming,delete t.networkTiming,Object.keys(t).forEach(e=>{const r=t[e];"string"==typeof r&&/^\w+_\d{13,}_\w+$/.test(r)&&delete t[e]}),Object.keys(t).forEach(e=>{t[e]&&"object"==typeof t[e]&&!Array.isArray(t[e])&&(t[e]=l(t[e]))}),t}const d=["Arial","Arial Black","Arial Narrow","Arial Unicode MS","Calibri","Cambria","Century Gothic","Comic Sans MS","Consolas","Courier","Courier New","Georgia","Helvetica","Impact","Lucida Console","Lucida Grande","Palatino","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana","Monaco","Menlo"];async function u(){const t={};try{t.basic={userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,cookieEnabled:navigator.cookieEnabled,screen:{width:screen.width,height:screen.height,colorDepth:screen.colorDepth},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset()}}catch(e){}try{t.hardware={concurrency:navigator.hardwareConcurrency||0,maxTouchPoints:navigator.maxTouchPoints||0,deviceMemory:navigator.deviceMemory}}catch(e){}try{t.canvas=await async function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=256,t.height=256,r.fillStyle="#f60",r.fillRect(0,0,256,256);const n=r.createLinearGradient(0,0,256,256);n.addColorStop(0,"#ff6b6b"),n.addColorStop(.5,"#4ecdc4"),n.addColorStop(1,"#1a1a2e"),r.fillStyle=n,r.fillRect(0,0,128,128);const o=r.createRadialGradient(192,64,10,192,64,60);o.addColorStop(0,"#e74c3c"),o.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=o,r.fillRect(128,0,128,128),r.fillStyle="#069",r.font="14px Arial",r.fillText("TraceTail",4,150),r.font="italic 12px Georgia",r.fillText("Canvas FP",4,170),r.font="20px serif",r.fillText("😀🌍🚀❤️",4,200),r.beginPath(),r.moveTo(130,140),r.bezierCurveTo(150,200,200,160,240,210),r.strokeStyle="#9b59b6",r.lineWidth=2,r.stroke(),r.beginPath(),r.arc(200,200,30,0,2*Math.PI),r.fillStyle="rgba(52,152,219,0.6)",r.fill(),r.shadowColor="rgba(0,0,0,0.5)",r.shadowBlur=6,r.shadowOffsetX=3,r.shadowOffsetY=3,r.fillStyle="#2ecc71",r.fillRect(60,200,50,40),r.shadowColor="transparent",r.globalCompositeOperation="multiply",r.fillStyle="#e67e22",r.fillRect(80,180,60,60),r.globalCompositeOperation="screen",r.fillStyle="#3498db",r.fillRect(100,190,60,60),r.globalCompositeOperation="source-over",r.font="11px Arial",r.fillStyle="#000",r.fillText("Subpx",10.5,245.5);const a=[r.getImageData(0,0,32,32),r.getImageData(128,0,32,32),r.getImageData(0,128,32,32),r.getImageData(180,180,32,32)].map(e=>Array.from(e.data.slice(0,64)).reduce((e,t)=>e+t,0));return{hash:e(a.join(",")),samples:a}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.canvas={error:"collection failed"}}try{t.webgl=function(){try{const e=document.createElement("canvas"),t=e.getContext("webgl")||e.getContext("experimental-webgl");if(!t)return{unavailable:!0};const r=t.getExtension("WEBGL_debug_renderer_info"),n=r?t.getParameter(r.UNMASKED_VENDOR_WEBGL):t.getParameter(t.VENDOR),o=r?t.getParameter(r.UNMASKED_RENDERER_WEBGL):t.getParameter(t.RENDERER);return{vendor:t.getParameter(t.VENDOR),renderer:t.getParameter(t.RENDERER),version:t.getParameter(t.VERSION),unmaskedVendor:n,unmaskedRenderer:o}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.webgl={error:"collection failed"}}try{t.fonts=function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=200,t.height=50;const n=[],o=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const a=o.map(e=>r.measureText(e).width);for(const e of d){r.font=`14px "${e}", monospace`;const t=o.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=a[t])&&void 0!==r?r:0))>.1})&&n.push(e)}return{detected:n,count:n.length,hash:e(n.join(","))}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.fonts={error:"collection failed"}}try{t.audio=function(){try{const e=window.AudioContext||window.webkitAudioContext;if(!e)return{unavailable:!0};const t=new e,r={sampleRate:t.sampleRate,maxChannelCount:t.destination.maxChannelCount,baseLatency:t.baseLatency};return t.close(),r}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.audio={error:"collection failed"}}return t}async function f(e,s){const c=function(e){const t={};for(const[s,c]of Object.entries(e))if(!r.has(s))if(c&&"object"==typeof c){const e=c;if(n(e)){o.has(s)&&(t[s]=a);continue}const r=i(s,e);if(r&&"object"==typeof r){const e=Object.keys(r);if(n(r)||0===e.length){o.has(s)&&(t[s]=a);continue}t[s]=r}else o.has(s)&&(t[s]=a)}else null!=c&&(t[s]=c);return t}(e),l=t(c),d=JSON.stringify(l);return(s?"free_fp2_":"fp2_")+(await async function(e){if(!e.length)return"0000000000000000";const t=(new TextEncoder).encode(e),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("").substring(0,32)}(d)).substring(0,16)}class m{constructor(e={}){this.cache=new Map,this.isFree=!e.apiKey,this.options={apiKey:e.apiKey||"",endpoint:e.endpoint||"/api",timeout:e.timeout||1e4,debug:e.debug||!1,caching:!1!==e.caching,respectDNT:e.respectDNT||!1,includeIP:!1!==e.includeIP,storeFingerprints:!1!==e.storeFingerprints,enableWorkers:!1!==e.enableWorkers,batchRequests:!1!==e.batchRequests,fallbackMode:e.fallbackMode||"basic"},this.log("TraceTail SDK initialized",{version:"2.3.7",options:this.options})}async generateFingerprint(e){const t=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const r=!0===(null==e?void 0:e.verbose),n=r?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(n)){const e=this.cache.get(n);if(e)return this.log("Using cached fingerprint",e),e}const o=await u(),a=Math.round(performance.now()-t),i=await f(o,this.isFree);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(o,i,r),processingTime:Math.round(performance.now()-t)};return this.options.caching&&this.cache.set(n,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const s={visitorId:i,confidence:await this.calculateConfidenceAsync(o),processingTime:a,...r&&{components:o}};return this.options.caching&&this.cache.set(n,s),this.log("Client-side fingerprint generated",s),s}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t,r){const n=new AbortController,o=setTimeout(()=>n.abort(),this.options.timeout);try{const a=await fetch(`${this.options.endpoint}/id`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`,"X-TraceTail-SDK":"js/2.3.7"},body:JSON.stringify({visitorId:t,components:e,verbose:r||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:n.signal});if(clearTimeout(o),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const i=await a.json(),s={visitorId:i.visitorId,confidence:i.confidence,processingTime:i.processingTime||0};if(r){if(!i.components)throw new Error("Server did not return components in verbose mode");s.components=i.components}return s}catch(e){throw clearTimeout(o),this.options.debug&&console.error("[TraceTail] Server error:",e),e}}static getVersion(){return"2.3.7"}static validateApiKey(e){return/^tt_(test|prod)_[a-zA-Z0-9]{32,}$/.test(e)}async calculateConfidenceAsync(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));o.length>=5?r+=.05:o.length>=3&&(r+=.02);try{const e=await async function(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){((await navigator.storage.estimate()).quota||0)/1073741824<.5&&(t+=.4,e.push("low_storage_quota"))}}catch(r){t+=.15,e.push("storage_api_error")}try{!window.webkitRequestFileSystem&&/Chrome/.test(navigator.userAgent)&&(t+=.2,e.push("no_filesystem_api"))}catch(r){t+=.1,e.push("filesystem_check_error")}try{/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&(navigator.serviceWorker||(t+=.3,e.push("no_service_worker_safari")))}catch(e){}try{navigator.brave&&(t+=.15,e.push("brave_browser"))}catch(e){}try{/Firefox/.test(navigator.userAgent)&&screen.width%200==0&&screen.height%100==0&&(t+=.2,e.push("firefox_rfp_screen"))}catch(e){}return{isPrivate:t>=.35,score:Math.min(1,t),signals:e}}();e.isPrivate&&(r-=.08,r-=.02*e.signals.length)}catch(e){r-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}calculateConfidence(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));return o.length>=5?r+=.05:o.length>=3&&(r+=.02),Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}isDNTEnabled(){return"1"===navigator.doNotTrack||"1"===window.doNotTrack||"1"===navigator.msDoNotTrack}log(e,t){this.options.debug&&console.log(`[TraceTail] ${e}`,t)}}exports.TraceTail=m,exports.default=m;
|
|
1
|
+
"use strict";function e(e){let t=0;const r=e.length;if(0===r)return"0";for(let n=0;n<r;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return Math.abs(t).toString(36)}function t(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(t);const r={},n=Object.keys(e).sort();for(const o of n)r[o]=t(e[o]);return r}Object.defineProperty(exports,"__esModule",{value:!0});const r=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function n(e){if(!e||"object"!=typeof e)return!1;if(!(e.error||e.unavailable||e.disabled))return!1;const t=Object.keys(e),r=new Set(["error","unavailable","disabled","id","timestamp"]);return 0===t.filter(e=>!r.has(e)).length}const o=new Set(["canvas","webgl","audio","fonts"]),a={unavailable:!0};function i(t,r){switch(t){case"canvas":return function(t){if(!t||"object"!=typeof t)return t;const r={...t};if(delete r.error,delete r.unavailable,delete r.disabled,delete r.id,delete r.renderTime,delete r.timestamp,Array.isArray(r.samples)){const t=32,n=r.samples.map(e=>Number.isFinite(e)?Math.round(e/t):0);r.canvasHash=e(n.join(",")),delete r.samples,delete r.hash}r.basic&&"string"==typeof r.basic&&(r.basic=s(r.basic));r.advanced&&"string"==typeof r.advanced&&(r.advanced=s(r.advanced));r.textMetrics&&"object"==typeof r.textMetrics&&(r.textMetrics=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(100*t[e])/100)}),t}(r.textMetrics));return r}(r);case"webgl":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,t.vendor&&(t.vendor=c(t.vendor));t.renderer&&(t.renderer=c(t.renderer));t.unmaskedVendor&&(t.unmaskedVendor=c(t.unmaskedVendor));t.unmaskedRenderer&&(t.unmaskedRenderer=c(t.unmaskedRenderer));t.parameters&&"object"==typeof t.parameters&&(t.parameters=function(e){if(!e||"object"!=typeof e)return e;const t={};return["MAX_TEXTURE_SIZE","MAX_VERTEX_ATTRIBS","MAX_FRAGMENT_UNIFORM_VECTORS","MAX_VARYING_VECTORS","MAX_VERTEX_UNIFORM_VECTORS","SHADING_LANGUAGE_VERSION","VERSION","VENDOR","RENDERER"].forEach(r=>{void 0!==e[r]&&(t[r]=e[r])}),t}(t.parameters));for(const e of["renderTests","renderVariance","renderHash","precisionTest","geometryCount","shadingLanguageVersion","maxTextureSize","maxViewportDims","maxVertexAttribs","extensions","contextCreationTime","shaderCompileTime"])delete t[e];return t}(r);case"audio":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};if(delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.baseLatency,delete t.contextState,delete t.audioFingerprint,t.context&&"object"==typeof t.context){const e={...t.context};delete e.currentTime,delete e.baseLatency,delete e.outputLatency,t.context=e}t.frequencyData&&Array.isArray(t.frequencyData)&&(t.frequencyData=function(e){return Array.isArray(e)?e.map(e=>5*Math.round(e/5)):e}(t.frequencyData));t.dynamicsCompressor&&"object"==typeof t.dynamicsCompressor&&(t.dynamicsCompressor=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(1e3*t[e])/1e3)}),t}(t.dynamicsCompressor));return t}(r);case"fonts":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,Array.isArray(t.detected)&&(t.detected=[...new Set(t.detected)].sort(),t.count=t.detected.length,delete t.hash);t.measurements&&"object"==typeof t.measurements&&(t.measurements=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(10*t[e])/10)}),t}(t.measurements));t.available&&Array.isArray(t.available)&&(t.available=[...new Set(t.available)].sort());t.systemFonts&&Array.isArray(t.systemFonts)&&(t.systemFonts=[...new Set(t.systemFonts)].sort());return delete t.detectionTime,delete t.loadingTime,t}(r);case"webAssembly":case"webassembly":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.id,delete t.cpuTimings,delete t.advancedCPUTimings,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.compilationFingerprint,delete t.executionContextFingerprint,delete t.memoryPatternHash,delete t.advancedDistinction,delete t.browserSpecificBehaviors;const r={wasmSupported:t.wasmSupported||!1,memoryGrowSupported:t.memoryGrowSupported||!1};if(t.apiImplementationSignature&&"string"==typeof t.apiImplementationSignature){const e=(n=t.apiImplementationSignature)&&"string"==typeof n?n.replace(/v\d+\.\d+\.\d+/g,"VERSION").replace(/\d{13,}/g,"TIMESTAMP"):n;e.includes("0.")||e.includes("1.")||e.includes("2.")||(r.apiImplementationSignature=e)}var n;return r}(r);case"hardware":case"basic":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,"string"==typeof t.userAgent&&(t.userAgent=function(e){var t;if(!e)return"";let r="unknown",n="";const o=[["edge",/Edg(?:e|A|iOS)?\/(\d+)/],["opera",/OPR\/(\d+)/],["samsung",/SamsungBrowser\/(\d+)/],["firefox",/Firefox\/(\d+)/],["chrome",/Chrome\/(\d+)/],["safari",/Version\/(\d+)[.\d]*\s+.*Safari/]];for(const[a,i]of o){const o=e.match(i);if(o){r=a,n=null!==(t=o[1])&&void 0!==t?t:"";break}}let a="unknown";/Windows NT/.test(e)?a="windows":/CrOS/.test(e)?a="chromeos":/(iPhone|iPad|iPod)/.test(e)?a="ios":/Android/.test(e)?a="android":/Mac OS X|Macintosh/.test(e)?a="macos":/Linux/.test(e)&&(a="linux");return`${r}/${n}|${a}`}(t.userAgent));delete t.timezoneOffset,t.screen&&"object"==typeof t.screen&&(t.screen=function(e){if(!e||"object"!=typeof e)return e;const t={...e};t.width&&t.height&&(t.aspectRatio=Math.round(t.width/t.height*100)/100);return t}(t.screen));t.memory&&"object"==typeof t.memory&&(t.memory=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&t[e]>1e6&&(t[e]=1073741824*Math.round(t[e]/1073741824))}),t}(t.memory));return delete t.performanceTiming,delete t.networkTiming,t}(r);default:return l(r)}}function s(e){try{let t=e.replace(/\d{13,}/g,"TIMESTAMP");return t=t.replace(/\d+\.\d{6,}/g,e=>parseFloat(e).toFixed(3)),t}catch(t){return e}}function c(e){if(!e||"string"!=typeof e)return e;let t=e.replace(/\b\d+\.\d+\.\d+\.\d+\b/g,"VERSION");return t=t.replace(/\b(Direct3D|OpenGL)\s+\d+\.\d+/g,"$1 API"),t}function l(e){if(!e||"object"!=typeof e)return e;const t={...e};return delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.timestamp,delete t.renderTime,delete t.detectionTime,delete t.loadingTime,delete t.currentTime,delete t.baseLatency,delete t.outputLatency,delete t.contextCreationTime,delete t.shaderCompileTime,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.performanceTiming,delete t.networkTiming,Object.keys(t).forEach(e=>{const r=t[e];"string"==typeof r&&/^\w+_\d{13,}_\w+$/.test(r)&&delete t[e]}),Object.keys(t).forEach(e=>{t[e]&&"object"==typeof t[e]&&!Array.isArray(t[e])&&(t[e]=l(t[e]))}),t}const u=["Arial","Arial Black","Arial Narrow","Arial Unicode MS","Calibri","Cambria","Century Gothic","Comic Sans MS","Consolas","Courier","Courier New","Georgia","Helvetica","Impact","Lucida Console","Lucida Grande","Palatino","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana","Monaco","Menlo"];async function d(){const t={};try{t.basic={userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,cookieEnabled:navigator.cookieEnabled,screen:{width:screen.width,height:screen.height,colorDepth:screen.colorDepth},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset()}}catch(e){}try{t.hardware={concurrency:navigator.hardwareConcurrency||0,maxTouchPoints:navigator.maxTouchPoints||0,deviceMemory:navigator.deviceMemory}}catch(e){}try{t.canvas=await async function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=256,t.height=256,r.fillStyle="#f60",r.fillRect(0,0,256,256);const n=r.createLinearGradient(0,0,256,256);n.addColorStop(0,"#ff6b6b"),n.addColorStop(.5,"#4ecdc4"),n.addColorStop(1,"#1a1a2e"),r.fillStyle=n,r.fillRect(0,0,128,128);const o=r.createRadialGradient(192,64,10,192,64,60);o.addColorStop(0,"#e74c3c"),o.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=o,r.fillRect(128,0,128,128),r.fillStyle="#069",r.font="14px Arial",r.fillText("TraceTail",4,150),r.font="italic 12px Georgia",r.fillText("Canvas FP",4,170),r.font="20px serif",r.fillText("😀🌍🚀❤️",4,200),r.beginPath(),r.moveTo(130,140),r.bezierCurveTo(150,200,200,160,240,210),r.strokeStyle="#9b59b6",r.lineWidth=2,r.stroke(),r.beginPath(),r.arc(200,200,30,0,2*Math.PI),r.fillStyle="rgba(52,152,219,0.6)",r.fill(),r.shadowColor="rgba(0,0,0,0.5)",r.shadowBlur=6,r.shadowOffsetX=3,r.shadowOffsetY=3,r.fillStyle="#2ecc71",r.fillRect(60,200,50,40),r.shadowColor="transparent",r.globalCompositeOperation="multiply",r.fillStyle="#e67e22",r.fillRect(80,180,60,60),r.globalCompositeOperation="screen",r.fillStyle="#3498db",r.fillRect(100,190,60,60),r.globalCompositeOperation="source-over",r.font="11px Arial",r.fillStyle="#000",r.fillText("Subpx",10.5,245.5);const a=[r.getImageData(0,0,32,32),r.getImageData(128,0,32,32),r.getImageData(0,128,32,32),r.getImageData(180,180,32,32)].map(e=>Array.from(e.data.slice(0,64)).reduce((e,t)=>e+t,0));return{hash:e(a.join(",")),samples:a}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.canvas={error:"collection failed"}}try{t.webgl=function(){try{const e=document.createElement("canvas"),t=e.getContext("webgl")||e.getContext("experimental-webgl");if(!t)return{unavailable:!0};const r=t.getExtension("WEBGL_debug_renderer_info"),n=r?t.getParameter(r.UNMASKED_VENDOR_WEBGL):t.getParameter(t.VENDOR),o=r?t.getParameter(r.UNMASKED_RENDERER_WEBGL):t.getParameter(t.RENDERER);return{vendor:t.getParameter(t.VENDOR),renderer:t.getParameter(t.RENDERER),version:t.getParameter(t.VERSION),unmaskedVendor:n,unmaskedRenderer:o}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.webgl={error:"collection failed"}}try{t.fonts=function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=200,t.height=50;const n=[],o=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const a=o.map(e=>r.measureText(e).width);for(const e of u){r.font=`14px "${e}", monospace`;const t=o.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=a[t])&&void 0!==r?r:0))>.1})&&n.push(e)}return{detected:n,count:n.length,hash:e(n.join(","))}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.fonts={error:"collection failed"}}try{t.audio=function(){try{const e=window.AudioContext||window.webkitAudioContext;if(!e)return{unavailable:!0};const t=new e,r={sampleRate:t.sampleRate,maxChannelCount:t.destination.maxChannelCount,baseLatency:t.baseLatency};return t.close(),r}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.audio={error:"collection failed"}}return t}async function f(e,s){const c=function(e){const t={};for(const[s,c]of Object.entries(e))if(!r.has(s))if(c&&"object"==typeof c){const e=c;if(n(e)){o.has(s)&&(t[s]=a);continue}const r=i(s,e);if(r&&"object"==typeof r){const e=Object.keys(r);if(n(r)||0===e.length){o.has(s)&&(t[s]=a);continue}t[s]=r}else o.has(s)&&(t[s]=a)}else null!=c&&(t[s]=c);return t}(e),l=t(c),u=JSON.stringify(l);return(s?"free_fp2_":"fp2_")+(await async function(e){if(!e.length)return"0000000000000000";const t=(new TextEncoder).encode(e),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("").substring(0,32)}(u)).substring(0,16)}const p=new Set(["Europe/Vienna","Europe/Brussels","Europe/Sofia","Europe/Zagreb","Asia/Nicosia","Asia/Famagusta","Europe/Prague","Europe/Copenhagen","Europe/Tallinn","Europe/Helsinki","Europe/Paris","Europe/Berlin","Europe/Busingen","Europe/Athens","Europe/Budapest","Europe/Dublin","Europe/Rome","Europe/Riga","Europe/Vilnius","Europe/Luxembourg","Europe/Malta","Europe/Amsterdam","Europe/Warsaw","Europe/Lisbon","Atlantic/Azores","Atlantic/Madeira","Europe/Bucharest","Europe/Bratislava","Europe/Ljubljana","Europe/Madrid","Africa/Ceuta","Atlantic/Canary","Europe/Stockholm"]),m=new Set(["Atlantic/Reykjavik","Europe/Vaduz","Europe/Oslo","Arctic/Longyearbyen"]),g=new Set(["Europe/London","Europe/Belfast","Europe/Guernsey","Europe/Jersey","Europe/Isle_of_Man"]),h=["America/","US/","Pacific/Honolulu"];function y(){try{return"undefined"!=typeof navigator?navigator:void 0}catch(e){return}}function b(){try{return"undefined"!=typeof window?window:void 0}catch(e){return}}function v(e,t){if(e){if(g.has(e))return"UK";if(p.has(e))return"EU";if(m.has(e))return"EEA";if(function(e){return h.some(t=>t.endsWith("/")?e.startsWith(t):e===t)}(e))return"US"}const r=t.toLowerCase().split("-")[1];if("gb"===r||"uk"===r)return"UK";if("us"===r)return"US";const n=new Set(["at","be","bg","hr","cy","cz","dk","ee","fi","fr","de","gr","hu","ie","it","lv","lt","lu","mt","nl","pl","pt","ro","sk","si","es","se"]);if(r&&n.has(r))return"EU";const o=new Set(["is","li","no"]);return r&&o.has(r)?"EEA":"OTHER"}function E(){const e=function(){try{const e=y();if(e&&!0===e.globalPrivacyControl)return!0;const t=b();return!0===(null==t?void 0:t.globalPrivacyControl)}catch(e){return!1}}(),t=function(){try{const e=y(),t=b();return[null==e?void 0:e.doNotTrack,null==e?void 0:e.msDoNotTrack,null==t?void 0:t.doNotTrack].some(e=>"1"===e||"yes"===e)}catch(e){return!1}}(),r=function(){try{if("undefined"==typeof Intl||"function"!=typeof Intl.DateTimeFormat)return"";const e=Intl.DateTimeFormat().resolvedOptions().timeZone;return"string"==typeof e?e:""}catch(e){return""}}(),n=function(){try{const e=y(),t=(null==e?void 0:e.language)||(Array.isArray(null==e?void 0:e.languages)?null==e?void 0:e.languages[0]:void 0);return"string"==typeof t?t:""}catch(e){return""}}(),o=v(r,n),a="UK"===o,i="EU"===o||"EEA"===o;return{gpcEnabled:e,doNotTrack:t,timezone:r,locale:n,region:o,isEU:"EU"===o,isEEA:i,isUK:a,likelyRequiresConsent:i||a||e||t}}class w{constructor(e={}){this.cache=new Map,this.isFree=!e.apiKey,this.options={apiKey:e.apiKey||"",endpoint:e.endpoint||"/api",timeout:e.timeout||1e4,debug:e.debug||!1,caching:!1!==e.caching,respectDNT:e.respectDNT||!1,includeIP:!1!==e.includeIP,storeFingerprints:!1!==e.storeFingerprints,enableWorkers:!1!==e.enableWorkers,batchRequests:!1!==e.batchRequests,fallbackMode:e.fallbackMode||"basic"},this.log("TraceTail SDK initialized",{version:"2.3.7",options:this.options})}async generateFingerprint(e){const t=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const r=!0===(null==e?void 0:e.verbose),n=r?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(n)){const e=this.cache.get(n);if(e)return this.log("Using cached fingerprint",e),e}const o=await d(),a=Math.round(performance.now()-t),i=await f(o,this.isFree);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(o,i,r),processingTime:Math.round(performance.now()-t)};return this.options.caching&&this.cache.set(n,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const s={visitorId:i,confidence:await this.calculateConfidenceAsync(o),processingTime:a,...r&&{components:o}};return this.options.caching&&this.cache.set(n,s),this.log("Client-side fingerprint generated",s),s}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t,r){const n=new AbortController,o=setTimeout(()=>n.abort(),this.options.timeout);try{const a=await fetch(`${this.options.endpoint}/id`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`,"X-TraceTail-SDK":"js/2.3.7"},body:JSON.stringify({visitorId:t,components:e,verbose:r||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:n.signal});if(clearTimeout(o),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const i=await a.json(),s={visitorId:i.visitorId,confidence:i.confidence,processingTime:i.processingTime||0};if(r){if(!i.components)throw new Error("Server did not return components in verbose mode");s.components=i.components}return s}catch(e){throw clearTimeout(o),this.options.debug&&console.error("[TraceTail] Server error:",e),e}}static getVersion(){return"2.3.7"}static getComplianceContext(){return E()}getComplianceContext(){return E()}static validateApiKey(e){return/^tt_(test|prod)_[a-zA-Z0-9]{32,}$/.test(e)}async calculateConfidenceAsync(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));o.length>=5?r+=.05:o.length>=3&&(r+=.02);try{const e=await async function(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){((await navigator.storage.estimate()).quota||0)/1073741824<.5&&(t+=.4,e.push("low_storage_quota"))}}catch(r){t+=.15,e.push("storage_api_error")}try{!window.webkitRequestFileSystem&&/Chrome/.test(navigator.userAgent)&&(t+=.2,e.push("no_filesystem_api"))}catch(r){t+=.1,e.push("filesystem_check_error")}try{/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&(navigator.serviceWorker||(t+=.3,e.push("no_service_worker_safari")))}catch(e){}try{navigator.brave&&(t+=.15,e.push("brave_browser"))}catch(e){}try{/Firefox/.test(navigator.userAgent)&&screen.width%200==0&&screen.height%100==0&&(t+=.2,e.push("firefox_rfp_screen"))}catch(e){}return{isPrivate:t>=.35,score:Math.min(1,t),signals:e}}();e.isPrivate&&(r-=.08,r-=.02*e.signals.length)}catch(e){r-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}calculateConfidence(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));return o.length>=5?r+=.05:o.length>=3&&(r+=.02),Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}isDNTEnabled(){return"1"===navigator.doNotTrack||"1"===window.doNotTrack||"1"===navigator.msDoNotTrack}log(e,t){this.options.debug&&console.log(`[TraceTail] ${e}`,t)}}exports.TraceTail=w,exports.default=w,exports.getComplianceContext=E;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e){let t=0;const r=e.length;if(0===r)return"0";for(let n=0;n<r;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return Math.abs(t).toString(36)}function t(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(t);const r={},n=Object.keys(e).sort();for(const o of n)r[o]=t(e[o]);return r}const r=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function n(e){if(!e||"object"!=typeof e)return!1;if(!(e.error||e.unavailable||e.disabled))return!1;const t=Object.keys(e),r=new Set(["error","unavailable","disabled","id","timestamp"]);return 0===t.filter(e=>!r.has(e)).length}const o=new Set(["canvas","webgl","audio","fonts"]),a={unavailable:!0};function i(t,r){switch(t){case"canvas":return function(t){if(!t||"object"!=typeof t)return t;const r={...t};if(delete r.error,delete r.unavailable,delete r.disabled,delete r.id,delete r.renderTime,delete r.timestamp,Array.isArray(r.samples)){const t=32,n=r.samples.map(e=>Number.isFinite(e)?Math.round(e/t):0);r.canvasHash=e(n.join(",")),delete r.samples,delete r.hash}r.basic&&"string"==typeof r.basic&&(r.basic=s(r.basic));r.advanced&&"string"==typeof r.advanced&&(r.advanced=s(r.advanced));r.textMetrics&&"object"==typeof r.textMetrics&&(r.textMetrics=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(100*t[e])/100)}),t}(r.textMetrics));return r}(r);case"webgl":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,t.vendor&&(t.vendor=c(t.vendor));t.renderer&&(t.renderer=c(t.renderer));t.unmaskedVendor&&(t.unmaskedVendor=c(t.unmaskedVendor));t.unmaskedRenderer&&(t.unmaskedRenderer=c(t.unmaskedRenderer));t.parameters&&"object"==typeof t.parameters&&(t.parameters=function(e){if(!e||"object"!=typeof e)return e;const t={};return["MAX_TEXTURE_SIZE","MAX_VERTEX_ATTRIBS","MAX_FRAGMENT_UNIFORM_VECTORS","MAX_VARYING_VECTORS","MAX_VERTEX_UNIFORM_VECTORS","SHADING_LANGUAGE_VERSION","VERSION","VENDOR","RENDERER"].forEach(r=>{void 0!==e[r]&&(t[r]=e[r])}),t}(t.parameters));for(const e of["renderTests","renderVariance","renderHash","precisionTest","geometryCount","shadingLanguageVersion","maxTextureSize","maxViewportDims","maxVertexAttribs","extensions","contextCreationTime","shaderCompileTime"])delete t[e];return t}(r);case"audio":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};if(delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.baseLatency,delete t.contextState,delete t.audioFingerprint,t.context&&"object"==typeof t.context){const e={...t.context};delete e.currentTime,delete e.baseLatency,delete e.outputLatency,t.context=e}t.frequencyData&&Array.isArray(t.frequencyData)&&(t.frequencyData=function(e){return Array.isArray(e)?e.map(e=>5*Math.round(e/5)):e}(t.frequencyData));t.dynamicsCompressor&&"object"==typeof t.dynamicsCompressor&&(t.dynamicsCompressor=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(1e3*t[e])/1e3)}),t}(t.dynamicsCompressor));return t}(r);case"fonts":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,Array.isArray(t.detected)&&(t.detected=[...new Set(t.detected)].sort(),t.count=t.detected.length,delete t.hash);t.measurements&&"object"==typeof t.measurements&&(t.measurements=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(10*t[e])/10)}),t}(t.measurements));t.available&&Array.isArray(t.available)&&(t.available=[...new Set(t.available)].sort());t.systemFonts&&Array.isArray(t.systemFonts)&&(t.systemFonts=[...new Set(t.systemFonts)].sort());return delete t.detectionTime,delete t.loadingTime,t}(r);case"webAssembly":case"webassembly":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.id,delete t.cpuTimings,delete t.advancedCPUTimings,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.compilationFingerprint,delete t.executionContextFingerprint,delete t.memoryPatternHash,delete t.advancedDistinction,delete t.browserSpecificBehaviors;const r={wasmSupported:t.wasmSupported||!1,memoryGrowSupported:t.memoryGrowSupported||!1};if(t.apiImplementationSignature&&"string"==typeof t.apiImplementationSignature){const e=(n=t.apiImplementationSignature)&&"string"==typeof n?n.replace(/v\d+\.\d+\.\d+/g,"VERSION").replace(/\d{13,}/g,"TIMESTAMP"):n;e.includes("0.")||e.includes("1.")||e.includes("2.")||(r.apiImplementationSignature=e)}var n;return r}(r);case"hardware":case"basic":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,"string"==typeof t.userAgent&&(t.userAgent=function(e){var t;if(!e)return"";let r="unknown",n="";const o=[["edge",/Edg(?:e|A|iOS)?\/(\d+)/],["opera",/OPR\/(\d+)/],["samsung",/SamsungBrowser\/(\d+)/],["firefox",/Firefox\/(\d+)/],["chrome",/Chrome\/(\d+)/],["safari",/Version\/(\d+)[.\d]*\s+.*Safari/]];for(const[a,i]of o){const o=e.match(i);if(o){r=a,n=null!==(t=o[1])&&void 0!==t?t:"";break}}let a="unknown";/Windows NT/.test(e)?a="windows":/CrOS/.test(e)?a="chromeos":/(iPhone|iPad|iPod)/.test(e)?a="ios":/Android/.test(e)?a="android":/Mac OS X|Macintosh/.test(e)?a="macos":/Linux/.test(e)&&(a="linux");return`${r}/${n}|${a}`}(t.userAgent));delete t.timezoneOffset,t.screen&&"object"==typeof t.screen&&(t.screen=function(e){if(!e||"object"!=typeof e)return e;const t={...e};t.width&&t.height&&(t.aspectRatio=Math.round(t.width/t.height*100)/100);return t}(t.screen));t.memory&&"object"==typeof t.memory&&(t.memory=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&t[e]>1e6&&(t[e]=1073741824*Math.round(t[e]/1073741824))}),t}(t.memory));return delete t.performanceTiming,delete t.networkTiming,t}(r);default:return l(r)}}function s(e){try{let t=e.replace(/\d{13,}/g,"TIMESTAMP");return t=t.replace(/\d+\.\d{6,}/g,e=>parseFloat(e).toFixed(3)),t}catch(t){return e}}function c(e){if(!e||"string"!=typeof e)return e;let t=e.replace(/\b\d+\.\d+\.\d+\.\d+\b/g,"VERSION");return t=t.replace(/\b(Direct3D|OpenGL)\s+\d+\.\d+/g,"$1 API"),t}function l(e){if(!e||"object"!=typeof e)return e;const t={...e};return delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.timestamp,delete t.renderTime,delete t.detectionTime,delete t.loadingTime,delete t.currentTime,delete t.baseLatency,delete t.outputLatency,delete t.contextCreationTime,delete t.shaderCompileTime,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.performanceTiming,delete t.networkTiming,Object.keys(t).forEach(e=>{const r=t[e];"string"==typeof r&&/^\w+_\d{13,}_\w+$/.test(r)&&delete t[e]}),Object.keys(t).forEach(e=>{t[e]&&"object"==typeof t[e]&&!Array.isArray(t[e])&&(t[e]=l(t[e]))}),t}const d=["Arial","Arial Black","Arial Narrow","Arial Unicode MS","Calibri","Cambria","Century Gothic","Comic Sans MS","Consolas","Courier","Courier New","Georgia","Helvetica","Impact","Lucida Console","Lucida Grande","Palatino","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana","Monaco","Menlo"];async function u(){const t={};try{t.basic={userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,cookieEnabled:navigator.cookieEnabled,screen:{width:screen.width,height:screen.height,colorDepth:screen.colorDepth},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset()}}catch(e){}try{t.hardware={concurrency:navigator.hardwareConcurrency||0,maxTouchPoints:navigator.maxTouchPoints||0,deviceMemory:navigator.deviceMemory}}catch(e){}try{t.canvas=await async function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=256,t.height=256,r.fillStyle="#f60",r.fillRect(0,0,256,256);const n=r.createLinearGradient(0,0,256,256);n.addColorStop(0,"#ff6b6b"),n.addColorStop(.5,"#4ecdc4"),n.addColorStop(1,"#1a1a2e"),r.fillStyle=n,r.fillRect(0,0,128,128);const o=r.createRadialGradient(192,64,10,192,64,60);o.addColorStop(0,"#e74c3c"),o.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=o,r.fillRect(128,0,128,128),r.fillStyle="#069",r.font="14px Arial",r.fillText("TraceTail",4,150),r.font="italic 12px Georgia",r.fillText("Canvas FP",4,170),r.font="20px serif",r.fillText("😀🌍🚀❤️",4,200),r.beginPath(),r.moveTo(130,140),r.bezierCurveTo(150,200,200,160,240,210),r.strokeStyle="#9b59b6",r.lineWidth=2,r.stroke(),r.beginPath(),r.arc(200,200,30,0,2*Math.PI),r.fillStyle="rgba(52,152,219,0.6)",r.fill(),r.shadowColor="rgba(0,0,0,0.5)",r.shadowBlur=6,r.shadowOffsetX=3,r.shadowOffsetY=3,r.fillStyle="#2ecc71",r.fillRect(60,200,50,40),r.shadowColor="transparent",r.globalCompositeOperation="multiply",r.fillStyle="#e67e22",r.fillRect(80,180,60,60),r.globalCompositeOperation="screen",r.fillStyle="#3498db",r.fillRect(100,190,60,60),r.globalCompositeOperation="source-over",r.font="11px Arial",r.fillStyle="#000",r.fillText("Subpx",10.5,245.5);const a=[r.getImageData(0,0,32,32),r.getImageData(128,0,32,32),r.getImageData(0,128,32,32),r.getImageData(180,180,32,32)].map(e=>Array.from(e.data.slice(0,64)).reduce((e,t)=>e+t,0));return{hash:e(a.join(",")),samples:a}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.canvas={error:"collection failed"}}try{t.webgl=function(){try{const e=document.createElement("canvas"),t=e.getContext("webgl")||e.getContext("experimental-webgl");if(!t)return{unavailable:!0};const r=t.getExtension("WEBGL_debug_renderer_info"),n=r?t.getParameter(r.UNMASKED_VENDOR_WEBGL):t.getParameter(t.VENDOR),o=r?t.getParameter(r.UNMASKED_RENDERER_WEBGL):t.getParameter(t.RENDERER);return{vendor:t.getParameter(t.VENDOR),renderer:t.getParameter(t.RENDERER),version:t.getParameter(t.VERSION),unmaskedVendor:n,unmaskedRenderer:o}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.webgl={error:"collection failed"}}try{t.fonts=function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=200,t.height=50;const n=[],o=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const a=o.map(e=>r.measureText(e).width);for(const e of d){r.font=`14px "${e}", monospace`;const t=o.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=a[t])&&void 0!==r?r:0))>.1})&&n.push(e)}return{detected:n,count:n.length,hash:e(n.join(","))}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.fonts={error:"collection failed"}}try{t.audio=function(){try{const e=window.AudioContext||window.webkitAudioContext;if(!e)return{unavailable:!0};const t=new e,r={sampleRate:t.sampleRate,maxChannelCount:t.destination.maxChannelCount,baseLatency:t.baseLatency};return t.close(),r}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.audio={error:"collection failed"}}return t}async function f(e,s){const c=function(e){const t={};for(const[s,c]of Object.entries(e))if(!r.has(s))if(c&&"object"==typeof c){const e=c;if(n(e)){o.has(s)&&(t[s]=a);continue}const r=i(s,e);if(r&&"object"==typeof r){const e=Object.keys(r);if(n(r)||0===e.length){o.has(s)&&(t[s]=a);continue}t[s]=r}else o.has(s)&&(t[s]=a)}else null!=c&&(t[s]=c);return t}(e),l=t(c),d=JSON.stringify(l);return(s?"free_fp2_":"fp2_")+(await async function(e){if(!e.length)return"0000000000000000";const t=(new TextEncoder).encode(e),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("").substring(0,32)}(d)).substring(0,16)}class m{constructor(e={}){this.cache=new Map,this.isFree=!e.apiKey,this.options={apiKey:e.apiKey||"",endpoint:e.endpoint||"/api",timeout:e.timeout||1e4,debug:e.debug||!1,caching:!1!==e.caching,respectDNT:e.respectDNT||!1,includeIP:!1!==e.includeIP,storeFingerprints:!1!==e.storeFingerprints,enableWorkers:!1!==e.enableWorkers,batchRequests:!1!==e.batchRequests,fallbackMode:e.fallbackMode||"basic"},this.log("TraceTail SDK initialized",{version:"2.3.7",options:this.options})}async generateFingerprint(e){const t=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const r=!0===(null==e?void 0:e.verbose),n=r?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(n)){const e=this.cache.get(n);if(e)return this.log("Using cached fingerprint",e),e}const o=await u(),a=Math.round(performance.now()-t),i=await f(o,this.isFree);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(o,i,r),processingTime:Math.round(performance.now()-t)};return this.options.caching&&this.cache.set(n,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const s={visitorId:i,confidence:await this.calculateConfidenceAsync(o),processingTime:a,...r&&{components:o}};return this.options.caching&&this.cache.set(n,s),this.log("Client-side fingerprint generated",s),s}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t,r){const n=new AbortController,o=setTimeout(()=>n.abort(),this.options.timeout);try{const a=await fetch(`${this.options.endpoint}/id`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`,"X-TraceTail-SDK":"js/2.3.7"},body:JSON.stringify({visitorId:t,components:e,verbose:r||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:n.signal});if(clearTimeout(o),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const i=await a.json(),s={visitorId:i.visitorId,confidence:i.confidence,processingTime:i.processingTime||0};if(r){if(!i.components)throw new Error("Server did not return components in verbose mode");s.components=i.components}return s}catch(e){throw clearTimeout(o),this.options.debug&&console.error("[TraceTail] Server error:",e),e}}static getVersion(){return"2.3.7"}static validateApiKey(e){return/^tt_(test|prod)_[a-zA-Z0-9]{32,}$/.test(e)}async calculateConfidenceAsync(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));o.length>=5?r+=.05:o.length>=3&&(r+=.02);try{const e=await async function(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){((await navigator.storage.estimate()).quota||0)/1073741824<.5&&(t+=.4,e.push("low_storage_quota"))}}catch(r){t+=.15,e.push("storage_api_error")}try{!window.webkitRequestFileSystem&&/Chrome/.test(navigator.userAgent)&&(t+=.2,e.push("no_filesystem_api"))}catch(r){t+=.1,e.push("filesystem_check_error")}try{/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&(navigator.serviceWorker||(t+=.3,e.push("no_service_worker_safari")))}catch(e){}try{navigator.brave&&(t+=.15,e.push("brave_browser"))}catch(e){}try{/Firefox/.test(navigator.userAgent)&&screen.width%200==0&&screen.height%100==0&&(t+=.2,e.push("firefox_rfp_screen"))}catch(e){}return{isPrivate:t>=.35,score:Math.min(1,t),signals:e}}();e.isPrivate&&(r-=.08,r-=.02*e.signals.length)}catch(e){r-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}calculateConfidence(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));return o.length>=5?r+=.05:o.length>=3&&(r+=.02),Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}isDNTEnabled(){return"1"===navigator.doNotTrack||"1"===window.doNotTrack||"1"===navigator.msDoNotTrack}log(e,t){this.options.debug&&console.log(`[TraceTail] ${e}`,t)}}export{m as TraceTail,m as default};
|
|
1
|
+
function e(e){let t=0;const r=e.length;if(0===r)return"0";for(let n=0;n<r;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return Math.abs(t).toString(36)}function t(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(t);const r={},n=Object.keys(e).sort();for(const o of n)r[o]=t(e[o]);return r}const r=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function n(e){if(!e||"object"!=typeof e)return!1;if(!(e.error||e.unavailable||e.disabled))return!1;const t=Object.keys(e),r=new Set(["error","unavailable","disabled","id","timestamp"]);return 0===t.filter(e=>!r.has(e)).length}const o=new Set(["canvas","webgl","audio","fonts"]),a={unavailable:!0};function i(t,r){switch(t){case"canvas":return function(t){if(!t||"object"!=typeof t)return t;const r={...t};if(delete r.error,delete r.unavailable,delete r.disabled,delete r.id,delete r.renderTime,delete r.timestamp,Array.isArray(r.samples)){const t=32,n=r.samples.map(e=>Number.isFinite(e)?Math.round(e/t):0);r.canvasHash=e(n.join(",")),delete r.samples,delete r.hash}r.basic&&"string"==typeof r.basic&&(r.basic=s(r.basic));r.advanced&&"string"==typeof r.advanced&&(r.advanced=s(r.advanced));r.textMetrics&&"object"==typeof r.textMetrics&&(r.textMetrics=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(100*t[e])/100)}),t}(r.textMetrics));return r}(r);case"webgl":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,t.vendor&&(t.vendor=c(t.vendor));t.renderer&&(t.renderer=c(t.renderer));t.unmaskedVendor&&(t.unmaskedVendor=c(t.unmaskedVendor));t.unmaskedRenderer&&(t.unmaskedRenderer=c(t.unmaskedRenderer));t.parameters&&"object"==typeof t.parameters&&(t.parameters=function(e){if(!e||"object"!=typeof e)return e;const t={};return["MAX_TEXTURE_SIZE","MAX_VERTEX_ATTRIBS","MAX_FRAGMENT_UNIFORM_VECTORS","MAX_VARYING_VECTORS","MAX_VERTEX_UNIFORM_VECTORS","SHADING_LANGUAGE_VERSION","VERSION","VENDOR","RENDERER"].forEach(r=>{void 0!==e[r]&&(t[r]=e[r])}),t}(t.parameters));for(const e of["renderTests","renderVariance","renderHash","precisionTest","geometryCount","shadingLanguageVersion","maxTextureSize","maxViewportDims","maxVertexAttribs","extensions","contextCreationTime","shaderCompileTime"])delete t[e];return t}(r);case"audio":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};if(delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.baseLatency,delete t.contextState,delete t.audioFingerprint,t.context&&"object"==typeof t.context){const e={...t.context};delete e.currentTime,delete e.baseLatency,delete e.outputLatency,t.context=e}t.frequencyData&&Array.isArray(t.frequencyData)&&(t.frequencyData=function(e){return Array.isArray(e)?e.map(e=>5*Math.round(e/5)):e}(t.frequencyData));t.dynamicsCompressor&&"object"==typeof t.dynamicsCompressor&&(t.dynamicsCompressor=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(1e3*t[e])/1e3)}),t}(t.dynamicsCompressor));return t}(r);case"fonts":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,delete t.id,Array.isArray(t.detected)&&(t.detected=[...new Set(t.detected)].sort(),t.count=t.detected.length,delete t.hash);t.measurements&&"object"==typeof t.measurements&&(t.measurements=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&(t[e]=Math.round(10*t[e])/10)}),t}(t.measurements));t.available&&Array.isArray(t.available)&&(t.available=[...new Set(t.available)].sort());t.systemFonts&&Array.isArray(t.systemFonts)&&(t.systemFonts=[...new Set(t.systemFonts)].sort());return delete t.detectionTime,delete t.loadingTime,t}(r);case"webAssembly":case"webassembly":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.id,delete t.cpuTimings,delete t.advancedCPUTimings,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.compilationFingerprint,delete t.executionContextFingerprint,delete t.memoryPatternHash,delete t.advancedDistinction,delete t.browserSpecificBehaviors;const r={wasmSupported:t.wasmSupported||!1,memoryGrowSupported:t.memoryGrowSupported||!1};if(t.apiImplementationSignature&&"string"==typeof t.apiImplementationSignature){const e=(n=t.apiImplementationSignature)&&"string"==typeof n?n.replace(/v\d+\.\d+\.\d+/g,"VERSION").replace(/\d{13,}/g,"TIMESTAMP"):n;e.includes("0.")||e.includes("1.")||e.includes("2.")||(r.apiImplementationSignature=e)}var n;return r}(r);case"hardware":case"basic":return function(e){if(!e||"object"!=typeof e)return e;const t={...e};delete t.error,delete t.unavailable,delete t.disabled,"string"==typeof t.userAgent&&(t.userAgent=function(e){var t;if(!e)return"";let r="unknown",n="";const o=[["edge",/Edg(?:e|A|iOS)?\/(\d+)/],["opera",/OPR\/(\d+)/],["samsung",/SamsungBrowser\/(\d+)/],["firefox",/Firefox\/(\d+)/],["chrome",/Chrome\/(\d+)/],["safari",/Version\/(\d+)[.\d]*\s+.*Safari/]];for(const[a,i]of o){const o=e.match(i);if(o){r=a,n=null!==(t=o[1])&&void 0!==t?t:"";break}}let a="unknown";/Windows NT/.test(e)?a="windows":/CrOS/.test(e)?a="chromeos":/(iPhone|iPad|iPod)/.test(e)?a="ios":/Android/.test(e)?a="android":/Mac OS X|Macintosh/.test(e)?a="macos":/Linux/.test(e)&&(a="linux");return`${r}/${n}|${a}`}(t.userAgent));delete t.timezoneOffset,t.screen&&"object"==typeof t.screen&&(t.screen=function(e){if(!e||"object"!=typeof e)return e;const t={...e};t.width&&t.height&&(t.aspectRatio=Math.round(t.width/t.height*100)/100);return t}(t.screen));t.memory&&"object"==typeof t.memory&&(t.memory=function(e){if(!e||"object"!=typeof e)return e;const t={...e};return Object.keys(t).forEach(e=>{"number"==typeof t[e]&&t[e]>1e6&&(t[e]=1073741824*Math.round(t[e]/1073741824))}),t}(t.memory));return delete t.performanceTiming,delete t.networkTiming,t}(r);default:return l(r)}}function s(e){try{let t=e.replace(/\d{13,}/g,"TIMESTAMP");return t=t.replace(/\d+\.\d{6,}/g,e=>parseFloat(e).toFixed(3)),t}catch(t){return e}}function c(e){if(!e||"string"!=typeof e)return e;let t=e.replace(/\b\d+\.\d+\.\d+\.\d+\b/g,"VERSION");return t=t.replace(/\b(Direct3D|OpenGL)\s+\d+\.\d+/g,"$1 API"),t}function l(e){if(!e||"object"!=typeof e)return e;const t={...e};return delete t.error,delete t.unavailable,delete t.disabled,delete t.id,delete t.timestamp,delete t.renderTime,delete t.detectionTime,delete t.loadingTime,delete t.currentTime,delete t.baseLatency,delete t.outputLatency,delete t.contextCreationTime,delete t.shaderCompileTime,delete t.memoryAllocationTime,delete t.compilationTime,delete t.executionTime,delete t.performanceTiming,delete t.networkTiming,Object.keys(t).forEach(e=>{const r=t[e];"string"==typeof r&&/^\w+_\d{13,}_\w+$/.test(r)&&delete t[e]}),Object.keys(t).forEach(e=>{t[e]&&"object"==typeof t[e]&&!Array.isArray(t[e])&&(t[e]=l(t[e]))}),t}const u=["Arial","Arial Black","Arial Narrow","Arial Unicode MS","Calibri","Cambria","Century Gothic","Comic Sans MS","Consolas","Courier","Courier New","Georgia","Helvetica","Impact","Lucida Console","Lucida Grande","Palatino","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana","Monaco","Menlo"];async function d(){const t={};try{t.basic={userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,cookieEnabled:navigator.cookieEnabled,screen:{width:screen.width,height:screen.height,colorDepth:screen.colorDepth},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset()}}catch(e){}try{t.hardware={concurrency:navigator.hardwareConcurrency||0,maxTouchPoints:navigator.maxTouchPoints||0,deviceMemory:navigator.deviceMemory}}catch(e){}try{t.canvas=await async function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=256,t.height=256,r.fillStyle="#f60",r.fillRect(0,0,256,256);const n=r.createLinearGradient(0,0,256,256);n.addColorStop(0,"#ff6b6b"),n.addColorStop(.5,"#4ecdc4"),n.addColorStop(1,"#1a1a2e"),r.fillStyle=n,r.fillRect(0,0,128,128);const o=r.createRadialGradient(192,64,10,192,64,60);o.addColorStop(0,"#e74c3c"),o.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=o,r.fillRect(128,0,128,128),r.fillStyle="#069",r.font="14px Arial",r.fillText("TraceTail",4,150),r.font="italic 12px Georgia",r.fillText("Canvas FP",4,170),r.font="20px serif",r.fillText("😀🌍🚀❤️",4,200),r.beginPath(),r.moveTo(130,140),r.bezierCurveTo(150,200,200,160,240,210),r.strokeStyle="#9b59b6",r.lineWidth=2,r.stroke(),r.beginPath(),r.arc(200,200,30,0,2*Math.PI),r.fillStyle="rgba(52,152,219,0.6)",r.fill(),r.shadowColor="rgba(0,0,0,0.5)",r.shadowBlur=6,r.shadowOffsetX=3,r.shadowOffsetY=3,r.fillStyle="#2ecc71",r.fillRect(60,200,50,40),r.shadowColor="transparent",r.globalCompositeOperation="multiply",r.fillStyle="#e67e22",r.fillRect(80,180,60,60),r.globalCompositeOperation="screen",r.fillStyle="#3498db",r.fillRect(100,190,60,60),r.globalCompositeOperation="source-over",r.font="11px Arial",r.fillStyle="#000",r.fillText("Subpx",10.5,245.5);const a=[r.getImageData(0,0,32,32),r.getImageData(128,0,32,32),r.getImageData(0,128,32,32),r.getImageData(180,180,32,32)].map(e=>Array.from(e.data.slice(0,64)).reduce((e,t)=>e+t,0));return{hash:e(a.join(",")),samples:a}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.canvas={error:"collection failed"}}try{t.webgl=function(){try{const e=document.createElement("canvas"),t=e.getContext("webgl")||e.getContext("experimental-webgl");if(!t)return{unavailable:!0};const r=t.getExtension("WEBGL_debug_renderer_info"),n=r?t.getParameter(r.UNMASKED_VENDOR_WEBGL):t.getParameter(t.VENDOR),o=r?t.getParameter(r.UNMASKED_RENDERER_WEBGL):t.getParameter(t.RENDERER);return{vendor:t.getParameter(t.VENDOR),renderer:t.getParameter(t.RENDERER),version:t.getParameter(t.VERSION),unmaskedVendor:n,unmaskedRenderer:o}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.webgl={error:"collection failed"}}try{t.fonts=function(){try{const t=document.createElement("canvas"),r=t.getContext("2d");if(!r)return{unavailable:!0};t.width=200,t.height=50;const n=[],o=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const a=o.map(e=>r.measureText(e).width);for(const e of u){r.font=`14px "${e}", monospace`;const t=o.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=a[t])&&void 0!==r?r:0))>.1})&&n.push(e)}return{detected:n,count:n.length,hash:e(n.join(","))}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.fonts={error:"collection failed"}}try{t.audio=function(){try{const e=window.AudioContext||window.webkitAudioContext;if(!e)return{unavailable:!0};const t=new e,r={sampleRate:t.sampleRate,maxChannelCount:t.destination.maxChannelCount,baseLatency:t.baseLatency};return t.close(),r}catch(e){return{error:e instanceof Error?e.message:String(e)}}}()}catch(e){t.audio={error:"collection failed"}}return t}async function f(e,s){const c=function(e){const t={};for(const[s,c]of Object.entries(e))if(!r.has(s))if(c&&"object"==typeof c){const e=c;if(n(e)){o.has(s)&&(t[s]=a);continue}const r=i(s,e);if(r&&"object"==typeof r){const e=Object.keys(r);if(n(r)||0===e.length){o.has(s)&&(t[s]=a);continue}t[s]=r}else o.has(s)&&(t[s]=a)}else null!=c&&(t[s]=c);return t}(e),l=t(c),u=JSON.stringify(l);return(s?"free_fp2_":"fp2_")+(await async function(e){if(!e.length)return"0000000000000000";const t=(new TextEncoder).encode(e),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("").substring(0,32)}(u)).substring(0,16)}const p=new Set(["Europe/Vienna","Europe/Brussels","Europe/Sofia","Europe/Zagreb","Asia/Nicosia","Asia/Famagusta","Europe/Prague","Europe/Copenhagen","Europe/Tallinn","Europe/Helsinki","Europe/Paris","Europe/Berlin","Europe/Busingen","Europe/Athens","Europe/Budapest","Europe/Dublin","Europe/Rome","Europe/Riga","Europe/Vilnius","Europe/Luxembourg","Europe/Malta","Europe/Amsterdam","Europe/Warsaw","Europe/Lisbon","Atlantic/Azores","Atlantic/Madeira","Europe/Bucharest","Europe/Bratislava","Europe/Ljubljana","Europe/Madrid","Africa/Ceuta","Atlantic/Canary","Europe/Stockholm"]),m=new Set(["Atlantic/Reykjavik","Europe/Vaduz","Europe/Oslo","Arctic/Longyearbyen"]),g=new Set(["Europe/London","Europe/Belfast","Europe/Guernsey","Europe/Jersey","Europe/Isle_of_Man"]),h=["America/","US/","Pacific/Honolulu"];function y(){try{return"undefined"!=typeof navigator?navigator:void 0}catch(e){return}}function b(){try{return"undefined"!=typeof window?window:void 0}catch(e){return}}function v(e,t){if(e){if(g.has(e))return"UK";if(p.has(e))return"EU";if(m.has(e))return"EEA";if(function(e){return h.some(t=>t.endsWith("/")?e.startsWith(t):e===t)}(e))return"US"}const r=t.toLowerCase().split("-")[1];if("gb"===r||"uk"===r)return"UK";if("us"===r)return"US";const n=new Set(["at","be","bg","hr","cy","cz","dk","ee","fi","fr","de","gr","hu","ie","it","lv","lt","lu","mt","nl","pl","pt","ro","sk","si","es","se"]);if(r&&n.has(r))return"EU";const o=new Set(["is","li","no"]);return r&&o.has(r)?"EEA":"OTHER"}function E(){const e=function(){try{const e=y();if(e&&!0===e.globalPrivacyControl)return!0;const t=b();return!0===(null==t?void 0:t.globalPrivacyControl)}catch(e){return!1}}(),t=function(){try{const e=y(),t=b();return[null==e?void 0:e.doNotTrack,null==e?void 0:e.msDoNotTrack,null==t?void 0:t.doNotTrack].some(e=>"1"===e||"yes"===e)}catch(e){return!1}}(),r=function(){try{if("undefined"==typeof Intl||"function"!=typeof Intl.DateTimeFormat)return"";const e=Intl.DateTimeFormat().resolvedOptions().timeZone;return"string"==typeof e?e:""}catch(e){return""}}(),n=function(){try{const e=y(),t=(null==e?void 0:e.language)||(Array.isArray(null==e?void 0:e.languages)?null==e?void 0:e.languages[0]:void 0);return"string"==typeof t?t:""}catch(e){return""}}(),o=v(r,n),a="UK"===o,i="EU"===o||"EEA"===o;return{gpcEnabled:e,doNotTrack:t,timezone:r,locale:n,region:o,isEU:"EU"===o,isEEA:i,isUK:a,likelyRequiresConsent:i||a||e||t}}class w{constructor(e={}){this.cache=new Map,this.isFree=!e.apiKey,this.options={apiKey:e.apiKey||"",endpoint:e.endpoint||"/api",timeout:e.timeout||1e4,debug:e.debug||!1,caching:!1!==e.caching,respectDNT:e.respectDNT||!1,includeIP:!1!==e.includeIP,storeFingerprints:!1!==e.storeFingerprints,enableWorkers:!1!==e.enableWorkers,batchRequests:!1!==e.batchRequests,fallbackMode:e.fallbackMode||"basic"},this.log("TraceTail SDK initialized",{version:"2.3.7",options:this.options})}async generateFingerprint(e){const t=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const r=!0===(null==e?void 0:e.verbose),n=r?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(n)){const e=this.cache.get(n);if(e)return this.log("Using cached fingerprint",e),e}const o=await d(),a=Math.round(performance.now()-t),i=await f(o,this.isFree);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(o,i,r),processingTime:Math.round(performance.now()-t)};return this.options.caching&&this.cache.set(n,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const s={visitorId:i,confidence:await this.calculateConfidenceAsync(o),processingTime:a,...r&&{components:o}};return this.options.caching&&this.cache.set(n,s),this.log("Client-side fingerprint generated",s),s}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t,r){const n=new AbortController,o=setTimeout(()=>n.abort(),this.options.timeout);try{const a=await fetch(`${this.options.endpoint}/id`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`,"X-TraceTail-SDK":"js/2.3.7"},body:JSON.stringify({visitorId:t,components:e,verbose:r||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:n.signal});if(clearTimeout(o),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const i=await a.json(),s={visitorId:i.visitorId,confidence:i.confidence,processingTime:i.processingTime||0};if(r){if(!i.components)throw new Error("Server did not return components in verbose mode");s.components=i.components}return s}catch(e){throw clearTimeout(o),this.options.debug&&console.error("[TraceTail] Server error:",e),e}}static getVersion(){return"2.3.7"}static getComplianceContext(){return E()}getComplianceContext(){return E()}static validateApiKey(e){return/^tt_(test|prod)_[a-zA-Z0-9]{32,}$/.test(e)}async calculateConfidenceAsync(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));o.length>=5?r+=.05:o.length>=3&&(r+=.02);try{const e=await async function(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){((await navigator.storage.estimate()).quota||0)/1073741824<.5&&(t+=.4,e.push("low_storage_quota"))}}catch(r){t+=.15,e.push("storage_api_error")}try{!window.webkitRequestFileSystem&&/Chrome/.test(navigator.userAgent)&&(t+=.2,e.push("no_filesystem_api"))}catch(r){t+=.1,e.push("filesystem_check_error")}try{/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&(navigator.serviceWorker||(t+=.3,e.push("no_service_worker_safari")))}catch(e){}try{navigator.brave&&(t+=.15,e.push("brave_browser"))}catch(e){}try{/Firefox/.test(navigator.userAgent)&&screen.width%200==0&&screen.height%100==0&&(t+=.2,e.push("firefox_rfp_screen"))}catch(e){}return{isPrivate:t>=.35,score:Math.min(1,t),signals:e}}();e.isPrivate&&(r-=.08,r-=.02*e.signals.length)}catch(e){r-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}calculateConfidence(e){const t={canvas:.15,webgl:.12,fonts:.1,audio:.08,basic:.05};let r=.5;const n=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[o,a]of Object.entries(t))n(e[o])&&(r+=a);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);r+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>n(e[t]));return o.length>=5?r+=.05:o.length>=3&&(r+=.02),Math.min(.99,Math.max(.4,Math.round(1e3*r)/1e3))}isDNTEnabled(){return"1"===navigator.doNotTrack||"1"===window.doNotTrack||"1"===navigator.msDoNotTrack}log(e,t){this.options.debug&&console.log(`[TraceTail] ${e}`,t)}}export{w as TraceTail,w as default,E as getComplianceContext};
|