@zaplier/sdk 1.2.2 → 1.2.4

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 CHANGED
@@ -6121,16 +6121,16 @@ function getAvailableComponents() {
6121
6121
  */
6122
6122
  class FetchTransport {
6123
6123
  constructor() {
6124
- this.name = 'fetch';
6125
- this.available = typeof fetch !== 'undefined';
6124
+ this.name = "fetch";
6125
+ this.available = typeof fetch !== "undefined";
6126
6126
  }
6127
6127
  async send(data, endpoint) {
6128
6128
  const start = Date.now();
6129
6129
  try {
6130
6130
  const response = await fetch(endpoint, {
6131
- method: 'POST',
6132
- headers: { 'Content-Type': 'application/json' },
6133
- body: JSON.stringify(data)
6131
+ method: "POST",
6132
+ headers: { "Content-Type": "application/json" },
6133
+ body: JSON.stringify(data),
6134
6134
  });
6135
6135
  if (!response.ok) {
6136
6136
  throw new Error(`HTTP ${response.status}`);
@@ -6138,56 +6138,7 @@ class FetchTransport {
6138
6138
  return {
6139
6139
  success: true,
6140
6140
  method: this.name,
6141
- latency: Date.now() - start
6142
- };
6143
- }
6144
- catch (error) {
6145
- return {
6146
- success: false,
6147
- method: this.name,
6148
6141
  latency: Date.now() - start,
6149
- error: error instanceof Error ? error.message : String(error)
6150
- };
6151
- }
6152
- }
6153
- }
6154
- /**
6155
- * Resource Spoofing Transport (GET requests disguised as assets)
6156
- */
6157
- class ResourceSpoofTransport {
6158
- constructor(baseUrl) {
6159
- this.name = 'resource';
6160
- this.available = typeof fetch !== 'undefined';
6161
- this.baseUrl = baseUrl;
6162
- }
6163
- async send(data, endpoint) {
6164
- const start = Date.now();
6165
- try {
6166
- // Compress and encode data
6167
- const encoded = this.encodeData(data);
6168
- // Try different resource types
6169
- const resourceTypes = [
6170
- { path: '/assets/styles.css', type: 'text/css' },
6171
- { path: '/images/pixel.gif', type: 'image/gif' },
6172
- { path: '/fonts/roboto.woff2', type: 'font/woff2' },
6173
- { path: '/js/analytics.js', type: 'application/javascript' }
6174
- ];
6175
- const randomType = resourceTypes[Math.floor(Math.random() * resourceTypes.length)];
6176
- const url = `${this.baseUrl}${randomType.path}?d=${encoded}&t=${Date.now()}`;
6177
- const response = await fetch(url, {
6178
- method: 'GET',
6179
- headers: {
6180
- 'Accept': randomType.type,
6181
- 'Cache-Control': 'no-cache',
6182
- 'User-Agent': navigator.userAgent
6183
- }
6184
- });
6185
- // Even if status is not OK, adblockers might have blocked it
6186
- // But the data might still reach the server
6187
- return {
6188
- success: true, // Optimistic success
6189
- method: this.name,
6190
- latency: Date.now() - start
6191
6142
  };
6192
6143
  }
6193
6144
  catch (error) {
@@ -6195,31 +6146,18 @@ class ResourceSpoofTransport {
6195
6146
  success: false,
6196
6147
  method: this.name,
6197
6148
  latency: Date.now() - start,
6198
- error: error instanceof Error ? error.message : String(error)
6149
+ error: error instanceof Error ? error.message : String(error),
6199
6150
  };
6200
6151
  }
6201
6152
  }
6202
- encodeData(data) {
6203
- try {
6204
- const json = JSON.stringify(data);
6205
- return btoa(encodeURIComponent(json)).replace(/[+/=]/g, (match) => ({
6206
- '+': '-',
6207
- '/': '_',
6208
- '=': ''
6209
- }[match] || match));
6210
- }
6211
- catch (error) {
6212
- return '';
6213
- }
6214
- }
6215
6153
  }
6216
6154
  /**
6217
6155
  * Elysia WebSocket Transport (Native WebSocket for anti-adblock)
6218
6156
  */
6219
6157
  class ElysiaWebSocketTransport {
6220
6158
  constructor(baseUrl, token) {
6221
- this.name = 'elysia-websocket';
6222
- this.available = typeof WebSocket !== 'undefined';
6159
+ this.name = "elysia-websocket";
6160
+ this.available = typeof WebSocket !== "undefined";
6223
6161
  this.connected = false;
6224
6162
  this.baseUrl = baseUrl;
6225
6163
  this.token = token;
@@ -6228,29 +6166,29 @@ class ElysiaWebSocketTransport {
6228
6166
  const start = Date.now();
6229
6167
  try {
6230
6168
  if (!this.token) {
6231
- throw new Error('Missing token for WebSocket connection');
6169
+ throw new Error("Missing token for WebSocket connection");
6232
6170
  }
6233
6171
  await this.connect();
6234
6172
  if (!this.ws || !this.connected) {
6235
- throw new Error('WebSocket not connected');
6173
+ throw new Error("WebSocket not connected");
6236
6174
  }
6237
6175
  return new Promise((resolve, reject) => {
6238
6176
  const messageHandler = (event) => {
6239
6177
  try {
6240
6178
  const response = JSON.parse(event.data);
6241
- this.ws?.removeEventListener('message', messageHandler);
6179
+ this.ws?.removeEventListener("message", messageHandler);
6242
6180
  resolve({
6243
6181
  success: response.success || false,
6244
6182
  method: this.name,
6245
- latency: Date.now() - start
6183
+ latency: Date.now() - start,
6246
6184
  });
6247
6185
  }
6248
6186
  catch (error) {
6249
- this.ws?.removeEventListener('message', messageHandler);
6250
- reject(new Error('Failed to parse WebSocket response'));
6187
+ this.ws?.removeEventListener("message", messageHandler);
6188
+ reject(new Error("Failed to parse WebSocket response"));
6251
6189
  }
6252
6190
  };
6253
- this.ws?.addEventListener('message', messageHandler);
6191
+ this.ws?.addEventListener("message", messageHandler);
6254
6192
  // Send the complete tracking data payload (includes fingerprintHash, stableCoreHash, etc.)
6255
6193
  this.ws?.send(JSON.stringify({
6256
6194
  // Include all data from the SDK payload
@@ -6258,7 +6196,7 @@ class ElysiaWebSocketTransport {
6258
6196
  // Override/ensure essential fields for WebSocket transport
6259
6197
  eventId: data.eventId || crypto.randomUUID(),
6260
6198
  sessionId: data.sessionId || data.s,
6261
- eventType: data.eventType || data.type || 'websocket_event',
6199
+ eventType: data.eventType || data.type || "websocket_event",
6262
6200
  eventName: data.eventName || data.name,
6263
6201
  url: data.url,
6264
6202
  userAgent: data.userAgent || navigator.userAgent,
@@ -6266,12 +6204,12 @@ class ElysiaWebSocketTransport {
6266
6204
  // Ensure these critical fields are included for identity resolution
6267
6205
  fingerprintHash: data.fingerprintHash,
6268
6206
  stableCoreHash: data.stableCoreHash,
6269
- stableCoreVector: data.stableCoreVector
6207
+ stableCoreVector: data.stableCoreVector,
6270
6208
  }));
6271
6209
  // Timeout after 5 seconds
6272
6210
  setTimeout(() => {
6273
- this.ws?.removeEventListener('message', messageHandler);
6274
- reject(new Error('WebSocket response timeout'));
6211
+ this.ws?.removeEventListener("message", messageHandler);
6212
+ reject(new Error("WebSocket response timeout"));
6275
6213
  }, 5000);
6276
6214
  });
6277
6215
  }
@@ -6280,7 +6218,7 @@ class ElysiaWebSocketTransport {
6280
6218
  success: false,
6281
6219
  method: this.name,
6282
6220
  latency: Date.now() - start,
6283
- error: error instanceof Error ? error.message : String(error)
6221
+ error: error instanceof Error ? error.message : String(error),
6284
6222
  };
6285
6223
  }
6286
6224
  }
@@ -6292,7 +6230,7 @@ class ElysiaWebSocketTransport {
6292
6230
  try {
6293
6231
  // Convert HTTP/HTTPS to WS/WSS
6294
6232
  const url = new URL(this.baseUrl);
6295
- const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
6233
+ const protocol = url.protocol === "https:" ? "wss:" : "ws:";
6296
6234
  const wsUrl = `${protocol}//${url.host}/ws/track?token=${encodeURIComponent(this.token)}`;
6297
6235
  this.ws = new WebSocket(wsUrl);
6298
6236
  this.ws.onopen = () => {
@@ -6301,7 +6239,7 @@ class ElysiaWebSocketTransport {
6301
6239
  };
6302
6240
  this.ws.onerror = () => {
6303
6241
  this.connected = false;
6304
- reject(new Error('WebSocket connection failed'));
6242
+ reject(new Error("WebSocket connection failed"));
6305
6243
  };
6306
6244
  this.ws.onclose = () => {
6307
6245
  this.connected = false;
@@ -6310,7 +6248,7 @@ class ElysiaWebSocketTransport {
6310
6248
  setTimeout(() => {
6311
6249
  if (!this.connected) {
6312
6250
  this.ws?.close();
6313
- reject(new Error('WebSocket connection timeout'));
6251
+ reject(new Error("WebSocket connection timeout"));
6314
6252
  }
6315
6253
  }, 5000);
6316
6254
  }
@@ -6331,14 +6269,18 @@ class ElysiaWebSocketTransport {
6331
6269
  */
6332
6270
  class WebRTCTransport {
6333
6271
  constructor() {
6334
- this.name = 'webrtc';
6335
- this.available = typeof globalThis.RTCPeerConnection !== 'undefined';
6272
+ this.name = "webrtc";
6273
+ this.available = typeof globalThis.RTCPeerConnection !== "undefined";
6336
6274
  this.connected = false;
6337
6275
  }
6338
6276
  async send(data, _endpoint) {
6339
6277
  const start = Date.now();
6340
6278
  if (!this.available) {
6341
- return { success: false, method: this.name, error: 'WebRTC not available' };
6279
+ return {
6280
+ success: false,
6281
+ method: this.name,
6282
+ error: "WebRTC not available",
6283
+ };
6342
6284
  }
6343
6285
  try {
6344
6286
  await this.setupConnection();
@@ -6347,14 +6289,14 @@ class WebRTCTransport {
6347
6289
  return {
6348
6290
  success: true,
6349
6291
  method: this.name,
6350
- latency: Date.now() - start
6292
+ latency: Date.now() - start,
6351
6293
  };
6352
6294
  }
6353
6295
  else {
6354
6296
  return {
6355
6297
  success: false,
6356
6298
  method: this.name,
6357
- error: 'DataChannel not ready'
6299
+ error: "DataChannel not ready",
6358
6300
  };
6359
6301
  }
6360
6302
  }
@@ -6362,7 +6304,7 @@ class WebRTCTransport {
6362
6304
  return {
6363
6305
  success: false,
6364
6306
  method: this.name,
6365
- error: error instanceof Error ? error.message : String(error)
6307
+ error: error instanceof Error ? error.message : String(error),
6366
6308
  };
6367
6309
  }
6368
6310
  }
@@ -6372,11 +6314,11 @@ class WebRTCTransport {
6372
6314
  return new Promise((resolve, reject) => {
6373
6315
  try {
6374
6316
  this.pc = new globalThis.RTCPeerConnection({
6375
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
6317
+ iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
6376
6318
  });
6377
- this.dataChannel = this.pc.createDataChannel('tracking', {
6319
+ this.dataChannel = this.pc.createDataChannel("tracking", {
6378
6320
  ordered: false,
6379
- maxRetransmits: 0
6321
+ maxRetransmits: 0,
6380
6322
  });
6381
6323
  this.dataChannel.onopen = () => {
6382
6324
  this.connected = true;
@@ -6413,45 +6355,51 @@ class AntiAdblockManager {
6413
6355
  totalRequests: 0,
6414
6356
  successfulRequests: 0,
6415
6357
  methodSuccess: new Map(),
6416
- methodFailures: new Map()
6358
+ methodFailures: new Map(),
6417
6359
  };
6418
6360
  this.baseUrl = baseUrl;
6419
6361
  this.token = token;
6420
6362
  this.config = {
6421
6363
  enabled: true,
6422
- methods: ['elysia-websocket', 'fetch', 'resource'], // Elysia WebSocket as primary
6364
+ methods: ["elysia-websocket", "fetch"],
6423
6365
  fallbackDelay: 100,
6424
6366
  maxRetries: 2,
6425
6367
  debug: false,
6426
- ...config
6368
+ ...config,
6427
6369
  };
6428
6370
  this.initializeTransports();
6429
6371
  }
6430
6372
  initializeTransports() {
6431
6373
  const transportMap = {
6432
- 'elysia-websocket': () => new ElysiaWebSocketTransport(this.baseUrl, this.token),
6374
+ "elysia-websocket": () => new ElysiaWebSocketTransport(this.baseUrl, this.token),
6433
6375
  fetch: () => new FetchTransport(),
6434
- resource: () => new ResourceSpoofTransport(this.baseUrl),
6435
- webrtc: () => new WebRTCTransport()
6376
+ webrtc: () => new WebRTCTransport(),
6436
6377
  };
6437
6378
  this.transports = this.config.methods
6438
- .map(method => transportMap[method]?.())
6379
+ .map((method) => transportMap[method]?.())
6439
6380
  .filter((transport) => transport !== undefined && transport.available);
6440
6381
  if (this.config.debug) {
6441
- console.log('[Zaplier] Anti-adblock initialized with transports:', this.transports.map(t => t.name));
6382
+ console.log("[Zaplier] Anti-adblock initialized with transports:", this.transports.map((t) => t.name));
6442
6383
  }
6443
6384
  }
6444
6385
  /**
6445
6386
  * Send data using the best available transport
6446
6387
  */
6447
- async send(data, endpoint = '/tracking/event') {
6388
+ async send(data, endpoint = "/tracking/event") {
6448
6389
  this.stats.totalRequests++;
6449
6390
  if (!this.config.enabled || this.transports.length === 0) {
6450
- return { success: false, method: 'none', error: 'No transports available' };
6391
+ return {
6392
+ success: false,
6393
+ method: "none",
6394
+ error: "No transports available",
6395
+ };
6451
6396
  }
6452
- let lastError = '';
6453
- // Try each transport in order
6397
+ let lastError = "";
6398
+ // Try each transport in order (sequential, not parallel)
6454
6399
  for (const transport of this.transports) {
6400
+ if (this.config.debug) {
6401
+ console.log(`[Zaplier] Trying transport: ${transport.name}`);
6402
+ }
6455
6403
  try {
6456
6404
  const result = await transport.send(data, `${this.baseUrl}${endpoint}`);
6457
6405
  // Update stats
@@ -6459,15 +6407,15 @@ class AntiAdblockManager {
6459
6407
  this.stats.successfulRequests++;
6460
6408
  this.updateMethodStats(transport.name, true);
6461
6409
  if (this.config.debug) {
6462
- console.log(`[Zaplier] Data sent successfully via ${transport.name}`, result);
6410
+ console.log(`[Zaplier] Data sent successfully via ${transport.name} - STOPPING fallback chain`, result);
6463
6411
  }
6464
- return result;
6412
+ return result; // SUCCESS - stop trying other transports
6465
6413
  }
6466
6414
  else {
6467
6415
  this.updateMethodStats(transport.name, false);
6468
- lastError = result.error || 'Unknown error';
6416
+ lastError = result.error || "Unknown error";
6469
6417
  if (this.config.debug) {
6470
- console.warn(`[Zaplier] Transport ${transport.name} failed:`, result.error);
6418
+ console.warn(`[Zaplier] Transport ${transport.name} failed:`, result.error);
6471
6419
  }
6472
6420
  }
6473
6421
  }
@@ -6475,18 +6423,18 @@ class AntiAdblockManager {
6475
6423
  lastError = error instanceof Error ? error.message : String(error);
6476
6424
  this.updateMethodStats(transport.name, false);
6477
6425
  if (this.config.debug) {
6478
- console.warn(`[Zaplier] Transport ${transport.name} threw error:`, error);
6426
+ console.warn(`[Zaplier] Transport ${transport.name} threw error:`, error);
6479
6427
  }
6480
6428
  }
6481
6429
  // Wait before trying next transport
6482
6430
  if (this.config.fallbackDelay > 0) {
6483
- await new Promise(resolve => setTimeout(resolve, this.config.fallbackDelay));
6431
+ await new Promise((resolve) => setTimeout(resolve, this.config.fallbackDelay));
6484
6432
  }
6485
6433
  }
6486
6434
  return {
6487
6435
  success: false,
6488
- method: 'all_failed',
6489
- error: `All transports failed. Last error: ${lastError}`
6436
+ method: "all_failed",
6437
+ error: `All transports failed. Last error: ${lastError}`,
6490
6438
  };
6491
6439
  }
6492
6440
  updateMethodStats(method, success) {
@@ -6520,7 +6468,7 @@ class AntiAdblockManager {
6520
6468
  * Destroy all transports
6521
6469
  */
6522
6470
  destroy() {
6523
- this.transports.forEach(transport => {
6471
+ this.transports.forEach((transport) => {
6524
6472
  if (transport.destroy) {
6525
6473
  transport.destroy();
6526
6474
  }
@@ -6541,7 +6489,7 @@ class AntiAdblockManager {
6541
6489
  results[transport.name] = {
6542
6490
  success: false,
6543
6491
  method: transport.name,
6544
- error: error instanceof Error ? error.message : String(error)
6492
+ error: error instanceof Error ? error.message : String(error),
6545
6493
  };
6546
6494
  }
6547
6495
  }
@@ -7677,7 +7625,7 @@ class ZaplierSDK {
7677
7625
  this.antiAdblockManager = new AntiAdblockManager(this.config.apiEndpoint, this.config.token, // Pass token to anti-adblock manager
7678
7626
  {
7679
7627
  enabled: true,
7680
- methods: ["elysia-websocket", "fetch", "resource"], // Elysia WebSocket as primary
7628
+ methods: ["elysia-websocket", "fetch"],
7681
7629
  fallbackDelay: 100,
7682
7630
  maxRetries: 2,
7683
7631
  debug: this.config.debug,