@traffical/node 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.
package/dist/client.js ADDED
@@ -0,0 +1,419 @@
1
+ /**
2
+ * Traffical Node.js SDK Client
3
+ *
4
+ * HTTP client with caching, background refresh, and graceful degradation.
5
+ * Wraps the pure core-ts resolution engine.
6
+ *
7
+ * Features:
8
+ * - ETag-based caching for efficient config fetches
9
+ * - Background refresh for keeping config up-to-date
10
+ * - Automatic decision tracking for intent-to-treat analysis
11
+ * - Batched event transport for efficiency
12
+ * - Graceful degradation with local config and schema defaults
13
+ */
14
+ import { resolveParameters, decide as coreDecide, DecisionDeduplicator, generateExposureId, generateTrackEventId, } from "@traffical/core";
15
+ import { EventBatcher } from "./event-batcher.js";
16
+ // =============================================================================
17
+ // Constants
18
+ // =============================================================================
19
+ const SDK_NAME = "node";
20
+ const SDK_VERSION = "0.1.0"; // Should match package.json version
21
+ const DEFAULT_BASE_URL = "https://sdk.traffical.io";
22
+ const DEFAULT_REFRESH_INTERVAL_MS = 60_000; // 1 minute
23
+ const OFFLINE_WARNING_INTERVAL_MS = 300_000; // 5 minutes
24
+ const DECISION_CACHE_MAX_SIZE = 1000; // Max decisions to cache for attribution lookup
25
+ // =============================================================================
26
+ // Traffical Client Class
27
+ // =============================================================================
28
+ /**
29
+ * TrafficalClient - the main SDK client for Node.js environments.
30
+ *
31
+ * Features:
32
+ * - ETag-based caching for efficient config fetches
33
+ * - Background refresh for keeping config up-to-date
34
+ * - Automatic decision tracking for intent-to-treat analysis
35
+ * - Batched event transport for efficiency
36
+ * - Graceful degradation with local config and schema defaults
37
+ * - Rate-limited offline warnings
38
+ */
39
+ export class TrafficalClient {
40
+ _options;
41
+ _state = {
42
+ bundle: null,
43
+ etag: null,
44
+ lastFetchTime: 0,
45
+ lastOfflineWarning: 0,
46
+ refreshTimer: null,
47
+ isInitialized: false,
48
+ };
49
+ _eventBatcher;
50
+ _decisionDedup;
51
+ /** Cache of recent decisions for attribution lookup on rewards */
52
+ _decisionCache = new Map();
53
+ constructor(options) {
54
+ this._options = {
55
+ orgId: options.orgId,
56
+ projectId: options.projectId,
57
+ env: options.env,
58
+ apiKey: options.apiKey,
59
+ baseUrl: options.baseUrl || DEFAULT_BASE_URL,
60
+ localConfig: options.localConfig,
61
+ refreshIntervalMs: options.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS,
62
+ strictMode: options.strictMode ?? false,
63
+ trackDecisions: options.trackDecisions !== false, // Default: true
64
+ };
65
+ // Initialize event batcher
66
+ this._eventBatcher = new EventBatcher({
67
+ endpoint: `${this._options.baseUrl}/v1/events/batch`,
68
+ apiKey: options.apiKey,
69
+ batchSize: options.eventBatchSize,
70
+ flushIntervalMs: options.eventFlushIntervalMs,
71
+ debug: options.debugEvents,
72
+ onError: (error) => {
73
+ console.warn(`[Traffical] Event batching error: ${error.message}`);
74
+ },
75
+ });
76
+ // Initialize decision deduplicator
77
+ this._decisionDedup = new DecisionDeduplicator({
78
+ ttlMs: options.decisionDeduplicationTtlMs,
79
+ });
80
+ // Initialize with local config if provided
81
+ if (this._options.localConfig) {
82
+ this._state.bundle = this._options.localConfig;
83
+ }
84
+ }
85
+ /**
86
+ * Initializes the client by fetching the config bundle.
87
+ * This is called automatically by createTrafficalClient.
88
+ */
89
+ async initialize() {
90
+ await this._fetchConfig();
91
+ this._startBackgroundRefresh();
92
+ this._state.isInitialized = true;
93
+ }
94
+ /**
95
+ * Stops background refresh and cleans up resources.
96
+ */
97
+ async destroy() {
98
+ if (this._state.refreshTimer) {
99
+ clearInterval(this._state.refreshTimer);
100
+ this._state.refreshTimer = null;
101
+ }
102
+ // Flush remaining events
103
+ await this._eventBatcher.destroy();
104
+ }
105
+ /**
106
+ * Synchronous destroy for process exit handlers.
107
+ * Use destroy() when possible for proper cleanup.
108
+ */
109
+ destroySync() {
110
+ if (this._state.refreshTimer) {
111
+ clearInterval(this._state.refreshTimer);
112
+ this._state.refreshTimer = null;
113
+ }
114
+ this._eventBatcher.destroySync();
115
+ }
116
+ /**
117
+ * Manually refreshes the config bundle.
118
+ */
119
+ async refreshConfig() {
120
+ await this._fetchConfig();
121
+ }
122
+ /**
123
+ * Gets the current config bundle version.
124
+ */
125
+ getConfigVersion() {
126
+ return this._state.bundle?.version ?? null;
127
+ }
128
+ /**
129
+ * Flush pending events immediately.
130
+ */
131
+ async flushEvents() {
132
+ await this._eventBatcher.flush();
133
+ }
134
+ /**
135
+ * Resolves parameters with defaults as fallback.
136
+ *
137
+ * Resolution priority (highest wins):
138
+ * 1. Policy overrides (from remote bundle)
139
+ * 2. Parameter defaults (from remote bundle)
140
+ * 3. Local config (if remote unavailable)
141
+ * 4. Caller defaults
142
+ */
143
+ getParams(options) {
144
+ const bundle = this._getEffectiveBundle();
145
+ return resolveParameters(bundle, options.context, options.defaults);
146
+ }
147
+ /**
148
+ * Makes a decision with full metadata for tracking.
149
+ *
150
+ * When trackDecisions is enabled (default), automatically sends a DecisionEvent
151
+ * to the backend for intent-to-treat analysis.
152
+ */
153
+ decide(options) {
154
+ const start = Date.now();
155
+ const bundle = this._getEffectiveBundle();
156
+ const decision = coreDecide(bundle, options.context, options.defaults);
157
+ const latencyMs = Date.now() - start;
158
+ // Cache decision for attribution lookup when trackReward is called
159
+ this._cacheDecision(decision);
160
+ // Auto-track decision if enabled
161
+ if (this._options.trackDecisions) {
162
+ this._trackDecision(decision, latencyMs, Object.keys(options.defaults));
163
+ }
164
+ return decision;
165
+ }
166
+ /**
167
+ * Tracks an exposure event.
168
+ *
169
+ * If the decision includes filtered context (from policies with contextLogging),
170
+ * it will be included in the exposure event for contextual bandit training.
171
+ */
172
+ trackExposure(decision) {
173
+ const unitKey = decision.metadata.unitKeyValue;
174
+ if (!unitKey) {
175
+ // Can't track without unit key
176
+ return;
177
+ }
178
+ const event = {
179
+ type: "exposure",
180
+ id: generateExposureId(), // Unique exposure ID (not same as decision)
181
+ decisionId: decision.decisionId,
182
+ orgId: this._options.orgId,
183
+ projectId: this._options.projectId,
184
+ env: this._options.env,
185
+ unitKey,
186
+ timestamp: new Date().toISOString(),
187
+ assignments: decision.assignments,
188
+ layers: decision.metadata.layers,
189
+ // Include filtered context for contextual bandit training
190
+ context: decision.metadata.filteredContext,
191
+ sdkName: SDK_NAME,
192
+ sdkVersion: SDK_VERSION,
193
+ };
194
+ this._eventBatcher.log(event);
195
+ }
196
+ /**
197
+ * Tracks a user event.
198
+ *
199
+ * @example
200
+ * // Track a purchase with revenue
201
+ * client.track('purchase', { value: 99.99, orderId: 'ord_123' });
202
+ *
203
+ * // Track a simple event
204
+ * client.track('add_to_cart', { itemId: 'sku_456' });
205
+ *
206
+ * // Track with explicit decision attribution
207
+ * client.track('checkout_complete', { value: 1 }, { decisionId: 'dec_xyz' });
208
+ */
209
+ track(event, properties, options) {
210
+ const value = typeof properties?.value === 'number' ? properties.value : undefined;
211
+ // Auto-populate attribution from cached decision if available
212
+ const attribution = this._getAttributionFromCache(options?.decisionId);
213
+ const trackEvent = {
214
+ type: "track",
215
+ id: generateTrackEventId(),
216
+ orgId: this._options.orgId,
217
+ projectId: this._options.projectId,
218
+ env: this._options.env,
219
+ unitKey: options?.unitKey || "",
220
+ timestamp: new Date().toISOString(),
221
+ event,
222
+ value,
223
+ properties,
224
+ decisionId: options?.decisionId,
225
+ attribution,
226
+ sdkName: SDK_NAME,
227
+ sdkVersion: SDK_VERSION,
228
+ };
229
+ this._eventBatcher.log(trackEvent);
230
+ }
231
+ /**
232
+ * @deprecated Use track() instead.
233
+ * Tracks a reward event.
234
+ * If decisionId is provided and the decision is cached, attribution is auto-populated.
235
+ */
236
+ trackReward(options) {
237
+ // Map old API to new track() API
238
+ this.track(options.event, options.properties, {
239
+ decisionId: undefined, // Not available in old API without decisionId
240
+ });
241
+ }
242
+ // ===========================================================================
243
+ // Private Methods
244
+ // ===========================================================================
245
+ /**
246
+ * Gets the effective bundle: remote > local > null
247
+ */
248
+ _getEffectiveBundle() {
249
+ return this._state.bundle ?? this._options.localConfig ?? null;
250
+ }
251
+ /**
252
+ * Fetches the config bundle from the edge worker.
253
+ * Uses ETag for efficient caching.
254
+ */
255
+ async _fetchConfig() {
256
+ const url = `${this._options.baseUrl}/v1/config/${this._options.projectId}?env=${this._options.env}`;
257
+ const headers = {
258
+ "Content-Type": "application/json",
259
+ Authorization: `Bearer ${this._options.apiKey}`,
260
+ };
261
+ // Add ETag for conditional request
262
+ if (this._state.etag) {
263
+ headers["If-None-Match"] = this._state.etag;
264
+ }
265
+ try {
266
+ const response = await fetch(url, { method: "GET", headers });
267
+ if (response.status === 304) {
268
+ // Not modified - bundle is still valid
269
+ this._state.lastFetchTime = Date.now();
270
+ return;
271
+ }
272
+ if (!response.ok) {
273
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
274
+ }
275
+ const bundle = (await response.json());
276
+ const etag = response.headers.get("ETag");
277
+ this._state.bundle = bundle;
278
+ this._state.etag = etag;
279
+ this._state.lastFetchTime = Date.now();
280
+ }
281
+ catch (error) {
282
+ this._logOfflineWarning(error);
283
+ }
284
+ }
285
+ /**
286
+ * Starts background refresh timer.
287
+ */
288
+ _startBackgroundRefresh() {
289
+ if (this._options.refreshIntervalMs <= 0) {
290
+ return;
291
+ }
292
+ this._state.refreshTimer = setInterval(() => {
293
+ this._fetchConfig().catch(() => {
294
+ // Errors are logged in _fetchConfig
295
+ });
296
+ }, this._options.refreshIntervalMs);
297
+ // Unref so timer doesn't keep process alive
298
+ if (typeof this._state.refreshTimer.unref === "function") {
299
+ this._state.refreshTimer.unref();
300
+ }
301
+ }
302
+ /**
303
+ * Logs an offline warning (rate-limited).
304
+ */
305
+ _logOfflineWarning(error) {
306
+ const now = Date.now();
307
+ if (now - this._state.lastOfflineWarning > OFFLINE_WARNING_INTERVAL_MS) {
308
+ console.warn(`[Traffical] Failed to fetch config: ${error instanceof Error ? error.message : String(error)}. Using ${this._state.bundle ? "cached" : "local"} config.`);
309
+ this._state.lastOfflineWarning = now;
310
+ }
311
+ }
312
+ /**
313
+ * Tracks a decision event (internal).
314
+ * Called automatically when trackDecisions is enabled.
315
+ */
316
+ _trackDecision(decision, latencyMs, requestedParameters) {
317
+ const unitKey = decision.metadata.unitKeyValue;
318
+ if (!unitKey) {
319
+ // Can't track without unit key
320
+ return;
321
+ }
322
+ // Hash assignments for deduplication
323
+ const hash = DecisionDeduplicator.hashAssignments(decision.assignments);
324
+ // Check deduplication
325
+ if (!this._decisionDedup.checkAndMark(unitKey, hash)) {
326
+ return; // Duplicate, skip
327
+ }
328
+ // Build the decision event
329
+ const event = {
330
+ type: "decision",
331
+ id: decision.decisionId,
332
+ orgId: this._options.orgId,
333
+ projectId: this._options.projectId,
334
+ env: this._options.env,
335
+ unitKey,
336
+ timestamp: decision.metadata.timestamp,
337
+ requestedParameters,
338
+ assignments: decision.assignments,
339
+ layers: decision.metadata.layers,
340
+ latencyMs,
341
+ // Include filtered context if available
342
+ context: decision.metadata.filteredContext,
343
+ sdkName: SDK_NAME,
344
+ sdkVersion: SDK_VERSION,
345
+ };
346
+ this._eventBatcher.log(event);
347
+ }
348
+ /**
349
+ * Caches a decision for attribution lookup when trackReward is called.
350
+ * Maintains a bounded cache to prevent memory leaks.
351
+ */
352
+ _cacheDecision(decision) {
353
+ // Evict oldest entries if cache is full
354
+ if (this._decisionCache.size >= DECISION_CACHE_MAX_SIZE) {
355
+ // Get first (oldest) key and delete it
356
+ const firstKey = this._decisionCache.keys().next().value;
357
+ if (firstKey) {
358
+ this._decisionCache.delete(firstKey);
359
+ }
360
+ }
361
+ this._decisionCache.set(decision.decisionId, decision);
362
+ }
363
+ /**
364
+ * Gets attribution info from cached decision if available.
365
+ */
366
+ _getAttributionFromCache(decisionId) {
367
+ if (!decisionId) {
368
+ return undefined;
369
+ }
370
+ const cachedDecision = this._decisionCache.get(decisionId);
371
+ if (!cachedDecision) {
372
+ return undefined;
373
+ }
374
+ const attribution = cachedDecision.metadata.layers
375
+ .filter((l) => l.policyId && l.allocationName)
376
+ .map((l) => ({
377
+ layerId: l.layerId,
378
+ policyId: l.policyId,
379
+ allocationName: l.allocationName,
380
+ }));
381
+ return attribution.length > 0 ? attribution : undefined;
382
+ }
383
+ }
384
+ // =============================================================================
385
+ // Factory Function
386
+ // =============================================================================
387
+ /**
388
+ * Creates and initializes a Traffical client.
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * const traffical = await createTrafficalClient({
393
+ * orgId: "org_123",
394
+ * projectId: "proj_456",
395
+ * env: "production",
396
+ * apiKey: "sk_...",
397
+ * });
398
+ *
399
+ * const params = traffical.getParams({
400
+ * context: { userId: "user_789" },
401
+ * defaults: {
402
+ * "ui.button.color": "#000",
403
+ * },
404
+ * });
405
+ * ```
406
+ */
407
+ export async function createTrafficalClient(options) {
408
+ const client = new TrafficalClient(options);
409
+ await client.initialize();
410
+ return client;
411
+ }
412
+ /**
413
+ * Creates a Traffical client without initializing (synchronous).
414
+ * Useful when you want to control initialization timing.
415
+ */
416
+ export function createTrafficalClientSync(options) {
417
+ return new TrafficalClient(options);
418
+ }
419
+ //# 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,74 @@
1
+ /**
2
+ * EventBatcher - Batched event transport for Node.js environments.
3
+ *
4
+ * Features:
5
+ * - Batches events for efficient network usage
6
+ * - Flushes on batch size or interval (whichever comes first)
7
+ * - Graceful shutdown with final flush
8
+ * - Error handling with configurable callback
9
+ *
10
+ * Unlike the browser EventLogger, this implementation:
11
+ * - Does not use sendBeacon (Node.js doesn't have it)
12
+ * - Does not persist failed events to storage
13
+ * - Uses standard fetch for HTTP requests
14
+ */
15
+ import type { TrackableEvent } from "@traffical/core";
16
+ /**
17
+ * Options for EventBatcher.
18
+ */
19
+ export interface EventBatcherOptions {
20
+ /** API endpoint for events */
21
+ endpoint: string;
22
+ /** API key for authentication */
23
+ apiKey: string;
24
+ /** Max events before auto-flush (default: 10) */
25
+ batchSize?: number;
26
+ /** Auto-flush interval in ms (default: 30000) */
27
+ flushIntervalMs?: number;
28
+ /** Callback on flush error */
29
+ onError?: (error: Error) => void;
30
+ /** Enable debug logging */
31
+ debug?: boolean;
32
+ }
33
+ export declare class EventBatcher {
34
+ private readonly _endpoint;
35
+ private readonly _apiKey;
36
+ private readonly _batchSize;
37
+ private readonly _flushIntervalMs;
38
+ private readonly _onError?;
39
+ private readonly _debug;
40
+ private _queue;
41
+ private _flushTimer;
42
+ private _isFlushing;
43
+ private _isDestroyed;
44
+ constructor(options: EventBatcherOptions);
45
+ /**
46
+ * Log an event (added to batch queue).
47
+ */
48
+ log(event: TrackableEvent): void;
49
+ /**
50
+ * Flush all queued events immediately.
51
+ */
52
+ flush(): Promise<void>;
53
+ /**
54
+ * Get the number of events in the queue.
55
+ */
56
+ get queueSize(): number;
57
+ /**
58
+ * Check if the batcher is destroyed.
59
+ */
60
+ get isDestroyed(): boolean;
61
+ /**
62
+ * Destroy the batcher (cleanup timers and flush remaining events).
63
+ */
64
+ destroy(): Promise<void>;
65
+ /**
66
+ * Synchronous destroy (for process exit handlers).
67
+ * Does not wait for flush to complete.
68
+ */
69
+ destroySync(): void;
70
+ private _sendEvents;
71
+ private _startFlushTimer;
72
+ private _log;
73
+ }
74
+ //# sourceMappingURL=event-batcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-batcher.d.ts","sourceRoot":"","sources":["../src/event-batcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,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;IACjC,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;gBAEjB,OAAO,EAAE,mBAAmB;IAYxC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAkBhC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB9B;;;OAGG;IACH,WAAW,IAAI,IAAI;YAgBL,WAAW;IAezB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,IAAI;CAKb"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * EventBatcher - Batched event transport for Node.js environments.
3
+ *
4
+ * Features:
5
+ * - Batches events for efficient network usage
6
+ * - Flushes on batch size or interval (whichever comes first)
7
+ * - Graceful shutdown with final flush
8
+ * - Error handling with configurable callback
9
+ *
10
+ * Unlike the browser EventLogger, this implementation:
11
+ * - Does not use sendBeacon (Node.js doesn't have it)
12
+ * - Does not persist failed events to storage
13
+ * - Uses standard fetch for HTTP requests
14
+ */
15
+ const DEFAULT_BATCH_SIZE = 10;
16
+ const DEFAULT_FLUSH_INTERVAL_MS = 30_000; // 30 seconds
17
+ export class EventBatcher {
18
+ _endpoint;
19
+ _apiKey;
20
+ _batchSize;
21
+ _flushIntervalMs;
22
+ _onError;
23
+ _debug;
24
+ _queue = [];
25
+ _flushTimer = null;
26
+ _isFlushing = false;
27
+ _isDestroyed = false;
28
+ constructor(options) {
29
+ this._endpoint = options.endpoint;
30
+ this._apiKey = options.apiKey;
31
+ this._batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
32
+ this._flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
33
+ this._onError = options.onError;
34
+ this._debug = options.debug ?? false;
35
+ // Start flush timer
36
+ this._startFlushTimer();
37
+ }
38
+ /**
39
+ * Log an event (added to batch queue).
40
+ */
41
+ log(event) {
42
+ if (this._isDestroyed) {
43
+ this._log("Attempted to log event after destroy, ignoring");
44
+ return;
45
+ }
46
+ this._queue.push(event);
47
+ this._log(`Event queued (queue size: ${this._queue.length})`);
48
+ // Auto-flush if batch is full
49
+ if (this._queue.length >= this._batchSize) {
50
+ this._log("Batch size reached, flushing");
51
+ this.flush().catch(() => {
52
+ // Errors handled in flush
53
+ });
54
+ }
55
+ }
56
+ /**
57
+ * Flush all queued events immediately.
58
+ */
59
+ async flush() {
60
+ if (this._isFlushing || this._queue.length === 0) {
61
+ return;
62
+ }
63
+ this._isFlushing = true;
64
+ // Take current queue
65
+ const events = [...this._queue];
66
+ this._queue = [];
67
+ try {
68
+ await this._sendEvents(events);
69
+ this._log(`Flushed ${events.length} events successfully`);
70
+ }
71
+ catch (error) {
72
+ // Put events back in queue for retry (at the front)
73
+ this._queue.unshift(...events);
74
+ this._log(`Flush failed, ${events.length} events re-queued`);
75
+ this._onError?.(error instanceof Error ? error : new Error(String(error)));
76
+ }
77
+ finally {
78
+ this._isFlushing = false;
79
+ }
80
+ }
81
+ /**
82
+ * Get the number of events in the queue.
83
+ */
84
+ get queueSize() {
85
+ return this._queue.length;
86
+ }
87
+ /**
88
+ * Check if the batcher is destroyed.
89
+ */
90
+ get isDestroyed() {
91
+ return this._isDestroyed;
92
+ }
93
+ /**
94
+ * Destroy the batcher (cleanup timers and flush remaining events).
95
+ */
96
+ async destroy() {
97
+ if (this._isDestroyed) {
98
+ return;
99
+ }
100
+ this._isDestroyed = true;
101
+ // Stop timer
102
+ if (this._flushTimer) {
103
+ clearInterval(this._flushTimer);
104
+ this._flushTimer = null;
105
+ }
106
+ // Final flush
107
+ if (this._queue.length > 0) {
108
+ this._log(`Destroying with ${this._queue.length} events in queue, flushing`);
109
+ await this.flush();
110
+ }
111
+ }
112
+ /**
113
+ * Synchronous destroy (for process exit handlers).
114
+ * Does not wait for flush to complete.
115
+ */
116
+ destroySync() {
117
+ this._isDestroyed = true;
118
+ if (this._flushTimer) {
119
+ clearInterval(this._flushTimer);
120
+ this._flushTimer = null;
121
+ }
122
+ // Attempt to flush but don't wait
123
+ if (this._queue.length > 0) {
124
+ this.flush().catch(() => {
125
+ // Best effort on shutdown
126
+ });
127
+ }
128
+ }
129
+ async _sendEvents(events) {
130
+ const response = await fetch(this._endpoint, {
131
+ method: "POST",
132
+ headers: {
133
+ "Content-Type": "application/json",
134
+ Authorization: `Bearer ${this._apiKey}`,
135
+ },
136
+ body: JSON.stringify({ events }),
137
+ });
138
+ if (!response.ok) {
139
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
140
+ }
141
+ }
142
+ _startFlushTimer() {
143
+ if (this._flushIntervalMs <= 0) {
144
+ return;
145
+ }
146
+ this._flushTimer = setInterval(() => {
147
+ if (this._queue.length > 0) {
148
+ this.flush().catch(() => {
149
+ // Errors handled in flush
150
+ });
151
+ }
152
+ }, this._flushIntervalMs);
153
+ // Unref the timer so it doesn't keep the process alive
154
+ // This is important for Node.js servers that need to shutdown gracefully
155
+ if (typeof this._flushTimer.unref === "function") {
156
+ this._flushTimer.unref();
157
+ }
158
+ }
159
+ _log(message) {
160
+ if (this._debug) {
161
+ console.log(`[Traffical EventBatcher] ${message}`);
162
+ }
163
+ }
164
+ }
165
+ //# sourceMappingURL=event-batcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-batcher.js","sourceRoot":"","sources":["../src/event-batcher.ts"],"names":[],"mappings":"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"}