@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 @@
1
+ {"version":3,"file":"posthog-bootstrap-CYfIy_WS.mjs","names":[],"sources":["../src/shared/utils/rate-limit.ts","../src/shared/utils/security.ts","../src/shared/utils/manager.ts","../src/shared/emitters/helpers.ts","../src/shared/utils/posthog-bootstrap.ts"],"sourcesContent":["/**\n * @fileoverview Rate limiting utilities for analytics calls\n * Rate limiting utilities for analytics calls\n *\n * Prevents overwhelming provider APIs, hitting rate limits, and excessive costs.\n * Uses token bucket algorithm for smooth rate limiting with bursts.\n *\n * @module rate-limit\n */\n\nimport { logWarn } from '@repo/shared/logger';\n\n/**\n * Rate limiter configuration\n */\nexport interface RateLimiterConfig {\n /** Maximum number of calls per window */\n maxCalls: number;\n /** Window size in milliseconds */\n windowMs: number;\n /** Maximum number of concurrent calls */\n maxConcurrent?: number;\n /** Whether to queue excess calls or drop them */\n queueExcess?: boolean;\n /** Maximum queue size */\n maxQueueSize?: number;\n}\n\n/**\n * Rate limiter for analytics calls\n *\n * Implements token bucket algorithm with optional call queuing.\n *\n * @example\n * ```typescript\n * const limiter = new RateLimiter({\n * maxCalls: 100,\n * windowMs: 1000, // 100 calls per second\n * maxConcurrent: 10,\n * });\n *\n * // Check if call is allowed\n * if (await limiter.tryAcquire()) {\n * await analytics.track('Event');\n * limiter.release();\n * }\n *\n * // Or use wrapper\n * await limiter.execute(() => analytics.track('Event'));\n * ```\n */\nexport class RateLimiter {\n private callCount = 0;\n private concurrentCount = 0;\n private windowStart = Date.now();\n private queue: Array<() => void> = [];\n private readonly config: Required<RateLimiterConfig>;\n\n constructor(config: RateLimiterConfig) {\n this.config = {\n maxCalls: config.maxCalls,\n windowMs: config.windowMs,\n maxConcurrent: config.maxConcurrent ?? Infinity,\n queueExcess: config.queueExcess ?? false,\n maxQueueSize: config.maxQueueSize ?? 1000,\n };\n }\n\n /**\n * Try to acquire a rate limit token\n *\n * @returns Promise resolving to whether the call is allowed\n */\n async tryAcquire(): Promise<boolean> {\n // Reset window if needed\n const now = Date.now();\n if (now - this.windowStart >= this.config.windowMs) {\n this.callCount = 0;\n this.windowStart = now;\n }\n\n // Check rate limit\n if (this.callCount >= this.config.maxCalls) {\n if (this.config.queueExcess && this.queue.length < this.config.maxQueueSize) {\n // Queue the call - will re-check rate limit when dequeued\n return new Promise<boolean>(resolve => {\n this.queue.push(() => {\n // Re-check rate limit when dequeued to prevent bypassing\n const now = Date.now();\n if (now - this.windowStart >= this.config.windowMs) {\n this.callCount = 0;\n this.windowStart = now;\n }\n if (this.callCount < this.config.maxCalls) {\n this.callCount++;\n resolve(true);\n } else {\n resolve(false);\n }\n });\n });\n }\n\n if (process.env.NODE_ENV === 'development') {\n logWarn('Rate limit exceeded', {\n maxCalls: this.config.maxCalls,\n windowMs: this.config.windowMs,\n currentCount: this.callCount,\n });\n }\n\n return false;\n }\n\n // Check concurrency limit\n if (this.concurrentCount >= this.config.maxConcurrent) {\n if (this.config.queueExcess && this.queue.length < this.config.maxQueueSize) {\n // Queue the call\n return new Promise<boolean>(resolve => {\n this.queue.push(() => resolve(true));\n });\n }\n\n return false;\n }\n\n this.callCount++;\n this.concurrentCount++;\n return true;\n }\n\n /**\n * Release a rate limit token\n */\n release(): void {\n this.concurrentCount = Math.max(0, this.concurrentCount - 1);\n\n // Process queue - only process if concurrency allows and rate limit allows\n if (this.queue.length > 0 && this.concurrentCount < this.config.maxConcurrent) {\n // Reset rate limit window if needed before processing queue\n const now = Date.now();\n if (now - this.windowStart >= this.config.windowMs) {\n this.callCount = 0;\n this.windowStart = now;\n }\n\n // Only process if rate limit allows\n if (this.callCount < this.config.maxCalls) {\n const next = this.queue.shift();\n if (next) {\n this.concurrentCount++;\n next();\n }\n }\n }\n }\n\n /**\n * Execute a function with rate limiting\n *\n * @param fn - Function to execute\n * @returns Promise resolving to function result\n */\n async execute<T>(fn: () => Promise<T>): Promise<T | null> {\n const allowed = await this.tryAcquire();\n\n if (!allowed) {\n return null;\n }\n\n try {\n return await fn();\n } finally {\n this.release();\n }\n }\n\n /**\n * Get current rate limiter stats\n */\n getStats(): {\n callCount: number;\n concurrentCount: number;\n queueSize: number;\n remainingCalls: number;\n windowStart: number;\n } {\n return {\n callCount: this.callCount,\n concurrentCount: this.concurrentCount,\n queueSize: this.queue.length,\n remainingCalls: Math.max(0, this.config.maxCalls - this.callCount),\n windowStart: this.windowStart,\n };\n }\n\n /**\n * Reset the rate limiter\n */\n reset(): void {\n this.callCount = 0;\n this.concurrentCount = 0;\n this.windowStart = Date.now();\n this.queue = [];\n }\n}\n\n/**\n * Simple in-memory rate limiter using Map\n *\n * Useful for per-provider or per-user rate limiting.\n */\nexport class MapRateLimiter {\n private limiters = new Map<string, RateLimiter>();\n private readonly config: RateLimiterConfig;\n\n constructor(config: RateLimiterConfig) {\n this.config = config;\n }\n\n /**\n * Get or create a rate limiter for a key\n */\n private getLimiter(key: string): RateLimiter {\n let limiter = this.limiters.get(key);\n\n if (!limiter) {\n limiter = new RateLimiter(this.config);\n this.limiters.set(key, limiter);\n }\n\n return limiter;\n }\n\n /**\n * Try to acquire a rate limit token for a key\n */\n async tryAcquire(key: string): Promise<boolean> {\n return this.getLimiter(key).tryAcquire();\n }\n\n /**\n * Release a rate limit token for a key\n */\n release(key: string): void {\n this.getLimiter(key).release();\n }\n\n /**\n * Execute a function with rate limiting for a key\n */\n async execute<T>(key: string, fn: () => Promise<T>): Promise<T | null> {\n return this.getLimiter(key).execute(fn);\n }\n\n /**\n * Get stats for a key\n */\n getStats(key: string): ReturnType<RateLimiter['getStats']> | null {\n const limiter = this.limiters.get(key);\n return limiter ? limiter.getStats() : null;\n }\n\n /**\n * Reset rate limiter for a key\n */\n reset(key: string): void {\n const limiter = this.limiters.get(key);\n if (limiter) {\n limiter.reset();\n }\n }\n\n /**\n * Clean up old limiters (call periodically)\n */\n cleanup(maxAge: number = 60000): void {\n const now = Date.now();\n\n for (const [key, limiter] of this.limiters.entries()) {\n const stats = limiter.getStats();\n\n // Remove if inactive for maxAge\n if (now - stats.windowStart > maxAge && stats.callCount === 0 && stats.queueSize === 0) {\n this.limiters.delete(key);\n }\n }\n }\n}\n","/**\n * @fileoverview Security and sanitization utilities for analytics data\n *\n * This module provides comprehensive security utilities for analytics data:\n *\n * - **PII Detection**: Detects personally identifiable information (emails, phones, SSNs, credit cards, IPs)\n * - **PII Redaction**: Redacts PII from strings before sending to analytics\n * - **XSS Protection**: Strips HTML and script tags to prevent XSS attacks\n * - **Property Validation**: Validates property keys to prevent prototype pollution\n * - **Payload Sanitization**: Comprehensive sanitization with size limits and depth checks\n * - **Size Limits**: Enforces maximum property and payload sizes\n *\n * **Security Features**:\n * - Maximum property value size: 100KB\n * - Maximum payload size: 1MB\n * - Maximum nesting depth: 10 levels\n * - Dangerous key filtering (prevents prototype pollution)\n * - HTML/script tag removal\n *\n * @module @od-oneapp/analytics/shared/utils/security\n */\n\nimport { logWarn } from '@repo/shared/logger';\n\n/**\n * Maximum allowed property value size (100KB).\n *\n * Prevents sending excessively large property values to analytics providers.\n *\n * @internal\n */\nconst MAX_PROPERTY_VALUE_SIZE = 100 * 1024;\n\n/**\n * Maximum allowed total payload size (1MB).\n *\n * Prevents sending excessively large payloads to analytics providers.\n *\n * @internal\n */\nconst MAX_PAYLOAD_SIZE = 1024 * 1024;\n\n/**\n * Maximum allowed object nesting depth.\n *\n * Prevents deeply nested objects that could cause performance issues or stack overflows.\n *\n * @internal\n */\nconst MAX_DEPTH = 10;\n\n/**\n * PII patterns for detection and filtering\n * Note: These regexes are intentionally complex for accurate PII detection.\n * They are used only on bounded, sanitized input with size limits.\n */\n/* eslint-disable security/detect-unsafe-regex */\nconst PII_PATTERNS = {\n email: /\\b[\\w%+.-]+@[\\d.A-Za-z-]+\\.[A-Za-z|]{2,}\\b/g,\n phone: /\\b(?:\\+?1[.-]?)?\\(?(\\d{3})\\)?[.-]?(\\d{3})[.-]?(\\d{4})\\b/g,\n ssn: /\\b\\d{3}-?\\d{2}-?\\d{4}\\b/g,\n creditCard: /\\b(?:\\d{4}[ -]?){3}\\d{4}\\b/g,\n ipv4: /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g,\n ipv6: /\\b(?:[\\da-f]{1,4}:){7}[\\da-f]{1,4}\\b/gi,\n};\n/* eslint-enable security/detect-unsafe-regex */\n\n/**\n * Dangerous property keys that should never be allowed\n */\nconst DANGEROUS_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__',\n]);\n\n/**\n * HTML/Script patterns for XSS protection\n * Note: These regexes are intentionally complex for accurate XSS detection.\n * They are used only on bounded, sanitized input with size limits.\n */\n/* eslint-disable security/detect-unsafe-regex */\nconst XSS_PATTERNS = {\n scriptTag: /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n onEvent: /\\bon\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi,\n javascript: /javascript:/gi,\n dataUri: /data:text\\/html/gi,\n};\n/* eslint-enable security/detect-unsafe-regex */\n\n/**\n * Sanitization options.\n *\n * Configures how sanitization should be performed, including size limits,\n * depth limits, and what content to strip.\n */\nexport interface SanitizationOptions {\n /** Maximum object nesting depth */\n maxDepth?: number;\n /** Maximum size per property value in bytes */\n maxPropertySize?: number;\n /** Maximum total payload size in bytes */\n maxPayloadSize?: number;\n /** Pattern for allowed property keys */\n allowedKeyPattern?: RegExp;\n /** Whether to strip PII */\n stripPII?: boolean;\n /** Whether to strip HTML/scripts */\n stripHTML?: boolean;\n /** Whether to allow prototype pollution keys */\n allowDangerousKeys?: boolean;\n}\n\n/**\n * Sanitization result.\n *\n * Contains the sanitized data, whether modifications were made, and any warnings\n * generated during sanitization.\n */\nexport interface SanitizationResult<T = unknown> {\n /** Sanitized data */\n data: T;\n /** Whether sanitization made changes */\n modified: boolean;\n /** Warnings generated during sanitization */\n warnings: string[];\n}\n\n/**\n * Check if a value contains PII (Personally Identifiable Information).\n *\n * Detects common PII patterns including:\n * - Email addresses\n * - Phone numbers\n * - Social Security Numbers\n * - Credit card numbers\n * - IPv4 and IPv6 addresses\n *\n * @param {string} value - String value to check for PII\n * @returns {boolean} `true` if PII is detected, `false` otherwise\n *\n * @example\n * ```typescript\n * if (containsPII(userInput)) {\n * const sanitized = redactPII(userInput);\n * // Use sanitized value\n * }\n * ```\n */\nexport function containsPII(value: string): boolean {\n return Object.values(PII_PATTERNS).some(pattern => pattern.test(value));\n}\n\n/**\n * Redact PII from a string.\n *\n * Replaces detected PII patterns with `[REDACTED_TYPE]` placeholders.\n * Useful for logging or analytics where PII should not be stored.\n *\n * @param {string} value - String value to redact PII from\n * @returns {string} String with PII redacted\n *\n * @example\n * ```typescript\n * const sanitized = redactPII('Contact john@example.com at 555-1234');\n * // Returns: 'Contact [REDACTED_EMAIL] at [REDACTED_PHONE]'\n * ```\n */\nexport function redactPII(value: string): string {\n let redacted = value;\n\n for (const [type, pattern] of Object.entries(PII_PATTERNS)) {\n redacted = redacted.replace(pattern, `[REDACTED_${type.toUpperCase()}]`);\n }\n\n return redacted;\n}\n\n/**\n * Strip HTML and script tags from a string.\n *\n * Removes HTML tags, script tags, event handlers, and other potentially dangerous\n * content to prevent XSS attacks. Also removes `data:text/html` URIs.\n *\n * @param {string} value - String value to strip HTML from\n * @returns {string} String with HTML and scripts removed\n *\n * @example\n * ```typescript\n * const sanitized = stripHTML('<script>alert(\"xss\")</script>Hello');\n * // Returns: 'Hello'\n * ```\n */\nexport function stripHTML(value: string): string {\n let stripped = value;\n\n for (const pattern of Object.values(XSS_PATTERNS)) {\n stripped = stripped.replace(pattern, '');\n }\n\n // Additional cleanup for remaining tags\n stripped = stripped.replaceAll(/<[^>]*>/g, '');\n\n return stripped;\n}\n\n/**\n * Validate that a property key is safe.\n *\n * Checks for dangerous keys that could cause prototype pollution or other\n * security issues. Also validates against allowed key patterns if provided.\n *\n * @param {string} key - Property key to validate\n * @param {SanitizationOptions} [options] - Sanitization options\n * @returns {{ valid: boolean; reason?: string }} Validation result with reason if invalid\n *\n * @example\n * ```typescript\n * const result = isValidPropertyKey('__proto__');\n * if (!result.valid) {\n * console.warn('Unsafe key:', result.reason);\n * }\n * ```\n */\nexport function isValidPropertyKey(\n key: string,\n options: SanitizationOptions = {},\n): { valid: boolean; reason?: string } {\n // Check for dangerous keys\n if (!options.allowDangerousKeys && DANGEROUS_KEYS.has(key)) {\n return { valid: false, reason: 'Dangerous key that could cause prototype pollution' };\n }\n\n // Check against allowed pattern\n if (options.allowedKeyPattern && !options.allowedKeyPattern.test(key)) {\n return { valid: false, reason: 'Key does not match allowed pattern' };\n }\n\n // Check for special characters that could cause issues\n if (/[<>[\\\\\\]{}]/.test(key)) {\n return { valid: false, reason: 'Key contains potentially dangerous characters' };\n }\n\n return { valid: true };\n}\n\n/**\n * Get the size of a value in bytes\n */\nfunction getValueSize(value: unknown): number {\n if (typeof value === 'string') {\n return new Blob([value]).size;\n }\n\n try {\n return new Blob([JSON.stringify(value)]).size;\n } catch {\n return 0;\n }\n}\n\n/**\n * Sanitize a single property value\n */\nfunction sanitizeValue(\n value: unknown,\n options: SanitizationOptions,\n warnings: string[],\n): { value: unknown; modified: boolean } {\n if (value === null || value === undefined) {\n return { value, modified: false };\n }\n\n let modified = false;\n\n // Handle strings\n if (typeof value === 'string') {\n let sanitized = value;\n\n // Check size\n const size = getValueSize(value);\n const maxSize = options.maxPropertySize ?? MAX_PROPERTY_VALUE_SIZE;\n\n if (size > maxSize) {\n sanitized = value.slice(0, Math.max(0, maxSize));\n warnings.push(`String value truncated from ${size} to ${maxSize} bytes`);\n modified = true;\n }\n\n // Strip PII if requested\n if (options.stripPII && containsPII(sanitized)) {\n sanitized = redactPII(sanitized);\n warnings.push('PII detected and redacted from value');\n modified = true;\n }\n\n // Strip HTML if requested\n if (options.stripHTML) {\n const stripped = stripHTML(sanitized);\n if (stripped !== sanitized) {\n sanitized = stripped;\n warnings.push('HTML/scripts stripped from value');\n modified = true;\n }\n }\n\n return { value: sanitized, modified };\n }\n\n // Handle numbers, booleans, etc.\n if (typeof value !== 'object') {\n return { value, modified: false };\n }\n\n // Arrays and objects handled by sanitizeProperties\n return { value, modified: false };\n}\n\n/**\n * Sanitize analytics properties recursively.\n *\n * Comprehensive sanitization of analytics properties including:\n * - Size limit enforcement\n * - Depth limit enforcement\n * - PII detection and redaction\n * - HTML/script tag removal\n * - Dangerous key filtering\n * - Circular reference detection\n *\n * @param {T} properties - Properties to sanitize\n * @param {SanitizationOptions} [options] - Sanitization options\n * @returns {SanitizationResult<T>} Sanitization result with sanitized data and warnings\n *\n * @throws {Error} If properties contain circular references or exceed payload size limit\n *\n * @example\n * ```typescript\n * const result = sanitizeProperties({\n * user_email: 'test@example.com',\n * phone: '555-1234',\n * description: '<script>alert(\"xss\")</script>Hello',\n * }, {\n * stripPII: true,\n * stripHTML: true,\n * });\n *\n * console.log(result.data);\n * // {\n * // user_email: '[REDACTED_EMAIL]',\n * // phone: '[REDACTED_PHONE]',\n * // description: 'Hello'\n * // }\n * ```\n */\nexport function sanitizeProperties<T extends Record<string, unknown>>(\n properties: T,\n options: SanitizationOptions = {},\n): SanitizationResult<T> {\n const warnings: string[] = [];\n let modified = false;\n\n // Check for circular references\n try {\n JSON.stringify(properties);\n } catch {\n throw new Error('Properties contain circular references');\n }\n\n // Check total payload size\n const totalSize = getValueSize(properties);\n const maxPayloadSize = options.maxPayloadSize ?? MAX_PAYLOAD_SIZE;\n\n if (totalSize > maxPayloadSize) {\n throw new Error(`Payload size ${totalSize} bytes exceeds maximum ${maxPayloadSize} bytes`);\n }\n\n /**\n * Recursive sanitization helper\n */\n function sanitizeRecursive(\n obj: Record<string, unknown>,\n depth: number = 0,\n ): Record<string, unknown> {\n const maxDepth = options.maxDepth ?? MAX_DEPTH;\n\n if (depth > maxDepth) {\n warnings.push(`Maximum nesting depth ${maxDepth} exceeded, truncating`);\n modified = true;\n return {};\n }\n\n const sanitized: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // Validate key\n const keyValidation = isValidPropertyKey(key, options);\n if (!keyValidation.valid) {\n warnings.push(`Skipping dangerous key \"${key}\": ${keyValidation.reason}`);\n modified = true;\n continue;\n }\n\n // Handle null/undefined\n if (value === null || value === undefined) {\n sanitized[key] = value;\n continue;\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n sanitized[key] = value.map(item => {\n if (typeof item === 'object' && item !== null) {\n return sanitizeRecursive(item as Record<string, unknown>, depth + 1);\n }\n\n const result = sanitizeValue(item, options, warnings);\n if (result.modified) modified = true;\n return result.value;\n });\n continue;\n }\n\n // Handle objects\n if (typeof value === 'object') {\n sanitized[key] = sanitizeRecursive(value as Record<string, unknown>, depth + 1);\n continue;\n }\n\n // Handle primitives\n const result = sanitizeValue(value, options, warnings);\n if (result.modified) modified = true;\n sanitized[key] = result.value;\n }\n\n return sanitized;\n }\n\n const sanitized = sanitizeRecursive(properties) as T;\n\n // Log warnings in development\n if (warnings.length > 0 && process.env.NODE_ENV === 'development') {\n logWarn('Analytics properties sanitization warnings', { warnings });\n }\n\n return {\n data: sanitized,\n modified,\n warnings,\n };\n}\n\n/**\n * Validate event name.\n *\n * Checks that an event name is safe and follows best practices:\n * - Non-empty string\n * - Not exceeding 255 characters\n * - No XSS patterns\n *\n * @param {string} event - Event name to validate\n * @returns {{ valid: boolean; reason?: string }} Validation result with reason if invalid\n *\n * @example\n * ```typescript\n * const result = validateEventName('Button Clicked');\n * if (!result.valid) {\n * console.error('Invalid event name:', result.reason);\n * }\n * ```\n */\nexport function validateEventName(event: string): {\n valid: boolean;\n reason?: string;\n} {\n if (!event || typeof event !== 'string') {\n return { valid: false, reason: 'Event name must be a non-empty string' };\n }\n\n if (event.trim() === '') {\n return { valid: false, reason: 'Event name cannot be empty or whitespace only' };\n }\n\n if (event.length > 255) {\n return { valid: false, reason: 'Event name cannot exceed 255 characters' };\n }\n\n // Check for XSS patterns\n if (Object.values(XSS_PATTERNS).some(pattern => pattern.test(event))) {\n return { valid: false, reason: 'Event name contains potentially malicious content' };\n }\n\n return { valid: true };\n}\n\n/**\n * Safe property value types that can be tracked.\n *\n * Only includes primitive types that are safe to send to analytics providers.\n */\nexport type SafePropertyValue = string | number | boolean | null | undefined;\n\n/**\n * Safe properties object type.\n *\n * Properties object with only safe value types.\n */\nexport type SafeProperties = Record<string, SafePropertyValue | SafePropertyValue[]>;\n\n/**\n * Create a type-safe analytics properties object.\n *\n * Sanitizes raw properties and returns a type-safe properties object.\n * Automatically strips PII in production and HTML/scripts always.\n *\n * @param {Record<string, unknown>} properties - Raw properties to make safe\n * @returns {SafeProperties} Type-safe properties object\n *\n * @example\n * ```typescript\n * const safeProps = createSafeProperties({\n * userId: 'user-123',\n * email: 'user@example.com', // Will be redacted in production\n * html: '<script>alert(\"xss\")</script>' // Will be stripped\n * });\n * ```\n */\nexport function createSafeProperties(properties: Record<string, unknown>): SafeProperties {\n const result = sanitizeProperties(properties, {\n stripPII: process.env.NODE_ENV === 'production',\n stripHTML: true,\n allowDangerousKeys: false,\n });\n\n if (result.warnings.length > 0 && process.env.NODE_ENV === 'development') {\n logWarn('Created safe properties with sanitization', {\n warnings: result.warnings,\n });\n }\n\n return result.data as SafeProperties;\n}\n","/**\n * @fileoverview Analytics Manager - Core orchestration for multi-provider analytics\n *\n * This module provides the core AnalyticsManager class that orchestrates multiple\n * analytics providers. It includes:\n *\n * - **Multi-Provider Support**: Manages multiple providers simultaneously\n * - **Event Deduplication**: LRU cache prevents duplicate events\n * - **Rate Limiting**: Per-provider rate limiting (100 calls/second default)\n * - **Batch Processing**: Concurrent batch processing with configurable concurrency\n * - **Performance Metrics**: Tracks provider performance and reliability\n * - **Error Handling**: Comprehensive error handling with graceful degradation\n *\n * **Node.js 22+ Features Used**:\n * - `Promise.withResolvers()`: External promise control for complex workflows\n * - `AbortSignal.timeout()`: Context-aware timeouts for provider operations\n * - High-resolution timing: Precise performance measurement (`process.hrtime.bigint()`)\n * - `Object.hasOwn()`: Safer property existence checks\n *\n * **Optimizations**:\n * - Spread operator instead of `structuredClone()` for better performance\n * - LRU cache for event deduplication (prevents memory leaks)\n * - Concurrent batch processing with configurable concurrency\n * - Comprehensive input sanitization and validation\n * - Per-provider rate limiting\n *\n * @module @od-oneapp/analytics/shared/utils/manager\n */\n\nimport { RateLimiter } from './rate-limit';\nimport { sanitizeProperties, validateEventName } from './security';\n\nimport type {\n EmitterAliasPayload,\n EmitterGroupPayload,\n EmitterIdentifyPayload,\n EmitterPagePayload,\n EmitterPayload,\n EmitterScreenPayload,\n EmitterTrackPayload,\n} from '../emitters/emitter-types';\nimport type {\n AnalyticsConfig,\n AnalyticsContext,\n AnalyticsProvider,\n EcommerceEventSpec,\n GroupTraits,\n PageProperties,\n Properties,\n PropertyObject,\n ProviderRegistry,\n TrackingOptions,\n UserTraits,\n} from '../types/types';\n\n/**\n * LRU Cache for event deduplication.\n *\n * Prevents memory leaks by limiting cache size. Uses least-recently-used eviction\n * policy to maintain bounded memory usage.\n *\n * @template K - Cache key type\n * @template V - Cache value type\n *\n * @internal\n */\nclass LRUCache<K, V> {\n private cache = new Map<K, V>();\n private readonly maxSize: number;\n\n constructor(maxSize: number = 1000) {\n this.maxSize = maxSize;\n }\n\n get(key: K): V | undefined {\n const value = this.cache.get(key);\n if (value !== undefined) {\n // Move to end (most recently used)\n this.cache.delete(key);\n this.cache.set(key, value);\n }\n return value;\n }\n\n set(key: K, value: V): void {\n // Remove if exists (to re-add at end)\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Add to end\n this.cache.set(key, value);\n\n // Evict oldest if over capacity\n if (this.cache.size > this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n }\n\n has(key: K): boolean {\n return this.cache.get(key) !== undefined;\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n\n/**\n * Provider metrics for tracking performance and reliability.\n *\n * Tracks initialization time, call counts, error counts, and last usage time\n * for each provider to monitor performance and reliability.\n *\n * @internal\n */\ninterface ProviderMetrics {\n initTime: bigint;\n callCount: number;\n errorCount: number;\n lastUsed: bigint;\n}\n\n/**\n * Event metadata for deduplication and tracking.\n *\n * Stores metadata about events to prevent duplicate processing and track\n * event processing status.\n *\n * @internal\n */\ninterface EventMetadata {\n timestamp: bigint;\n processed: boolean;\n}\n\n/**\n * Analytics Manager - Main entry point for analytics tracking.\n *\n * Orchestrates multiple analytics providers, handles event deduplication,\n * rate limiting, batch processing, and error handling.\n *\n * **Key Features**:\n * - Multi-provider support (PostHog, Segment, Vercel, Console)\n * - Event deduplication via LRU cache\n * - Rate limiting (100 calls/second per provider)\n * - Batch processing with concurrency control\n * - Performance metrics tracking\n * - Graceful error handling\n *\n * **Usage**:\n * ```typescript\n * const manager = new AnalyticsManager(config, providerRegistry);\n * await manager.initialize();\n * await manager.emit(track('Event Name', { property: 'value' }));\n * ```\n */\nexport class AnalyticsManager {\n private providers = new Map<string, AnalyticsProvider>();\n private context: AnalyticsContext = {};\n private isInitialized = false;\n\n // Provider metrics tracking (provider name -> metrics)\n private readonly providerMetrics = new Map<string, ProviderMetrics>();\n\n // Event deduplication with LRU cache (prevents memory leaks)\n private readonly eventCache = new LRUCache<string, EventMetadata>(1000);\n\n // Rate limiting per provider (100 calls per second default)\n private readonly rateLimiter = new RateLimiter({\n maxCalls: 100,\n windowMs: 1000,\n maxConcurrent: 10,\n queueExcess: false,\n });\n\n constructor(\n private config: AnalyticsConfig,\n private availableProviders: ProviderRegistry,\n ) {}\n\n /**\n * Initialize all configured providers\n * Throws error if all providers fail to initialize\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n const initPromises: Promise<void>[] = [];\n const initStartTime = process.hrtime.bigint();\n\n for (const [providerName, providerConfig] of Object.entries(this.config.providers)) {\n const providerFactory = this.availableProviders[providerName];\n\n if (providerFactory) {\n try {\n const provider = providerFactory(providerConfig);\n this.providers.set(providerName, provider);\n\n // Initialize provider with enhanced error handling and timeout (Node 22+)\n initPromises.push(\n (async () => {\n const providerInitStart: bigint = typeof process.hrtime?.bigint === 'function'\n ? process.hrtime.bigint()\n : BigInt(Date.now() * 1000000); // Fallback for non-Node environments\n\n try {\n // Use AbortSignal.timeout() for initialization timeout (Node 22+)\n const timeoutSignal = AbortSignal.timeout(10000); // 10 second timeout\n\n const initPromise = provider.initialize(providerConfig);\n\n // Race against timeout\n await Promise.race([\n initPromise,\n new Promise<void>((_resolve, reject) => {\n timeoutSignal.addEventListener('abort', () =>\n reject(new Error(`Provider ${providerName} initialization timed out`)),\n );\n }),\n ]);\n\n // Track successful initialization metrics\n const now: bigint = typeof process.hrtime?.bigint === 'function'\n ? process.hrtime.bigint()\n : BigInt(Date.now() * 1000000); // Fallback for non-Node environments\n this.providerMetrics.set(providerName, {\n initTime: now - providerInitStart,\n callCount: 0,\n errorCount: 0,\n lastUsed: now,\n });\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n method: 'initialize',\n });\n }\n // Remove failed provider to ensure it doesn't affect others\n this.providers.delete(providerName);\n throw error; // Re-throw to track failure\n }\n })(),\n );\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n method: 'create',\n });\n }\n }\n } else if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Provider ${providerName} not available in this environment`);\n }\n }\n\n // Wait for all providers to initialize with enhanced monitoring\n const results = await Promise.allSettled(initPromises);\n const initEndTime = process.hrtime.bigint();\n\n const successCount = results.filter(r => r.status === 'fulfilled').length;\n const failureCount = results.filter(r => r.status === 'rejected').length;\n\n // FIX #10: Throw error if all providers fail\n if (successCount === 0 && initPromises.length > 0) {\n throw new Error(\n `Analytics initialization failed: All ${initPromises.length} providers failed to initialize`,\n );\n }\n\n this.isInitialized = true;\n\n if (this.config.debug && this.config.onInfo) {\n const initTimeMs = Number(initEndTime - initStartTime) / 1_000_000;\n this.config.onInfo(\n `Analytics initialized in ${initTimeMs.toFixed(2)}ms with ${successCount} providers ` +\n `(${failureCount} failed): ${[...this.providers.keys()].join(', ')}`,\n );\n }\n }\n\n /**\n * Set global analytics context\n * FIX #13: Use spread operator instead of structuredClone for better performance\n */\n setContext(context: AnalyticsContext): void {\n // Use spread operator for better performance\n this.context = { ...this.context, ...context };\n\n // Update context on providers that support it with enhanced error handling\n for (const [providerName, provider] of this.providers) {\n if (provider.setContext) {\n try {\n // Use spread operator instead of structuredClone\n provider.setContext({ ...this.context });\n\n // Update metrics for successful context update\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n method: 'setContext',\n context: Object.keys(context).join(', '),\n });\n }\n }\n }\n }\n }\n\n /**\n * Get current analytics context\n * FIX #13: Use spread operator instead of structuredClone\n */\n getContext(): AnalyticsContext {\n return { ...this.context };\n }\n\n /**\n * Track an event\n * FIX #3: Replace any types with proper TypeScript types\n * FIX #14/#15: Integrate security utilities and rate limiting\n */\n async track(payload: EmitterTrackPayload): Promise<void>;\n async track(event: string, properties?: Properties, options?: TrackingOptions): Promise<void>;\n async track(\n eventOrPayload: string | EmitterTrackPayload,\n properties?: Properties,\n options?: TrackingOptions,\n ): Promise<void> {\n // If first argument is an emitter payload, use it\n if (typeof eventOrPayload === 'object') {\n const payload = eventOrPayload;\n return this.track(payload.event, payload.properties, {\n ...options,\n // Merge context from payload\n context: { ...this.context, ...payload.context },\n });\n }\n\n // Traditional track call\n const event = eventOrPayload;\n\n if (!this.isInitialized) {\n if (this.config.onError) {\n this.config.onError(new Error('Analytics not initialized'), {\n provider: 'analytics',\n event,\n method: 'track',\n });\n }\n return;\n }\n\n // FIX #14: Validate event name\n const eventValidation = validateEventName(event);\n if (!eventValidation.valid) {\n if (this.config.onError) {\n this.config.onError(new Error(`Invalid event name: ${eventValidation.reason}`), {\n provider: 'analytics',\n event,\n method: 'track',\n });\n }\n return;\n }\n\n // FIX #14: Sanitize properties\n const sanitized = sanitizeProperties(properties ?? {}, {\n stripPII: process.env.NODE_ENV === 'production',\n stripHTML: true,\n allowDangerousKeys: false,\n });\n\n const targetProviders = this.getTargetProviders(options);\n const enhancedProperties = { ...this.context, ...sanitized.data };\n\n const promises = [...targetProviders.entries()].map(async ([name, provider]) => {\n // FIX #15: Apply rate limiting\n const allowed = await this.rateLimiter.tryAcquire();\n if (!allowed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Rate limit exceeded for provider ${name}`);\n }\n // Report rate limit rejection to onError handler to prevent silent event loss\n if (this.config.onError) {\n this.config.onError(new Error(`Rate limit exceeded for provider ${name}`), {\n provider: name,\n event,\n method: 'track',\n });\n }\n return;\n }\n\n try {\n await provider.track(event, enhancedProperties as PropertyObject, this.context);\n\n // Update metrics\n const metrics = this.providerMetrics.get(name);\n if (metrics) {\n metrics.callCount++;\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n // Update error metrics\n const metrics = this.providerMetrics.get(name);\n if (metrics) {\n metrics.errorCount++;\n }\n\n // Error boundary: report error but don't let it affect other providers\n if (this.config.onError) {\n this.config.onError(error, {\n provider: name,\n event,\n method: 'track',\n });\n }\n } finally {\n this.rateLimiter.release();\n }\n });\n\n // Use allSettled to ensure all providers are called even if some fail\n await Promise.allSettled(promises);\n }\n\n /**\n * Identify a user\n * FIX #3: Replace any types with proper TypeScript types\n */\n async identify(payload: EmitterIdentifyPayload): Promise<void>;\n async identify(userId: string, traits?: UserTraits, options?: TrackingOptions): Promise<void>;\n async identify(\n userIdOrPayload: string | EmitterIdentifyPayload,\n traits?: UserTraits,\n options?: TrackingOptions,\n ): Promise<void> {\n // If first argument is an emitter payload, use it\n if (typeof userIdOrPayload === 'object') {\n const payload = userIdOrPayload;\n return this.identify(payload.userId, payload.traits, {\n ...options,\n // Merge context from payload\n context: { ...this.context, ...payload.context },\n });\n }\n\n // Traditional identify call\n const userId = userIdOrPayload;\n\n if (!this.isInitialized) {\n if (this.config.onError) {\n this.config.onError(new Error('Analytics not initialized'), {\n provider: 'analytics',\n method: 'identify',\n userId,\n });\n }\n return;\n }\n\n // Sanitize traits\n const sanitized = sanitizeProperties(traits ?? {}, {\n stripPII: process.env.NODE_ENV === 'production',\n stripHTML: true,\n allowDangerousKeys: false,\n });\n\n // Update context with user info\n this.setContext({ userId, ...sanitized.data });\n\n const targetProviders = this.getTargetProviders(options);\n const enhancedTraits = { ...sanitized.data } as UserTraits;\n\n const promises = [...targetProviders.entries()].map(async ([name, provider]) => {\n if (provider.identify) {\n const allowed = await this.rateLimiter.tryAcquire();\n if (!allowed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Rate limit exceeded for provider ${name}`);\n }\n // Report rate limit rejection to onError handler to prevent silent event loss\n if (this.config.onError) {\n this.config.onError(new Error(`Rate limit exceeded for provider ${name}`), {\n provider: name,\n userId,\n method: 'identify',\n });\n }\n return;\n }\n\n try {\n // Pass context as TrackingOptions (provider.identify expects TrackingOptions as third parameter)\n await provider.identify(userId, enhancedTraits, {\n ...options,\n context: this.context,\n });\n\n const metrics = this.providerMetrics.get(name);\n if (metrics) {\n metrics.callCount++;\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n const metrics = this.providerMetrics.get(name);\n if (metrics) {\n metrics.errorCount++;\n }\n\n if (this.config.onError) {\n this.config.onError(error, {\n provider: name,\n method: 'identify',\n userId,\n });\n }\n } finally {\n this.rateLimiter.release();\n }\n }\n });\n\n await Promise.allSettled(promises);\n }\n\n /**\n * Track a page view\n * FIX #3: Replace any types with proper TypeScript types\n */\n async page(payload: EmitterPagePayload): Promise<void>;\n async page(name?: string, properties?: PageProperties, options?: TrackingOptions): Promise<void>;\n async page(\n nameOrPayload?: string | EmitterPagePayload,\n properties?: PageProperties,\n options?: TrackingOptions,\n ): Promise<void> {\n // If first argument is an emitter payload, use it\n if (typeof nameOrPayload === 'object') {\n const payload = nameOrPayload;\n return this.page(payload.name, payload.properties, {\n ...options,\n // Merge context from payload\n context: { ...this.context, ...payload.context },\n });\n }\n\n // Traditional page call\n const name = nameOrPayload;\n\n if (!this.isInitialized) {\n if (this.config.onError) {\n this.config.onError(new Error('Analytics not initialized'), {\n provider: 'analytics',\n name,\n method: 'page',\n });\n }\n return;\n }\n\n // Sanitize properties\n const sanitized = sanitizeProperties(properties ?? {}, {\n stripPII: process.env.NODE_ENV === 'production',\n stripHTML: true,\n allowDangerousKeys: false,\n });\n\n const targetProviders = this.getTargetProviders(options);\n const enhancedProperties = { ...sanitized.data } as PageProperties;\n\n const promises = [...targetProviders.entries()].map(async ([providerName, provider]) => {\n if (provider.page) {\n const allowed = await this.rateLimiter.tryAcquire();\n if (!allowed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Rate limit exceeded for provider ${providerName}`);\n }\n // Report rate limit rejection to onError handler to prevent silent event loss\n if (this.config.onError) {\n this.config.onError(new Error(`Rate limit exceeded for provider ${providerName}`), {\n provider: providerName,\n name,\n method: 'page',\n });\n }\n return;\n }\n\n try {\n // Pass context as TrackingOptions (provider.page expects TrackingOptions as third parameter)\n await provider.page(name ?? '', enhancedProperties, {\n ...options,\n context: this.context,\n });\n\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.callCount++;\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.errorCount++;\n }\n\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n name: name ?? '',\n method: 'page',\n });\n }\n } finally {\n this.rateLimiter.release();\n }\n }\n });\n\n await Promise.allSettled(promises);\n }\n\n /**\n * Track a screen view (mobile equivalent of page)\n */\n async screen(payload: EmitterScreenPayload): Promise<void>;\n async screen(\n name?: string,\n properties?: PageProperties,\n options?: TrackingOptions,\n ): Promise<void>;\n async screen(\n nameOrPayload?: string | EmitterScreenPayload,\n properties?: PageProperties,\n options?: TrackingOptions,\n ): Promise<void> {\n // If first argument is an emitter payload, use it\n if (typeof nameOrPayload === 'object') {\n const payload = nameOrPayload;\n return this.screen(payload.name, payload.properties, {\n ...options,\n context: { ...this.context, ...payload.context },\n });\n }\n\n const name = nameOrPayload;\n\n if (!this.isInitialized) {\n if (this.config.onError) {\n this.config.onError(new Error('Analytics not initialized'), {\n provider: 'analytics',\n name,\n method: 'screen',\n });\n }\n return;\n }\n\n const sanitized = sanitizeProperties(properties ?? {}, {\n stripPII: process.env.NODE_ENV === 'production',\n stripHTML: true,\n allowDangerousKeys: false,\n });\n\n const targetProviders = this.getTargetProviders(options);\n const enhancedProperties = { ...sanitized.data } as PageProperties;\n\n const promises = [...targetProviders.entries()].map(async ([providerName, provider]) => {\n if (provider.screen) {\n const allowed = await this.rateLimiter.tryAcquire();\n if (!allowed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Rate limit exceeded for provider ${providerName}`);\n }\n if (this.config.onError) {\n this.config.onError(new Error(`Rate limit exceeded for provider ${providerName}`), {\n provider: providerName,\n name,\n method: 'screen',\n });\n }\n return;\n }\n\n try {\n await provider.screen(name ?? '', enhancedProperties, {\n ...options,\n context: this.context,\n });\n\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.callCount++;\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.errorCount++;\n }\n\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n name: name ?? '',\n method: 'screen',\n });\n }\n } finally {\n this.rateLimiter.release();\n }\n }\n });\n\n await Promise.allSettled(promises);\n }\n\n /**\n * Associate user with a group\n * FIX #3: Replace any types with proper TypeScript types\n */\n async group(payload: EmitterGroupPayload): Promise<void>;\n async group(groupId: string, traits?: GroupTraits, options?: TrackingOptions): Promise<void>;\n async group(\n groupIdOrPayload: string | EmitterGroupPayload,\n traits?: GroupTraits,\n options?: TrackingOptions,\n ): Promise<void> {\n // If first argument is an emitter payload, use it\n if (typeof groupIdOrPayload === 'object') {\n const payload = groupIdOrPayload;\n return this.group(payload.groupId, payload.traits, {\n ...options,\n // Merge context from payload\n context: { ...this.context, ...payload.context },\n });\n }\n\n // Traditional group call\n const groupId = groupIdOrPayload;\n\n if (!this.isInitialized) {\n if (this.config.onError) {\n this.config.onError(new Error('Analytics not initialized'), {\n provider: 'analytics',\n groupId,\n method: 'group',\n });\n }\n return;\n }\n\n // Sanitize traits\n const sanitized = sanitizeProperties(traits ?? {}, {\n stripPII: process.env.NODE_ENV === 'production',\n stripHTML: true,\n allowDangerousKeys: false,\n });\n\n // Update context with group info\n this.setContext({ organizationId: groupId, ...sanitized.data });\n\n const targetProviders = this.getTargetProviders(options);\n const enhancedTraits = { ...sanitized.data } as GroupTraits;\n\n const promises = [...targetProviders.entries()].map(async ([providerName, provider]) => {\n if (provider.group) {\n const allowed = await this.rateLimiter.tryAcquire();\n if (!allowed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Rate limit exceeded for provider ${providerName}`);\n }\n // Report rate limit rejection to onError handler to prevent silent event loss\n if (this.config.onError) {\n this.config.onError(new Error(`Rate limit exceeded for provider ${providerName}`), {\n provider: providerName,\n groupId,\n method: 'group',\n });\n }\n return;\n }\n\n try {\n // Pass context as TrackingOptions (provider.group expects TrackingOptions as third parameter)\n await provider.group(groupId, enhancedTraits, {\n ...options,\n context: this.context,\n });\n\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.callCount++;\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.errorCount++;\n }\n\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n groupId,\n method: 'group',\n });\n }\n } finally {\n this.rateLimiter.release();\n }\n }\n });\n\n await Promise.allSettled(promises);\n }\n\n /**\n * Alias one user ID to another\n * No any types - already properly typed\n */\n async alias(payload: EmitterAliasPayload): Promise<void>;\n async alias(userId: string, previousId: string, options?: TrackingOptions): Promise<void>;\n async alias(\n userIdOrPayload: string | EmitterAliasPayload,\n previousId?: string,\n options?: TrackingOptions,\n ): Promise<void> {\n // If first argument is an emitter payload, use it\n if (typeof userIdOrPayload === 'object') {\n const payload = userIdOrPayload;\n return this.alias(payload.userId, payload.previousId, {\n ...options,\n // Merge context from payload\n context: { ...this.context, ...payload.context },\n });\n }\n\n // Traditional alias call\n const userId = userIdOrPayload;\n const prevId = previousId as string;\n\n if (!this.isInitialized) {\n if (this.config.onError) {\n this.config.onError(new Error('Analytics not initialized'), {\n provider: 'analytics',\n method: 'alias',\n previousId: prevId,\n userId,\n });\n }\n return;\n }\n\n const targetProviders = this.getTargetProviders(options);\n\n const promises = [...targetProviders.entries()].map(async ([providerName, provider]) => {\n if (provider.alias) {\n const allowed = await this.rateLimiter.tryAcquire();\n if (!allowed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo(`Rate limit exceeded for provider ${providerName}`);\n }\n // Report rate limit rejection to onError handler to prevent silent event loss\n if (this.config.onError) {\n this.config.onError(new Error(`Rate limit exceeded for provider ${providerName}`), {\n provider: providerName,\n userId,\n previousId,\n method: 'alias',\n });\n }\n return;\n }\n\n try {\n await provider.alias(userId, prevId, this.context);\n\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.callCount++;\n metrics.lastUsed = process.hrtime.bigint();\n }\n } catch (error) {\n const metrics = this.providerMetrics.get(providerName);\n if (metrics) {\n metrics.errorCount++;\n }\n\n if (this.config.onError) {\n this.config.onError(error, {\n provider: providerName,\n method: 'alias',\n previousId: prevId,\n userId,\n });\n }\n } finally {\n this.rateLimiter.release();\n }\n }\n });\n\n await Promise.allSettled(promises);\n }\n\n /**\n * Get list of active provider names\n */\n getActiveProviders(): string[] {\n return [...this.providers.keys()];\n }\n\n /**\n * Get a specific provider instance\n */\n getProvider(name: string): AnalyticsProvider | undefined {\n return this.providers.get(name);\n }\n\n /**\n * Reset analytics context and identity\n */\n reset(): void {\n this.context = {};\n this.eventCache.clear();\n }\n\n /**\n * Shutdown all providers and cleanup resources\n */\n async shutdown(): Promise<void> {\n const shutdownPromises = [...this.providers.entries()].map(async ([name, provider]) => {\n try {\n if (typeof (provider as any).destroy === 'function') {\n await (provider as any).destroy();\n }\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error, {\n provider: name,\n method: 'shutdown',\n });\n }\n }\n });\n\n await Promise.allSettled(shutdownPromises);\n this.providers.clear();\n this.isInitialized = false;\n }\n\n /**\n * Process any emitter payload with Node 22+ optimizations\n * FIX #12: Use LRU cache for event deduplication (prevents memory leaks)\n */\n async emit(payload: EmitterPayload, options?: { timeout?: number }): Promise<void> {\n const emitStartTime = process.hrtime.bigint();\n\n // FIX #12: Use LRU cache for deduplication instead of WeakMap\n // Create order-independent cache key by sorting object keys\n const createCacheKey = (p: EmitterPayload): string => {\n const sorted = (obj: unknown): unknown => {\n if (obj === null || typeof obj !== 'object' || obj instanceof Array) {\n return obj;\n }\n const sortedObj: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sortedObj[key] = sorted((obj as Record<string, unknown>)[key]);\n }\n return sortedObj;\n };\n return JSON.stringify(sorted(p));\n };\n const cacheKey = createCacheKey(payload);\n if (this.eventCache.has(cacheKey)) {\n const metadata = this.eventCache.get(cacheKey);\n if (metadata?.processed) {\n if (this.config.debug && this.config.onInfo) {\n this.config.onInfo('Skipping duplicate event processing');\n }\n return;\n }\n }\n\n // Mark as being processed and track metadata\n this.eventCache.set(cacheKey, {\n timestamp: emitStartTime,\n processed: true,\n });\n\n try {\n // Apply timeout if specified using AbortSignal.timeout() (Node 22+)\n if (options?.timeout) {\n const timeoutSignal = AbortSignal.timeout(options.timeout);\n await Promise.race([\n this.processPayloadByType(payload),\n new Promise<never>((_resolve, reject) => {\n timeoutSignal.addEventListener('abort', () =>\n reject(new Error(`Event processing timed out after ${options.timeout}ms`)),\n );\n }),\n ]);\n } else {\n await this.processPayloadByType(payload);\n }\n\n // Log performance metrics in debug mode\n if (this.config.debug && this.config.onInfo) {\n const processingTime = Number(process.hrtime.bigint() - emitStartTime) / 1_000_000;\n this.config.onInfo(`Event processed in ${processingTime.toFixed(2)}ms`);\n }\n } catch (error) {\n // Update metadata to mark as failed\n this.eventCache.set(cacheKey, {\n timestamp: emitStartTime,\n processed: false,\n });\n throw error;\n }\n }\n\n /**\n * Route payload to appropriate method based on type\n */\n private async processPayloadByType(payload: EmitterPayload): Promise<void> {\n switch (payload.type) {\n case 'track':\n return this.track(payload);\n case 'identify':\n return this.identify(payload);\n case 'page':\n return this.page(payload);\n case 'screen':\n return this.screen(payload);\n case 'group':\n return this.group(payload);\n case 'alias':\n return this.alias(payload);\n }\n }\n\n /**\n * Process an emitter payload (legacy method - use emit() instead)\n * @deprecated Use emit() for better type safety\n */\n async processEmitterPayload(payload: EmitterPayload): Promise<void> {\n return this.emit(payload);\n }\n\n /**\n * Batch emit multiple payloads with Node 22+ optimizations\n * FIX #14: Process chunks concurrently instead of sequentially\n * FIX #13: Use spread operator instead of structuredClone\n */\n async emitBatch(\n payloads: EmitterPayload[],\n options?: {\n timeout?: number;\n concurrency?: number;\n failFast?: boolean;\n },\n ): Promise<void> {\n const batchStartTime = process.hrtime.bigint();\n const concurrency = options?.concurrency ?? 10; // Default concurrency limit\n\n if (payloads.length === 0) return;\n\n // FIX #13: Use structuredClone for deep cloning to ensure nested data safety\n const clonedPayloads = payloads.map(p => structuredClone(p));\n\n // Process in chunks for better memory management\n const chunks: EmitterPayload[][] = [];\n for (let i = 0; i < clonedPayloads.length; i += concurrency) {\n chunks.push(clonedPayloads.slice(i, i + concurrency));\n }\n\n const processChunk = async (chunk: EmitterPayload[]) => {\n const chunkPromises = chunk.map(payload =>\n this.emit(\n payload,\n options?.timeout !== undefined ? { timeout: options.timeout } : undefined,\n ),\n );\n\n if (options?.failFast) {\n await Promise.all(chunkPromises);\n } else {\n await Promise.allSettled(chunkPromises);\n }\n };\n\n // FIX #14: Process chunks concurrently instead of sequentially\n const chunkPromises = chunks.map(chunk => processChunk(chunk));\n await Promise.all(chunkPromises);\n\n // Log batch processing metrics in debug mode\n if (this.config.debug && this.config.onInfo) {\n const batchTime = Number(process.hrtime.bigint() - batchStartTime) / 1_000_000;\n this.config.onInfo(\n `Batch of ${payloads.length} events processed in ${batchTime.toFixed(2)}ms ` +\n `(concurrency: ${concurrency})`,\n );\n }\n }\n\n /**\n * Create a bound emitter function for convenience\n */\n createEmitter(): (payload: EmitterPayload) => Promise<void> {\n // Extract arrow function to avoid consistent-function-scoping warning\n const boundEmit = this.emit.bind(this);\n return boundEmit;\n }\n\n /**\n * Track an ecommerce event specification\n * @deprecated Use emit(ecommerce.EVENT_NAME(...)) instead\n */\n async trackEcommerce(eventSpec: EcommerceEventSpec): Promise<void> {\n return this.track(eventSpec.name, eventSpec.properties);\n }\n\n /**\n * Get target providers based on tracking options\n */\n private getTargetProviders(options?: TrackingOptions): Map<string, AnalyticsProvider> {\n let targetProviders = new Map(this.providers);\n\n if (options) {\n // Handle runtime provider additions with enhanced error handling\n if (options.providers && Object.hasOwn(options, 'providers')) {\n for (const [name, config] of Object.entries(options.providers)) {\n const factory = this.availableProviders[name];\n if (factory) {\n try {\n const provider = factory(config);\n targetProviders.set(name, provider);\n\n // Initialize runtime metrics tracking (Node 22+)\n this.providerMetrics.set(name, {\n initTime: process.hrtime.bigint(),\n callCount: 0,\n errorCount: 0,\n lastUsed: process.hrtime.bigint(),\n });\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error, {\n provider: name,\n method: 'runtime-create',\n });\n }\n }\n }\n }\n }\n\n // Handle 'only' option with safer property checking\n if (options.only && Object.hasOwn(options, 'only')) {\n const onlyProviders = new Map();\n for (const name of options.only) {\n if (targetProviders.has(name)) {\n onlyProviders.set(name, targetProviders.get(name));\n }\n }\n targetProviders = onlyProviders;\n }\n\n // Handle 'exclude' option with safer property checking\n if (options.exclude && Object.hasOwn(options, 'exclude')) {\n for (const name of options.exclude) {\n targetProviders.delete(name);\n }\n }\n }\n\n return targetProviders;\n }\n\n /**\n * Get analytics performance metrics using Node 22+ features\n */\n getAnalyticsMetrics(): {\n providers: Record<\n string,\n {\n initTimeMs: number;\n callCount: number;\n errorCount: number;\n lastUsedMs: number;\n successRate: number;\n }\n >;\n events: {\n totalProcessed: number;\n cacheSize: number;\n memoryUsage: {\n rss: number;\n heapTotal: number;\n heapUsed: number;\n external: number;\n arrayBuffers: number;\n };\n };\n } {\n const now = process.hrtime.bigint();\n const providers: Record<\n string,\n {\n initTimeMs: number;\n callCount: number;\n errorCount: number;\n lastUsedMs: number;\n successRate: number;\n }\n > = {};\n\n // Collect provider metrics\n for (const [providerName, metrics] of this.providerMetrics) {\n providers[providerName] = {\n initTimeMs: Number(metrics.initTime) / 1_000_000,\n callCount: metrics.callCount,\n errorCount: metrics.errorCount,\n lastUsedMs: Number(now - metrics.lastUsed) / 1_000_000,\n successRate: metrics.callCount > 0 ? 1 - metrics.errorCount / metrics.callCount : 1,\n };\n }\n\n return {\n providers,\n events: {\n totalProcessed: this.eventCache.size,\n cacheSize: this.eventCache.size,\n memoryUsage: process.memoryUsage(),\n },\n };\n }\n\n /**\n * Health check for analytics system using Node 22+ timing\n * FIX #16: Send actual test events instead of just setContext\n */\n async healthCheck(timeout: number = 5000): Promise<{\n healthy: boolean;\n providers: Record<string, boolean>;\n metrics: ReturnType<AnalyticsManager['getAnalyticsMetrics']>;\n totalCheckTime: number;\n }> {\n const checkStartTime = process.hrtime.bigint();\n const providerHealth: Record<string, boolean> = {};\n\n // Use AbortSignal.timeout() for health check timeout (Node 22+)\n const timeoutSignal = AbortSignal.timeout(timeout);\n\n try {\n const healthPromises = [...this.providers.entries()].map(async ([name, provider]) => {\n try {\n // FIX #16: Send actual test event instead of just setContext\n await Promise.race([\n provider.track('__health_check__', { timestamp: Date.now(), provider: name }),\n new Promise<void>((_resolve, reject) => {\n timeoutSignal.addEventListener('abort', () =>\n reject(new Error('Health check timeout')),\n );\n }),\n ]);\n providerHealth[name] = true;\n } catch {\n providerHealth[name] = false;\n }\n });\n\n await Promise.allSettled(healthPromises);\n\n const checkEndTime = process.hrtime.bigint();\n const totalCheckTime = Number(checkEndTime - checkStartTime) / 1_000_000;\n\n const healthyCount = Object.values(providerHealth).filter(Boolean).length;\n\n return {\n healthy: healthyCount > 0 && this.isInitialized,\n providers: providerHealth,\n metrics: this.getAnalyticsMetrics(),\n totalCheckTime,\n };\n } catch {\n return {\n healthy: false,\n providers: providerHealth,\n metrics: this.getAnalyticsMetrics(),\n totalCheckTime: Number(process.hrtime.bigint() - checkStartTime) / 1_000_000,\n };\n }\n }\n}\n\n/**\n * Factory function to create analytics manager\n */\nexport function createAnalyticsManager(\n config: AnalyticsConfig,\n availableProviders: ProviderRegistry,\n): AnalyticsManager {\n return new AnalyticsManager(config, availableProviders);\n}\n","/**\n * @fileoverview Helper Functions for Analytics Emitters\n *\n * These utilities make it easier to use the emitter-first approach for analytics.\n * Provides builders, batch processing, session management, and convenience\n * functions for common tracking patterns.\n *\n * **Builders**:\n * - `ContextBuilder`: Build consistent context across events\n * - `PayloadBuilder`: Chain emitter creation with shared options\n * - `EventBatch`: Batch related events with shared context\n *\n * **Session Management**:\n * - `createUserSession()`: Create a user session tracking flow\n * - `createAnonymousSession()`: Create an anonymous user tracking flow\n *\n * **Convenience Functions**:\n * - `withMetadata()`: Add consistent metadata to events\n * - `withUTM()`: Add UTM parameters to events\n * - Type guards: `isTrackPayload()`, `isIdentifyPayload()`, etc.\n *\n * @module @od-oneapp/analytics/shared/emitters/helpers\n */\n\nimport { alias, group, identify, page, track } from './emitters';\n\nimport type {\n EmitterAliasPayload,\n EmitterContext,\n EmitterGroupPayload,\n EmitterIdentifyPayload,\n EmitterOptions,\n EmitterPagePayload,\n EmitterPayload,\n EmitterTrackPayload,\n} from './emitter-types';\n\n/**\n * Builder for creating consistent context across analytics events.\n *\n * @remarks\n * Use this builder to create a reusable context object that can be applied\n * to multiple events. This ensures consistency and reduces repetition.\n *\n * @example\n * ```typescript\n * const context = new ContextBuilder()\n * .setUser('user-123', { plan: 'pro' })\n * .setOrganization('org-456')\n * .setPage({ path: '/dashboard', title: 'Dashboard' })\n * .build();\n *\n * await analytics.emit(track('Button Clicked', {}, { context }));\n * ```\n */\nexport class ContextBuilder {\n private context: EmitterContext = {};\n\n constructor(initialContext?: Partial<EmitterContext>) {\n if (initialContext) {\n this.context = { ...initialContext };\n }\n }\n\n setUser(_userId: string, traits?: Record<string, any>): this {\n this.context.traits = { ...this.context.traits, ...traits };\n return this;\n }\n\n setOrganization(groupId: string): this {\n this.context.groupId = groupId;\n return this;\n }\n\n setPage(pageInfo: { path?: string; url?: string; title?: string; referrer?: string }): this {\n this.context.page = { ...this.context.page, ...pageInfo };\n return this;\n }\n\n setCampaign(utmParams: Record<string, string>): this {\n this.context.campaign = { ...this.context.campaign, ...utmParams };\n return this;\n }\n\n setDevice(deviceInfo: Record<string, any>): this {\n this.context.device = { ...this.context.device, ...deviceInfo };\n return this;\n }\n\n build(): EmitterContext {\n return { ...this.context };\n }\n}\n\n/**\n * Builder for chaining emitter creation with shared options.\n *\n * @remarks\n * Use this builder to create multiple events with shared options like\n * timestamp, anonymousId, or integrations. This is useful when tracking\n * multiple related events in a single flow.\n *\n * @example\n * ```typescript\n * const builder = new PayloadBuilder(context)\n * .withTimestamp(new Date())\n * .withAnonymousId('anon-123');\n *\n * await analytics.emit(builder.track('Event 1', {}));\n * await analytics.emit(builder.track('Event 2', {}));\n * ```\n */\nexport class PayloadBuilder {\n private options: EmitterOptions = {};\n\n constructor(context?: EmitterContext) {\n if (context) {\n this.options.context = context;\n }\n }\n\n withTimestamp(timestamp: Date | string): this {\n this.options.timestamp = timestamp;\n return this;\n }\n\n withAnonymousId(anonymousId: string): this {\n this.options.anonymousId = anonymousId;\n return this;\n }\n\n withIntegrations(integrations: Record<string, boolean | Record<string, any>>): this {\n this.options.integrations = integrations;\n return this;\n }\n\n track(event: string, properties?: Record<string, any>): EmitterTrackPayload {\n return track(event, properties, this.options);\n }\n\n identify(userId: string, traits?: Record<string, any>): EmitterIdentifyPayload {\n return identify(userId, traits, this.options);\n }\n\n page(name?: string, properties?: Record<string, any>): EmitterPagePayload {\n return page(undefined, name, properties, this.options);\n }\n\n group(groupId: string, traits?: Record<string, any>): EmitterGroupPayload {\n return group(groupId, traits, this.options);\n }\n\n alias(userId: string, previousId: string): EmitterAliasPayload {\n return alias(userId, previousId, this.options);\n }\n}\n\n/**\n * Batch processor for related events with shared context.\n *\n * @remarks\n * Use this class to collect multiple events and emit them together with\n * a shared context. This is useful for tracking user flows or multi-step\n * processes where events should be grouped together.\n *\n * @example\n * ```typescript\n * const batch = new EventBatch(context)\n * .addTrack('Step 1 Completed', { step: 1 })\n * .addTrack('Step 2 Completed', { step: 2 })\n * .addTrack('Flow Completed', { totalSteps: 2 });\n *\n * for (const event of batch.getEvents()) {\n * await analytics.emit(event);\n * }\n * ```\n */\nexport class EventBatch {\n private events: EmitterPayload[] = [];\n private sharedContext: EmitterContext;\n\n constructor(context?: EmitterContext) {\n this.sharedContext = context ?? {};\n }\n\n add(payload: EmitterPayload): this {\n // Merge shared context with payload context\n const enrichedPayload = {\n ...payload,\n context: { ...this.sharedContext, ...payload.context },\n };\n this.events.push(enrichedPayload);\n return this;\n }\n\n addTrack(event: string, properties?: Record<string, any>): this {\n return this.add(track(event, properties, { context: this.sharedContext }));\n }\n\n addIdentify(userId: string, traits?: Record<string, any>): this {\n return this.add(identify(userId, traits, { context: this.sharedContext }));\n }\n\n addPage(name?: string, properties?: Record<string, any>): this {\n return this.add(page(undefined, name, properties, { context: this.sharedContext }));\n }\n\n addGroup(groupId: string, traits?: Record<string, any>): this {\n return this.add(group(groupId, traits, { context: this.sharedContext }));\n }\n\n getEvents(): EmitterPayload[] {\n return [...this.events];\n }\n\n clear(): void {\n this.events = [];\n }\n}\n\n/**\n * Creates a user session tracking flow with pre-configured context.\n *\n * @remarks\n * This helper creates a session object with methods for tracking events\n * within a specific user session. All events will include the sessionId\n * and user context automatically.\n *\n * @param userId - Unique identifier for the user\n * @param sessionId - Unique identifier for the session\n * @returns Session object with `identify`, `track`, `page`, and `group` methods\n *\n * @example\n * ```typescript\n * const session = createUserSession('user-123', 'session-456');\n * await analytics.emit(session.track('Button Clicked', { button: 'signup' }));\n * await analytics.emit(session.page('Dashboard'));\n * ```\n */\nexport function createUserSession(userId: string, sessionId: string) {\n const context = new ContextBuilder().setUser(userId).build();\n\n return {\n // Identify the user\n identify: (traits?: Record<string, any>) =>\n identify(userId, { ...traits, sessionId }, { context }),\n\n // Track an event in this session\n track: (event: string, properties?: Record<string, any>) =>\n track(event, { ...properties, sessionId }, { context }),\n\n // Track a page view in this session\n page: (name?: string, properties?: Record<string, any>) =>\n page(undefined, name, { ...properties, sessionId }, { context }),\n\n // Associate with a group\n group: (groupId: string, traits?: Record<string, any>) =>\n group(groupId, { ...traits, sessionId }, { context }),\n };\n}\n\n/**\n * Creates an anonymous user tracking flow.\n *\n * @remarks\n * This helper creates a session object for tracking anonymous users before\n * they are identified. When the user signs up or logs in, use the `alias`\n * method to link their anonymous activity to their user ID.\n *\n * @param anonymousId - Unique identifier for the anonymous user\n * @returns Session object with `track`, `page`, `identify`, and `alias` methods\n *\n * @example\n * ```typescript\n * const anonymousSession = createAnonymousSession('anon-123');\n * await analytics.emit(anonymousSession.track('Page Viewed', { page: 'home' }));\n *\n * // Later, when user signs up\n * await analytics.emit(anonymousSession.alias('user-123'));\n * await analytics.emit(anonymousSession.identify('user-123', { email: 'user@example.com' }));\n * ```\n */\nexport function createAnonymousSession(anonymousId: string) {\n const options: EmitterOptions = { anonymousId };\n\n return {\n // Track an event\n track: (event: string, properties?: Record<string, any>) => track(event, properties, options),\n\n // Track a page view\n page: (name?: string, properties?: Record<string, any>) =>\n page(undefined, name, properties, options),\n\n // Convert to identified user\n identify: (userId: string, traits?: Record<string, any>) => identify(userId, traits, options),\n\n // Alias when user signs up\n alias: (userId: string) => alias(userId, anonymousId, options),\n };\n}\n\n/**\n * Type guard to check if a payload is a track event.\n *\n * @param payload - The payload to check\n * @returns True if the payload is a track event\n */\nexport const isTrackPayload = (payload: EmitterPayload): payload is EmitterTrackPayload =>\n payload.type === 'track';\n\n/**\n * Type guard to check if a payload is an identify event.\n *\n * @param payload - The payload to check\n * @returns True if the payload is an identify event\n */\nexport const isIdentifyPayload = (payload: EmitterPayload): payload is EmitterIdentifyPayload =>\n payload.type === 'identify';\n\n/**\n * Type guard to check if a payload is a page event.\n *\n * @param payload - The payload to check\n * @returns True if the payload is a page event\n */\nexport const isPagePayload = (payload: EmitterPayload): payload is EmitterPagePayload =>\n payload.type === 'page';\n\n/**\n * Type guard to check if a payload is a group event.\n *\n * @param payload - The payload to check\n * @returns True if the payload is a group event\n */\nexport const isGroupPayload = (payload: EmitterPayload): payload is EmitterGroupPayload =>\n payload.type === 'group';\n\n/**\n * Type guard to check if a payload is an alias event.\n *\n * @param payload - The payload to check\n * @returns True if the payload is an alias event\n */\nexport const isAliasPayload = (payload: EmitterPayload): payload is EmitterAliasPayload =>\n payload.type === 'alias';\n\n/**\n * Adds consistent metadata to an analytics event payload.\n *\n * @remarks\n * This helper enriches an event payload with metadata that will be included\n * in the event's context.app object. Useful for tracking version, source,\n * or other application-level metadata.\n *\n * @param payload - The event payload to enrich\n * @param metadata - Metadata to add (version, source, or custom properties)\n * @returns The enriched payload with metadata in context.app\n *\n * @example\n * ```typescript\n * const event = track('Button Clicked', { button: 'signup' });\n * const enriched = withMetadata(event, { version: '1.0.0', source: 'webapp' });\n * await analytics.emit(enriched);\n * ```\n */\nexport function withMetadata<T extends EmitterPayload>(\n payload: T,\n metadata: { version?: string; source?: string; [key: string]: unknown },\n): T {\n return {\n ...payload,\n context: {\n ...payload.context,\n app: {\n ...payload.context?.app,\n ...metadata,\n },\n },\n };\n}\n\n/**\n * Adds UTM parameters to an analytics event payload.\n *\n * @remarks\n * This helper enriches an event payload with UTM campaign parameters that\n * will be included in the event's context.campaign object. Useful for\n * tracking marketing campaign attribution.\n *\n * @param payload - The event payload to enrich\n * @param utm - UTM parameters (source, medium, campaign, term, content)\n * @returns The enriched payload with UTM parameters in context.campaign\n *\n * @example\n * ```typescript\n * const event = track('Signup Started', {});\n * const enriched = withUTM(event, {\n * source: 'google',\n * medium: 'cpc',\n * campaign: 'summer-sale'\n * });\n * await analytics.emit(enriched);\n * ```\n */\nexport function withUTM<T extends EmitterPayload>(\n payload: T,\n utm: { source?: string; medium?: string; campaign?: string; term?: string; content?: string },\n): T {\n return {\n ...payload,\n context: {\n ...payload.context,\n campaign: {\n ...payload.context?.campaign,\n ...utm,\n },\n },\n };\n}\n","/**\n * @fileoverview PostHog bootstrap utilities for Next.js server-side rendering\n * PostHog bootstrap utilities for Next.js server-side rendering\n * Enables consistent feature flag delivery from server to client\n */\n\nimport type { BootstrapData, PostHogCookie } from '../types/posthog-types';\n\n/**\n * Generate a unique distinct ID (compatible with PostHog format)\n */\nexport function generateDistinctId(): string {\n // Use a similar format to PostHog's default distinct ID generation\n const timestamp = Date.now().toString(36);\n const randomStr = Math.random().toString(36).slice(2, 15);\n return `${timestamp}-${randomStr}`;\n}\n\n/**\n * Parse PostHog cookie to extract distinct ID\n */\nexport function parsePostHogCookie(\n cookieValue: string,\n _projectApiKey: string,\n): PostHogCookie | null {\n try {\n const parsed = JSON.parse(cookieValue);\n\n // Validate the cookie structure\n if (parsed && typeof parsed.distinct_id === 'string') {\n return parsed as PostHogCookie;\n }\n\n return null;\n } catch {\n // Silently fail - cookies may be malformed\n return null;\n }\n}\n\n/**\n * Get PostHog cookie name for a project\n */\nexport function getPostHogCookieName(projectApiKey: string): string {\n return `ph_${projectApiKey}_posthog`;\n}\n\n/**\n * Extract distinct ID from cookies (Next.js compatible)\n */\nexport function getDistinctIdFromCookies(\n cookies: any, // Next.js cookies object or cookie string\n projectApiKey: string,\n): string | null {\n try {\n const cookieName = getPostHogCookieName(projectApiKey);\n\n // Handle Next.js cookies() object\n if (cookies && typeof cookies.get === 'function') {\n const cookie = cookies.get(cookieName);\n if (cookie?.value) {\n const parsed = parsePostHogCookie(cookie.value, projectApiKey);\n return parsed?.distinct_id ?? null;\n }\n }\n\n // Handle raw cookie string\n if (typeof cookies === 'string') {\n const cookieMatch = cookies.match(new RegExp(`${cookieName}=([^;]+)`));\n if (cookieMatch?.[1]) {\n const parsed = parsePostHogCookie(decodeURIComponent(cookieMatch[1]), projectApiKey);\n return parsed?.distinct_id ?? null;\n }\n }\n\n return null;\n } catch {\n // Silently fail - cookies may be malformed or missing\n return null;\n }\n}\n\n/**\n * Create bootstrap data for PostHog client initialization\n */\nexport function createBootstrapData(distinctId: string): BootstrapData {\n return {\n distinctID: distinctId,\n };\n}\n\n/**\n * Cached bootstrap data fetcher (React cache compatible)\n */\nconst bootstrapCache = new Map<string, { data: BootstrapData; timestamp: number }>();\nconst CACHE_TTL = 30000; // 30 seconds\n\nexport function getCachedBootstrapData(distinctId: string): BootstrapData | null {\n const cached = bootstrapCache.get(distinctId);\n\n if (cached && Date.now() - cached.timestamp < CACHE_TTL) {\n return cached.data;\n }\n\n // Clean up expired entries\n for (const [key, value] of bootstrapCache.entries()) {\n if (Date.now() - value.timestamp >= CACHE_TTL) {\n bootstrapCache.delete(key);\n }\n }\n\n return null;\n}\n\nexport function setCachedBootstrapData(distinctId: string, data: BootstrapData): void {\n bootstrapCache.set(distinctId, {\n data,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Validate bootstrap data structure\n */\nexport function validateBootstrapData(data: any): data is BootstrapData {\n return data && typeof data === 'object' && typeof data.distinctID === 'string';\n}\n\n/**\n * Create minimal bootstrap data when full data is unavailable\n */\nexport function createMinimalBootstrapData(distinctId?: string): BootstrapData {\n return {\n distinctID: distinctId ?? generateDistinctId(),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import { C as EmitterPagePayload, D as EmitterTrackPayload, b as EmitterIdentifyPayload, g as EmitterContext, p as EmitterAliasPayload, v as EmitterGroupPayload, w as EmitterPayload } from "./types-BxBnNQ0V.mjs";
2
+ import { s as BootstrapData } from "./vercel-types-lwakUfoI.mjs";
3
+
4
+ //#region src/shared/emitters/helpers.d.ts
5
+ declare class ContextBuilder {
6
+ private context;
7
+ constructor(initialContext?: Partial<EmitterContext>);
8
+ setUser(_userId: string, traits?: Record<string, any>): this;
9
+ setOrganization(groupId: string): this;
10
+ setPage(pageInfo: {
11
+ path?: string;
12
+ url?: string;
13
+ title?: string;
14
+ referrer?: string;
15
+ }): this;
16
+ setCampaign(utmParams: Record<string, string>): this;
17
+ setDevice(deviceInfo: Record<string, any>): this;
18
+ build(): EmitterContext;
19
+ }
20
+ declare class PayloadBuilder {
21
+ private options;
22
+ constructor(context?: EmitterContext);
23
+ withTimestamp(timestamp: Date | string): this;
24
+ withAnonymousId(anonymousId: string): this;
25
+ withIntegrations(integrations: Record<string, boolean | Record<string, any>>): this;
26
+ track(event: string, properties?: Record<string, any>): EmitterTrackPayload;
27
+ identify(userId: string, traits?: Record<string, any>): EmitterIdentifyPayload;
28
+ page(name?: string, properties?: Record<string, any>): EmitterPagePayload;
29
+ group(groupId: string, traits?: Record<string, any>): EmitterGroupPayload;
30
+ alias(userId: string, previousId: string): EmitterAliasPayload;
31
+ }
32
+ declare class EventBatch {
33
+ private events;
34
+ private sharedContext;
35
+ constructor(context?: EmitterContext);
36
+ add(payload: EmitterPayload): this;
37
+ addTrack(event: string, properties?: Record<string, any>): this;
38
+ addIdentify(userId: string, traits?: Record<string, any>): this;
39
+ addPage(name?: string, properties?: Record<string, any>): this;
40
+ addGroup(groupId: string, traits?: Record<string, any>): this;
41
+ getEvents(): EmitterPayload[];
42
+ clear(): void;
43
+ }
44
+ declare function createUserSession(userId: string, sessionId: string): {
45
+ identify: (traits?: Record<string, any>) => EmitterIdentifyPayload;
46
+ track: (event: string, properties?: Record<string, any>) => EmitterTrackPayload;
47
+ page: (name?: string, properties?: Record<string, any>) => EmitterPagePayload;
48
+ group: (groupId: string, traits?: Record<string, any>) => EmitterGroupPayload;
49
+ };
50
+ declare function createAnonymousSession(anonymousId: string): {
51
+ track: (event: string, properties?: Record<string, any>) => EmitterTrackPayload;
52
+ page: (name?: string, properties?: Record<string, any>) => EmitterPagePayload;
53
+ identify: (userId: string, traits?: Record<string, any>) => EmitterIdentifyPayload;
54
+ alias: (userId: string) => EmitterAliasPayload;
55
+ };
56
+ declare const isTrackPayload: (payload: EmitterPayload) => payload is EmitterTrackPayload;
57
+ declare const isIdentifyPayload: (payload: EmitterPayload) => payload is EmitterIdentifyPayload;
58
+ declare const isPagePayload: (payload: EmitterPayload) => payload is EmitterPagePayload;
59
+ declare const isGroupPayload: (payload: EmitterPayload) => payload is EmitterGroupPayload;
60
+ declare const isAliasPayload: (payload: EmitterPayload) => payload is EmitterAliasPayload;
61
+ declare function withMetadata<T extends EmitterPayload>(payload: T, metadata: {
62
+ version?: string;
63
+ source?: string;
64
+ [key: string]: unknown;
65
+ }): T;
66
+ declare function withUTM<T extends EmitterPayload>(payload: T, utm: {
67
+ source?: string;
68
+ medium?: string;
69
+ campaign?: string;
70
+ term?: string;
71
+ content?: string;
72
+ }): T;
73
+ //#endregion
74
+ //#region src/shared/utils/posthog-bootstrap.d.ts
75
+ declare function generateDistinctId(): string;
76
+ declare function getDistinctIdFromCookies(cookies: any, projectApiKey: string): string | null;
77
+ declare function createBootstrapData(distinctId: string): BootstrapData;
78
+ declare function createMinimalBootstrapData(distinctId?: string): BootstrapData;
79
+ //#endregion
80
+ export { ContextBuilder as a, createAnonymousSession as c, isGroupPayload as d, isIdentifyPayload as f, withUTM as g, withMetadata as h, getDistinctIdFromCookies as i, createUserSession as l, isTrackPayload as m, createMinimalBootstrapData as n, EventBatch as o, isPagePayload as p, generateDistinctId as r, PayloadBuilder as s, createBootstrapData as t, isAliasPayload as u };
81
+ //# sourceMappingURL=posthog-bootstrap-DWxFrxlt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posthog-bootstrap-DWxFrxlt.d.mts","names":[],"sources":["../src/shared/emitters/helpers.ts","../src/shared/utils/posthog-bootstrap.ts"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { A as GroupTraits, F as UserTraits, M as Properties, c as ProviderConfig, i as AnalyticsProvider, j as PageProperties, n as AnalyticsContext } from "./types-BxBnNQ0V.mjs";
2
+
3
+ //#region src/providers/http/client.d.ts
4
+ declare class HttpClientProvider implements AnalyticsProvider {
5
+ readonly name = "http";
6
+ private config;
7
+ private isInitialized;
8
+ private queue;
9
+ private flushTimer;
10
+ private userId?;
11
+ private anonymousId;
12
+ private isFlushing;
13
+ constructor(providerConfig: ProviderConfig);
14
+ initialize(): Promise<void>;
15
+ track(event: string, properties?: Properties, _context?: AnalyticsContext): Promise<void>;
16
+ identify(userId: string, traits?: UserTraits, _context?: AnalyticsContext): Promise<void>;
17
+ page(name?: string, properties?: PageProperties, _context?: AnalyticsContext): Promise<void>;
18
+ group(groupId: string, traits?: GroupTraits, _context?: AnalyticsContext): Promise<void>;
19
+ alias(userId: string, previousId: string, _context?: AnalyticsContext): Promise<void>;
20
+ flush(): Promise<void>;
21
+ shutdown(): Promise<void>;
22
+ getQueueLength(): number;
23
+ private handleVisibilityChange;
24
+ private handleBeforeUnload;
25
+ private enqueue;
26
+ private sendBatch;
27
+ private sendRequest;
28
+ private getOrCreateAnonymousId;
29
+ private generateAnonymousId;
30
+ private sleep;
31
+ private log;
32
+ private warn;
33
+ private error;
34
+ }
35
+ //#endregion
36
+ export { HttpClientProvider };
37
+ //# sourceMappingURL=providers-http-client.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers-http-client.d.mts","names":[],"sources":["../src/providers/http/client.ts"],"mappings":";;;cA6Da,kBAAA,YAA8B,iBAAA;EAAA,SAChC,IAAA;EAAA,QAED,MAAA;EAAA,QAIA,aAAA;EAAA,QACA,KAAA;EAAA,QACA,UAAA;EAAA,QACA,MAAA;EAAA,QACA,WAAA;EAAA,QACA,UAAA;cAEI,cAAA,EAAgB,cAAA;EAmBtB,UAAA,CAAA,GAAc,OAAA;EA8Bd,KAAA,CACJ,KAAA,UACA,UAAA,GAAY,UAAA,EACZ,QAAA,GAAW,gBAAA,GACV,OAAA;EAgBG,QAAA,CACJ,MAAA,UACA,MAAA,GAAQ,UAAA,EACR,QAAA,GAAW,gBAAA,GACV,OAAA;EAkBG,IAAA,CACJ,IAAA,WACA,UAAA,GAAY,cAAA,EACZ,QAAA,GAAW,gBAAA,GACV,OAAA;EAgBG,KAAA,CACJ,OAAA,UACA,MAAA,GAAQ,WAAA,EACR,QAAA,GAAW,gBAAA,GACV,OAAA;EAgBG,KAAA,CAAM,MAAA,UAAgB,UAAA,UAAoB,QAAA,GAAW,gBAAA,GAAmB,OAAA;EAmBxE,KAAA,CAAA,GAAS,OAAA;EA2BT,QAAA,CAAA,GAAY,OAAA;EAsBlB,cAAA,CAAA;EAAA,QAQQ,sBAAA;EAAA,QAMA,kBAAA;EAAA,QAoBA,OAAA;EAAA,QAgBM,SAAA;EAAA,QAkDA,WAAA;EAAA,QAwCN,sBAAA;EAAA,QAkBA,mBAAA;EAAA,QAUA,KAAA;EAAA,QAQA,GAAA;EAAA,QAMA,IAAA;EAAA,QAIA,KAAA;AAAA"}