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