@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":"service-cYtBBL8x.mjs","names":[],"sources":["../src/server/manager.ts","../src/shared/utils/validation.ts","../src/shared/ingestion/schemas.ts","../src/shared/ingestion/service.ts"],"sourcesContent":["/**\n * @fileoverview Server analytics manager with static provider registry\n * Server analytics manager with static provider registry\n */\n\nimport { SegmentServerProvider } from '@integrations/segment/analytics-provider/server';\nimport { VercelServerProvider } from '@integrations/vercel/analytics-provider/server';\n\nimport { ConsoleProvider } from '../providers/console/server';\nimport { HttpServerProvider } from '../providers/http/server';\nimport { createAnalyticsManager } from '../shared/utils/manager';\n\nimport type { AnalyticsConfig, AnalyticsManager, ProviderRegistry } from '../shared/types/types';\n\n// Static provider registry for server environments\nconst SERVER_PROVIDERS: ProviderRegistry = {\n console: config => new ConsoleProvider(config),\n http: config => new HttpServerProvider(config),\n segment: config => new SegmentServerProvider(config),\n vercel: config => new VercelServerProvider(config),\n};\n\n/**\n * Create and initialize a server analytics instance\n * This is the primary way to create analytics for server-side applications\n *\n * @example\n * ```typescript\n * const analytics = await createServerAnalytics({\n * providers: {\n * segment: { writeKey: process.env.SEGMENT_KEY! },\n * },\n * });\n * await analytics.page('/admin', { title: 'Admin Dashboard' });\n * ```\n * @param config - Analytics configuration including providers and settings\n * @returns Promise resolving to initialized analytics manager\n */\nexport async function createServerAnalytics(config: AnalyticsConfig): Promise<AnalyticsManager> {\n const manager = createAnalyticsManager(config, SERVER_PROVIDERS);\n await manager.initialize();\n return manager;\n}\n\n/**\n * Create a server analytics instance without initializing\n * Useful when you need to control initialization timing\n *\n * @example\n * ```typescript\n * const analytics = createServerAnalyticsUninitialized(config);\n * if (shouldEmit) {\n * await analytics.initialize();\n * await analytics.track('CRON Completed');\n * }\n * ```\n * @param config - Analytics configuration including providers and settings\n * @returns Uninitialized analytics manager instance\n */\nexport function createServerAnalyticsUninitialized(config: AnalyticsConfig): AnalyticsManager {\n return createAnalyticsManager(config, SERVER_PROVIDERS);\n}\n","/**\n * @fileoverview Validation utilities for analytics configuration\n *\n * This module provides comprehensive validation for analytics configurations,\n * including provider validation, environment-specific checks, and helpful\n * warnings for common misconfigurations.\n *\n * **Features**:\n * - Configuration structure validation\n * - Provider-specific field validation\n * - Environment variable validation\n * - Environment-specific warnings\n * - Detailed error reporting\n *\n * @module @od-oneapp/analytics/shared/utils/validation\n */\n\nimport { logError, logInfo, logWarn } from '@repo/shared/logger';\n\nimport { PROVIDER_REQUIREMENTS } from './config';\n\nimport type { AnalyticsConfig, ProviderConfig } from '../types/types';\n\n/**\n * Validation error structure.\n *\n * Represents a single validation error with field, message, and provider context.\n */\nexport interface ValidationError {\n /** Field name that failed validation */\n field: string;\n /** Human-readable error message */\n message: string;\n /** Provider name (or 'global' for config-level errors) */\n provider: string;\n}\n\n/**\n * Validation result structure.\n *\n * Contains validation errors, warnings, and overall validity status.\n */\nexport interface ValidationResult {\n /** Array of validation errors */\n errors: ValidationError[];\n /** Whether the configuration is valid (no errors) */\n isValid: boolean;\n /** Array of warning messages */\n warnings: string[];\n}\n\n/**\n * Comprehensive configuration validation.\n *\n * Validates the entire analytics configuration structure, including:\n * - Configuration object structure\n * - Providers object existence\n * - Individual provider configurations\n * - Environment-specific warnings\n *\n * Accepts `unknown` input for defensive validation of potentially malformed configs.\n *\n * @param {unknown} config - Analytics configuration to validate\n * @returns {ValidationResult} Validation result with errors, warnings, and validity status\n *\n * @example\n * ```typescript\n * const result = validateAnalyticsConfig(config);\n * if (!result.isValid) {\n * console.error('Validation errors:', result.errors);\n * }\n * if (result.warnings.length > 0) {\n * console.warn('Warnings:', result.warnings);\n * }\n * ```\n */\nexport function validateAnalyticsConfig(config: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: string[] = [];\n\n // Check if config exists and is an object\n if (!config || typeof config !== 'object') {\n errors.push({\n provider: 'global',\n field: 'config',\n message: 'Analytics configuration is required and must be an object',\n });\n return { isValid: false, errors, warnings };\n }\n\n const typedConfig = config as AnalyticsConfig;\n\n // Check if providers object exists\n if (!typedConfig.providers || typeof typedConfig.providers !== 'object') {\n errors.push({\n provider: 'global',\n field: 'providers',\n message: 'Providers configuration is required and must be an object',\n });\n return { isValid: false, errors, warnings };\n }\n\n // Check if at least one provider is configured\n const providerCount = Object.keys(typedConfig.providers).length;\n if (providerCount === 0) {\n warnings.push('No providers configured. Analytics will not track any events.');\n }\n\n // Validate each provider\n for (const [providerName, providerConfig] of Object.entries(typedConfig.providers)) {\n const providerErrors = validateProvider(providerName, providerConfig);\n errors.push(...providerErrors);\n }\n\n // Environment-specific warnings\n const isBrowser = typeof window !== 'undefined';\n\n // Mixpanel warning for client-side usage\n if (isBrowser && typedConfig.providers.mixpanel) {\n warnings.push(\n 'Mixpanel provider configured on client-side. Consider using server-side for better performance.',\n );\n }\n\n if (!isBrowser && typedConfig.providers.vercel) {\n warnings.push(\n 'Vercel Analytics has limited server-side support. Consider using client-side for better features.',\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validate a single provider configuration.\n *\n * Checks that the provider is known and that all required fields are present.\n *\n * @param {string} providerName - Name of the provider to validate\n * @param {ProviderConfig} config - Provider configuration to validate\n * @returns {ValidationError[]} Array of validation errors (empty if valid)\n *\n * @example\n * ```typescript\n * const errors = validateProvider('posthog', { apiKey: 'phc_xxx' });\n * if (errors.length > 0) {\n * console.error('Provider errors:', errors);\n * }\n * ```\n */\nexport function validateProvider(providerName: string, config: ProviderConfig): ValidationError[] {\n const errors: ValidationError[] = [];\n\n // Check if provider is known\n const knownProviders = ['segment', 'posthog', 'vercel', 'console', 'mixpanel'];\n if (!knownProviders.includes(providerName)) {\n errors.push({\n provider: providerName,\n field: 'name',\n message: `Unknown provider '${providerName}'. Known providers: ${knownProviders.join(', ')}`,\n });\n return errors;\n }\n\n // Check required fields\n const requiredFields = PROVIDER_REQUIREMENTS[providerName] ?? [];\n for (const field of requiredFields) {\n const value = config[field as keyof ProviderConfig];\n\n if (!value) {\n errors.push({\n provider: providerName,\n field,\n message: `Required field '${field}' is missing for provider '${providerName}'`,\n });\n } else if (typeof value === 'string' && value.trim() === '') {\n errors.push({\n provider: providerName,\n field,\n message: `Required field '${field}' cannot be empty for provider '${providerName}'`,\n });\n }\n }\n\n // Provider-specific validation\n switch (providerName) {\n case 'segment':\n if (config.writeKey && !isValidSegmentWriteKey(config.writeKey)) {\n errors.push({\n provider: providerName,\n field: 'writeKey',\n message: 'Segment writeKey appears to be invalid format',\n });\n }\n break;\n\n case 'posthog':\n if (config.apiKey && !isValidPostHogApiKey(config.apiKey)) {\n errors.push({\n provider: providerName,\n field: 'apiKey',\n message: 'PostHog apiKey appears to be invalid format',\n });\n }\n break;\n }\n\n return errors;\n}\n\n/**\n * Validate environment variables for analytics.\n *\n * Checks common analytics environment variables for:\n * - Empty values\n * - Placeholder text\n * - Development environment warnings\n *\n * @returns {ValidationResult} Validation result with warnings about environment variables\n *\n * @example\n * ```typescript\n * const result = validateEnvironmentVariables();\n * if (result.warnings.length > 0) {\n * console.warn('Environment warnings:', result.warnings);\n * }\n * ```\n */\nexport function validateEnvironmentVariables(): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: string[] = [];\n\n // Check for common environment variables\n const envVars = {\n POSTHOG_API_KEY: process.env.POSTHOG_API_KEY,\n SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY,\n };\n\n for (const [varName, value] of Object.entries(envVars)) {\n if (value && typeof value === 'string') {\n if (value.trim() === '') {\n warnings.push(`Environment variable ${varName} is set but empty`);\n } else if (value.includes('your-') || value.includes('paste-')) {\n warnings.push(`Environment variable ${varName} appears to contain placeholder text`);\n }\n }\n }\n\n // Warn about development environment\n if (\n process.env.NODE_ENV === 'development' &&\n !envVars.SEGMENT_WRITE_KEY &&\n !envVars.POSTHOG_API_KEY\n ) {\n warnings.push(\n 'No analytics environment variables detected in development. Consider using console provider for debugging.',\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validates Segment write key format.\n *\n * Checks that the write key matches Segment's expected format:\n * - Exactly 32 alphanumeric characters\n * - Not a placeholder value\n *\n * @param {string} writeKey - Write key to validate\n * @returns {boolean} `true` if valid, `false` otherwise\n *\n * @internal\n */\nfunction isValidSegmentWriteKey(writeKey: string): boolean {\n // Segment write keys are exactly 32 characters, alphanumeric\n if (!/^[\\dA-Za-z]{32}$/.test(writeKey)) {\n return false;\n }\n\n // Check for common placeholder patterns\n const placeholders = ['your-write-key', 'paste-key-here', 'xxxxxxxx', 'example'];\n if (placeholders.some(p => writeKey.toLowerCase().includes(p.toLowerCase()))) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Validates PostHog API key format.\n *\n * Checks that the API key matches PostHog's expected format:\n * - Starts with `phc_` prefix\n * - Followed by 43 alphanumeric/dash/underscore characters\n * - Not a placeholder value\n *\n * @param {string} apiKey - API key to validate\n * @returns {boolean} `true` if valid, `false` otherwise\n *\n * @internal\n */\nfunction isValidPostHogApiKey(apiKey: string): boolean {\n // PostHog keys: phc_ prefix + 43 alphanumeric/dash/underscore characters\n if (!/^phc_[\\w-]{43}$/.test(apiKey)) {\n return false;\n }\n\n // Check for placeholder patterns\n const placeholders = ['your-api-key', 'paste-key-here', 'xxxxxxxx', 'example'];\n if (placeholders.some(p => apiKey.toLowerCase().includes(p.toLowerCase()))) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Utility to throw validation errors (for strict validation).\n *\n * Validates the configuration and throws an error if validation fails.\n * Useful for ensuring configuration is valid before using analytics.\n *\n * @param {AnalyticsConfig} config - Analytics configuration to validate\n * @throws {Error} If configuration validation fails\n *\n * @example\n * ```typescript\n * try {\n * validateConfigOrThrow(config);\n * // Configuration is valid, proceed\n * } catch (error) {\n * console.error('Invalid config:', error.message);\n * }\n * ```\n */\nexport function validateConfigOrThrow(config: AnalyticsConfig): void {\n const result = validateAnalyticsConfig(config);\n\n if (!result.isValid) {\n const errorMessages = result.errors\n .map(error => `${error.provider}.${error.field}: ${error.message}`)\n .join('\\n');\n\n throw new Error(`Analytics configuration validation failed:\\n${errorMessages}`);\n }\n\n // Log warnings but don't throw\n if (result.warnings.length > 0 && config.onError) {\n config.onError(new Error('Analytics configuration warnings'), {\n provider: 'analytics',\n method: 'validateConfig',\n warnings: result.warnings,\n });\n }\n}\n\n/**\n * Development helper to check configuration.\n *\n * Logs configuration details and validation results for debugging.\n * Only useful in development environments.\n *\n * @param {AnalyticsConfig} config - Analytics configuration to debug\n * @returns {Promise<void>} Promise that resolves when debugging is complete\n *\n * @example\n * ```typescript\n * if (process.env.NODE_ENV === 'development') {\n * await debugConfig(config);\n * }\n * ```\n */\nexport async function debugConfig(config: AnalyticsConfig): Promise<void> {\n const result = validateAnalyticsConfig(config);\n\n logInfo('Analytics Configuration Debug', {\n config,\n validationResult: result,\n });\n\n if (result.errors.length > 0) {\n logError('Analytics configuration errors: Validation failed', {\n errors: result.errors,\n });\n }\n\n if (result.warnings.length > 0) {\n logWarn('Analytics configuration warnings', { warnings: result.warnings });\n }\n}\n","/**\n * @fileoverview Event Ingestion Schemas and Validation\n *\n * Defines Zod schemas for validating event ingestion payloads. These schemas\n * ensure type-safe, secure event ingestion with proper validation.\n *\n * **Key Features**:\n * - CloudEvents-style fields for future interoperability\n * - Support for single events and batched arrays\n * - Strict validation of required fields\n * - Typed extensions per event category\n *\n * @module @od-oneapp/analytics/shared/ingestion/schemas\n */\n\nimport { z } from 'zod';\n\n// =============================================================================\n// Base Schemas\n// =============================================================================\n\n/**\n * Property value schema - safe, serializable values only.\n */\nexport const PropertyValueSchema = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.date(), // Accept Date objects only; ISO strings are already handled as strings\n]);\n\n/**\n * Property object schema with nested structure support.\n */\nexport const PropertyObjectSchema: z.ZodType<Record<string, unknown>> = z.record(\n z.string(),\n z.lazy(() =>\n z.union([PropertyValueSchema, z.array(PropertyValueSchema), z.record(z.string(), z.unknown())]),\n ),\n);\n\n/**\n * Emitter context schema - contextual information about the environment.\n */\nexport const EmitterContextSchema = z\n .object({\n /** Application information */\n app: z\n .object({\n name: z.string().optional(),\n version: z.string().optional(),\n build: z.string().optional(),\n namespace: z.string().optional(),\n })\n .optional(),\n\n /** Campaign/UTM information */\n campaign: z\n .object({\n name: z.string().optional(),\n source: z.string().optional(),\n medium: z.string().optional(),\n term: z.string().optional(),\n content: z.string().optional(),\n })\n .passthrough()\n .optional(),\n\n /** Device information */\n device: z\n .object({\n id: z.string().optional(),\n manufacturer: z.string().optional(),\n model: z.string().optional(),\n name: z.string().optional(),\n type: z.string().optional(),\n version: z.string().optional(),\n })\n .optional(),\n\n /** User's IP address */\n ip: z.string().optional(),\n\n /** Library making the request */\n library: z\n .object({\n name: z.string(),\n version: z.string(),\n })\n .optional(),\n\n /** User's locale (e.g., 'en-US') */\n locale: z.string().optional(),\n\n /** Network information */\n network: z\n .object({\n bluetooth: z.boolean().optional(),\n carrier: z.string().optional(),\n cellular: z.boolean().optional(),\n wifi: z.boolean().optional(),\n })\n .optional(),\n\n /** OS information */\n os: z\n .object({\n name: z.string().optional(),\n version: z.string().optional(),\n })\n .optional(),\n\n /** Page information */\n page: z\n .object({\n path: z.string().optional(),\n // Use permissive string validation for referrer/url since real-world values\n // may be malformed, truncated, or non-standard (e.g., data: URIs, about:blank)\n referrer: z.string().optional(),\n search: z.string().optional(),\n title: z.string().optional(),\n url: z.string().optional(),\n })\n .optional(),\n\n /** Screen information */\n screen: z\n .object({\n density: z.number().optional(),\n height: z.number().int().positive().optional(),\n width: z.number().int().positive().optional(),\n })\n .optional(),\n\n /** User's timezone (tzdata string) */\n timezone: z.string().optional(),\n\n /** Group/account ID */\n groupId: z.string().optional(),\n\n /** User agent string */\n userAgent: z.string().optional(),\n\n /** Channel where request originated */\n channel: z.enum(['server', 'browser', 'mobile', 'api']).optional(),\n\n /** Location context */\n location: z\n .object({\n city: z.string().optional(),\n country: z.string().optional(),\n latitude: z.number().optional(),\n longitude: z.number().optional(),\n region: z.string().optional(),\n })\n .optional(),\n })\n .passthrough();\n\n// =============================================================================\n// Event Type Schemas\n// =============================================================================\n\n/**\n * Base payload schema - common fields for all event types.\n */\nconst BasePayloadSchema = z\n .object({\n /** Anonymous ID if user is not identified */\n anonymousId: z.string().max(255).optional(),\n\n /** User ID (at least one of userId or anonymousId required) */\n userId: z.string().max(255).optional(),\n\n /** Timestamp when the event occurred */\n timestamp: z.union([z.string().datetime(), z.date()]).optional(),\n\n /** Original timestamp before processing */\n originalTimestamp: z.union([z.string().datetime(), z.date()]).optional(),\n\n /** Context and control fields */\n context: EmitterContextSchema.optional(),\n\n /** Message ID for deduplication */\n messageId: z.string().uuid().optional(),\n })\n .refine(data => Boolean(data.anonymousId) || Boolean(data.userId), {\n message: 'Either anonymousId or userId must be provided',\n });\n\n/**\n * Track event payload schema.\n * Uses safeExtend() because BasePayloadSchema has refinements (Zod v4 requirement).\n */\nexport const TrackEventSchema = BasePayloadSchema.safeExtend({\n type: z.literal('track'),\n event: z.string().min(1).max(255),\n properties: PropertyObjectSchema.optional(),\n});\n\n/**\n * Identify event payload schema.\n * Uses safeExtend() because BasePayloadSchema has refinements (Zod v4 requirement).\n */\nexport const IdentifyEventSchema = BasePayloadSchema.safeExtend({\n type: z.literal('identify'),\n userId: z.string().min(1).max(255),\n traits: PropertyObjectSchema.optional(),\n});\n\n/**\n * Page event payload schema.\n * Uses safeExtend() because BasePayloadSchema has refinements (Zod v4 requirement).\n */\nexport const PageEventSchema = BasePayloadSchema.safeExtend({\n type: z.literal('page'),\n name: z.string().max(255).optional(),\n category: z.string().max(255).optional(),\n properties: PropertyObjectSchema.optional(),\n});\n\n/**\n * Screen event payload schema.\n * Uses safeExtend() because BasePayloadSchema has refinements (Zod v4 requirement).\n */\nexport const ScreenEventSchema = BasePayloadSchema.safeExtend({\n type: z.literal('screen'),\n name: z.string().max(255).optional(),\n category: z.string().max(255).optional(),\n properties: PropertyObjectSchema.optional(),\n});\n\n/**\n * Group event payload schema.\n * Uses safeExtend() because BasePayloadSchema has refinements (Zod v4 requirement).\n */\nexport const GroupEventSchema = BasePayloadSchema.safeExtend({\n type: z.literal('group'),\n groupId: z.string().min(1).max(255),\n traits: PropertyObjectSchema.optional(),\n});\n\n/**\n * Alias event payload schema.\n * Uses safeExtend() because BasePayloadSchema has refinements (Zod v4 requirement).\n */\nexport const AliasEventSchema = BasePayloadSchema.safeExtend({\n type: z.literal('alias'),\n userId: z.string().min(1).max(255),\n previousId: z.string().min(1).max(255),\n});\n\n/**\n * Union of all event payload schemas.\n */\nexport const EventPayloadSchema = z.discriminatedUnion('type', [\n TrackEventSchema,\n IdentifyEventSchema,\n PageEventSchema,\n ScreenEventSchema,\n GroupEventSchema,\n AliasEventSchema,\n]);\n\n// =============================================================================\n// Ingestion Request Schemas\n// =============================================================================\n\n/**\n * Single event ingestion request schema.\n */\nexport const SingleEventRequestSchema = EventPayloadSchema;\n\n/**\n * Batch event ingestion request schema.\n *\n * The batch size limit is enforced at the service level via `maxBatchSize` config\n * (default: 100) rather than in the schema, allowing for flexible configuration.\n */\nexport const BatchEventRequestSchema = z.object({\n batch: z.array(EventPayloadSchema).min(1),\n});\n\n/**\n * Combined ingestion request schema - accepts single event or batch.\n */\nexport const IngestionRequestSchema = z.union([BatchEventRequestSchema, SingleEventRequestSchema]);\n\n// =============================================================================\n// Ingestion Response Schemas\n// =============================================================================\n\n/**\n * Event processing result.\n */\nexport const EventResultSchema = z.object({\n /** Server-generated event ID */\n id: z.string().uuid(),\n\n /** Original message ID if provided */\n messageId: z.string().uuid().optional(),\n\n /** Event type */\n type: z.enum(['track', 'identify', 'page', 'screen', 'group', 'alias']),\n\n /** Processing status */\n status: z.enum(['accepted', 'rejected']),\n\n /** Error message if rejected */\n error: z.string().optional(),\n});\n\n/**\n * Successful ingestion response schema.\n */\nexport const IngestionSuccessResponseSchema = z.object({\n /** Whether the request was successful */\n success: z.literal(true),\n\n /** Number of events accepted */\n accepted: z.number().int().nonnegative(),\n\n /** Number of events rejected */\n rejected: z.number().int().nonnegative(),\n\n /** Per-event results */\n results: z.array(EventResultSchema),\n\n /** Server timestamp when events were received */\n receivedAt: z.string().datetime(),\n});\n\n/**\n * Error response schema.\n */\nexport const IngestionErrorResponseSchema = z.object({\n /** Whether the request was successful */\n success: z.literal(false),\n\n /** Error code */\n code: z.string(),\n\n /** Error message */\n error: z.string(),\n\n /** Field-level validation errors */\n fieldErrors: z\n .array(\n z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n }),\n )\n .optional(),\n});\n\n/**\n * Combined response schema.\n */\nexport const IngestionResponseSchema = z.union([\n IngestionSuccessResponseSchema,\n IngestionErrorResponseSchema,\n]);\n\n// =============================================================================\n// Type Exports\n// =============================================================================\n\nexport type PropertyValue = z.infer<typeof PropertyValueSchema>;\nexport type PropertyObject = z.infer<typeof PropertyObjectSchema>;\nexport type EmitterContext = z.infer<typeof EmitterContextSchema>;\nexport type TrackEvent = z.infer<typeof TrackEventSchema>;\nexport type IdentifyEvent = z.infer<typeof IdentifyEventSchema>;\nexport type PageEvent = z.infer<typeof PageEventSchema>;\nexport type ScreenEvent = z.infer<typeof ScreenEventSchema>;\nexport type GroupEvent = z.infer<typeof GroupEventSchema>;\nexport type AliasEvent = z.infer<typeof AliasEventSchema>;\nexport type EventPayload = z.infer<typeof EventPayloadSchema>;\nexport type SingleEventRequest = z.infer<typeof SingleEventRequestSchema>;\nexport type BatchEventRequest = z.infer<typeof BatchEventRequestSchema>;\nexport type IngestionRequest = z.infer<typeof IngestionRequestSchema>;\nexport type EventResult = z.infer<typeof EventResultSchema>;\nexport type IngestionSuccessResponse = z.infer<typeof IngestionSuccessResponseSchema>;\nexport type IngestionErrorResponse = z.infer<typeof IngestionErrorResponseSchema>;\nexport type IngestionResponse = z.infer<typeof IngestionResponseSchema>;\n","/**\n * @fileoverview Event Ingestion Service\n *\n * Provides server-side event ingestion functionality. Handles validation,\n * normalization, and forwarding of events to the analytics system.\n *\n * **Key Features**:\n * - Validates incoming events against Zod schemas\n * - Normalizes event payloads with defaults\n * - Forwards events to AnalyticsManager\n * - Tracks ingestion metrics\n * - Handles batch processing efficiently\n *\n * @module @od-oneapp/analytics/shared/ingestion/service\n */\n\nimport { logDebug, logError, logInfo, logWarn } from '@repo/shared/logs';\n\nimport { sanitizeProperties, validateEventName } from '../utils/security';\n\nimport { BatchEventRequestSchema, EventPayloadSchema, IngestionRequestSchema } from './schemas';\n\nimport type {\n BatchEventRequest,\n EmitterContext,\n EventPayload,\n EventResult,\n IngestionErrorResponse,\n IngestionRequest,\n IngestionSuccessResponse,\n} from './schemas';\nimport type { EmitterPayload } from '../emitters/emitter-types';\nimport type { AnalyticsManager } from '../types/types';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Ingestion context provided by the caller (usually the API route handler).\n */\nexport interface IngestionContext {\n /** Source identifier (app/module/emitter id) */\n source: string;\n\n /** Tenant/project ID for multi-tenancy */\n tenantId?: string;\n\n /** User ID from auth context */\n userId?: string;\n\n /** Account/organization ID */\n accountId?: string;\n\n /** Client IP address */\n ip?: string;\n\n /** Client user agent */\n userAgent?: string;\n\n /** Environment (dev/stage/prod) */\n environment?: string;\n\n /** Trace ID for observability */\n traceId?: string;\n\n /** Correlation ID for request tracing */\n correlationId?: string;\n\n /** API version */\n apiVersion?: string;\n\n /** SDK version from client */\n sdkVersion?: string;\n}\n\n/**\n * Ingestion service configuration.\n */\nexport interface IngestionServiceConfig {\n /** Maximum events per batch (default: 100) */\n maxBatchSize?: number;\n\n /** Maximum payload size in bytes (default: 1MB) */\n maxPayloadSize?: number;\n\n /** Whether to strip PII from properties (default: true in production) */\n stripPII?: boolean;\n\n /** Whether to strip HTML from properties (default: true) */\n stripHTML?: boolean;\n\n /** Timeout for processing each event in ms (default: 5000) */\n eventTimeout?: number;\n\n /** Concurrency for batch processing (default: 10) */\n batchConcurrency?: number;\n}\n\n/**\n * Ingestion metrics for observability.\n */\nexport interface IngestionMetrics {\n /** Total events received */\n totalReceived: number;\n\n /** Events accepted */\n accepted: number;\n\n /** Events rejected */\n rejected: number;\n\n /** Events by type */\n byType: Record<string, number>;\n\n /** Processing time in ms */\n processingTimeMs: number;\n}\n\n// =============================================================================\n// Default Configuration\n// =============================================================================\n\nconst DEFAULT_CONFIG: Required<IngestionServiceConfig> = {\n maxBatchSize: 100,\n maxPayloadSize: 1024 * 1024, // 1MB\n stripPII: true, // Default to safe; callers can override\n stripHTML: true,\n eventTimeout: 5000,\n batchConcurrency: 10,\n};\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Generate a UUID v4.\n */\nfunction generateUUID(): string {\n return crypto.randomUUID();\n}\n\n/**\n * Get current ISO timestamp.\n */\nfunction getCurrentTimestamp(): string {\n return new Date().toISOString();\n}\n\n/**\n * Check if request is a batch request.\n */\nfunction isBatchRequest(request: IngestionRequest): request is BatchEventRequest {\n return 'batch' in request && Array.isArray(request.batch);\n}\n\n/**\n * Normalize an event payload with defaults and server metadata.\n */\nfunction normalizeEvent(\n event: EventPayload,\n context: IngestionContext,\n receivedAt: string,\n): EventPayload {\n const normalized = { ...event };\n\n // Generate message ID if not provided\n if (!normalized.messageId) {\n normalized.messageId = generateUUID();\n }\n\n // Set timestamp if not provided\n if (!normalized.timestamp) {\n normalized.timestamp = receivedAt;\n }\n\n // Preserve original timestamp\n if (!normalized.originalTimestamp) {\n normalized.originalTimestamp = normalized.timestamp;\n }\n\n // Merge context with server-provided context\n const mergedContext: EmitterContext = {\n ...normalized.context,\n channel: normalized.context?.channel ?? 'api',\n ip: context.ip ?? normalized.context?.ip,\n userAgent: context.userAgent ?? normalized.context?.userAgent,\n library: normalized.context?.library ?? {\n name: context.source,\n version: context.sdkVersion ?? 'unknown',\n },\n };\n\n normalized.context = mergedContext;\n\n // Set userId from auth context if not provided\n if (!normalized.userId && context.userId) {\n normalized.userId = context.userId;\n }\n\n return normalized;\n}\n\n/**\n * Convert EventPayload to EmitterPayload format for AnalyticsManager.\n * Explicitly maps fields to ensure type safety.\n */\nfunction toEmitterPayload(event: EventPayload): EmitterPayload {\n // Explicitly construct the EmitterPayload from EventPayload fields\n // to maintain type safety and avoid unsafe double casts\n const basePayload = {\n userId: event.userId,\n anonymousId: event.anonymousId,\n timestamp: event.timestamp,\n context: event.context,\n messageId: event.messageId,\n };\n\n switch (event.type) {\n case 'track':\n return {\n type: 'track',\n event: event.event,\n properties: event.properties,\n ...basePayload,\n } as EmitterPayload;\n case 'identify':\n return {\n type: 'identify',\n traits: event.traits,\n ...basePayload,\n } as EmitterPayload;\n case 'page':\n return {\n type: 'page',\n name: event.name,\n category: event.category,\n properties: event.properties,\n ...basePayload,\n } as EmitterPayload;\n case 'screen':\n return {\n type: 'screen',\n name: event.name,\n category: event.category,\n properties: event.properties,\n ...basePayload,\n } as EmitterPayload;\n case 'group':\n return {\n type: 'group',\n groupId: event.groupId,\n traits: event.traits,\n ...basePayload,\n } as EmitterPayload;\n case 'alias':\n return {\n type: 'alias',\n previousId: event.previousId,\n ...basePayload,\n } as EmitterPayload;\n default:\n // This should never happen due to discriminated union validation\n throw new Error(`Unknown event type: ${(event as { type: string }).type}`);\n }\n}\n\n// =============================================================================\n// Ingestion Service Class\n// =============================================================================\n\n/**\n * Event Ingestion Service.\n *\n * Handles validation, normalization, and forwarding of analytics events.\n * Designed for high-volume ingestion with batching and rate limiting support.\n *\n * @example\n * ```typescript\n * const service = new IngestionService(analyticsManager);\n *\n * const result = await service.ingest(requestBody, {\n * source: 'web-app',\n * tenantId: 'tenant-123',\n * userId: 'user-456',\n * });\n *\n * if (result.success) {\n * console.log(`Accepted ${result.accepted} events`);\n * }\n * ```\n */\nexport class IngestionService {\n private readonly config: Required<IngestionServiceConfig>;\n\n constructor(\n private readonly analyticsManager: AnalyticsManager,\n config: IngestionServiceConfig = {},\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Parse and validate the ingestion request payload.\n *\n * @param payload - Raw request payload (parsed JSON)\n * @returns Parsed and validated request, or error response\n */\n parseRequest(\n payload: unknown,\n ): { success: true; data: IngestionRequest } | { success: false; error: IngestionErrorResponse } {\n // Validate payload size (rough estimate)\n try {\n const payloadSize = JSON.stringify(payload).length;\n if (payloadSize > this.config.maxPayloadSize) {\n return {\n success: false,\n error: {\n success: false,\n code: 'PAYLOAD_TOO_LARGE',\n error: `Payload size ${payloadSize} exceeds maximum ${this.config.maxPayloadSize} bytes`,\n },\n };\n }\n } catch {\n return {\n success: false,\n error: {\n success: false,\n code: 'INVALID_JSON',\n error: 'Failed to serialize payload for size check',\n },\n };\n }\n\n // Validate against schema\n const result = IngestionRequestSchema.safeParse(payload);\n\n if (!result.success) {\n const fieldErrors = result.error.issues.map(err => ({\n path: err.path.map(p => (typeof p === 'symbol' ? String(p) : p)),\n message: err.message,\n }));\n\n return {\n success: false,\n error: {\n success: false,\n code: 'VALIDATION_ERROR',\n error: 'Request validation failed',\n fieldErrors,\n },\n };\n }\n\n // Check batch size\n if (isBatchRequest(result.data) && result.data.batch.length > this.config.maxBatchSize) {\n return {\n success: false,\n error: {\n success: false,\n code: 'BATCH_TOO_LARGE',\n error: `Batch size ${result.data.batch.length} exceeds maximum ${this.config.maxBatchSize}`,\n },\n };\n }\n\n return { success: true, data: result.data };\n }\n\n /**\n * Ingest events from a validated request.\n *\n * @param request - Validated ingestion request\n * @param context - Ingestion context from the caller\n * @returns Ingestion response with per-event results\n */\n async ingest(\n request: IngestionRequest,\n context: IngestionContext,\n ): Promise<IngestionSuccessResponse> {\n const startTime = process.hrtime.bigint();\n const receivedAt = getCurrentTimestamp();\n\n // Extract events from request (single or batch)\n const events: EventPayload[] = isBatchRequest(request) ? request.batch : [request];\n\n const results: EventResult[] = [];\n const metrics: IngestionMetrics = {\n totalReceived: events.length,\n accepted: 0,\n rejected: 0,\n byType: {},\n processingTimeMs: 0,\n };\n\n // Process events\n const processedEvents: EmitterPayload[] = [];\n\n for (const event of events) {\n const eventId = generateUUID();\n\n try {\n // Validate event name for track events\n if (event.type === 'track') {\n const validation = validateEventName(event.event);\n if (!validation.valid) {\n results.push({\n id: eventId,\n messageId: event.messageId,\n type: event.type,\n status: 'rejected',\n error: `Invalid event name: ${validation.reason}`,\n });\n metrics.rejected++;\n continue;\n }\n }\n\n // Normalize event\n const normalized = normalizeEvent(event, context, receivedAt);\n\n // Sanitize properties\n if ('properties' in normalized && normalized.properties) {\n const sanitized = sanitizeProperties(normalized.properties, {\n stripPII: this.config.stripPII,\n stripHTML: this.config.stripHTML,\n allowDangerousKeys: false,\n });\n (normalized as { properties: Record<string, unknown> }).properties = sanitized.data;\n\n if (sanitized.warnings.length > 0) {\n logDebug('Event properties sanitized', {\n eventId,\n warnings: sanitized.warnings,\n });\n }\n }\n\n if ('traits' in normalized && normalized.traits) {\n const sanitized = sanitizeProperties(normalized.traits, {\n stripPII: this.config.stripPII,\n stripHTML: this.config.stripHTML,\n allowDangerousKeys: false,\n });\n (normalized as { traits: Record<string, unknown> }).traits = sanitized.data;\n }\n\n // Convert to emitter payload and queue for processing\n const emitterPayload = toEmitterPayload(normalized);\n processedEvents.push(emitterPayload);\n\n results.push({\n id: eventId,\n messageId: normalized.messageId,\n type: event.type,\n status: 'accepted',\n });\n\n metrics.accepted++;\n metrics.byType[event.type] = (metrics.byType[event.type] ?? 0) + 1;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n\n results.push({\n id: eventId,\n messageId: event.messageId,\n type: event.type,\n status: 'rejected',\n error: errorMessage,\n });\n\n metrics.rejected++;\n\n logWarn('Event processing failed', {\n eventId,\n type: event.type,\n error: errorMessage,\n });\n }\n }\n\n // Forward accepted events to analytics manager (non-blocking)\n // Note: This provides at-most-once delivery semantics. Events may be lost\n // if the analytics manager fails. For guaranteed delivery, consider using\n // a durable queue (Redis, SQS) for critical events.\n if (processedEvents.length > 0) {\n // Use emitBatch for efficient processing\n void (async () => {\n try {\n await this.analyticsManager.emitBatch(processedEvents, {\n timeout: this.config.eventTimeout,\n concurrency: this.config.batchConcurrency,\n failFast: false, // Process all events even if some fail\n });\n } catch (error) {\n logError('Failed to emit events to analytics manager', {\n error: error instanceof Error ? error.message : 'Unknown error',\n eventCount: processedEvents.length,\n traceId: context.traceId,\n });\n }\n })();\n }\n\n // Calculate processing time\n const endTime = process.hrtime.bigint();\n metrics.processingTimeMs = Number(endTime - startTime) / 1_000_000;\n\n // Log metrics\n logInfo('Event ingestion completed', {\n traceId: context.traceId,\n source: context.source,\n tenantId: context.tenantId,\n totalReceived: metrics.totalReceived,\n accepted: metrics.accepted,\n rejected: metrics.rejected,\n processingTimeMs: metrics.processingTimeMs.toFixed(2),\n byType: metrics.byType,\n });\n\n return {\n success: true,\n accepted: metrics.accepted,\n rejected: metrics.rejected,\n results,\n receivedAt,\n };\n }\n\n /**\n * Process a raw request body through parsing and ingestion.\n *\n * Convenience method that combines parseRequest and ingest.\n *\n * @param payload - Raw request payload\n * @param context - Ingestion context\n * @returns Ingestion response (success or error)\n */\n async processRequest(\n payload: unknown,\n context: IngestionContext,\n ): Promise<IngestionSuccessResponse | IngestionErrorResponse> {\n const parseResult = this.parseRequest(payload);\n\n if (!parseResult.success) {\n return parseResult.error;\n }\n\n return this.ingest(parseResult.data, context);\n }\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create an ingestion service instance.\n *\n * @param analyticsManager - Initialized AnalyticsManager instance\n * @param config - Optional service configuration\n * @returns Configured IngestionService instance\n *\n * @example\n * ```typescript\n * import { createServerAnalytics } from '@od-oneapp/analytics/server';\n * import { createIngestionService } from '@od-oneapp/analytics/server';\n *\n * const analytics = await createServerAnalytics(config);\n * const ingestionService = createIngestionService(analytics);\n * ```\n */\nexport function createIngestionService(\n analyticsManager: AnalyticsManager,\n config?: IngestionServiceConfig,\n): IngestionService {\n return new IngestionService(analyticsManager, config);\n}\n\n/**\n * Validate a single event payload.\n *\n * Useful for pre-validation before queuing events.\n *\n * @param payload - Event payload to validate\n * @returns Validation result with parsed data or errors\n */\nexport function validateEventPayload(\n payload: unknown,\n): { success: true; data: EventPayload } | { success: false; errors: string[] } {\n const result = EventPayloadSchema.safeParse(payload);\n\n if (!result.success) {\n return {\n success: false,\n errors: result.error.issues.map(\n e => `${e.path.map(p => (typeof p === 'symbol' ? String(p) : p)).join('.')}: ${e.message}`,\n ),\n };\n }\n\n return { success: true, data: result.data };\n}\n\n/**\n * Validate a batch of event payloads.\n *\n * @param payloads - Array of event payloads to validate\n * @returns Validation result with parsed data or errors\n */\nexport function validateBatchPayload(\n payloads: unknown[],\n): { success: true; data: EventPayload[] } | { success: false; errors: string[] } {\n const result = BatchEventRequestSchema.safeParse({ batch: payloads });\n\n if (!result.success) {\n return {\n success: false,\n errors: result.error.issues.map(\n e => `${e.path.map(p => (typeof p === 'symbol' ? String(p) : p)).join('.')}: ${e.message}`,\n ),\n };\n }\n\n return { success: true, data: result.data.batch };\n}\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { c as ProviderConfig, d as TrackingOptions, i as AnalyticsProvider, n as AnalyticsContext, r as AnalyticsManager, t as AnalyticsConfig } from "./types-BxBnNQ0V.mjs";
2
+ import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-DldkVSPp.mjs";
3
+ import { t as index_d_exports$1 } from "./index-jPzXRn52.mjs";
4
+ import { t as index_d_exports } from "./index-BkIWe--N.mjs";
5
+
6
+ //#region src/shared.d.ts
7
+ declare function createAnalytics(config: AnalyticsConfig): Promise<AnalyticsManager>;
8
+ declare const environmentInfo: {
9
+ isServer: boolean;
10
+ isNextJS: boolean;
11
+ runtime: string;
12
+ nodeEnv: "development" | "production" | "test";
13
+ };
14
+ //#endregion
15
+ export { type AnalyticsConfig, type AnalyticsContext, type AnalyticsManager, type AnalyticsProvider, type ProviderConfig, type TrackingOptions, index_d_exports as ai, alias, createAnalytics, index_d_exports$1 as ecommerce, environmentInfo, group, identify, page, track };
16
+ //# sourceMappingURL=shared.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.mts","names":[],"sources":["../src/shared.ts"],"mappings":";;;;;;iBAkGsB,eAAA,CAAgB,MAAA,EAAQ,eAAA,GAAkB,OAAA,CAAQ,gBAAA;AAAA,cAmD3D,eAAA"}
@@ -0,0 +1,93 @@
1
+ import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-6-nKo8i-.mjs";
2
+ import { t as ecommerce_exports } from "./ecommerce-Cgu4wlux.mjs";
3
+ import { t as ai_exports } from "./ai-YMnynb-t.mjs";
4
+
5
+ //#region src/shared.ts
6
+ /**
7
+ * Detects if code is running in a server environment.
8
+ *
9
+ * Checks for absence of `window` object and presence of `global` object.
10
+ *
11
+ * @returns {boolean} `true` if running on server, `false` if running in browser
12
+ *
13
+ * @internal
14
+ */
15
+ function isServerEnvironment() {
16
+ return typeof window === "undefined" && typeof global !== "undefined";
17
+ }
18
+ /**
19
+ * Detects if code is running in a Next.js environment.
20
+ *
21
+ * Checks for Next.js-specific environment variables and globals.
22
+ *
23
+ * @returns {boolean} `true` if running in Next.js, `false` otherwise
24
+ *
25
+ * @internal
26
+ */
27
+ function isNextJSEnvironment() {
28
+ return process.env.NEXT_RUNTIME !== void 0 || typeof globalThis.__NEXT_DATA__ !== "undefined" || typeof globalThis.EdgeRuntime !== "undefined" || typeof process !== "undefined" && process.title?.includes("next") || typeof process !== "undefined" && process.env.NEXT_PUBLIC_APP_ENV !== void 0;
29
+ }
30
+ /**
31
+ * Creates an analytics manager appropriate for the current environment.
32
+ *
33
+ * Automatically detects the runtime environment (server/client, Next.js/plain) and
34
+ * creates the appropriate analytics manager instance. This allows packages to use
35
+ * analytics without knowing which environment they're running in.
36
+ *
37
+ * @param {AnalyticsConfig} config - Analytics configuration with provider settings
38
+ * @returns {Promise<AnalyticsManager>} Promise resolving to analytics manager instance
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const analytics = await createAnalytics({
43
+ * providers: {
44
+ * posthog: { apiKey: process.env.POSTHOG_API_KEY }
45
+ * }
46
+ * });
47
+ *
48
+ * await analytics.emit(track('User Action', { action: 'click' }));
49
+ * ```
50
+ */
51
+ async function createAnalytics(config) {
52
+ const isServer = isServerEnvironment();
53
+ const isNextJS = isNextJSEnvironment();
54
+ if (isServer) if (isNextJS) {
55
+ const { createServerAnalytics } = await import("./server-next.mjs");
56
+ return createServerAnalytics(config);
57
+ } else {
58
+ const { createServerAnalytics } = await import("./server.mjs");
59
+ return createServerAnalytics(config);
60
+ }
61
+ else if (isNextJS) {
62
+ const { createNextJSClientAnalytics } = await import("./client-next.mjs");
63
+ return createNextJSClientAnalytics(config);
64
+ } else {
65
+ const { createClientAnalytics } = await import("./client.mjs");
66
+ return createClientAnalytics(config);
67
+ }
68
+ }
69
+ /**
70
+ * Environment information for debugging and introspection.
71
+ *
72
+ * Provides runtime information about the current environment, useful for debugging
73
+ * and conditional logic based on environment.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * import { environmentInfo } from '@od-oneapp/analytics/shared';
78
+ *
79
+ * console.log('Running on server:', environmentInfo.isServer);
80
+ * console.log('Next.js environment:', environmentInfo.isNextJS);
81
+ * console.log('Runtime:', environmentInfo.runtime);
82
+ * ```
83
+ */
84
+ const environmentInfo = {
85
+ isServer: isServerEnvironment(),
86
+ isNextJS: isNextJSEnvironment(),
87
+ runtime: typeof process !== "undefined" ? process.env.NEXT_RUNTIME ?? "node" : "browser",
88
+ nodeEnv: typeof process !== "undefined" ? "development" : "production"
89
+ };
90
+
91
+ //#endregion
92
+ export { ai_exports as ai, alias, createAnalytics, ecommerce_exports as ecommerce, environmentInfo, group, identify, page, track };
93
+ //# sourceMappingURL=shared.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.mjs","names":[],"sources":["../src/shared.ts"],"sourcesContent":["/**\n * @fileoverview Shared Environment Analytics Exports\n *\n * This module provides environment-agnostic analytics functionality for packages\n * that can run in both client and server environments. It automatically detects\n * the runtime environment and uses the appropriate analytics implementation.\n *\n * **Environment Detection**:\n * - Detects server vs client environments\n * - Detects Next.js vs plain Node.js/React environments\n * - Automatically selects the correct analytics manager\n *\n * **Key Features**:\n * - Single API that works in all environments\n * - Automatic environment detection\n * - Type-safe event tracking\n * - Ecommerce and AI event emitters\n *\n * **Usage**: Use this module when you need analytics in code that runs in both\n * client and server contexts (e.g., shared utilities, isomorphic code).\n *\n * @example\n * ```typescript\n * // In environment-agnostic code\n * import { createAnalytics, track } from '@od-oneapp/analytics/shared';\n *\n * // Works in both client and server environments\n * const analytics = await createAnalytics(config);\n * await analytics.emit(track('Event Name', { property: 'value' }));\n * ```\n *\n * @module @od-oneapp/analytics/shared\n */\n\n// Import types for proper typing\nimport type { AnalyticsConfig, AnalyticsManager } from './shared/types/types';\n\n/**\n * Detects if code is running in a server environment.\n *\n * Checks for absence of `window` object and presence of `global` object.\n *\n * @returns {boolean} `true` if running on server, `false` if running in browser\n *\n * @internal\n */\nfunction isServerEnvironment(): boolean {\n return typeof window === 'undefined' && typeof global !== 'undefined';\n}\n\n/**\n * Detects if code is running in a Next.js environment.\n *\n * Checks for Next.js-specific environment variables and globals.\n *\n * @returns {boolean} `true` if running in Next.js, `false` otherwise\n *\n * @internal\n */\nfunction isNextJSEnvironment(): boolean {\n // Check for Next.js-specific environment variables and globals\n return (\n // Next.js runtime environment variable\n process.env.NEXT_RUNTIME !== undefined ||\n // Next.js data global (client-side)\n typeof (globalThis as any).__NEXT_DATA__ !== 'undefined' ||\n // Edge runtime global\n typeof (globalThis as any).EdgeRuntime !== 'undefined' ||\n // Next.js process title\n (typeof process !== 'undefined' && process.title?.includes('next')) ||\n // Next.js in development mode\n (typeof process !== 'undefined' &&\n process.env.NODE_ENV === 'development' &&\n process.env.NEXT_PUBLIC_APP_ENV !== undefined)\n );\n}\n\n/**\n * Creates an analytics manager appropriate for the current environment.\n *\n * Automatically detects the runtime environment (server/client, Next.js/plain) and\n * creates the appropriate analytics manager instance. This allows packages to use\n * analytics without knowing which environment they're running in.\n *\n * @param {AnalyticsConfig} config - Analytics configuration with provider settings\n * @returns {Promise<AnalyticsManager>} Promise resolving to analytics manager instance\n *\n * @example\n * ```typescript\n * const analytics = await createAnalytics({\n * providers: {\n * posthog: { apiKey: process.env.POSTHOG_API_KEY }\n * }\n * });\n *\n * await analytics.emit(track('User Action', { action: 'click' }));\n * ```\n */\nexport async function createAnalytics(config: AnalyticsConfig): Promise<AnalyticsManager> {\n const isServer = isServerEnvironment();\n const isNextJS = isNextJSEnvironment();\n\n if (isServer) {\n if (isNextJS) {\n const { createServerAnalytics } = await import('./server-next');\n return createServerAnalytics(config);\n } else {\n const { createServerAnalytics } = await import('./server');\n return createServerAnalytics(config);\n }\n } else {\n if (isNextJS) {\n const { createNextJSClientAnalytics } = await import('./client-next');\n return createNextJSClientAnalytics(config);\n } else {\n const { createClientAnalytics } = await import('./client');\n return createClientAnalytics(config);\n }\n }\n}\n\n// Re-export essential types that shared packages need\nexport type {\n AnalyticsConfig,\n AnalyticsContext,\n AnalyticsManager,\n AnalyticsProvider,\n ProviderConfig,\n TrackingOptions,\n} from './shared/types/types';\n\n// Re-export emitters for environment-agnostic usage\nexport { aiSdk as ai, alias, ecommerce, group, identify, page, track } from './shared/emitters';\n\n/**\n * Environment information for debugging and introspection.\n *\n * Provides runtime information about the current environment, useful for debugging\n * and conditional logic based on environment.\n *\n * @example\n * ```typescript\n * import { environmentInfo } from '@od-oneapp/analytics/shared';\n *\n * console.log('Running on server:', environmentInfo.isServer);\n * console.log('Next.js environment:', environmentInfo.isNextJS);\n * console.log('Runtime:', environmentInfo.runtime);\n * ```\n */\nexport const environmentInfo = {\n isServer: isServerEnvironment(),\n isNextJS: isNextJSEnvironment(),\n runtime: typeof process !== 'undefined' ? (process.env.NEXT_RUNTIME ?? 'node') : 'browser',\n nodeEnv: typeof process !== 'undefined' ? process.env.NODE_ENV : 'production',\n};\n"],"mappings":";;;;;;;;;;;;;;AA8CA,SAAS,sBAA+B;AACtC,QAAO,OAAO,WAAW,eAAe,OAAO,WAAW;;;;;;;;;;;AAY5D,SAAS,sBAA+B;AAEtC,QAEE,QAAQ,IAAI,iBAAiB,UAE7B,OAAQ,WAAmB,kBAAkB,eAE7C,OAAQ,WAAmB,gBAAgB,eAE1C,OAAO,YAAY,eAAe,QAAQ,OAAO,SAAS,OAAO,IAEjE,OAAO,YAAY,eAElB,QAAQ,IAAI,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;AAyB1C,eAAsB,gBAAgB,QAAoD;CACxF,MAAM,WAAW,qBAAqB;CACtC,MAAM,WAAW,qBAAqB;AAEtC,KAAI,SACF,KAAI,UAAU;EACZ,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,SAAO,sBAAsB,OAAO;QAC/B;EACL,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,SAAO,sBAAsB,OAAO;;UAGlC,UAAU;EACZ,MAAM,EAAE,gCAAgC,MAAM,OAAO;AACrD,SAAO,4BAA4B,OAAO;QACrC;EACL,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,SAAO,sBAAsB,OAAO;;;;;;;;;;;;;;;;;;AAiC1C,MAAa,kBAAkB;CAC7B,UAAU,qBAAqB;CAC/B,UAAU,qBAAqB;CAC/B,SAAS,OAAO,YAAY,cAAe,QAAQ,IAAI,gBAAgB,SAAU;CACjF,SAAS,OAAO,YAAY,8BAAqC;CAClE"}
@@ -0,0 +1,354 @@
1
+ //#region src/shared/types/base-types.d.ts
2
+ type PropertyValue = string | number | boolean | Date | null | undefined;
3
+ interface PropertyObject {
4
+ [key: string]: PropertyValue | PropertyValue[] | PropertyObject;
5
+ }
6
+ type Properties = PropertyObject;
7
+ type UserTraits = Record<string, PropertyValue | PropertyValue[]>;
8
+ type GroupTraits = Record<string, PropertyValue | PropertyValue[]>;
9
+ type PageProperties = Record<string, PropertyValue | PropertyValue[] | PropertyObject>;
10
+ //#endregion
11
+ //#region src/shared/emitters/emitter-types.d.ts
12
+ interface EmitterContext {
13
+ active?: boolean;
14
+ app?: {
15
+ name?: string;
16
+ version?: string;
17
+ build?: string;
18
+ namespace?: string;
19
+ };
20
+ campaign?: {
21
+ name?: string;
22
+ source?: string;
23
+ medium?: string;
24
+ term?: string;
25
+ content?: string;
26
+ [key: string]: string | undefined;
27
+ };
28
+ device?: {
29
+ id?: string;
30
+ advertisingId?: string;
31
+ adTrackingEnabled?: boolean;
32
+ manufacturer?: string;
33
+ model?: string;
34
+ name?: string;
35
+ type?: string;
36
+ version?: string;
37
+ token?: string;
38
+ };
39
+ ip?: string;
40
+ library?: {
41
+ name: string;
42
+ version: string;
43
+ };
44
+ locale?: string;
45
+ network?: {
46
+ bluetooth?: boolean;
47
+ carrier?: string;
48
+ cellular?: boolean;
49
+ wifi?: boolean;
50
+ };
51
+ os?: {
52
+ name?: string;
53
+ version?: string;
54
+ };
55
+ page?: {
56
+ path?: string;
57
+ referrer?: string;
58
+ search?: string;
59
+ title?: string;
60
+ url?: string;
61
+ };
62
+ referrer?: {
63
+ id?: string;
64
+ type?: string;
65
+ name?: string;
66
+ url?: string;
67
+ link?: string;
68
+ };
69
+ screen?: {
70
+ density?: number;
71
+ height?: number;
72
+ width?: number;
73
+ };
74
+ timezone?: string;
75
+ groupId?: string;
76
+ traits?: UserTraits;
77
+ userAgent?: string;
78
+ userAgentData?: {
79
+ brands?: {
80
+ brand: string;
81
+ version: string;
82
+ }[];
83
+ mobile?: boolean;
84
+ platform?: string;
85
+ bitness?: string;
86
+ model?: string;
87
+ platformVersion?: string;
88
+ uaFullVersion?: string;
89
+ fullVersionList?: {
90
+ brand: string;
91
+ version: string;
92
+ }[];
93
+ wow64?: boolean;
94
+ };
95
+ channel?: string;
96
+ location?: {
97
+ city?: string;
98
+ country?: string;
99
+ latitude?: number;
100
+ longitude?: number;
101
+ region?: string;
102
+ speed?: number;
103
+ };
104
+ [key: string]: unknown;
105
+ }
106
+ type IntegrationConfig = boolean | Record<string, PropertyValue | PropertyValue[]>;
107
+ interface EmitterOptions {
108
+ anonymousId?: string;
109
+ callback?: (...args: unknown[]) => void;
110
+ context?: EmitterContext;
111
+ integrations?: Record<string, IntegrationConfig>;
112
+ timestamp?: Date | string;
113
+ }
114
+ interface EmitterIntegrations {
115
+ [destination: string]: IntegrationConfig | undefined;
116
+ All?: boolean;
117
+ }
118
+ interface EmitterBasePayload {
119
+ type: 'identify' | 'track' | 'page' | 'screen' | 'group' | 'alias';
120
+ anonymousId?: string;
121
+ userId?: string;
122
+ originalTimestamp?: Date | string;
123
+ receivedAt?: Date | string;
124
+ sentAt?: Date | string;
125
+ timestamp?: Date | string;
126
+ context?: EmitterContext;
127
+ integrations?: EmitterIntegrations;
128
+ messageId?: string;
129
+ version?: number;
130
+ }
131
+ interface EmitterIdentifyPayload extends EmitterBasePayload {
132
+ traits?: UserTraits;
133
+ type: 'identify';
134
+ userId: string;
135
+ }
136
+ interface EmitterTrackPayload extends EmitterBasePayload {
137
+ event: string;
138
+ properties?: Properties;
139
+ type: 'track';
140
+ }
141
+ interface EmitterPagePayload extends EmitterBasePayload {
142
+ category?: string;
143
+ name?: string;
144
+ properties?: Properties;
145
+ type: 'page';
146
+ }
147
+ interface EmitterScreenPayload extends EmitterBasePayload {
148
+ name?: string;
149
+ properties?: Properties;
150
+ type: 'screen';
151
+ }
152
+ interface EmitterGroupPayload extends EmitterBasePayload {
153
+ groupId: string;
154
+ traits?: GroupTraits;
155
+ type: 'group';
156
+ }
157
+ interface EmitterAliasPayload extends EmitterBasePayload {
158
+ previousId: string;
159
+ type: 'alias';
160
+ userId: string;
161
+ }
162
+ type EmitterPayload = EmitterIdentifyPayload | EmitterTrackPayload | EmitterPagePayload | EmitterScreenPayload | EmitterGroupPayload | EmitterAliasPayload;
163
+ interface EmitterUserTraits {
164
+ email?: string;
165
+ firstName?: string;
166
+ lastName?: string;
167
+ name?: string;
168
+ phone?: string;
169
+ username?: string;
170
+ age?: number;
171
+ birthday?: Date | string;
172
+ gender?: string;
173
+ address?: {
174
+ street?: string;
175
+ city?: string;
176
+ state?: string;
177
+ postalCode?: string;
178
+ country?: string;
179
+ };
180
+ company?: {
181
+ name?: string;
182
+ id?: string;
183
+ industry?: string;
184
+ employee_count?: number;
185
+ plan?: string;
186
+ };
187
+ avatar?: string;
188
+ createdAt?: Date | string;
189
+ description?: string;
190
+ id?: string;
191
+ website?: string;
192
+ [key: string]: PropertyValue | PropertyValue[] | EmitterUserTraits['address'] | EmitterUserTraits['company'] | undefined;
193
+ }
194
+ interface EmitterProduct {
195
+ id?: string;
196
+ name?: string;
197
+ price?: number;
198
+ quantity?: number;
199
+ category?: string;
200
+ brand?: string;
201
+ variant?: string;
202
+ [key: string]: PropertyValue | PropertyValue[] | undefined;
203
+ }
204
+ interface EmitterEventProperties {
205
+ currency?: string;
206
+ revenue?: number;
207
+ value?: number;
208
+ products?: EmitterProduct[];
209
+ category?: string;
210
+ description?: string;
211
+ title?: string;
212
+ query?: string;
213
+ recipient?: string;
214
+ share_via?: string;
215
+ [key: string]: PropertyValue | PropertyValue[] | EmitterProduct[] | undefined;
216
+ }
217
+ interface EmitterGroupTraits {
218
+ avatar?: string;
219
+ createdAt?: Date | string;
220
+ description?: string;
221
+ employees?: number;
222
+ industry?: string;
223
+ name?: string;
224
+ plan?: string;
225
+ website?: string;
226
+ [key: string]: PropertyValue | PropertyValue[] | undefined;
227
+ }
228
+ interface AnalyticsEmitter {
229
+ alias(userId: string, previousId?: string, options?: EmitterOptions, callback?: (...args: unknown[]) => void): void | Promise<void>;
230
+ group(groupId: string, traits?: GroupTraits, options?: EmitterOptions, callback?: (...args: unknown[]) => void): void | Promise<void>;
231
+ identify(userId: string, traits?: UserTraits, options?: EmitterOptions, callback?: (...args: unknown[]) => void): void | Promise<void>;
232
+ page(category?: string, name?: string, properties?: Properties, options?: EmitterOptions, callback?: (...args: unknown[]) => void): void | Promise<void>;
233
+ screen(name?: string, properties?: Properties, options?: EmitterOptions, callback?: (...args: unknown[]) => void): void | Promise<void>;
234
+ track(event: string, properties?: Properties, options?: EmitterOptions, callback?: (...args: unknown[]) => void): void | Promise<void>;
235
+ }
236
+ interface EmitterConfig {
237
+ apiKey?: string;
238
+ batching?: boolean;
239
+ batchSize?: number;
240
+ debug?: boolean;
241
+ defaultContext?: Partial<EmitterContext>;
242
+ endpoint?: string;
243
+ flushInterval?: number;
244
+ integrations?: Record<string, IntegrationConfig>;
245
+ trackClicks?: boolean;
246
+ trackPages?: boolean;
247
+ }
248
+ //#endregion
249
+ //#region src/shared/types/types.d.ts
250
+ interface PostHogBootstrap {
251
+ distinctID?: string;
252
+ isIdentifiedID?: boolean;
253
+ featureFlags?: Record<string, string | boolean>;
254
+ featureFlagPayloads?: Record<string, unknown>;
255
+ }
256
+ interface ProviderConfig {
257
+ apiKey?: string | undefined;
258
+ measurementId?: string | undefined;
259
+ token?: string | undefined;
260
+ writeKey?: string | undefined;
261
+ enabled?: boolean | undefined;
262
+ events?: string[] | 'all' | undefined;
263
+ options?: Record<string, unknown> | undefined;
264
+ }
265
+ interface AnalyticsProvider {
266
+ readonly name: string;
267
+ initialize(config: ProviderConfig): Promise<void>;
268
+ track(event: string, properties: Properties, context?: AnalyticsContext): Promise<void>;
269
+ identify?(userId: string, traits: UserTraits, context?: AnalyticsContext): Promise<void>;
270
+ page?(name: string, properties: PageProperties, context?: AnalyticsContext): Promise<void>;
271
+ screen?(name: string, properties: PageProperties, context?: AnalyticsContext): Promise<void>;
272
+ group?(groupId: string, traits: GroupTraits, context?: AnalyticsContext): Promise<void>;
273
+ alias?(userId: string, previousId: string, context?: AnalyticsContext): Promise<void>;
274
+ setContext?(context: AnalyticsContext): void;
275
+ }
276
+ interface ErrorContext {
277
+ provider: string;
278
+ method: string;
279
+ [key: string]: unknown;
280
+ }
281
+ interface AnalyticsConfig {
282
+ debug?: boolean | undefined;
283
+ nextjs?: {
284
+ deferUntilConsent?: boolean | undefined;
285
+ bufferEvents?: boolean | undefined;
286
+ maxBufferSize?: number | undefined;
287
+ checkConsent?: (() => boolean | Promise<boolean>) | undefined;
288
+ posthog?: {
289
+ bootstrap?: PostHogBootstrap | undefined;
290
+ apiKey?: string | undefined;
291
+ host?: string | undefined;
292
+ } | undefined;
293
+ [key: string]: unknown;
294
+ } | undefined;
295
+ onError?: ((error: unknown, context: ErrorContext) => void) | undefined;
296
+ onInfo?: ((message: string) => void) | undefined;
297
+ providers: Record<string, ProviderConfig>;
298
+ }
299
+ interface TrackingOptions {
300
+ providers?: Record<string, ProviderConfig> | undefined;
301
+ only?: string[] | undefined;
302
+ exclude?: string[] | undefined;
303
+ context?: AnalyticsContext | undefined;
304
+ }
305
+ type ProviderFactory = (config: ProviderConfig) => AnalyticsProvider;
306
+ type ProviderRegistry = Record<string, ProviderFactory>;
307
+ interface AnalyticsContext {
308
+ userId?: string;
309
+ sessionId?: string;
310
+ organizationId?: string;
311
+ environment?: string;
312
+ traits?: UserTraits;
313
+ [key: string]: unknown;
314
+ }
315
+ interface EcommerceEventSpec {
316
+ name: string;
317
+ properties: Properties;
318
+ category?: string;
319
+ }
320
+ interface AnalyticsManager {
321
+ getContext(): AnalyticsContext;
322
+ initialize(): Promise<void>;
323
+ setContext(context: AnalyticsContext): void;
324
+ createEmitter(): (payload: EmitterPayload) => Promise<void>;
325
+ emit(payload: EmitterPayload, options?: {
326
+ timeout?: number;
327
+ }): Promise<void>;
328
+ emitBatch(payloads: EmitterPayload[], options?: {
329
+ timeout?: number;
330
+ concurrency?: number;
331
+ failFast?: boolean;
332
+ }): Promise<void>;
333
+ track(payload: EmitterTrackPayload): Promise<void>;
334
+ track(event: string, properties?: Properties, options?: TrackingOptions): Promise<void>;
335
+ identify(payload: EmitterIdentifyPayload): Promise<void>;
336
+ identify(userId: string, traits?: UserTraits, options?: TrackingOptions): Promise<void>;
337
+ page(payload: EmitterPagePayload): Promise<void>;
338
+ page(name?: string, properties?: PageProperties, options?: TrackingOptions): Promise<void>;
339
+ screen?(payload: EmitterScreenPayload): Promise<void>;
340
+ screen?(name?: string, properties?: PageProperties, options?: TrackingOptions): Promise<void>;
341
+ group(payload: EmitterGroupPayload): Promise<void>;
342
+ group(groupId: string, traits?: GroupTraits, options?: TrackingOptions): Promise<void>;
343
+ alias(payload: EmitterAliasPayload): Promise<void>;
344
+ alias(userId: string, previousId: string, options?: TrackingOptions): Promise<void>;
345
+ getActiveProviders(): string[];
346
+ getProvider(name: string): AnalyticsProvider | undefined;
347
+ reset(): void;
348
+ shutdown(): Promise<void>;
349
+ processEmitterPayload(payload: EmitterPayload): Promise<void>;
350
+ trackEcommerce(eventSpec: EcommerceEventSpec): Promise<void>;
351
+ }
352
+ //#endregion
353
+ export { GroupTraits as A, EmitterPagePayload as C, EmitterTrackPayload as D, EmitterScreenPayload as E, UserTraits as F, Properties as M, PropertyObject as N, EmitterUserTraits as O, PropertyValue as P, EmitterOptions as S, EmitterProduct as T, EmitterEventProperties as _, EcommerceEventSpec as a, EmitterIdentifyPayload as b, ProviderConfig as c, TrackingOptions as d, AnalyticsEmitter as f, EmitterContext as g, EmitterConfig as h, AnalyticsProvider as i, PageProperties as j, IntegrationConfig as k, ProviderFactory as l, EmitterBasePayload as m, AnalyticsContext as n, ErrorContext as o, EmitterAliasPayload as p, AnalyticsManager as r, PostHogBootstrap as s, AnalyticsConfig as t, ProviderRegistry as u, EmitterGroupPayload as v, EmitterPayload as w, EmitterIntegrations as x, EmitterGroupTraits as y };
354
+ //# sourceMappingURL=types-BxBnNQ0V.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-BxBnNQ0V.d.mts","names":[],"sources":["../src/shared/types/base-types.ts","../src/shared/emitters/emitter-types.ts","../src/shared/types/types.ts"],"mappings":"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"}