@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
@@ -0,0 +1,75 @@
1
+ /**
2
+ * EventLogger - Smart event batching with browser-specific features.
3
+ *
4
+ * Features:
5
+ * - Batches events (flush every N events or M seconds)
6
+ * - Uses navigator.sendBeacon() on page unload
7
+ * - Persists failed events to localStorage
8
+ * - Retries failed events on next session
9
+ * - Visibility-aware: flushes on visibilitychange to hidden
10
+ */
11
+ import type { TrackableEvent } from "@traffical/core";
12
+ import type { StorageProvider } from "./storage.js";
13
+ export interface EventLoggerOptions {
14
+ /** API endpoint for events */
15
+ endpoint: string;
16
+ /** API key for authentication */
17
+ apiKey: string;
18
+ /** Storage provider for failed events */
19
+ storage: StorageProvider;
20
+ /** Max events before auto-flush (default: 10) */
21
+ batchSize?: number;
22
+ /** Auto-flush interval in ms (default: 30000) */
23
+ flushIntervalMs?: number;
24
+ /** Callback on flush error */
25
+ onError?: (error: Error) => void;
26
+ }
27
+ export declare class EventLogger {
28
+ private _endpoint;
29
+ private _apiKey;
30
+ private _storage;
31
+ private _batchSize;
32
+ private _flushIntervalMs;
33
+ private _onError?;
34
+ private _queue;
35
+ private _flushTimer;
36
+ private _isFlushing;
37
+ constructor(options: EventLoggerOptions);
38
+ /**
39
+ * Log an event (added to batch queue).
40
+ */
41
+ log(event: TrackableEvent): void;
42
+ /**
43
+ * Flush all queued events immediately.
44
+ */
45
+ flush(): Promise<void>;
46
+ /**
47
+ * Flush using fetch with keepalive (for page unload).
48
+ *
49
+ * We use fetch with keepalive: true instead of sendBeacon because:
50
+ * - sendBeacon cannot send custom headers (like Authorization)
51
+ * - keepalive ensures the request completes even as the page unloads
52
+ * - Same reliability guarantees as sendBeacon
53
+ *
54
+ * Returns true if request was initiated, false otherwise.
55
+ */
56
+ flushBeacon(): boolean;
57
+ /**
58
+ * Get the number of events in the queue.
59
+ */
60
+ get queueSize(): number;
61
+ /**
62
+ * Destroy the logger (cleanup timers and listeners).
63
+ */
64
+ destroy(): void;
65
+ private _sendEvents;
66
+ private _persistFailedEvents;
67
+ private _retryFailedEvents;
68
+ private _startFlushTimer;
69
+ private _setupListeners;
70
+ private _removeListeners;
71
+ private _onPageHide;
72
+ private _onVisibilityChange;
73
+ private _onBeforeUnload;
74
+ }
75
+ //# sourceMappingURL=event-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-logger.d.ts","sourceRoot":"","sources":["../src/event-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAOpD,MAAM,WAAW,kBAAkB;IACjC,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,OAAO,EAAE,eAAe,CAAC;IACzB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,CAAyB;IAE1C,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,kBAAkB;IAkBvC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAShC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B;;;;;;;;;OASG;IACH,WAAW,IAAI,OAAO;IAgCtB;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,OAAO,IAAI,IAAI;YAQD,WAAW;IAezB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,WAAW,CAEjB;IAEF,OAAO,CAAC,mBAAmB,CAIzB;IAEF,OAAO,CAAC,eAAe,CAErB;CACH"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * EventLogger - Smart event batching with browser-specific features.
3
+ *
4
+ * Features:
5
+ * - Batches events (flush every N events or M seconds)
6
+ * - Uses navigator.sendBeacon() on page unload
7
+ * - Persists failed events to localStorage
8
+ * - Retries failed events on next session
9
+ * - Visibility-aware: flushes on visibilitychange to hidden
10
+ */
11
+ const FAILED_EVENTS_KEY = "failed_events";
12
+ const DEFAULT_BATCH_SIZE = 10;
13
+ const DEFAULT_FLUSH_INTERVAL_MS = 30000; // 30 seconds
14
+ const MAX_FAILED_EVENTS = 100;
15
+ export class EventLogger {
16
+ constructor(options) {
17
+ this._queue = [];
18
+ this._flushTimer = null;
19
+ this._isFlushing = false;
20
+ this._onPageHide = () => {
21
+ this.flushBeacon();
22
+ };
23
+ this._onVisibilityChange = () => {
24
+ if (document.visibilityState === "hidden") {
25
+ this.flushBeacon();
26
+ }
27
+ };
28
+ this._onBeforeUnload = () => {
29
+ this.flushBeacon();
30
+ };
31
+ this._endpoint = options.endpoint;
32
+ this._apiKey = options.apiKey;
33
+ this._storage = options.storage;
34
+ this._batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
35
+ this._flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
36
+ this._onError = options.onError;
37
+ // Set up browser event listeners
38
+ this._setupListeners();
39
+ // Retry failed events from previous session
40
+ this._retryFailedEvents();
41
+ // Start flush timer
42
+ this._startFlushTimer();
43
+ }
44
+ /**
45
+ * Log an event (added to batch queue).
46
+ */
47
+ log(event) {
48
+ this._queue.push(event);
49
+ // Auto-flush if batch is full
50
+ if (this._queue.length >= this._batchSize) {
51
+ this.flush();
52
+ }
53
+ }
54
+ /**
55
+ * Flush all queued events immediately.
56
+ */
57
+ async flush() {
58
+ if (this._isFlushing || this._queue.length === 0) {
59
+ return;
60
+ }
61
+ this._isFlushing = true;
62
+ // Take current queue
63
+ const events = [...this._queue];
64
+ this._queue = [];
65
+ try {
66
+ await this._sendEvents(events);
67
+ }
68
+ catch (error) {
69
+ // Persist failed events for retry
70
+ this._persistFailedEvents(events);
71
+ this._onError?.(error instanceof Error ? error : new Error(String(error)));
72
+ }
73
+ finally {
74
+ this._isFlushing = false;
75
+ }
76
+ }
77
+ /**
78
+ * Flush using fetch with keepalive (for page unload).
79
+ *
80
+ * We use fetch with keepalive: true instead of sendBeacon because:
81
+ * - sendBeacon cannot send custom headers (like Authorization)
82
+ * - keepalive ensures the request completes even as the page unloads
83
+ * - Same reliability guarantees as sendBeacon
84
+ *
85
+ * Returns true if request was initiated, false otherwise.
86
+ */
87
+ flushBeacon() {
88
+ if (this._queue.length === 0) {
89
+ return true;
90
+ }
91
+ if (typeof fetch === "undefined") {
92
+ // Fetch not available - try async flush
93
+ this.flush();
94
+ return false;
95
+ }
96
+ const events = [...this._queue];
97
+ this._queue = [];
98
+ // Use fetch with keepalive instead of sendBeacon
99
+ // This allows us to include the Authorization header
100
+ fetch(this._endpoint, {
101
+ method: "POST",
102
+ headers: {
103
+ "Content-Type": "application/json",
104
+ Authorization: `Bearer ${this._apiKey}`,
105
+ },
106
+ body: JSON.stringify({ events }),
107
+ keepalive: true,
108
+ }).catch(() => {
109
+ // Persist for retry on next session
110
+ this._persistFailedEvents(events);
111
+ });
112
+ return true;
113
+ }
114
+ /**
115
+ * Get the number of events in the queue.
116
+ */
117
+ get queueSize() {
118
+ return this._queue.length;
119
+ }
120
+ /**
121
+ * Destroy the logger (cleanup timers and listeners).
122
+ */
123
+ destroy() {
124
+ if (this._flushTimer) {
125
+ clearInterval(this._flushTimer);
126
+ this._flushTimer = null;
127
+ }
128
+ this._removeListeners();
129
+ }
130
+ async _sendEvents(events) {
131
+ const response = await fetch(this._endpoint, {
132
+ method: "POST",
133
+ headers: {
134
+ "Content-Type": "application/json",
135
+ Authorization: `Bearer ${this._apiKey}`,
136
+ },
137
+ body: JSON.stringify({ events }),
138
+ });
139
+ if (!response.ok) {
140
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
141
+ }
142
+ }
143
+ _persistFailedEvents(events) {
144
+ const existing = this._storage.get(FAILED_EVENTS_KEY) ?? [];
145
+ // Limit total stored events
146
+ const combined = [...existing, ...events].slice(-MAX_FAILED_EVENTS);
147
+ this._storage.set(FAILED_EVENTS_KEY, combined);
148
+ }
149
+ _retryFailedEvents() {
150
+ const failed = this._storage.get(FAILED_EVENTS_KEY);
151
+ if (!failed || failed.length === 0) {
152
+ return;
153
+ }
154
+ // Clear stored events
155
+ this._storage.remove(FAILED_EVENTS_KEY);
156
+ // Add to queue for retry
157
+ this._queue.push(...failed);
158
+ }
159
+ _startFlushTimer() {
160
+ if (this._flushIntervalMs <= 0)
161
+ return;
162
+ this._flushTimer = setInterval(() => {
163
+ this.flush().catch(() => {
164
+ // Errors handled in flush
165
+ });
166
+ }, this._flushIntervalMs);
167
+ }
168
+ _setupListeners() {
169
+ if (typeof window === "undefined")
170
+ return;
171
+ // Flush on page hide (covers tab close, navigation, etc.)
172
+ window.addEventListener("pagehide", this._onPageHide);
173
+ // Flush when page becomes hidden (tab switch, minimize)
174
+ document.addEventListener("visibilitychange", this._onVisibilityChange);
175
+ // Fallback: beforeunload for older browsers
176
+ window.addEventListener("beforeunload", this._onBeforeUnload);
177
+ }
178
+ _removeListeners() {
179
+ if (typeof window === "undefined")
180
+ return;
181
+ window.removeEventListener("pagehide", this._onPageHide);
182
+ document.removeEventListener("visibilitychange", this._onVisibilityChange);
183
+ window.removeEventListener("beforeunload", this._onBeforeUnload);
184
+ }
185
+ }
186
+ //# sourceMappingURL=event-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-logger.js","sourceRoot":"","sources":["../src/event-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * ExposureDeduplicator - Prevents duplicate exposure events.
3
+ *
4
+ * Same user seeing same variant should only count as 1 exposure.
5
+ * Uses session-based deduplication with localStorage persistence.
6
+ */
7
+ import type { StorageProvider } from "./storage.js";
8
+ export interface ExposureDeduplicatorOptions {
9
+ /** Storage provider for persistence */
10
+ storage: StorageProvider;
11
+ /** Session TTL in milliseconds (default: 30 minutes) */
12
+ sessionTtlMs?: number;
13
+ }
14
+ export declare class ExposureDeduplicator {
15
+ private _storage;
16
+ private _sessionTtlMs;
17
+ private _seen;
18
+ private _sessionStart;
19
+ constructor(options: ExposureDeduplicatorOptions);
20
+ /**
21
+ * Generate a deduplication key for an exposure.
22
+ *
23
+ * Key format: {unitKey}:{policyId}:{variant}
24
+ */
25
+ static createKey(unitKey: string, policyId: string, variant: string): string;
26
+ /**
27
+ * Check if an exposure should be tracked (not a duplicate).
28
+ * Returns true if this is a new exposure, false if duplicate.
29
+ */
30
+ shouldTrack(key: string): boolean;
31
+ /**
32
+ * Check and mark in one operation.
33
+ * Returns true if this was a new exposure (and is now marked as seen).
34
+ */
35
+ checkAndMark(unitKey: string, policyId: string, variant: string): boolean;
36
+ /**
37
+ * Clear all seen exposures (useful for testing or logout).
38
+ */
39
+ clear(): void;
40
+ /**
41
+ * Get the number of unique exposures in the current session.
42
+ */
43
+ get size(): number;
44
+ private _isSessionExpired;
45
+ private _resetSession;
46
+ private _persist;
47
+ private _restore;
48
+ }
49
+ //# sourceMappingURL=exposure-dedup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exposure-dedup.d.ts","sourceRoot":"","sources":["../src/exposure-dedup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAKpD,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,OAAO,EAAE,eAAe,CAAC;IACzB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AASD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,aAAa,CAAS;gBAElB,OAAO,EAAE,2BAA2B;IAUhD;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAI5E;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAiBjC;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAKzE;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,QAAQ;CAejB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * ExposureDeduplicator - Prevents duplicate exposure events.
3
+ *
4
+ * Same user seeing same variant should only count as 1 exposure.
5
+ * Uses session-based deduplication with localStorage persistence.
6
+ */
7
+ const STORAGE_KEY = "exposure_dedup";
8
+ const DEFAULT_SESSION_TTL_MS = 30 * 60 * 1000; // 30 minutes
9
+ export class ExposureDeduplicator {
10
+ constructor(options) {
11
+ this._storage = options.storage;
12
+ this._sessionTtlMs = options.sessionTtlMs ?? DEFAULT_SESSION_TTL_MS;
13
+ this._seen = new Set();
14
+ this._sessionStart = Date.now();
15
+ // Restore from storage
16
+ this._restore();
17
+ }
18
+ /**
19
+ * Generate a deduplication key for an exposure.
20
+ *
21
+ * Key format: {unitKey}:{policyId}:{variant}
22
+ */
23
+ static createKey(unitKey, policyId, variant) {
24
+ return `${unitKey}:${policyId}:${variant}`;
25
+ }
26
+ /**
27
+ * Check if an exposure should be tracked (not a duplicate).
28
+ * Returns true if this is a new exposure, false if duplicate.
29
+ */
30
+ shouldTrack(key) {
31
+ // Check if session has expired
32
+ if (this._isSessionExpired()) {
33
+ this._resetSession();
34
+ }
35
+ if (this._seen.has(key)) {
36
+ return false;
37
+ }
38
+ // Mark as seen
39
+ this._seen.add(key);
40
+ this._persist();
41
+ return true;
42
+ }
43
+ /**
44
+ * Check and mark in one operation.
45
+ * Returns true if this was a new exposure (and is now marked as seen).
46
+ */
47
+ checkAndMark(unitKey, policyId, variant) {
48
+ const key = ExposureDeduplicator.createKey(unitKey, policyId, variant);
49
+ return this.shouldTrack(key);
50
+ }
51
+ /**
52
+ * Clear all seen exposures (useful for testing or logout).
53
+ */
54
+ clear() {
55
+ this._seen.clear();
56
+ this._storage.remove(STORAGE_KEY);
57
+ }
58
+ /**
59
+ * Get the number of unique exposures in the current session.
60
+ */
61
+ get size() {
62
+ return this._seen.size;
63
+ }
64
+ _isSessionExpired() {
65
+ return Date.now() - this._sessionStart > this._sessionTtlMs;
66
+ }
67
+ _resetSession() {
68
+ this._seen.clear();
69
+ this._sessionStart = Date.now();
70
+ this._storage.remove(STORAGE_KEY);
71
+ }
72
+ _persist() {
73
+ const state = {
74
+ seen: Array.from(this._seen),
75
+ sessionStart: this._sessionStart,
76
+ };
77
+ this._storage.set(STORAGE_KEY, state, this._sessionTtlMs);
78
+ }
79
+ _restore() {
80
+ const state = this._storage.get(STORAGE_KEY);
81
+ if (!state)
82
+ return;
83
+ // Check if stored session is still valid
84
+ const sessionAge = Date.now() - state.sessionStart;
85
+ if (sessionAge > this._sessionTtlMs) {
86
+ this._storage.remove(STORAGE_KEY);
87
+ return;
88
+ }
89
+ // Restore state
90
+ this._seen = new Set(state.seen);
91
+ this._sessionStart = state.sessionStart;
92
+ }
93
+ }
94
+ //# sourceMappingURL=exposure-dedup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exposure-dedup.js","sourceRoot":"","sources":["../src/exposure-dedup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,sBAAsB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAgB5D,MAAM,OAAO,oBAAoB;IAM/B,YAAY,OAAoC;QAC9C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,IAAI,sBAAsB,CAAC;QACpE,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEhC,uBAAuB;QACvB,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,OAAe,EAAE,QAAgB,EAAE,OAAe;QACjE,OAAO,GAAG,OAAO,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,GAAW;QACrB,+BAA+B;QAC/B,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,eAAe;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEhB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,OAAe,EAAE,QAAgB,EAAE,OAAe;QAC7D,MAAM,GAAG,GAAG,oBAAoB,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAEO,iBAAiB;QACvB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;IAC9D,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAEO,QAAQ;QACd,MAAM,KAAK,GAAuB;YAChC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YAC5B,YAAY,EAAE,IAAI,CAAC,aAAa;SACjC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5D,CAAC;IAEO,QAAQ;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAqB,WAAW,CAAC,CAAC;QACjE,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,yCAAyC;QACzC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC;QACnD,IAAI,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,gBAAgB;QAChB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,YAAY,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Global entry point for IIFE bundle.
3
+ *
4
+ * Exports `window.Traffical` for script tag usage:
5
+ *
6
+ * ```html
7
+ * <script src="https://cdn.traffical.io/js-client/v1/traffical.min.js"></script>
8
+ * <script>
9
+ * Traffical.init({ ... }).then(function(client) {
10
+ * var params = client.getParams({ ... });
11
+ * });
12
+ * </script>
13
+ * ```
14
+ */
15
+ import { TrafficalClient, type TrafficalClientOptions } from "./client.js";
16
+ import type { TrafficalPlugin } from "./plugins/index.js";
17
+ import { createDOMBindingPlugin, type DOMBindingPlugin, type DOMBindingPluginOptions } from "./plugins/dom-binding.js";
18
+ /**
19
+ * Initialize the Traffical client (async).
20
+ * Returns the client instance.
21
+ */
22
+ declare function init(options: TrafficalClientOptions): Promise<TrafficalClient>;
23
+ /**
24
+ * Initialize the Traffical client (sync).
25
+ * Returns the client instance immediately, but config fetch happens async.
26
+ */
27
+ declare function initSync(options: TrafficalClientOptions): TrafficalClient;
28
+ /**
29
+ * Get the singleton client instance.
30
+ * Returns null if not initialized.
31
+ */
32
+ declare function instance(): TrafficalClient | null;
33
+ /**
34
+ * Destroy the singleton instance.
35
+ */
36
+ declare function destroy(): void;
37
+ export { init, initSync, instance, destroy, TrafficalClient, type TrafficalClientOptions, type TrafficalPlugin, createDOMBindingPlugin, type DOMBindingPlugin, type DOMBindingPluginOptions, };
38
+ //# sourceMappingURL=global.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.d.ts","sourceRoot":"","sources":["../src/global.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,eAAe,EAGf,KAAK,sBAAsB,EAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC7B,MAAM,0BAA0B,CAAC;AAKlC;;;GAGG;AACH,iBAAe,IAAI,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CAQ7E;AAED;;;GAGG;AACH,iBAAS,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAclE;AAED;;;GAGG;AACH,iBAAS,QAAQ,IAAI,eAAe,GAAG,IAAI,CAE1C;AAED;;GAEG;AACH,iBAAS,OAAO,IAAI,IAAI,CAKvB;AAGD,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EAEpB,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,CAAC"}
package/dist/global.js ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Global entry point for IIFE bundle.
3
+ *
4
+ * Exports `window.Traffical` for script tag usage:
5
+ *
6
+ * ```html
7
+ * <script src="https://cdn.traffical.io/js-client/v1/traffical.min.js"></script>
8
+ * <script>
9
+ * Traffical.init({ ... }).then(function(client) {
10
+ * var params = client.getParams({ ... });
11
+ * });
12
+ * </script>
13
+ * ```
14
+ */
15
+ import { TrafficalClient, createTrafficalClient, createTrafficalClientSync, } from "./client.js";
16
+ import { createDOMBindingPlugin, } from "./plugins/dom-binding.js";
17
+ // Global state for singleton pattern
18
+ let _instance = null;
19
+ /**
20
+ * Initialize the Traffical client (async).
21
+ * Returns the client instance.
22
+ */
23
+ async function init(options) {
24
+ if (_instance) {
25
+ console.warn("[Traffical] Client already initialized. Returning existing instance.");
26
+ return _instance;
27
+ }
28
+ _instance = await createTrafficalClient(options);
29
+ return _instance;
30
+ }
31
+ /**
32
+ * Initialize the Traffical client (sync).
33
+ * Returns the client instance immediately, but config fetch happens async.
34
+ */
35
+ function initSync(options) {
36
+ if (_instance) {
37
+ console.warn("[Traffical] Client already initialized. Returning existing instance.");
38
+ return _instance;
39
+ }
40
+ _instance = createTrafficalClientSync(options);
41
+ // Start async initialization in background
42
+ _instance.initialize().catch((error) => {
43
+ console.warn("[Traffical] Initialization error:", error);
44
+ });
45
+ return _instance;
46
+ }
47
+ /**
48
+ * Get the singleton client instance.
49
+ * Returns null if not initialized.
50
+ */
51
+ function instance() {
52
+ return _instance;
53
+ }
54
+ /**
55
+ * Destroy the singleton instance.
56
+ */
57
+ function destroy() {
58
+ if (_instance) {
59
+ _instance.destroy();
60
+ _instance = null;
61
+ }
62
+ }
63
+ // Export the Traffical global object
64
+ export { init, initSync, instance, destroy, TrafficalClient,
65
+ // DOM binding plugin
66
+ createDOMBindingPlugin, };
67
+ //# sourceMappingURL=global.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.js","sourceRoot":"","sources":["../src/global.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,yBAAyB,GAE1B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,GAGvB,MAAM,0BAA0B,CAAC;AAElC,qCAAqC;AACrC,IAAI,SAAS,GAA2B,IAAI,CAAC;AAE7C;;;GAGG;AACH,KAAK,UAAU,IAAI,CAAC,OAA+B;IACjD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QACrF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,SAAS,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CAAC,OAA+B;IAC/C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QACrF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,SAAS,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAE/C,2CAA2C;IAC3C,SAAS,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrC,OAAO,CAAC,IAAI,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ;IACf,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,OAAO;IACd,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,OAAO,EAAE,CAAC;QACpB,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;AACH,CAAC;AAED,qCAAqC;AACrC,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,eAAe;AAGf,qBAAqB;AACrB,sBAAsB,GAGvB,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @traffical/js-client
3
+ *
4
+ * Traffical JavaScript SDK for browser environments.
5
+ *
6
+ * Features:
7
+ * - Error boundary wrapping (P0) - SDK errors never crash your app
8
+ * - Exposure deduplication (P0) - Same user/variant = 1 exposure
9
+ * - Smart event batching (P1) - Batches events, uses sendBeacon on unload
10
+ * - Plugin system (P2) - Extensible via plugins
11
+ * - DOM binding plugin - Auto-apply parameters to DOM elements
12
+ * - Auto stable ID - Anonymous user identification
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { createTrafficalClient, createDOMBindingPlugin } from '@traffical/js-client';
17
+ *
18
+ * const traffical = await createTrafficalClient({
19
+ * orgId: 'org_123',
20
+ * projectId: 'proj_456',
21
+ * env: 'production',
22
+ * apiKey: 'pk_...',
23
+ * plugins: [createDOMBindingPlugin()],
24
+ * });
25
+ *
26
+ * const params = traffical.getParams({
27
+ * context: { userId: 'user_789' },
28
+ * defaults: { 'ui.button.color': '#000' },
29
+ * });
30
+ * ```
31
+ */
32
+ export * from "@traffical/core";
33
+ export { TrafficalClient, createTrafficalClient, createTrafficalClientSync, type TrafficalClientOptions, } from "./client.js";
34
+ export { ErrorBoundary, type ErrorBoundaryOptions } from "./error-boundary.js";
35
+ export { EventLogger, type EventLoggerOptions } from "./event-logger.js";
36
+ export { ExposureDeduplicator, type ExposureDeduplicatorOptions } from "./exposure-dedup.js";
37
+ export { StableIdProvider, type StableIdProviderOptions } from "./stable-id.js";
38
+ export { createStorageProvider, LocalStorageProvider, MemoryStorageProvider, type StorageProvider, } from "./storage.js";
39
+ export { PluginManager, type TrafficalPlugin, type PluginOptions } from "./plugins/index.js";
40
+ export { createDOMBindingPlugin, type DOMBindingPlugin, type DOMBindingPluginOptions, } from "./plugins/dom-binding.js";
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAG7F,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @traffical/js-client
3
+ *
4
+ * Traffical JavaScript SDK for browser environments.
5
+ *
6
+ * Features:
7
+ * - Error boundary wrapping (P0) - SDK errors never crash your app
8
+ * - Exposure deduplication (P0) - Same user/variant = 1 exposure
9
+ * - Smart event batching (P1) - Batches events, uses sendBeacon on unload
10
+ * - Plugin system (P2) - Extensible via plugins
11
+ * - DOM binding plugin - Auto-apply parameters to DOM elements
12
+ * - Auto stable ID - Anonymous user identification
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { createTrafficalClient, createDOMBindingPlugin } from '@traffical/js-client';
17
+ *
18
+ * const traffical = await createTrafficalClient({
19
+ * orgId: 'org_123',
20
+ * projectId: 'proj_456',
21
+ * env: 'production',
22
+ * apiKey: 'pk_...',
23
+ * plugins: [createDOMBindingPlugin()],
24
+ * });
25
+ *
26
+ * const params = traffical.getParams({
27
+ * context: { userId: 'user_789' },
28
+ * defaults: { 'ui.button.color': '#000' },
29
+ * });
30
+ * ```
31
+ */
32
+ // Re-export everything from core
33
+ export * from "@traffical/core";
34
+ // Export client
35
+ export { TrafficalClient, createTrafficalClient, createTrafficalClientSync, } from "./client.js";
36
+ // Export components for advanced usage
37
+ export { ErrorBoundary } from "./error-boundary.js";
38
+ export { EventLogger } from "./event-logger.js";
39
+ export { ExposureDeduplicator } from "./exposure-dedup.js";
40
+ export { StableIdProvider } from "./stable-id.js";
41
+ export { createStorageProvider, LocalStorageProvider, MemoryStorageProvider, } from "./storage.js";
42
+ // Export plugin system
43
+ export { PluginManager } from "./plugins/index.js";
44
+ // Export DOM binding plugin
45
+ export { createDOMBindingPlugin, } from "./plugins/dom-binding.js";
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,iCAAiC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,gBAAgB;AAChB,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,yBAAyB,GAE1B,MAAM,aAAa,CAAC;AAErB,uCAAuC;AACvC,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAoC,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAgC,MAAM,gBAAgB,CAAC;AAChF,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,GAEtB,MAAM,cAAc,CAAC;AAEtB,uBAAuB;AACvB,OAAO,EAAE,aAAa,EAA4C,MAAM,oBAAoB,CAAC;AAE7F,4BAA4B;AAC5B,OAAO,EACL,sBAAsB,GAGvB,MAAM,0BAA0B,CAAC"}