@tracetail/js 2.3.12 → 2.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { type CoreComponents } from './core';
|
|
9
9
|
export interface FingerprintOptions {
|
|
10
|
-
|
|
10
|
+
/** API key for server-enhanced, keyed fingerprints. Omit to run in keyless free mode
|
|
11
|
+
* (client-only, `free_fp2_`-prefixed IDs) — matching the CDN script-tag SDK. */
|
|
12
|
+
apiKey?: string;
|
|
11
13
|
endpoint?: string;
|
|
12
14
|
timeout?: number;
|
|
13
15
|
debug?: boolean;
|
|
@@ -41,7 +43,9 @@ export { CoreComponents as ComponentData };
|
|
|
41
43
|
export declare class TraceTail {
|
|
42
44
|
private options;
|
|
43
45
|
private cache;
|
|
44
|
-
|
|
46
|
+
/** True when constructed without an API key — client-only, free_fp2_-prefixed IDs. */
|
|
47
|
+
private readonly isFree;
|
|
48
|
+
constructor(options?: FingerprintOptions);
|
|
45
49
|
/**
|
|
46
50
|
* Generate a browser fingerprint with optional server-side processing
|
|
47
51
|
*/
|
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)}async function t(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)}async function r(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){const r=await navigator.storage.estimate();(r.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}}function n(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(n);const t={},r=Object.keys(e).sort();for(const a of r)t[a]=n(e[a]);return t}Object.defineProperty(exports,"__esModule",{value:!0});const a=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function o(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 i=new Set(["canvas","webgl"]),s=new Set(["canvas","webgl","audio","fonts"]),c={unavailable:!0};function l(e,t=!1){const r={};for(const[n,l]of Object.entries(e))if(!(a.has(n)||t&&i.has(n)))if(l&&"object"==typeof l&&!Array.isArray(l)){const e=l;if(o(e)||0===Object.keys(e).length){s.has(n)&&(r[n]=c);continue}r[n]=l}else null!=l?r[n]=l:s.has(n)&&(r[n]=c);return r}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 f(){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,pixelRatio:window.devicePixelRatio||1},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset(),hardwareConcurrency:navigator.hardwareConcurrency,maxTouchPoints:navigator.maxTouchPoints,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 a=r.createRadialGradient(192,64,10,192,64,60);a.addColorStop(0,"#e74c3c"),a.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=a,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 o=[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(o.join(",")),samples:o}}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),a=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:a}}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=[],a=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const o=a.map(e=>r.measureText(e).width);for(const e of u){r.font=`14px "${e}", monospace`;const t=a.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=o[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}class h{constructor(e){if(this.cache=new Map,!e.apiKey)throw new Error("TraceTail: API key is required. Get yours at https://tracetail.io");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 a=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const o=!0===(null==e?void 0:e.verbose),i=o?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(i)){const e=this.cache.get(i);if(e)return this.log("Using cached fingerprint",e),e}const s=await f(),c=Math.round(performance.now()-a);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(s,o),processingTime:Math.round(performance.now()-a)};return this.options.caching&&this.cache.set(i,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const u=await async function(e){const a=await r(),o=n(l(e,!0)),i=JSON.stringify(o),s=await t(i);if(a.isPrivate)return"fp2_"+s.substring(0,16);const c=n(l(e,!1)),u=JSON.stringify(c),f=await t(u);return"fp2_"+(s.substring(0,12)+f.substring(0,4))}(s),h={visitorId:u,confidence:await this.calculateConfidenceAsync(s),processingTime:c,...o&&{components:s}};return this.options.caching&&this.cache.set(i,h),this.log("Client-side fingerprint generated",h),h}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t){const r=new AbortController,n=setTimeout(()=>r.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({components:e,verbose:t||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:r.signal});if(clearTimeout(n),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const o=await a.json(),i={visitorId:o.visitorId,confidence:o.confidence,processingTime:o.processingTime||0};if(t){if(!o.components)throw new Error("Server did not return components in verbose mode");i.components=o.components}return i}catch(e){throw clearTimeout(n),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 n=.5;const a=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[r,o]of Object.entries(t))a(e[r])&&(n+=o);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);n+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>a(e[t]));o.length>=5?n+=.05:o.length>=3&&(n+=.02);try{const e=await r();e.isPrivate&&(n-=.08,n-=.02*e.signals.length)}catch(e){n-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*n)/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[a,o]of Object.entries(t))n(e[a])&&(r+=o);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 a=Object.keys(e).filter(t=>n(e[t]));return a.length>=5?r+=.05:a.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=h,exports.default=h;
|
|
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)}async function t(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)}async function r(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){const r=await navigator.storage.estimate();(r.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}}function n(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(n);const t={},r=Object.keys(e).sort();for(const a of r)t[a]=n(e[a]);return t}Object.defineProperty(exports,"__esModule",{value:!0});const a=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function o(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 i=new Set(["canvas","webgl"]),s=new Set(["canvas","webgl","audio","fonts"]),c={unavailable:!0};function l(e,t=!1){const r={};for(const[n,l]of Object.entries(e))if(!(a.has(n)||t&&i.has(n)))if(l&&"object"==typeof l&&!Array.isArray(l)){const e=l;if(o(e)||0===Object.keys(e).length){s.has(n)&&(r[n]=c);continue}r[n]=l}else null!=l?r[n]=l:s.has(n)&&(r[n]=c);return r}const f=["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,pixelRatio:window.devicePixelRatio||1},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset(),hardwareConcurrency:navigator.hardwareConcurrency,maxTouchPoints:navigator.maxTouchPoints,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 a=r.createRadialGradient(192,64,10,192,64,60);a.addColorStop(0,"#e74c3c"),a.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=a,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 o=[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(o.join(",")),samples:o}}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),a=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:a}}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=[],a=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const o=a.map(e=>r.measureText(e).width);for(const e of f){r.font=`14px "${e}", monospace`;const t=a.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=o[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}class h{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 a=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const o=!0===(null==e?void 0:e.verbose),i=o?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(i)){const e=this.cache.get(i);if(e)return this.log("Using cached fingerprint",e),e}const s=await u(),c=Math.round(performance.now()-a);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(s,o),processingTime:Math.round(performance.now()-a)};return this.options.caching&&this.cache.set(i,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const f=await async function(e,a){const o=await r(),i=n(l(e,!0)),s=JSON.stringify(i),c=await t(s);if(o.isPrivate)return(a?"free_fp2_":"fp2_")+c.substring(0,16);const f=n(l(e,!1)),u=JSON.stringify(f),h=await t(u);return(a?"free_fp2_":"fp2_")+(c.substring(0,12)+h.substring(0,4))}(s,this.isFree),h={visitorId:f,confidence:await this.calculateConfidenceAsync(s),processingTime:c,...o&&{components:s}};return this.options.caching&&this.cache.set(i,h),this.log("Client-side fingerprint generated",h),h}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t){const r=new AbortController,n=setTimeout(()=>r.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({components:e,verbose:t||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:r.signal});if(clearTimeout(n),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const o=await a.json(),i={visitorId:o.visitorId,confidence:o.confidence,processingTime:o.processingTime||0};if(t){if(!o.components)throw new Error("Server did not return components in verbose mode");i.components=o.components}return i}catch(e){throw clearTimeout(n),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 n=.5;const a=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[r,o]of Object.entries(t))a(e[r])&&(n+=o);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);n+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>a(e[t]));o.length>=5?n+=.05:o.length>=3&&(n+=.02);try{const e=await r();e.isPrivate&&(n-=.08,n-=.02*e.signals.length)}catch(e){n-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*n)/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[a,o]of Object.entries(t))n(e[a])&&(r+=o);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 a=Object.keys(e).filter(t=>n(e[t]));return a.length>=5?r+=.05:a.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=h,exports.default=h;
|
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)}async function t(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)}async function r(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){const r=await navigator.storage.estimate();(r.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}}function n(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(n);const t={},r=Object.keys(e).sort();for(const a of r)t[a]=n(e[a]);return t}const a=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function o(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 i=new Set(["canvas","webgl"]),s=new Set(["canvas","webgl","audio","fonts"]),c={unavailable:!0};function l(e,t=!1){const r={};for(const[n,l]of Object.entries(e))if(!(a.has(n)||t&&i.has(n)))if(l&&"object"==typeof l&&!Array.isArray(l)){const e=l;if(o(e)||0===Object.keys(e).length){s.has(n)&&(r[n]=c);continue}r[n]=l}else null!=l?r[n]=l:s.has(n)&&(r[n]=c);return r}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 f(){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,pixelRatio:window.devicePixelRatio||1},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset(),hardwareConcurrency:navigator.hardwareConcurrency,maxTouchPoints:navigator.maxTouchPoints,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 a=r.createRadialGradient(192,64,10,192,64,60);a.addColorStop(0,"#e74c3c"),a.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=a,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 o=[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(o.join(",")),samples:o}}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),a=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:a}}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=[],a=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const o=a.map(e=>r.measureText(e).width);for(const e of u){r.font=`14px "${e}", monospace`;const t=a.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=o[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}class h{constructor(e){if(this.cache=new Map,!e.apiKey)throw new Error("TraceTail: API key is required. Get yours at https://tracetail.io");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 a=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const o=!0===(null==e?void 0:e.verbose),i=o?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(i)){const e=this.cache.get(i);if(e)return this.log("Using cached fingerprint",e),e}const s=await f(),c=Math.round(performance.now()-a);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(s,o),processingTime:Math.round(performance.now()-a)};return this.options.caching&&this.cache.set(i,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const u=await async function(e){const a=await r(),o=n(l(e,!0)),i=JSON.stringify(o),s=await t(i);if(a.isPrivate)return"fp2_"+s.substring(0,16);const c=n(l(e,!1)),u=JSON.stringify(c),f=await t(u);return"fp2_"+(s.substring(0,12)+f.substring(0,4))}(s),h={visitorId:u,confidence:await this.calculateConfidenceAsync(s),processingTime:c,...o&&{components:s}};return this.options.caching&&this.cache.set(i,h),this.log("Client-side fingerprint generated",h),h}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t){const r=new AbortController,n=setTimeout(()=>r.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({components:e,verbose:t||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:r.signal});if(clearTimeout(n),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const o=await a.json(),i={visitorId:o.visitorId,confidence:o.confidence,processingTime:o.processingTime||0};if(t){if(!o.components)throw new Error("Server did not return components in verbose mode");i.components=o.components}return i}catch(e){throw clearTimeout(n),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 n=.5;const a=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[r,o]of Object.entries(t))a(e[r])&&(n+=o);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);n+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>a(e[t]));o.length>=5?n+=.05:o.length>=3&&(n+=.02);try{const e=await r();e.isPrivate&&(n-=.08,n-=.02*e.signals.length)}catch(e){n-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*n)/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[a,o]of Object.entries(t))n(e[a])&&(r+=o);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 a=Object.keys(e).filter(t=>n(e[t]));return a.length>=5?r+=.05:a.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{h as TraceTail,h 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)}async function t(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)}async function r(){const e=[];let t=0;try{if(navigator.storage&&navigator.storage.estimate){const r=await navigator.storage.estimate();(r.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}}function n(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(n);const t={},r=Object.keys(e).sort();for(const a of r)t[a]=n(e[a]);return t}const a=new Set(["network","processingTime","timestamp","realUserDetection","storage","battery","webrtc","performance","timing","memoryProfile","advancedAudio"]);function o(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 i=new Set(["canvas","webgl"]),s=new Set(["canvas","webgl","audio","fonts"]),c={unavailable:!0};function l(e,t=!1){const r={};for(const[n,l]of Object.entries(e))if(!(a.has(n)||t&&i.has(n)))if(l&&"object"==typeof l&&!Array.isArray(l)){const e=l;if(o(e)||0===Object.keys(e).length){s.has(n)&&(r[n]=c);continue}r[n]=l}else null!=l?r[n]=l:s.has(n)&&(r[n]=c);return r}const f=["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,pixelRatio:window.devicePixelRatio||1},timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffset:(new Date).getTimezoneOffset(),hardwareConcurrency:navigator.hardwareConcurrency,maxTouchPoints:navigator.maxTouchPoints,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 a=r.createRadialGradient(192,64,10,192,64,60);a.addColorStop(0,"#e74c3c"),a.addColorStop(1,"rgba(46,204,113,0.4)"),r.fillStyle=a,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 o=[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(o.join(",")),samples:o}}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),a=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:a}}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=[],a=["mmmmmmmmmmlli","ABCDEFGHIJKLMNOPQRSTUVWXYZ","1234567890"];r.font="14px monospace";const o=a.map(e=>r.measureText(e).width);for(const e of f){r.font=`14px "${e}", monospace`;const t=a.map(e=>r.measureText(e).width);t.some((e,t)=>{var r;return Math.abs(e-(null!==(r=o[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}class h{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 a=performance.now();try{if(this.options.respectDNT&&this.isDNTEnabled())throw new Error("TraceTail: Do Not Track is enabled");const o=!0===(null==e?void 0:e.verbose),i=o?"fingerprint_verbose":"fingerprint_basic";if(this.options.caching&&this.cache.has(i)){const e=this.cache.get(i);if(e)return this.log("Using cached fingerprint",e),e}const s=await u(),c=Math.round(performance.now()-a);if(this.options.apiKey&&this.options.endpoint)try{const e={...await this.sendToServer(s,o),processingTime:Math.round(performance.now()-a)};return this.options.caching&&this.cache.set(i,e),this.log("Server-enhanced fingerprint generated",e),e}catch(e){this.log("Server processing failed, falling back to client-side",e)}const f=await async function(e,a){const o=await r(),i=n(l(e,!0)),s=JSON.stringify(i),c=await t(s);if(o.isPrivate)return(a?"free_fp2_":"fp2_")+c.substring(0,16);const f=n(l(e,!1)),u=JSON.stringify(f),h=await t(u);return(a?"free_fp2_":"fp2_")+(c.substring(0,12)+h.substring(0,4))}(s,this.isFree),h={visitorId:f,confidence:await this.calculateConfidenceAsync(s),processingTime:c,...o&&{components:s}};return this.options.caching&&this.cache.set(i,h),this.log("Client-side fingerprint generated",h),h}catch(e){throw this.log("Fingerprint generation failed",e),e}}async sendToServer(e,t){const r=new AbortController,n=setTimeout(()=>r.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({components:e,verbose:t||!1,clientCapabilities:{timestamp:Date.now(),sdkVersion:"2.3.7"}}),signal:r.signal});if(clearTimeout(n),!a.ok){if(401===a.status)throw new Error("Invalid API key");throw new Error(`Server returned ${a.status}`)}const o=await a.json(),i={visitorId:o.visitorId,confidence:o.confidence,processingTime:o.processingTime||0};if(t){if(!o.components)throw new Error("Server did not return components in verbose mode");i.components=o.components}return i}catch(e){throw clearTimeout(n),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 n=.5;const a=e=>{if(!e)return!1;if("object"==typeof e){const t=e;return!t.error&&!t.unavailable}return!0};for(const[r,o]of Object.entries(t))a(e[r])&&(n+=o);if(e.basic&&"object"==typeof e.basic){const t=Object.keys(e.basic).filter(t=>void 0!==e.basic[t]);n+=Math.min(.1,.012*t.length)}const o=Object.keys(e).filter(t=>a(e[t]));o.length>=5?n+=.05:o.length>=3&&(n+=.02);try{const e=await r();e.isPrivate&&(n-=.08,n-=.02*e.signals.length)}catch(e){n-=.03}return Math.min(.99,Math.max(.4,Math.round(1e3*n)/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[a,o]of Object.entries(t))n(e[a])&&(r+=o);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 a=Object.keys(e).filter(t=>n(e[t]));return a.length>=5?r+=.05:a.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{h as TraceTail,h as default};
|