@zaplier/sdk 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +58 -164
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +58 -164
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +58 -164
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/fingerprint.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -5133,46 +5133,47 @@ async function collectFingerprint(options = {}) {
|
|
|
5133
5133
|
const parallelTasks = [];
|
|
5134
5134
|
// Group 1: Independent rendering components (can run in parallel)
|
|
5135
5135
|
if (shouldIncludeComponent("canvas", opts) && isCanvasAvailable$1()) {
|
|
5136
|
-
parallelTasks.push(collectComponent("canvas", getCanvasFingerprint, opts).then(result => ({
|
|
5136
|
+
parallelTasks.push(collectComponent("canvas", getCanvasFingerprint, opts).then((result) => ({
|
|
5137
5137
|
component: "canvas",
|
|
5138
|
-
result
|
|
5138
|
+
result,
|
|
5139
5139
|
})));
|
|
5140
5140
|
}
|
|
5141
5141
|
if (shouldIncludeComponent("webgl", opts) && isWebGLAvailable()) {
|
|
5142
|
-
parallelTasks.push(collectComponent("webgl", getWebGLFingerprint, opts).then(result => ({
|
|
5142
|
+
parallelTasks.push(collectComponent("webgl", getWebGLFingerprint, opts).then((result) => ({
|
|
5143
5143
|
component: "webgl",
|
|
5144
|
-
result
|
|
5144
|
+
result,
|
|
5145
5145
|
})));
|
|
5146
5146
|
}
|
|
5147
5147
|
if (shouldIncludeComponent("audio", opts) && isAudioAvailable()) {
|
|
5148
|
-
parallelTasks.push(collectComponent("audio", getAudioFingerprint, opts).then(result => ({
|
|
5148
|
+
parallelTasks.push(collectComponent("audio", getAudioFingerprint, opts).then((result) => ({
|
|
5149
5149
|
component: "audio",
|
|
5150
|
-
result
|
|
5150
|
+
result,
|
|
5151
5151
|
})));
|
|
5152
5152
|
}
|
|
5153
5153
|
// Group 2: Fast synchronous components (can run in parallel)
|
|
5154
5154
|
if (shouldIncludeComponent("fonts", opts) && isFontDetectionAvailable()) {
|
|
5155
|
-
parallelTasks.push(collectComponent("fonts", () => getFontFingerprint(!opts.gdprMode), opts).then(result => ({
|
|
5155
|
+
parallelTasks.push(collectComponent("fonts", () => getFontFingerprint(!opts.gdprMode), opts).then((result) => ({
|
|
5156
5156
|
component: "fonts",
|
|
5157
|
-
result
|
|
5157
|
+
result,
|
|
5158
5158
|
})));
|
|
5159
5159
|
}
|
|
5160
5160
|
if (shouldIncludeComponent("screen", opts) && isScreenAvailable()) {
|
|
5161
|
-
parallelTasks.push(collectComponent("screen", getScreenFingerprint, opts).then(result => ({
|
|
5161
|
+
parallelTasks.push(collectComponent("screen", getScreenFingerprint, opts).then((result) => ({
|
|
5162
5162
|
component: "screen",
|
|
5163
|
-
result
|
|
5163
|
+
result,
|
|
5164
5164
|
})));
|
|
5165
5165
|
}
|
|
5166
|
-
if (shouldIncludeComponent("browser", opts) &&
|
|
5167
|
-
|
|
5166
|
+
if (shouldIncludeComponent("browser", opts) &&
|
|
5167
|
+
isBrowserFingerprintingAvailable()) {
|
|
5168
|
+
parallelTasks.push(collectComponent("browser", getBrowserFingerprint, opts).then((result) => ({
|
|
5168
5169
|
component: "browser",
|
|
5169
|
-
result
|
|
5170
|
+
result,
|
|
5170
5171
|
})));
|
|
5171
5172
|
}
|
|
5172
5173
|
// Execute all parallel tasks and handle results
|
|
5173
5174
|
const parallelResults = await Promise.allSettled(parallelTasks);
|
|
5174
5175
|
parallelResults.forEach((promiseResult, index) => {
|
|
5175
|
-
if (promiseResult.status ===
|
|
5176
|
+
if (promiseResult.status === "fulfilled" && promiseResult.value.result) {
|
|
5176
5177
|
const { component, result } = promiseResult.value;
|
|
5177
5178
|
fingerprintData[component] = result;
|
|
5178
5179
|
collectedComponents.push(component);
|
|
@@ -5180,10 +5181,10 @@ async function collectFingerprint(options = {}) {
|
|
|
5180
5181
|
else {
|
|
5181
5182
|
// Extract component name from the corresponding task
|
|
5182
5183
|
const taskComponent = parallelTasks[index];
|
|
5183
|
-
const componentName = taskComponent?.toString().match(/component: "(\w+)"/)?.[1] ||
|
|
5184
|
+
const componentName = taskComponent?.toString().match(/component: "(\w+)"/)?.[1] || "unknown";
|
|
5184
5185
|
failedComponents.push({
|
|
5185
5186
|
component: componentName,
|
|
5186
|
-
error: promiseResult.status ===
|
|
5187
|
+
error: promiseResult.status === "rejected"
|
|
5187
5188
|
? promiseResult.reason?.message || "Promise rejected"
|
|
5188
5189
|
: "Collection failed or timeout",
|
|
5189
5190
|
});
|
|
@@ -5231,7 +5232,7 @@ async function collectFingerprint(options = {}) {
|
|
|
5231
5232
|
const fallbackHardware = {
|
|
5232
5233
|
hardwareConcurrency: navigator.hardwareConcurrency || 0,
|
|
5233
5234
|
deviceMemory: navigator.deviceMemory || 0,
|
|
5234
|
-
platform: navigator.platform ||
|
|
5235
|
+
platform: navigator.platform || "unknown",
|
|
5235
5236
|
};
|
|
5236
5237
|
fingerprintData.hardware = {
|
|
5237
5238
|
value: fallbackHardware,
|
|
@@ -5698,146 +5699,31 @@ async function collectFingerprint(options = {}) {
|
|
|
5698
5699
|
platform: (browser?.platform || "unknown").toLowerCase(),
|
|
5699
5700
|
// PRIORITY 5: Device type (critical for differentiation, ultra-stable)
|
|
5700
5701
|
deviceType,
|
|
5701
|
-
// PRIORITY 6:
|
|
5702
|
-
//
|
|
5703
|
-
//
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
return "qhd"; // QHD/WQHD
|
|
5727
|
-
// Standard high-resolution displays
|
|
5728
|
-
if (width >= 2048)
|
|
5729
|
-
return "qxga"; // QXGA
|
|
5730
|
-
if (width >= 1920)
|
|
5731
|
-
return "fhd"; // Full HD 1080p
|
|
5732
|
-
if (width >= 1680)
|
|
5733
|
-
return "wsxga+"; // WSXGA+
|
|
5734
|
-
if (width >= 1600)
|
|
5735
|
-
return "uxga"; // UXGA
|
|
5736
|
-
if (width >= 1440)
|
|
5737
|
-
return "wxga++"; // WXGA++
|
|
5738
|
-
if (width >= 1366)
|
|
5739
|
-
return "hd"; // HD 720p
|
|
5740
|
-
if (width >= 1280)
|
|
5741
|
-
return "sxga"; // SXGA
|
|
5742
|
-
// Tablet and mobile displays
|
|
5743
|
-
if (width >= 1024)
|
|
5744
|
-
return "xga"; // XGA (tablets)
|
|
5745
|
-
if (width >= 768)
|
|
5746
|
-
return "svga"; // SVGA (small tablets)
|
|
5747
|
-
if (width >= 640)
|
|
5748
|
-
return "vga"; // VGA (phones)
|
|
5749
|
-
if (width >= 480)
|
|
5750
|
-
return "hvga"; // HVGA (older phones)
|
|
5751
|
-
if (width >= 320)
|
|
5752
|
-
return "qvga"; // QVGA (legacy phones)
|
|
5753
|
-
return "minimal"; // Sub-QVGA
|
|
5754
|
-
};
|
|
5755
|
-
// Enhanced aspect ratio classification for device type hints
|
|
5756
|
-
const getAspectRatioClass = (width, height) => {
|
|
5757
|
-
if (height === 0)
|
|
5758
|
-
return "unknown";
|
|
5759
|
-
const ratio = width / height;
|
|
5760
|
-
// Ultra-wide displays (gaming, productivity)
|
|
5761
|
-
if (ratio >= 3.0)
|
|
5762
|
-
return "super_ultrawide"; // 32:9+
|
|
5763
|
-
if (ratio >= 2.3)
|
|
5764
|
-
return "ultrawide"; // 21:9
|
|
5765
|
-
if (ratio >= 2.0)
|
|
5766
|
-
return "wide"; // 18:9
|
|
5767
|
-
// Standard desktop ratios
|
|
5768
|
-
if (ratio >= 1.7 && ratio <= 1.8)
|
|
5769
|
-
return "standard"; // 16:9
|
|
5770
|
-
if (ratio >= 1.6 && ratio <= 1.67)
|
|
5771
|
-
return "classic"; // 16:10, 5:3
|
|
5772
|
-
if (ratio >= 1.3 && ratio <= 1.35)
|
|
5773
|
-
return "traditional"; // 4:3
|
|
5774
|
-
// Mobile/portrait ratios
|
|
5775
|
-
if (ratio >= 0.5 && ratio <= 0.8)
|
|
5776
|
-
return "mobile_portrait"; // Phones in portrait
|
|
5777
|
-
if (ratio >= 0.4 && ratio <= 0.5)
|
|
5778
|
-
return "tall_mobile"; // Modern tall phones
|
|
5779
|
-
return "custom"; // Non-standard ratio
|
|
5780
|
-
};
|
|
5781
|
-
// Ensure w and h are valid numbers
|
|
5782
|
-
const width = w || 0;
|
|
5783
|
-
const height = h || 0;
|
|
5784
|
-
// Screen density class based on common DPR patterns
|
|
5785
|
-
const getDensityClass = (pixelRatio) => {
|
|
5786
|
-
if (!pixelRatio)
|
|
5787
|
-
return "standard";
|
|
5788
|
-
if (pixelRatio >= 3.0)
|
|
5789
|
-
return "ultra_high"; // iPhone Plus, high-end Android
|
|
5790
|
-
if (pixelRatio >= 2.0)
|
|
5791
|
-
return "high"; // Retina, standard high-DPI
|
|
5792
|
-
if (pixelRatio >= 1.5)
|
|
5793
|
-
return "medium"; // Mid-range displays
|
|
5794
|
-
if (pixelRatio >= 1.25)
|
|
5795
|
-
return "enhanced"; // Slightly enhanced DPI
|
|
5796
|
-
return "standard"; // Standard 1x displays
|
|
5797
|
-
};
|
|
5798
|
-
// CRITICAL: Do NOT include exact dimensions in stableCoreVector for mobile!
|
|
5799
|
-
// Reason: Screen dimensions change when:
|
|
5800
|
-
// - Chrome address bar appears/disappears (scroll behavior)
|
|
5801
|
-
// - Virtual keyboard opens/closes
|
|
5802
|
-
// - Screen rotates (portrait ↔ landscape)
|
|
5803
|
-
// - Browser zoom changes
|
|
5804
|
-
// These changes would cause stableCoreHash to change, breaking visitor identification
|
|
5805
|
-
//
|
|
5806
|
-
// INSTEAD: Use ONLY stable screen characteristics (bucket, aspect, density)
|
|
5807
|
-
// For device differentiation (S22 vs A54), use:
|
|
5808
|
-
// - screenFrame (bezel measurements)
|
|
5809
|
-
// - Combination of bucket + hardware + display
|
|
5810
|
-
// - Vector similarity in IdentityResolver
|
|
5811
|
-
return {
|
|
5812
|
-
bucket: getScreenBucket(width),
|
|
5813
|
-
aspectClass: getAspectRatioClass(width, height),
|
|
5814
|
-
densityClass: getDensityClass(screen.pixelRatio || window.devicePixelRatio),
|
|
5815
|
-
// Simplified ratio for matching (rounded to prevent micro-variations)
|
|
5816
|
-
ratio: height > 0 ? Math.round((width / height) * 100) / 100 : 0,
|
|
5817
|
-
// Size category for general device classification
|
|
5818
|
-
sizeCategory: width >= 2560
|
|
5819
|
-
? "large"
|
|
5820
|
-
: width >= 1920
|
|
5821
|
-
? "desktop"
|
|
5822
|
-
: width >= 1024
|
|
5823
|
-
? "laptop"
|
|
5824
|
-
: width >= 768
|
|
5825
|
-
? "tablet"
|
|
5826
|
-
: "mobile",
|
|
5827
|
-
// ❌ REMOVED: exact dimensions (causes instability on mobile)
|
|
5828
|
-
// Device differentiation is now handled by:
|
|
5829
|
-
// 1. screenFrame (bezel measurements - stable)
|
|
5830
|
-
// 2. hardware + display combination
|
|
5831
|
-
// 3. Vector similarity in IdentityResolver
|
|
5832
|
-
};
|
|
5833
|
-
})()
|
|
5834
|
-
: {
|
|
5835
|
-
bucket: "unknown",
|
|
5836
|
-
aspectClass: "unknown",
|
|
5837
|
-
densityClass: "unknown",
|
|
5838
|
-
ratio: 0,
|
|
5839
|
-
sizeCategory: "unknown",
|
|
5840
|
-
},
|
|
5702
|
+
// ❌ PRIORITY 6: Screen - REMOVED FROM stableCoreVector
|
|
5703
|
+
// REASON: Screen properties are UNSTABLE across all device types:
|
|
5704
|
+
//
|
|
5705
|
+
// Desktop:
|
|
5706
|
+
// - DevTools changes viewport (lateral vs bottom)
|
|
5707
|
+
// - Browser zoom changes dimensions
|
|
5708
|
+
// - Window resize changes available space
|
|
5709
|
+
//
|
|
5710
|
+
// Mobile:
|
|
5711
|
+
// - Address bar appears/disappears on scroll
|
|
5712
|
+
// - Virtual keyboard opens/closes
|
|
5713
|
+
// - Screen rotation (portrait ↔ landscape)
|
|
5714
|
+
// - Pull-to-refresh changes viewport
|
|
5715
|
+
//
|
|
5716
|
+
// RESULT: Even "bucket" detection is unreliable due to viewport changes
|
|
5717
|
+
//
|
|
5718
|
+
// SOLUTION: Device differentiation now relies ONLY on:
|
|
5719
|
+
// 1. screenFrame (bezel measurements - MORE stable)
|
|
5720
|
+
// 2. hardware (cores, memory, arch - STABLE)
|
|
5721
|
+
// 3. display (color depth, gamut - STABLE)
|
|
5722
|
+
// 4. platform + deviceType + ua (ULTRA-STABLE)
|
|
5723
|
+
// 5. timezone + primaryLanguage (USER-STABLE)
|
|
5724
|
+
//
|
|
5725
|
+
// Note: screen is still collected in full fingerprint for analytics,
|
|
5726
|
+
// but excluded from stableCoreHash to ensure visitor identification stability
|
|
5841
5727
|
// CRITICAL: Do NOT include availability flags (canvas/webgl/audio) in stableCoreVector
|
|
5842
5728
|
// These flags can change between requests due to timeouts, permissions, or hardware issues
|
|
5843
5729
|
// and would cause the stableCoreHash to change, breaking visitor identification
|
|
@@ -6028,12 +5914,13 @@ async function collectFingerprint(options = {}) {
|
|
|
6028
5914
|
};
|
|
6029
5915
|
// ADDITIONAL ENTROPY: Add a deterministic but unique component based on ultra-stable signals
|
|
6030
5916
|
// This helps prevent collisions while maintaining deterministic behavior
|
|
5917
|
+
// Note: screen removed as it's unstable (viewport changes)
|
|
6031
5918
|
const entropyComponents = [
|
|
6032
5919
|
coreVector.ua || "",
|
|
6033
5920
|
coreVector.platform || "",
|
|
6034
5921
|
coreVector.deviceType || "",
|
|
6035
|
-
coreVector.screen?.bucket || "",
|
|
6036
5922
|
coreVector.timezone || "",
|
|
5923
|
+
coreVector.primaryLanguage || "",
|
|
6037
5924
|
].filter(Boolean);
|
|
6038
5925
|
if (entropyComponents.length >= 3) {
|
|
6039
5926
|
// Create a stable entropy string from the most stable components
|
|
@@ -6058,15 +5945,19 @@ async function collectFingerprint(options = {}) {
|
|
|
6058
5945
|
// - Screen frame (can vary slightly)
|
|
6059
5946
|
// - Vendor flavors (can change)
|
|
6060
5947
|
// - Exact hardware values (use buckets)
|
|
6061
|
-
// DEBUG: Log coreVector components
|
|
6062
|
-
if (opts.debug ||
|
|
6063
|
-
|
|
5948
|
+
// DEBUG: Log coreVector components for monitoring
|
|
5949
|
+
if (opts.debug ||
|
|
5950
|
+
(typeof window !== "undefined" && window._rabbitTrackerDebug)) {
|
|
5951
|
+
console.log("[RabbitTracker DEBUG] coreVector components:", {
|
|
6064
5952
|
ua: coreVector.ua,
|
|
6065
5953
|
platform: coreVector.platform,
|
|
6066
5954
|
deviceType: coreVector.deviceType,
|
|
6067
|
-
screenBucket: coreVector.screen?.bucket,
|
|
6068
5955
|
timezone: coreVector.timezone,
|
|
6069
|
-
|
|
5956
|
+
primaryLanguage: coreVector.primaryLanguage,
|
|
5957
|
+
hasHardware: !!coreVector.hardware,
|
|
5958
|
+
hasDisplay: !!coreVector.display,
|
|
5959
|
+
hasScreenFrame: !!coreVector.screenFrame,
|
|
5960
|
+
_entropy: coreVector._entropy,
|
|
6070
5961
|
});
|
|
6071
5962
|
}
|
|
6072
5963
|
// Generate ultra-stable hash with additional collision resistance
|
|
@@ -6111,7 +6002,10 @@ async function collectFingerprint(options = {}) {
|
|
|
6111
6002
|
ua: coreVector.ua,
|
|
6112
6003
|
deviceType: coreVector.deviceType,
|
|
6113
6004
|
platform: coreVector.platform,
|
|
6114
|
-
|
|
6005
|
+
timezone: coreVector.timezone,
|
|
6006
|
+
hasScreenFrame: !!coreVector.screenFrame,
|
|
6007
|
+
hardwareClass: coreVector.hardware?.class,
|
|
6008
|
+
displayClass: coreVector.display?.class,
|
|
6115
6009
|
totalComponentsInHash: Object.keys(enhancedComponentValues).length,
|
|
6116
6010
|
});
|
|
6117
6011
|
}
|