@traffical/js-client 0.1.2

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.
Files changed (52) hide show
  1. package/README.md +209 -0
  2. package/dist/client.d.ts +167 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +429 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/error-boundary.d.ts +47 -0
  7. package/dist/error-boundary.d.ts.map +1 -0
  8. package/dist/error-boundary.js +118 -0
  9. package/dist/error-boundary.js.map +1 -0
  10. package/dist/event-logger.d.ts +75 -0
  11. package/dist/event-logger.d.ts.map +1 -0
  12. package/dist/event-logger.js +186 -0
  13. package/dist/event-logger.js.map +1 -0
  14. package/dist/exposure-dedup.d.ts +49 -0
  15. package/dist/exposure-dedup.d.ts.map +1 -0
  16. package/dist/exposure-dedup.js +94 -0
  17. package/dist/exposure-dedup.js.map +1 -0
  18. package/dist/global.d.ts +38 -0
  19. package/dist/global.d.ts.map +1 -0
  20. package/dist/global.js +67 -0
  21. package/dist/global.js.map +1 -0
  22. package/dist/index.d.ts +41 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +46 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/plugins/decision-tracking.d.ts +68 -0
  27. package/dist/plugins/decision-tracking.d.ts.map +1 -0
  28. package/dist/plugins/decision-tracking.js +83 -0
  29. package/dist/plugins/decision-tracking.js.map +1 -0
  30. package/dist/plugins/dom-binding.d.ts +48 -0
  31. package/dist/plugins/dom-binding.d.ts.map +1 -0
  32. package/dist/plugins/dom-binding.js +211 -0
  33. package/dist/plugins/dom-binding.js.map +1 -0
  34. package/dist/plugins/index.d.ts +70 -0
  35. package/dist/plugins/index.d.ts.map +1 -0
  36. package/dist/plugins/index.js +194 -0
  37. package/dist/plugins/index.js.map +1 -0
  38. package/dist/plugins/types.d.ts +62 -0
  39. package/dist/plugins/types.d.ts.map +1 -0
  40. package/dist/plugins/types.js +7 -0
  41. package/dist/plugins/types.js.map +1 -0
  42. package/dist/stable-id.d.ts +44 -0
  43. package/dist/stable-id.d.ts.map +1 -0
  44. package/dist/stable-id.js +129 -0
  45. package/dist/stable-id.js.map +1 -0
  46. package/dist/storage.d.ts +41 -0
  47. package/dist/storage.d.ts.map +1 -0
  48. package/dist/storage.js +144 -0
  49. package/dist/storage.js.map +1 -0
  50. package/dist/traffical.min.js +3 -0
  51. package/dist/traffical.min.js.map +7 -0
  52. package/package.json +51 -0
package/dist/client.js ADDED
@@ -0,0 +1,429 @@
1
+ /**
2
+ * TrafficalClient - JavaScript SDK for browser environments.
3
+ *
4
+ * Features:
5
+ * - Same API as Node SDK: getParams(), decide(), trackExposure(), track()
6
+ * - Error boundary wrapping (P0)
7
+ * - Exposure deduplication (P0)
8
+ * - Smart event batching with beacon on unload (P1)
9
+ * - Plugin system (P2)
10
+ * - Auto stable ID for anonymous users
11
+ */
12
+ import { resolveParameters, decide as coreDecide, generateExposureId, generateTrackEventId, generateDecisionId, } from "@traffical/core";
13
+ import { ErrorBoundary } from "./error-boundary.js";
14
+ import { EventLogger } from "./event-logger.js";
15
+ import { ExposureDeduplicator } from "./exposure-dedup.js";
16
+ import { StableIdProvider } from "./stable-id.js";
17
+ import { createStorageProvider } from "./storage.js";
18
+ import { PluginManager, createDecisionTrackingPlugin } from "./plugins/index.js";
19
+ // =============================================================================
20
+ // Constants
21
+ // =============================================================================
22
+ const SDK_NAME = "js-client";
23
+ const SDK_VERSION = "0.1.0"; // Should match package.json version
24
+ const DEFAULT_BASE_URL = "https://sdk.traffical.io";
25
+ const DEFAULT_REFRESH_INTERVAL_MS = 60000; // 1 minute
26
+ const OFFLINE_WARNING_INTERVAL_MS = 300000; // 5 minutes
27
+ const DECISION_CACHE_MAX_SIZE = 100; // Max decisions to cache for attribution lookup
28
+ // =============================================================================
29
+ // TrafficalClient Class
30
+ // =============================================================================
31
+ export class TrafficalClient {
32
+ constructor(options) {
33
+ this._state = {
34
+ bundle: null,
35
+ etag: null,
36
+ lastFetchTime: 0,
37
+ lastOfflineWarning: 0,
38
+ refreshTimer: null,
39
+ isInitialized: false,
40
+ };
41
+ /** Cache of recent decisions for attribution lookup when track() is called */
42
+ this._decisionCache = new Map();
43
+ this._options = {
44
+ orgId: options.orgId,
45
+ projectId: options.projectId,
46
+ env: options.env,
47
+ apiKey: options.apiKey,
48
+ baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
49
+ localConfig: options.localConfig,
50
+ refreshIntervalMs: options.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS,
51
+ };
52
+ // Initialize components
53
+ this._errorBoundary = new ErrorBoundary(options.errorBoundary);
54
+ this._storage = options.storage ?? createStorageProvider();
55
+ this._eventLogger = new EventLogger({
56
+ endpoint: `${this._options.baseUrl}/v1/events/batch`,
57
+ apiKey: options.apiKey,
58
+ storage: this._storage,
59
+ batchSize: options.eventBatchSize,
60
+ flushIntervalMs: options.eventFlushIntervalMs,
61
+ onError: (error) => {
62
+ console.warn("[Traffical] Event logging error:", error.message);
63
+ },
64
+ });
65
+ this._exposureDedup = new ExposureDeduplicator({
66
+ storage: this._storage,
67
+ sessionTtlMs: options.exposureSessionTtlMs,
68
+ });
69
+ this._stableId = new StableIdProvider({
70
+ storage: this._storage,
71
+ });
72
+ this._plugins = new PluginManager();
73
+ // Register decision tracking plugin (enabled by default)
74
+ if (options.trackDecisions !== false) {
75
+ this._plugins.register({
76
+ plugin: createDecisionTrackingPlugin({ deduplicationTtlMs: options.decisionDeduplicationTtlMs }, {
77
+ orgId: this._options.orgId,
78
+ projectId: this._options.projectId,
79
+ env: this._options.env,
80
+ log: (event) => this._eventLogger.log(event),
81
+ }),
82
+ priority: 100, // High priority so it runs before user plugins
83
+ });
84
+ }
85
+ // Register user-provided plugins
86
+ if (options.plugins) {
87
+ for (const plugin of options.plugins) {
88
+ this._plugins.register(plugin);
89
+ }
90
+ }
91
+ // Initialize with local config if provided
92
+ if (this._options.localConfig) {
93
+ this._state.bundle = this._options.localConfig;
94
+ // Notify plugins about the local config
95
+ this._plugins.runConfigUpdate(this._options.localConfig);
96
+ }
97
+ }
98
+ // ===========================================================================
99
+ // Initialization
100
+ // ===========================================================================
101
+ /**
102
+ * Initializes the client by fetching the config bundle.
103
+ */
104
+ async initialize() {
105
+ await this._errorBoundary.captureAsync("initialize", async () => {
106
+ await this._fetchConfig();
107
+ this._startBackgroundRefresh();
108
+ this._state.isInitialized = true;
109
+ // Run plugin onInitialize hooks
110
+ await this._plugins.runInitialize();
111
+ }, undefined);
112
+ }
113
+ /**
114
+ * Check if the client is initialized.
115
+ */
116
+ get isInitialized() {
117
+ return this._state.isInitialized;
118
+ }
119
+ /**
120
+ * Stops background refresh and cleans up resources.
121
+ */
122
+ destroy() {
123
+ if (this._state.refreshTimer) {
124
+ clearInterval(this._state.refreshTimer);
125
+ this._state.refreshTimer = null;
126
+ }
127
+ // Flush any remaining events
128
+ this._eventLogger.flushBeacon();
129
+ this._eventLogger.destroy();
130
+ // Run plugin onDestroy hooks
131
+ this._plugins.runDestroy();
132
+ }
133
+ // ===========================================================================
134
+ // Config Management
135
+ // ===========================================================================
136
+ /**
137
+ * Manually refreshes the config bundle.
138
+ */
139
+ async refreshConfig() {
140
+ await this._errorBoundary.swallow("refreshConfig", async () => {
141
+ await this._fetchConfig();
142
+ });
143
+ }
144
+ /**
145
+ * Gets the current config bundle version.
146
+ */
147
+ getConfigVersion() {
148
+ return this._state.bundle?.version ?? null;
149
+ }
150
+ // ===========================================================================
151
+ // Parameter Resolution
152
+ // ===========================================================================
153
+ /**
154
+ * Resolves parameters with defaults as fallback.
155
+ */
156
+ getParams(options) {
157
+ return this._errorBoundary.capture("getParams", () => {
158
+ const bundle = this._getEffectiveBundle();
159
+ const context = this._enrichContext(options.context);
160
+ const params = resolveParameters(bundle, context, options.defaults);
161
+ // Run plugin onResolve hooks (e.g., DOM binding plugin)
162
+ this._plugins.runResolve(params);
163
+ return params;
164
+ }, options.defaults);
165
+ }
166
+ /**
167
+ * Makes a decision with full metadata for tracking.
168
+ */
169
+ decide(options) {
170
+ return this._errorBoundary.capture("decide", () => {
171
+ const bundle = this._getEffectiveBundle();
172
+ // Run plugin onBeforeDecision hooks
173
+ let context = this._enrichContext(options.context);
174
+ context = this._plugins.runBeforeDecision(context);
175
+ const decision = coreDecide(bundle, context, options.defaults);
176
+ // Cache decision for attribution lookup when track() is called
177
+ this._cacheDecision(decision);
178
+ // Run plugin onDecision hooks (e.g., DOM binding plugin)
179
+ this._plugins.runDecision(decision);
180
+ return decision;
181
+ }, {
182
+ decisionId: generateDecisionId(),
183
+ assignments: options.defaults,
184
+ metadata: {
185
+ timestamp: new Date().toISOString(),
186
+ unitKeyValue: "",
187
+ layers: [],
188
+ },
189
+ });
190
+ }
191
+ // ===========================================================================
192
+ // Event Tracking
193
+ // ===========================================================================
194
+ /**
195
+ * Tracks an exposure event.
196
+ * Automatically deduplicates exposures for the same user/variant.
197
+ */
198
+ trackExposure(decision) {
199
+ this._errorBoundary.capture("trackExposure", () => {
200
+ const unitKey = decision.metadata.unitKeyValue;
201
+ if (!unitKey)
202
+ return;
203
+ // Check each layer for deduplication
204
+ for (const layer of decision.metadata.layers) {
205
+ if (!layer.policyId || !layer.allocationName)
206
+ continue;
207
+ // Deduplicate
208
+ const isNew = this._exposureDedup.checkAndMark(unitKey, layer.policyId, layer.allocationName);
209
+ if (!isNew)
210
+ continue;
211
+ const event = {
212
+ type: "exposure",
213
+ id: generateExposureId(), // Unique exposure ID (not same as decision)
214
+ decisionId: decision.decisionId,
215
+ orgId: this._options.orgId,
216
+ projectId: this._options.projectId,
217
+ env: this._options.env,
218
+ unitKey,
219
+ timestamp: new Date().toISOString(),
220
+ assignments: decision.assignments,
221
+ layers: decision.metadata.layers,
222
+ context: decision.metadata.filteredContext,
223
+ sdkName: SDK_NAME,
224
+ sdkVersion: SDK_VERSION,
225
+ };
226
+ // Run plugin onExposure hooks
227
+ if (!this._plugins.runExposure(event)) {
228
+ continue;
229
+ }
230
+ this._eventLogger.log(event);
231
+ }
232
+ }, undefined);
233
+ }
234
+ /**
235
+ * Tracks a user event.
236
+ *
237
+ * @param eventName - The event name (e.g., 'purchase', 'add_to_cart')
238
+ * @param properties - Optional event properties (including value for optimization)
239
+ * @param options - Optional tracking options (decisionId, unitKey)
240
+ *
241
+ * @example
242
+ * // Track a purchase with revenue
243
+ * client.track('purchase', { value: 99.99, orderId: 'ord_123' });
244
+ *
245
+ * // Track a simple event
246
+ * client.track('add_to_cart', { itemId: 'sku_456' });
247
+ *
248
+ * // Track with explicit decision attribution
249
+ * client.track('checkout_complete', { value: 1 }, { decisionId: decision.decisionId });
250
+ */
251
+ track(eventName, properties, options) {
252
+ this._errorBoundary.capture("track", () => {
253
+ const unitKey = options?.unitKey ?? this._stableId.getId();
254
+ const value = typeof properties?.value === 'number' ? properties.value : undefined;
255
+ // Auto-populate attribution from cached decision if available
256
+ let attribution;
257
+ const decisionId = options?.decisionId;
258
+ if (decisionId) {
259
+ const cachedDecision = this._decisionCache.get(decisionId);
260
+ if (cachedDecision) {
261
+ attribution = cachedDecision.metadata.layers
262
+ .filter((l) => l.policyId && l.allocationName)
263
+ .map((l) => ({
264
+ layerId: l.layerId,
265
+ policyId: l.policyId,
266
+ allocationName: l.allocationName,
267
+ }));
268
+ }
269
+ }
270
+ const event = {
271
+ type: "track",
272
+ id: generateTrackEventId(),
273
+ orgId: this._options.orgId,
274
+ projectId: this._options.projectId,
275
+ env: this._options.env,
276
+ unitKey,
277
+ timestamp: new Date().toISOString(),
278
+ event: eventName,
279
+ value,
280
+ properties,
281
+ decisionId,
282
+ attribution,
283
+ sdkName: SDK_NAME,
284
+ sdkVersion: SDK_VERSION,
285
+ };
286
+ // Run plugin onTrack hooks
287
+ if (!this._plugins.runTrack(event)) {
288
+ return;
289
+ }
290
+ this._eventLogger.log(event);
291
+ }, undefined);
292
+ }
293
+ /**
294
+ * Flush pending events immediately.
295
+ */
296
+ async flushEvents() {
297
+ await this._errorBoundary.swallow("flushEvents", async () => {
298
+ await this._eventLogger.flush();
299
+ });
300
+ }
301
+ // ===========================================================================
302
+ // Plugin Management
303
+ // ===========================================================================
304
+ /**
305
+ * Register a plugin.
306
+ */
307
+ use(plugin) {
308
+ this._plugins.register(plugin);
309
+ return this;
310
+ }
311
+ /**
312
+ * Get a registered plugin by name.
313
+ */
314
+ getPlugin(name) {
315
+ return this._plugins.get(name);
316
+ }
317
+ // ===========================================================================
318
+ // Stable ID
319
+ // ===========================================================================
320
+ /**
321
+ * Get the stable ID for the current user.
322
+ */
323
+ getStableId() {
324
+ return this._stableId.getId();
325
+ }
326
+ /**
327
+ * Set a custom stable ID (e.g., when user logs in).
328
+ */
329
+ setStableId(id) {
330
+ this._stableId.setId(id);
331
+ }
332
+ // ===========================================================================
333
+ // Private Methods
334
+ // ===========================================================================
335
+ _getEffectiveBundle() {
336
+ return this._state.bundle ?? this._options.localConfig ?? null;
337
+ }
338
+ _enrichContext(context) {
339
+ // Add stable ID if not already present
340
+ const bundle = this._getEffectiveBundle();
341
+ const unitKey = bundle?.hashing?.unitKey ?? "userId";
342
+ if (!context[unitKey]) {
343
+ return {
344
+ ...context,
345
+ [unitKey]: this._stableId.getId(),
346
+ };
347
+ }
348
+ return context;
349
+ }
350
+ async _fetchConfig() {
351
+ const url = `${this._options.baseUrl}/v1/config/${this._options.projectId}?env=${this._options.env}`;
352
+ const headers = {
353
+ "Content-Type": "application/json",
354
+ Authorization: `Bearer ${this._options.apiKey}`,
355
+ };
356
+ if (this._state.etag) {
357
+ headers["If-None-Match"] = this._state.etag;
358
+ }
359
+ try {
360
+ const response = await fetch(url, { method: "GET", headers });
361
+ if (response.status === 304) {
362
+ this._state.lastFetchTime = Date.now();
363
+ return;
364
+ }
365
+ if (!response.ok) {
366
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
367
+ }
368
+ const bundle = (await response.json());
369
+ const etag = response.headers.get("ETag");
370
+ this._state.bundle = bundle;
371
+ this._state.etag = etag;
372
+ this._state.lastFetchTime = Date.now();
373
+ // Run plugin onConfigUpdate hooks (e.g., DOM binding plugin)
374
+ this._plugins.runConfigUpdate(bundle);
375
+ }
376
+ catch (error) {
377
+ this._logOfflineWarning(error);
378
+ }
379
+ }
380
+ _startBackgroundRefresh() {
381
+ if (this._options.refreshIntervalMs <= 0)
382
+ return;
383
+ this._state.refreshTimer = setInterval(() => {
384
+ this._fetchConfig().catch(() => {
385
+ // Errors logged in _fetchConfig
386
+ });
387
+ }, this._options.refreshIntervalMs);
388
+ }
389
+ _logOfflineWarning(error) {
390
+ const now = Date.now();
391
+ if (now - this._state.lastOfflineWarning > OFFLINE_WARNING_INTERVAL_MS) {
392
+ console.warn(`[Traffical] Failed to fetch config: ${error instanceof Error ? error.message : String(error)}. Using ${this._state.bundle ? "cached" : "local"} config.`);
393
+ this._state.lastOfflineWarning = now;
394
+ }
395
+ }
396
+ /**
397
+ * Caches a decision for attribution lookup when track() is called.
398
+ * Maintains a bounded cache to prevent memory leaks.
399
+ */
400
+ _cacheDecision(decision) {
401
+ // Evict oldest entries if cache is full
402
+ if (this._decisionCache.size >= DECISION_CACHE_MAX_SIZE) {
403
+ // Get first (oldest) key and delete it
404
+ const firstKey = this._decisionCache.keys().next().value;
405
+ if (firstKey) {
406
+ this._decisionCache.delete(firstKey);
407
+ }
408
+ }
409
+ this._decisionCache.set(decision.decisionId, decision);
410
+ }
411
+ }
412
+ // =============================================================================
413
+ // Factory Functions
414
+ // =============================================================================
415
+ /**
416
+ * Creates and initializes a Traffical client.
417
+ */
418
+ export async function createTrafficalClient(options) {
419
+ const client = new TrafficalClient(options);
420
+ await client.initialize();
421
+ return client;
422
+ }
423
+ /**
424
+ * Creates a Traffical client without initializing (synchronous).
425
+ */
426
+ export function createTrafficalClientSync(options) {
427
+ return new TrafficalClient(options);
428
+ }
429
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ErrorBoundary - Ensures SDK never crashes customer's application.
3
+ *
4
+ * Wraps all public methods to catch errors and return safe defaults.
5
+ * Optionally reports errors to Traffical backend for monitoring.
6
+ */
7
+ export interface ErrorBoundaryOptions {
8
+ /** Whether to report errors to Traffical backend */
9
+ reportErrors?: boolean;
10
+ /** Endpoint for error reporting */
11
+ errorEndpoint?: string;
12
+ /** SDK key for identification */
13
+ sdkKey?: string;
14
+ /** Callback when error occurs */
15
+ onError?: (tag: string, error: Error) => void;
16
+ }
17
+ export declare class ErrorBoundary {
18
+ private _seen;
19
+ private _options;
20
+ private _lastError;
21
+ constructor(options?: ErrorBoundaryOptions);
22
+ /**
23
+ * Wrap a synchronous function to catch errors and return fallback.
24
+ */
25
+ capture<T>(tag: string, fn: () => T, fallback: T): T;
26
+ /**
27
+ * Wrap an async function to catch errors and return fallback.
28
+ */
29
+ captureAsync<T>(tag: string, fn: () => Promise<T>, fallback: T): Promise<T>;
30
+ /**
31
+ * Execute an async operation without expecting a return value.
32
+ * Used for fire-and-forget operations like event tracking.
33
+ */
34
+ swallow(tag: string, fn: () => Promise<void>): Promise<void>;
35
+ /**
36
+ * Get the last error that occurred (for debugging).
37
+ */
38
+ getLastError(): Error | null;
39
+ /**
40
+ * Clear the seen errors set (for testing or session reset).
41
+ */
42
+ clearSeen(): void;
43
+ private _onError;
44
+ private _reportError;
45
+ private _resolveError;
46
+ }
47
+ //# sourceMappingURL=error-boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../src/error-boundary.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/C;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAsB;gBAE5B,OAAO,GAAE,oBAAyB;IAI9C;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC;IASpD;;OAEG;IACG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASjF;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlE;;OAEG;IACH,YAAY,IAAI,KAAK,GAAG,IAAI;IAM5B;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB,OAAO,CAAC,QAAQ;YAyBF,YAAY;IAyB1B,OAAO,CAAC,aAAa;CAStB"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * ErrorBoundary - Ensures SDK never crashes customer's application.
3
+ *
4
+ * Wraps all public methods to catch errors and return safe defaults.
5
+ * Optionally reports errors to Traffical backend for monitoring.
6
+ */
7
+ export class ErrorBoundary {
8
+ constructor(options = {}) {
9
+ this._seen = new Set();
10
+ this._lastError = null;
11
+ this._options = options;
12
+ }
13
+ /**
14
+ * Wrap a synchronous function to catch errors and return fallback.
15
+ */
16
+ capture(tag, fn, fallback) {
17
+ try {
18
+ return fn();
19
+ }
20
+ catch (error) {
21
+ this._onError(tag, error);
22
+ return fallback;
23
+ }
24
+ }
25
+ /**
26
+ * Wrap an async function to catch errors and return fallback.
27
+ */
28
+ async captureAsync(tag, fn, fallback) {
29
+ try {
30
+ return await fn();
31
+ }
32
+ catch (error) {
33
+ this._onError(tag, error);
34
+ return fallback;
35
+ }
36
+ }
37
+ /**
38
+ * Execute an async operation without expecting a return value.
39
+ * Used for fire-and-forget operations like event tracking.
40
+ */
41
+ async swallow(tag, fn) {
42
+ try {
43
+ await fn();
44
+ }
45
+ catch (error) {
46
+ this._onError(tag, error);
47
+ }
48
+ }
49
+ /**
50
+ * Get the last error that occurred (for debugging).
51
+ */
52
+ getLastError() {
53
+ const error = this._lastError;
54
+ this._lastError = null;
55
+ return error;
56
+ }
57
+ /**
58
+ * Clear the seen errors set (for testing or session reset).
59
+ */
60
+ clearSeen() {
61
+ this._seen.clear();
62
+ }
63
+ _onError(tag, error) {
64
+ const resolvedError = this._resolveError(error);
65
+ this._lastError = resolvedError;
66
+ // Deduplicate - only handle each unique error once
67
+ const errorKey = `${tag}:${resolvedError.name}:${resolvedError.message}`;
68
+ if (this._seen.has(errorKey)) {
69
+ return;
70
+ }
71
+ this._seen.add(errorKey);
72
+ // Log to console (development)
73
+ console.warn(`[Traffical] Error in ${tag}:`, resolvedError.message);
74
+ // Call user-provided callback
75
+ this._options.onError?.(tag, resolvedError);
76
+ // Optionally report to backend
77
+ if (this._options.reportErrors && this._options.errorEndpoint) {
78
+ this._reportError(tag, resolvedError).catch(() => {
79
+ // Silently fail - we don't want error reporting to cause errors
80
+ });
81
+ }
82
+ }
83
+ async _reportError(tag, error) {
84
+ if (!this._options.errorEndpoint)
85
+ return;
86
+ try {
87
+ await fetch(this._options.errorEndpoint, {
88
+ method: "POST",
89
+ headers: {
90
+ "Content-Type": "application/json",
91
+ ...(this._options.sdkKey && { "X-Traffical-Key": this._options.sdkKey }),
92
+ },
93
+ body: JSON.stringify({
94
+ tag,
95
+ error: error.name,
96
+ message: error.message,
97
+ stack: error.stack,
98
+ timestamp: new Date().toISOString(),
99
+ sdk: "@traffical/js-client",
100
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
101
+ }),
102
+ });
103
+ }
104
+ catch {
105
+ // Silently fail
106
+ }
107
+ }
108
+ _resolveError(error) {
109
+ if (error instanceof Error) {
110
+ return error;
111
+ }
112
+ if (typeof error === "string") {
113
+ return new Error(error);
114
+ }
115
+ return new Error("An unknown error occurred");
116
+ }
117
+ }
118
+ //# sourceMappingURL=error-boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.js","sourceRoot":"","sources":["../src/error-boundary.ts"],"names":[],"mappings":"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"}