@od-oneapp/analytics 2026.1.1301

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 (184) hide show
  1. package/README.md +509 -0
  2. package/dist/ai-YMnynb-t.mjs +3347 -0
  3. package/dist/ai-YMnynb-t.mjs.map +1 -0
  4. package/dist/chunk-DQk6qfdC.mjs +18 -0
  5. package/dist/client-CTzJVFU5.mjs +9 -0
  6. package/dist/client-CTzJVFU5.mjs.map +1 -0
  7. package/dist/client-CcFTauAh.mjs +54 -0
  8. package/dist/client-CcFTauAh.mjs.map +1 -0
  9. package/dist/client-CeOLjbac.mjs +281 -0
  10. package/dist/client-CeOLjbac.mjs.map +1 -0
  11. package/dist/client-D339NFJS.mjs +267 -0
  12. package/dist/client-D339NFJS.mjs.map +1 -0
  13. package/dist/client-next.d.mts +62 -0
  14. package/dist/client-next.d.mts.map +1 -0
  15. package/dist/client-next.mjs +525 -0
  16. package/dist/client-next.mjs.map +1 -0
  17. package/dist/client.d.mts +30 -0
  18. package/dist/client.d.mts.map +1 -0
  19. package/dist/client.mjs +186 -0
  20. package/dist/client.mjs.map +1 -0
  21. package/dist/config-DPS6bSYo.d.mts +34 -0
  22. package/dist/config-DPS6bSYo.d.mts.map +1 -0
  23. package/dist/config-P6P5adJg.mjs +287 -0
  24. package/dist/config-P6P5adJg.mjs.map +1 -0
  25. package/dist/console-8bND3mMU.mjs +128 -0
  26. package/dist/console-8bND3mMU.mjs.map +1 -0
  27. package/dist/ecommerce-Cgu4wlux.mjs +993 -0
  28. package/dist/ecommerce-Cgu4wlux.mjs.map +1 -0
  29. package/dist/emitters-6-nKo8i-.mjs +208 -0
  30. package/dist/emitters-6-nKo8i-.mjs.map +1 -0
  31. package/dist/emitters-DldkVSPp.d.mts +12 -0
  32. package/dist/emitters-DldkVSPp.d.mts.map +1 -0
  33. package/dist/index-BfNWgfa5.d.mts +1494 -0
  34. package/dist/index-BfNWgfa5.d.mts.map +1 -0
  35. package/dist/index-BkIWe--N.d.mts +953 -0
  36. package/dist/index-BkIWe--N.d.mts.map +1 -0
  37. package/dist/index-jPzXRn52.d.mts +184 -0
  38. package/dist/index-jPzXRn52.d.mts.map +1 -0
  39. package/dist/manager-DvRRjza6.d.mts +76 -0
  40. package/dist/manager-DvRRjza6.d.mts.map +1 -0
  41. package/dist/posthog-bootstrap-CYfIy_WS.mjs +1769 -0
  42. package/dist/posthog-bootstrap-CYfIy_WS.mjs.map +1 -0
  43. package/dist/posthog-bootstrap-DWxFrxlt.d.mts +81 -0
  44. package/dist/posthog-bootstrap-DWxFrxlt.d.mts.map +1 -0
  45. package/dist/providers-http-client.d.mts +37 -0
  46. package/dist/providers-http-client.d.mts.map +1 -0
  47. package/dist/providers-http-client.mjs +320 -0
  48. package/dist/providers-http-client.mjs.map +1 -0
  49. package/dist/providers-http-server.d.mts +31 -0
  50. package/dist/providers-http-server.d.mts.map +1 -0
  51. package/dist/providers-http-server.mjs +297 -0
  52. package/dist/providers-http-server.mjs.map +1 -0
  53. package/dist/providers-http.d.mts +46 -0
  54. package/dist/providers-http.d.mts.map +1 -0
  55. package/dist/providers-http.mjs +4 -0
  56. package/dist/server-edge.d.mts +9 -0
  57. package/dist/server-edge.d.mts.map +1 -0
  58. package/dist/server-edge.mjs +373 -0
  59. package/dist/server-edge.mjs.map +1 -0
  60. package/dist/server-next.d.mts +67 -0
  61. package/dist/server-next.d.mts.map +1 -0
  62. package/dist/server-next.mjs +193 -0
  63. package/dist/server-next.mjs.map +1 -0
  64. package/dist/server.d.mts +10 -0
  65. package/dist/server.mjs +7 -0
  66. package/dist/service-cYtBBL8x.mjs +945 -0
  67. package/dist/service-cYtBBL8x.mjs.map +1 -0
  68. package/dist/shared.d.mts +16 -0
  69. package/dist/shared.d.mts.map +1 -0
  70. package/dist/shared.mjs +93 -0
  71. package/dist/shared.mjs.map +1 -0
  72. package/dist/types-BxBnNQ0V.d.mts +354 -0
  73. package/dist/types-BxBnNQ0V.d.mts.map +1 -0
  74. package/dist/types-CBvxUEaF.d.mts +216 -0
  75. package/dist/types-CBvxUEaF.d.mts.map +1 -0
  76. package/dist/types.d.mts +4 -0
  77. package/dist/types.mjs +0 -0
  78. package/dist/vercel-types-lwakUfoI.d.mts +102 -0
  79. package/dist/vercel-types-lwakUfoI.d.mts.map +1 -0
  80. package/package.json +129 -0
  81. package/src/client/index.ts +164 -0
  82. package/src/client/manager.ts +71 -0
  83. package/src/client/next/components.tsx +270 -0
  84. package/src/client/next/hooks.ts +217 -0
  85. package/src/client/next/manager.ts +141 -0
  86. package/src/client/next.ts +144 -0
  87. package/src/client-next.ts +101 -0
  88. package/src/client.ts +89 -0
  89. package/src/examples/ai-sdk-patterns.ts +583 -0
  90. package/src/examples/emitter-patterns.ts +476 -0
  91. package/src/examples/nextjs-emitter-patterns.tsx +403 -0
  92. package/src/next/app-router.tsx +564 -0
  93. package/src/next/client.ts +419 -0
  94. package/src/next/index.ts +84 -0
  95. package/src/next/middleware.ts +429 -0
  96. package/src/next/rsc.tsx +300 -0
  97. package/src/next/server.ts +253 -0
  98. package/src/next/types.d.ts +220 -0
  99. package/src/providers/base-provider.ts +419 -0
  100. package/src/providers/console/client.ts +10 -0
  101. package/src/providers/console/index.ts +152 -0
  102. package/src/providers/console/server.ts +6 -0
  103. package/src/providers/console/types.ts +15 -0
  104. package/src/providers/http/client.ts +464 -0
  105. package/src/providers/http/index.ts +30 -0
  106. package/src/providers/http/server.ts +396 -0
  107. package/src/providers/http/types.ts +135 -0
  108. package/src/providers/posthog/client.ts +518 -0
  109. package/src/providers/posthog/index.ts +11 -0
  110. package/src/providers/posthog/server.ts +329 -0
  111. package/src/providers/posthog/types.ts +104 -0
  112. package/src/providers/segment/client.ts +113 -0
  113. package/src/providers/segment/index.ts +11 -0
  114. package/src/providers/segment/server.ts +115 -0
  115. package/src/providers/segment/types.ts +51 -0
  116. package/src/providers/vercel/client.ts +102 -0
  117. package/src/providers/vercel/index.ts +11 -0
  118. package/src/providers/vercel/server.ts +89 -0
  119. package/src/providers/vercel/types.ts +27 -0
  120. package/src/server/index.ts +103 -0
  121. package/src/server/manager.ts +62 -0
  122. package/src/server/next.ts +210 -0
  123. package/src/server-edge.ts +442 -0
  124. package/src/server-next.ts +39 -0
  125. package/src/server.ts +106 -0
  126. package/src/shared/emitters/ai/README.md +981 -0
  127. package/src/shared/emitters/ai/events/agent.ts +130 -0
  128. package/src/shared/emitters/ai/events/artifacts.ts +167 -0
  129. package/src/shared/emitters/ai/events/chat.ts +126 -0
  130. package/src/shared/emitters/ai/events/chatbot-ecommerce.ts +133 -0
  131. package/src/shared/emitters/ai/events/completion.ts +103 -0
  132. package/src/shared/emitters/ai/events/content-generation.ts +347 -0
  133. package/src/shared/emitters/ai/events/conversation.ts +332 -0
  134. package/src/shared/emitters/ai/events/product-features.ts +1402 -0
  135. package/src/shared/emitters/ai/events/streaming.ts +114 -0
  136. package/src/shared/emitters/ai/events/tool.ts +93 -0
  137. package/src/shared/emitters/ai/index.ts +69 -0
  138. package/src/shared/emitters/ai/track-ai-sdk.ts +74 -0
  139. package/src/shared/emitters/ai/track-ai.ts +50 -0
  140. package/src/shared/emitters/ai/types.ts +1041 -0
  141. package/src/shared/emitters/ai/utils.ts +468 -0
  142. package/src/shared/emitters/ecommerce/events/cart-checkout.ts +106 -0
  143. package/src/shared/emitters/ecommerce/events/coupon.ts +49 -0
  144. package/src/shared/emitters/ecommerce/events/engagement.ts +61 -0
  145. package/src/shared/emitters/ecommerce/events/marketplace.ts +119 -0
  146. package/src/shared/emitters/ecommerce/events/order.ts +199 -0
  147. package/src/shared/emitters/ecommerce/events/product.ts +205 -0
  148. package/src/shared/emitters/ecommerce/events/registry.ts +123 -0
  149. package/src/shared/emitters/ecommerce/events/wishlist-sharing.ts +140 -0
  150. package/src/shared/emitters/ecommerce/index.ts +46 -0
  151. package/src/shared/emitters/ecommerce/track-ecommerce.ts +53 -0
  152. package/src/shared/emitters/ecommerce/types.ts +314 -0
  153. package/src/shared/emitters/ecommerce/utils.ts +216 -0
  154. package/src/shared/emitters/emitter-types.ts +974 -0
  155. package/src/shared/emitters/emitters.ts +292 -0
  156. package/src/shared/emitters/helpers.ts +419 -0
  157. package/src/shared/emitters/index.ts +66 -0
  158. package/src/shared/index.ts +142 -0
  159. package/src/shared/ingestion/index.ts +66 -0
  160. package/src/shared/ingestion/schemas.ts +386 -0
  161. package/src/shared/ingestion/service.ts +628 -0
  162. package/src/shared/node22-features.ts +848 -0
  163. package/src/shared/providers/console-provider.ts +160 -0
  164. package/src/shared/types/base-types.ts +54 -0
  165. package/src/shared/types/console-types.ts +19 -0
  166. package/src/shared/types/posthog-types.ts +131 -0
  167. package/src/shared/types/segment-types.ts +15 -0
  168. package/src/shared/types/types.ts +397 -0
  169. package/src/shared/types/vercel-types.ts +19 -0
  170. package/src/shared/utils/config-client.ts +19 -0
  171. package/src/shared/utils/config.ts +250 -0
  172. package/src/shared/utils/emitter-adapter.ts +212 -0
  173. package/src/shared/utils/manager.test.ts +36 -0
  174. package/src/shared/utils/manager.ts +1322 -0
  175. package/src/shared/utils/posthog-bootstrap.ts +136 -0
  176. package/src/shared/utils/posthog-client-utils.ts +48 -0
  177. package/src/shared/utils/posthog-next-utils.ts +282 -0
  178. package/src/shared/utils/posthog-server-utils.ts +210 -0
  179. package/src/shared/utils/rate-limit.ts +289 -0
  180. package/src/shared/utils/security.ts +545 -0
  181. package/src/shared/utils/validation-client.ts +161 -0
  182. package/src/shared/utils/validation.ts +399 -0
  183. package/src/shared.ts +155 -0
  184. package/src/types/index.ts +62 -0
@@ -0,0 +1,396 @@
1
+ /**
2
+ * @fileoverview HTTP provider for server/Node.js environments
3
+ *
4
+ * Provides HTTP-based analytics event sending for server-side applications.
5
+ * Sends events to a remote ingestion endpoint (e.g., oneapp-api/ingest).
6
+ *
7
+ * Features:
8
+ * - Event batching for efficiency
9
+ * - Automatic flush on interval or batch size
10
+ * - Retry with exponential backoff
11
+ * - Graceful shutdown with final flush
12
+ *
13
+ * @module @od-oneapp/analytics/providers/http/server
14
+ */
15
+
16
+ import { logDebug, logError, logWarn } from '@repo/shared/logs';
17
+
18
+ import type { HttpProviderConfig, IngestionResponse, QueuedEvent } from './types';
19
+ import type {
20
+ AnalyticsContext,
21
+ AnalyticsProvider,
22
+ GroupTraits,
23
+ PageProperties,
24
+ Properties,
25
+ ProviderConfig,
26
+ UserTraits,
27
+ } from '../../shared/types/types';
28
+
29
+ /** Default configuration values */
30
+ const DEFAULTS = {
31
+ batchSize: 10,
32
+ flushInterval: 5000,
33
+ timeout: 10000,
34
+ retries: 3,
35
+ } as const;
36
+
37
+ /** Base delay for exponential backoff in ms */
38
+ const BACKOFF_BASE_MS = 1000;
39
+
40
+ /**
41
+ * HTTP Analytics Provider for server environments.
42
+ *
43
+ * Sends analytics events to a remote endpoint via HTTP POST requests.
44
+ * Events are batched and flushed periodically for efficiency.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const provider = new HttpServerProvider({
49
+ * options: {
50
+ * endpoint: 'https://api.oneapp.dev/v1/ingest',
51
+ * apiKey: process.env.ANALYTICS_API_KEY,
52
+ * },
53
+ * });
54
+ * await provider.initialize();
55
+ * await provider.track('Button Clicked', { button: 'signup' });
56
+ * await provider.flush(); // Send queued events
57
+ * ```
58
+ */
59
+ export class HttpServerProvider implements AnalyticsProvider {
60
+ readonly name = 'http';
61
+
62
+ private config: Required<
63
+ Pick<HttpProviderConfig, 'batchSize' | 'flushInterval' | 'timeout' | 'retries'>
64
+ > &
65
+ HttpProviderConfig;
66
+ private isInitialized = false;
67
+ private queue: QueuedEvent[] = [];
68
+ private flushTimer: ReturnType<typeof setInterval> | null = null;
69
+ private userId?: string;
70
+ private anonymousId: string;
71
+ private isFlushing = false;
72
+
73
+ constructor(providerConfig: ProviderConfig) {
74
+ const options = (providerConfig.options ?? {}) as unknown as HttpProviderConfig;
75
+
76
+ if (!options.endpoint) {
77
+ throw new Error('HttpProvider requires an endpoint URL');
78
+ }
79
+
80
+ this.config = {
81
+ ...options,
82
+ batchSize: options.batchSize ?? DEFAULTS.batchSize,
83
+ flushInterval: options.flushInterval ?? DEFAULTS.flushInterval,
84
+ timeout: options.timeout ?? DEFAULTS.timeout,
85
+ retries: options.retries ?? DEFAULTS.retries,
86
+ };
87
+
88
+ this.userId = options.userId;
89
+ this.anonymousId = options.anonymousId ?? this.generateAnonymousId();
90
+ }
91
+
92
+ async initialize(): Promise<void> {
93
+ if (this.isInitialized) return;
94
+
95
+ // Start auto-flush timer if interval > 0
96
+ if (this.config.flushInterval > 0) {
97
+ this.flushTimer = setInterval(() => {
98
+ void this.flush();
99
+ }, this.config.flushInterval);
100
+
101
+ // Unref the timer so it doesn't prevent Node.js from exiting
102
+ if (typeof this.flushTimer.unref === 'function') {
103
+ this.flushTimer.unref();
104
+ }
105
+ }
106
+
107
+ if (this.config.debug) {
108
+ logDebug('HTTP Analytics Provider initialized', {
109
+ provider: 'http',
110
+ endpoint: this.config.endpoint,
111
+ batchSize: this.config.batchSize,
112
+ flushInterval: this.config.flushInterval,
113
+ });
114
+ }
115
+
116
+ this.isInitialized = true;
117
+ }
118
+
119
+ async track(
120
+ event: string,
121
+ properties: Properties = {},
122
+ _context?: AnalyticsContext,
123
+ ): Promise<void> {
124
+ if (!this.isInitialized) {
125
+ logWarn('HTTP provider not initialized', { provider: 'http', operation: 'track', event });
126
+ return;
127
+ }
128
+
129
+ this.enqueue({
130
+ type: 'track',
131
+ event,
132
+ properties,
133
+ timestamp: new Date().toISOString(),
134
+ userId: this.userId,
135
+ anonymousId: this.anonymousId,
136
+ });
137
+ }
138
+
139
+ async identify(
140
+ userId: string,
141
+ traits: UserTraits = {},
142
+ _context?: AnalyticsContext,
143
+ ): Promise<void> {
144
+ if (!this.isInitialized) {
145
+ logWarn('HTTP provider not initialized', { provider: 'http', operation: 'identify', userId });
146
+ return;
147
+ }
148
+
149
+ // Update stored user ID
150
+ this.userId = userId;
151
+
152
+ this.enqueue({
153
+ type: 'identify',
154
+ userId,
155
+ traits,
156
+ timestamp: new Date().toISOString(),
157
+ anonymousId: this.anonymousId,
158
+ });
159
+ }
160
+
161
+ async page(
162
+ name?: string,
163
+ properties: PageProperties = {},
164
+ _context?: AnalyticsContext,
165
+ ): Promise<void> {
166
+ if (!this.isInitialized) {
167
+ logWarn('HTTP provider not initialized', { provider: 'http', operation: 'page', name });
168
+ return;
169
+ }
170
+
171
+ this.enqueue({
172
+ type: 'page',
173
+ name,
174
+ properties,
175
+ timestamp: new Date().toISOString(),
176
+ userId: this.userId,
177
+ anonymousId: this.anonymousId,
178
+ });
179
+ }
180
+
181
+ async group(
182
+ groupId: string,
183
+ traits: GroupTraits = {},
184
+ _context?: AnalyticsContext,
185
+ ): Promise<void> {
186
+ if (!this.isInitialized) {
187
+ logWarn('HTTP provider not initialized', { provider: 'http', operation: 'group', groupId });
188
+ return;
189
+ }
190
+
191
+ this.enqueue({
192
+ type: 'group',
193
+ groupId,
194
+ traits,
195
+ timestamp: new Date().toISOString(),
196
+ userId: this.userId,
197
+ anonymousId: this.anonymousId,
198
+ });
199
+ }
200
+
201
+ async alias(userId: string, previousId: string, _context?: AnalyticsContext): Promise<void> {
202
+ if (!this.isInitialized) {
203
+ logWarn('HTTP provider not initialized', {
204
+ provider: 'http',
205
+ operation: 'alias',
206
+ userId,
207
+ previousId,
208
+ });
209
+ return;
210
+ }
211
+
212
+ this.enqueue({
213
+ type: 'alias',
214
+ userId,
215
+ previousId,
216
+ timestamp: new Date().toISOString(),
217
+ anonymousId: this.anonymousId,
218
+ });
219
+ }
220
+
221
+ /**
222
+ * Flush all queued events to the remote endpoint.
223
+ * Called automatically on interval or when batch size is reached.
224
+ */
225
+ async flush(): Promise<void> {
226
+ if (this.queue.length === 0 || this.isFlushing) return;
227
+
228
+ this.isFlushing = true;
229
+
230
+ // Take all events from queue
231
+ const events = [...this.queue];
232
+ this.queue = [];
233
+
234
+ try {
235
+ await this.sendBatch(events);
236
+ } catch (error) {
237
+ // Re-queue events on failure (they'll be retried on next flush)
238
+ this.queue.unshift(...events);
239
+ logError('Failed to flush events, re-queued for retry', {
240
+ provider: 'http',
241
+ eventCount: events.length,
242
+ error: error instanceof Error ? error.message : String(error),
243
+ });
244
+ } finally {
245
+ this.isFlushing = false;
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Shutdown the provider gracefully.
251
+ * Flushes remaining events and stops the flush timer.
252
+ */
253
+ async shutdown(): Promise<void> {
254
+ if (this.flushTimer) {
255
+ clearInterval(this.flushTimer);
256
+ this.flushTimer = null;
257
+ }
258
+
259
+ // Final flush
260
+ await this.flush();
261
+ this.isInitialized = false;
262
+ }
263
+
264
+ /**
265
+ * Get the current queue length (for testing/monitoring).
266
+ */
267
+ getQueueLength(): number {
268
+ return this.queue.length;
269
+ }
270
+
271
+ // ============================================================================
272
+ // Private Methods
273
+ // ============================================================================
274
+
275
+ private enqueue(event: QueuedEvent): void {
276
+ this.queue.push(event);
277
+
278
+ if (this.config.debug) {
279
+ logDebug('Event queued', {
280
+ provider: 'http',
281
+ type: event.type,
282
+ queueLength: this.queue.length,
283
+ });
284
+ }
285
+
286
+ // Flush if batch size reached
287
+ if (this.queue.length >= this.config.batchSize) {
288
+ void this.flush();
289
+ }
290
+ }
291
+
292
+ private async sendBatch(events: QueuedEvent[]): Promise<void> {
293
+ const payload = { batch: events };
294
+
295
+ let lastError: Error | null = null;
296
+
297
+ for (let attempt = 0; attempt <= this.config.retries; attempt++) {
298
+ try {
299
+ const response = await this.sendRequest(payload);
300
+
301
+ if (response.success) {
302
+ if (this.config.debug) {
303
+ logDebug('Batch sent successfully', {
304
+ provider: 'http',
305
+ accepted: response.accepted,
306
+ rejected: response.rejected,
307
+ });
308
+ }
309
+ return;
310
+ }
311
+
312
+ // Request succeeded but ingestion failed
313
+ logWarn('Batch partially rejected', {
314
+ provider: 'http',
315
+ accepted: response.accepted,
316
+ rejected: response.rejected,
317
+ error: response.error,
318
+ });
319
+ return;
320
+ } catch (error) {
321
+ lastError = error instanceof Error ? error : new Error(String(error));
322
+
323
+ if (attempt < this.config.retries) {
324
+ // Exponential backoff: 1s, 2s, 4s, ...
325
+ const delay = BACKOFF_BASE_MS * Math.pow(2, attempt);
326
+
327
+ if (this.config.debug) {
328
+ logDebug('Retrying batch send', {
329
+ provider: 'http',
330
+ attempt: attempt + 1,
331
+ maxRetries: this.config.retries,
332
+ delayMs: delay,
333
+ });
334
+ }
335
+
336
+ await this.sleep(delay);
337
+ }
338
+ }
339
+ }
340
+
341
+ // All retries exhausted
342
+ throw lastError ?? new Error('Failed to send batch after retries');
343
+ }
344
+
345
+ private async sendRequest(payload: { batch: QueuedEvent[] }): Promise<IngestionResponse> {
346
+ const headers: Record<string, string> = {
347
+ 'Content-Type': 'application/json',
348
+ ...this.config.headers,
349
+ };
350
+
351
+ if (this.config.apiKey) {
352
+ headers['X-API-Key'] = this.config.apiKey;
353
+ }
354
+
355
+ const controller = new AbortController();
356
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
357
+
358
+ try {
359
+ const response = await fetch(this.config.endpoint, {
360
+ method: 'POST',
361
+ headers,
362
+ body: JSON.stringify(payload),
363
+ signal: controller.signal,
364
+ });
365
+
366
+ if (!response.ok) {
367
+ // Handle rate limiting
368
+ if (response.status === 429) {
369
+ const retryAfter = response.headers.get('Retry-After');
370
+ throw new Error(`Rate limited. Retry after ${retryAfter ?? 'unknown'} seconds`);
371
+ }
372
+
373
+ const errorBody = await response.text();
374
+ throw new Error(`HTTP ${response.status}: ${errorBody}`);
375
+ }
376
+
377
+ return (await response.json()) as IngestionResponse;
378
+ } finally {
379
+ clearTimeout(timeoutId);
380
+ }
381
+ }
382
+
383
+ private generateAnonymousId(): string {
384
+ // Use crypto.randomUUID if available (Node 19+), otherwise fallback
385
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
386
+ return crypto.randomUUID();
387
+ }
388
+
389
+ // Fallback for older Node versions
390
+ return `anon_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;
391
+ }
392
+
393
+ private sleep(ms: number): Promise<void> {
394
+ return new Promise(resolve => setTimeout(resolve, ms));
395
+ }
396
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * @fileoverview HTTP provider type definitions
3
+ *
4
+ * Defines TypeScript types and interfaces for HTTP Analytics provider configuration.
5
+ * This provider sends events to a remote analytics endpoint (e.g., oneapp-api/ingest).
6
+ *
7
+ * @module @od-oneapp/analytics/providers/http/types
8
+ */
9
+
10
+ /**
11
+ * Configuration for the HTTP analytics provider.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const config: HttpProviderConfig = {
16
+ * endpoint: 'https://api.oneapp.dev/v1/ingest',
17
+ * apiKey: process.env.ANALYTICS_API_KEY,
18
+ * batchSize: 10,
19
+ * flushInterval: 5000,
20
+ * };
21
+ * ```
22
+ */
23
+ export interface HttpProviderConfig {
24
+ /**
25
+ * The URL of the analytics ingestion endpoint.
26
+ * Must be a valid HTTPS URL in production.
27
+ *
28
+ * @example 'https://api.oneapp.dev/v1/ingest'
29
+ */
30
+ endpoint: string;
31
+
32
+ /**
33
+ * API key for authentication.
34
+ * Sent as X-API-Key header.
35
+ * Optional if the endpoint is configured for open mode.
36
+ */
37
+ apiKey?: string;
38
+
39
+ /**
40
+ * Number of events to batch before sending.
41
+ * Events are queued until this threshold is reached or flushInterval expires.
42
+ *
43
+ * @default 10
44
+ */
45
+ batchSize?: number;
46
+
47
+ /**
48
+ * Interval in milliseconds to auto-flush queued events.
49
+ * Set to 0 to disable auto-flush (manual flush only).
50
+ *
51
+ * @default 5000
52
+ */
53
+ flushInterval?: number;
54
+
55
+ /**
56
+ * Request timeout in milliseconds.
57
+ *
58
+ * @default 10000
59
+ */
60
+ timeout?: number;
61
+
62
+ /**
63
+ * Number of retry attempts on failed requests.
64
+ * Uses exponential backoff between retries.
65
+ *
66
+ * @default 3
67
+ */
68
+ retries?: number;
69
+
70
+ /**
71
+ * Additional headers to include in requests.
72
+ * Note: X-API-Key and Content-Type are set automatically.
73
+ */
74
+ headers?: Record<string, string>;
75
+
76
+ /**
77
+ * Enable debug logging for HTTP requests.
78
+ *
79
+ * @default false
80
+ */
81
+ debug?: boolean;
82
+
83
+ /**
84
+ * User ID to include with all events.
85
+ * Can be set after initialization via identify().
86
+ */
87
+ userId?: string;
88
+
89
+ /**
90
+ * Anonymous ID for unidentified users.
91
+ * Auto-generated if not provided.
92
+ */
93
+ anonymousId?: string;
94
+ }
95
+
96
+ /**
97
+ * Internal event queue item structure.
98
+ * @internal
99
+ */
100
+ export interface QueuedEvent {
101
+ type: 'track' | 'identify' | 'page' | 'screen' | 'group' | 'alias';
102
+ timestamp: string;
103
+ userId?: string;
104
+ anonymousId?: string;
105
+ // Track events
106
+ event?: string;
107
+ properties?: Record<string, unknown>;
108
+ // Identify events
109
+ traits?: Record<string, unknown>;
110
+ // Page/screen events
111
+ name?: string;
112
+ category?: string;
113
+ // Group events
114
+ groupId?: string;
115
+ // Alias events
116
+ previousId?: string;
117
+ }
118
+
119
+ /**
120
+ * Response from the ingestion endpoint.
121
+ */
122
+ export interface IngestionResponse {
123
+ success: boolean;
124
+ accepted?: number;
125
+ rejected?: number;
126
+ results?: Array<{
127
+ id: string;
128
+ type: string;
129
+ status: 'accepted' | 'rejected';
130
+ error?: string;
131
+ }>;
132
+ receivedAt?: string;
133
+ error?: string;
134
+ code?: string;
135
+ }