@tracetail/js 2.3.13 → 2.3.14
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/core.d.ts +29 -8
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/core.d.ts
CHANGED
|
@@ -31,12 +31,29 @@ export declare function sortObjectKeysRecursively(obj: unknown): unknown;
|
|
|
31
31
|
export declare const UNSTABLE_IN_PRIVACY_KEYS: Set<string>;
|
|
32
32
|
/**
|
|
33
33
|
* Extract stable components for hashing.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
*
|
|
35
|
+
* BYTE-FOR-BYTE identical to extractStableComponents() in the script-tag SDK
|
|
36
|
+
* (client/src/sdk/tracetail.ts). It applies the SAME per-signal normalization
|
|
37
|
+
* pipeline (optimizeComponentStability) so the npm package and the CDN SDK hash
|
|
38
|
+
* the exact same canonical JSON and therefore produce identical visitor IDs.
|
|
39
|
+
*
|
|
40
|
+
* The `_privacyMode` parameter is retained for API compatibility but is NOT used
|
|
41
|
+
* to alter the hash — the CDN SDK has no privacy-mode branch in its hashed set,
|
|
42
|
+
* so neither do we (consistency over optionality).
|
|
43
|
+
*/
|
|
44
|
+
export declare function extractStableComponents(components: Record<string, unknown>, _privacyMode?: boolean): Record<string, unknown>;
|
|
45
|
+
export declare function optimizeCanvasStability(data: any): any;
|
|
46
|
+
export declare function optimizeWebGLStability(data: any): any;
|
|
47
|
+
export declare function optimizeAudioStability(data: any): any;
|
|
48
|
+
export declare function optimizeFontStability(data: any): any;
|
|
49
|
+
/**
|
|
50
|
+
* Reduce a User-Agent string to its stable parts: browser family + major
|
|
51
|
+
* version + OS family. Identical to normalizeUserAgent() in the script-tag SDK.
|
|
36
52
|
*/
|
|
37
|
-
export declare function
|
|
53
|
+
export declare function normalizeUserAgent(ua: string): string;
|
|
38
54
|
export interface CoreComponents {
|
|
39
55
|
basic?: Record<string, unknown>;
|
|
56
|
+
hardware?: Record<string, unknown>;
|
|
40
57
|
canvas?: Record<string, unknown>;
|
|
41
58
|
webgl?: Record<string, unknown>;
|
|
42
59
|
fonts?: Record<string, unknown>;
|
|
@@ -50,11 +67,15 @@ export interface CoreComponents {
|
|
|
50
67
|
export declare function collectCoreComponents(): Promise<CoreComponents>;
|
|
51
68
|
/**
|
|
52
69
|
* Generate a visitor ID from collected components.
|
|
53
|
-
* Uses the same extraction → sort → hash → prefix pipeline as the script-tag SDK.
|
|
54
70
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
71
|
+
* IDENTICAL ID-assembly to generateVisitorId() in the script-tag SDK
|
|
72
|
+
* (client/src/sdk/tracetail.ts):
|
|
73
|
+
*
|
|
74
|
+
* prefix + SHA256( JSON.stringify( sortKeys( extractStableComponents(components) ) ) ).substring(0, 16)
|
|
75
|
+
*
|
|
76
|
+
* There is NO privacy-mode branch and NO "blended" two-hash assembly — those
|
|
77
|
+
* diverged from the CDN SDK and broke cross-SDK parity. The only difference
|
|
78
|
+
* between free and keyed is the prefix (`free_fp2_` vs `fp2_`), exactly as the
|
|
79
|
+
* CDN SDK switches on `globalOptions.freeVersion`.
|
|
59
80
|
*/
|
|
60
81
|
export declare function generateCoreVisitorId(components: Record<string, unknown>, isFree: boolean): Promise<string>;
|
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 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;
|
|
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;
|
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 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};
|
|
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};
|