@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,30 @@
1
+ import { C as EmitterPagePayload, D as EmitterTrackPayload, S as EmitterOptions, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, g as EmitterContext, i as AnalyticsProvider, n as AnalyticsContext, p as EmitterAliasPayload, r as AnalyticsManager, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload } from "./types-BxBnNQ0V.mjs";
2
+ import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-DldkVSPp.mjs";
3
+ import { a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, i as getDistinctIdFromCookies, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload } from "./posthog-bootstrap-DWxFrxlt.mjs";
4
+ import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-CBvxUEaF.mjs";
5
+ import { t as index_d_exports$1 } from "./index-jPzXRn52.mjs";
6
+ import { t as index_d_exports } from "./index-BkIWe--N.mjs";
7
+ import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-DPS6bSYo.mjs";
8
+ import { a as ConsoleConfig, c as PostHogConfig, i as SegmentOptions, l as PostHogOptions, n as VercelOptions, o as ConsoleOptions, r as SegmentConfig, s as BootstrapData, t as VercelConfig } from "./vercel-types-lwakUfoI.mjs";
9
+ import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-DvRRjza6.mjs";
10
+
11
+ //#region src/client/manager.d.ts
12
+ declare function createClientAnalytics(config: AnalyticsConfig): Promise<AnalyticsManager>;
13
+ declare function createClientAnalyticsUninitialized(config: AnalyticsConfig): AnalyticsManager;
14
+ //#endregion
15
+ //#region src/shared/utils/validation-client.d.ts
16
+ interface ValidationError {
17
+ field: string;
18
+ message: string;
19
+ provider: string;
20
+ }
21
+ interface ValidationResult {
22
+ errors: ValidationError[];
23
+ isValid: boolean;
24
+ warnings: string[];
25
+ }
26
+ declare function validateAnalyticsConfig(config: unknown): ValidationResult;
27
+ declare function validateProvider(providerName: string, config: ProviderConfig): ValidationError[];
28
+ //#endregion
29
+ export { AnalyticsConfig, AnalyticsContext, AnalyticsManager, AnalyticsManager$1 as AnalyticsManagerClass, AnalyticsProvider, BaseProductProperties, BootstrapData, CartProperties, ConsoleConfig, ConsoleOptions, ContextBuilder, EcommerceEventSpec, EmitterAliasPayload, EmitterContext, EmitterGroupPayload, EmitterIdentifyPayload, EmitterOptions, EmitterPagePayload, EmitterPayload, EmitterTrackPayload, EventBatch, ExtendedProductProperties, OrderProperties, PROVIDER_REQUIREMENTS, PayloadBuilder, PostHogConfig, PostHogOptions, ProviderConfig, ProviderRegistry, SegmentConfig, SegmentOptions, TrackingOptions, VercelConfig, VercelOptions, index_d_exports as ai, alias, createAnalyticsManager, createAnonymousSession, createBootstrapData, createClientAnalytics, createClientAnalyticsUninitialized, createConfigBuilder, createEmitterProcessor, createMinimalBootstrapData, createUserSession, index_d_exports$1 as ecommerce, generateDistinctId, getAnalyticsConfig, getDistinctIdFromCookies, group, identify, isAliasPayload, isGroupPayload, isIdentifyPayload, isPagePayload, isTrackPayload, page, processEmitterPayload, screen, track, trackEcommerceEvent, validateAnalyticsConfig, validateConfig, validateProvider, withMetadata, withUTM };
30
+ //# sourceMappingURL=client.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client/manager.ts","../src/shared/utils/validation-client.ts"],"mappings":";;;;;;;;;;;iBAiDsB,qBAAA,CAAsB,MAAA,EAAQ,eAAA,GAAkB,OAAA,CAAQ,gBAAA;AAAA,iBAmB9D,kCAAA,CAAmC,MAAA,EAAQ,eAAA,GAAkB,gBAAA;;;UC1DnE,eAAA;EACR,KAAA;EACA,OAAA;EACA,QAAA;AAAA;AAAA,UAGQ,gBAAA;EACR,MAAA,EAAQ,eAAA;EACR,OAAA;EACA,QAAA;AAAA;AAAA,iBAOc,uBAAA,CAAwB,MAAA,YAAkB,gBAAA;AAAA,iBAuD1C,gBAAA,CAAiB,YAAA,UAAsB,MAAA,EAAQ,cAAA,GAAiB,eAAA"}
@@ -0,0 +1,186 @@
1
+ import { t as ConsoleProvider } from "./console-8bND3mMU.mjs";
2
+ import { HttpClientProvider } from "./providers-http-client.mjs";
3
+ import { _ as AnalyticsManager, a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, i as getDistinctIdFromCookies, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload, v as createAnalyticsManager } from "./posthog-bootstrap-CYfIy_WS.mjs";
4
+ import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-6-nKo8i-.mjs";
5
+ import { t as ecommerce_exports } from "./ecommerce-Cgu4wlux.mjs";
6
+ import { t as ai_exports } from "./ai-YMnynb-t.mjs";
7
+ import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-P6P5adJg.mjs";
8
+ import { SegmentClientProvider } from "@integrations/segment/analytics-provider/client";
9
+ import { VercelClientProvider } from "@integrations/vercel/analytics-provider/client";
10
+
11
+ //#region src/client/manager.ts
12
+ /**
13
+ * @fileoverview Client Analytics Manager
14
+ *
15
+ * Client-side analytics manager with static provider registry. Provides
16
+ * factory functions for creating client analytics instances with support
17
+ * for multiple providers (Console, HTTP, Segment, Vercel).
18
+ *
19
+ * **Providers Supported**:
20
+ * - `console`: Console logging provider (development/debugging)
21
+ * - `http`: HTTP provider for remote ingestion (oneapp-api)
22
+ * - `segment`: Segment.io analytics provider
23
+ * - `vercel`: Vercel Analytics provider
24
+ *
25
+ * @module @od-oneapp/analytics/client/manager
26
+ */
27
+ const CLIENT_PROVIDERS = {
28
+ console: (config) => new ConsoleProvider(config),
29
+ http: (config) => new HttpClientProvider(config),
30
+ segment: (config) => new SegmentClientProvider(config),
31
+ vercel: (config) => new VercelClientProvider(config)
32
+ };
33
+ /**
34
+ * Create and initialize a client analytics instance
35
+ * This is the primary way to create analytics for client-side applications
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const analytics = await createClientAnalytics({
40
+ * providers: {
41
+ * http: { endpoint: '/api/v1/ingest' },
42
+ * },
43
+ * });
44
+ * await analytics.track('Button Clicked', { variant: 'primary' });
45
+ * ```
46
+ * @param config - Analytics configuration including providers and settings
47
+ * @returns Promise resolving to initialized analytics manager
48
+ */
49
+ async function createClientAnalytics(config) {
50
+ const manager = createAnalyticsManager(config, CLIENT_PROVIDERS);
51
+ await manager.initialize();
52
+ return manager;
53
+ }
54
+ /**
55
+ * Create a client analytics instance without initializing
56
+ * Useful when you need to control initialization timing
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const analytics = createClientAnalyticsUninitialized(config);
61
+ * // later inside a lazy effect
62
+ * await analytics.initialize();
63
+ * ```
64
+ * @param config - Analytics configuration including providers and settings
65
+ * @returns Uninitialized analytics manager instance
66
+ */
67
+ function createClientAnalyticsUninitialized(config) {
68
+ return createAnalyticsManager(config, CLIENT_PROVIDERS);
69
+ }
70
+
71
+ //#endregion
72
+ //#region src/shared/utils/validation-client.ts
73
+ /**
74
+ * @fileoverview Client-safe validation utilities for analytics configuration
75
+ * Client-safe validation utilities for analytics configuration
76
+ * This file contains only validation functions that are safe to use in browser environments
77
+ */
78
+ /**
79
+ * Comprehensive configuration validation (client-safe version)
80
+ * Accepts unknown input for defensive validation of potentially malformed configs
81
+ */
82
+ function validateAnalyticsConfig(config) {
83
+ const errors = [];
84
+ const warnings = [];
85
+ if (!config || typeof config !== "object") {
86
+ errors.push({
87
+ provider: "global",
88
+ field: "config",
89
+ message: "Analytics configuration is required and must be an object"
90
+ });
91
+ return {
92
+ isValid: false,
93
+ errors,
94
+ warnings
95
+ };
96
+ }
97
+ const typedConfig = config;
98
+ if (!typedConfig.providers || typeof typedConfig.providers !== "object") {
99
+ errors.push({
100
+ provider: "global",
101
+ field: "providers",
102
+ message: "Providers configuration is required and must be an object"
103
+ });
104
+ return {
105
+ isValid: false,
106
+ errors,
107
+ warnings
108
+ };
109
+ }
110
+ if (Object.keys(typedConfig.providers).length === 0) warnings.push("No providers configured. Analytics will not track any events.");
111
+ for (const [providerName, providerConfig] of Object.entries(typedConfig.providers)) {
112
+ const providerErrors = validateProvider(providerName, providerConfig);
113
+ errors.push(...providerErrors);
114
+ }
115
+ if (typedConfig.providers.mixpanel) warnings.push("Mixpanel provider configured on client-side. Consider using server-side for better performance.");
116
+ return {
117
+ isValid: errors.length === 0,
118
+ errors,
119
+ warnings
120
+ };
121
+ }
122
+ /**
123
+ * Validate a single provider configuration
124
+ */
125
+ function validateProvider(providerName, config) {
126
+ const errors = [];
127
+ const knownProviders = [
128
+ "segment",
129
+ "posthog",
130
+ "vercel",
131
+ "console",
132
+ "mixpanel"
133
+ ];
134
+ if (!knownProviders.includes(providerName)) {
135
+ errors.push({
136
+ provider: providerName,
137
+ field: "name",
138
+ message: `Unknown provider '${providerName}'. Known providers: ${knownProviders.join(", ")}`
139
+ });
140
+ return errors;
141
+ }
142
+ const requiredFields = PROVIDER_REQUIREMENTS[providerName] ?? [];
143
+ for (const field of requiredFields) {
144
+ const value = config[field];
145
+ if (!value) errors.push({
146
+ provider: providerName,
147
+ field,
148
+ message: `Required field '${field}' is missing for provider '${providerName}'`
149
+ });
150
+ else if (typeof value === "string" && value.trim() === "") errors.push({
151
+ provider: providerName,
152
+ field,
153
+ message: `Required field '${field}' cannot be empty for provider '${providerName}'`
154
+ });
155
+ }
156
+ switch (providerName) {
157
+ case "segment":
158
+ if (config.writeKey && !isValidSegmentWriteKey(config.writeKey)) errors.push({
159
+ provider: providerName,
160
+ field: "writeKey",
161
+ message: "Segment writeKey appears to be invalid format"
162
+ });
163
+ break;
164
+ case "posthog":
165
+ if (config.apiKey && !isValidPostHogApiKey(config.apiKey)) errors.push({
166
+ provider: providerName,
167
+ field: "apiKey",
168
+ message: "PostHog apiKey appears to be invalid format"
169
+ });
170
+ break;
171
+ }
172
+ return errors;
173
+ }
174
+ /**
175
+ * Helper functions for format validation
176
+ */
177
+ function isValidSegmentWriteKey(writeKey) {
178
+ return /^[\dA-Za-z]{20,40}$/.test(writeKey);
179
+ }
180
+ function isValidPostHogApiKey(apiKey) {
181
+ return /^phc_[\dA-Za-z]{43}$/.test(apiKey);
182
+ }
183
+
184
+ //#endregion
185
+ export { AnalyticsManager as AnalyticsManagerClass, ContextBuilder, EventBatch, PROVIDER_REQUIREMENTS, PayloadBuilder, ai_exports as ai, alias, createAnalyticsManager, createAnonymousSession, createBootstrapData, createClientAnalytics, createClientAnalyticsUninitialized, createConfigBuilder, createEmitterProcessor, createMinimalBootstrapData, createUserSession, ecommerce_exports as ecommerce, generateDistinctId, getAnalyticsConfig, getDistinctIdFromCookies, group, identify, isAliasPayload, isGroupPayload, isIdentifyPayload, isPagePayload, isTrackPayload, page, processEmitterPayload, screen, track, trackEcommerceEvent, validateAnalyticsConfig, validateConfig, validateProvider, withMetadata, withUTM };
186
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../src/client/manager.ts","../src/shared/utils/validation-client.ts"],"sourcesContent":["/**\n * @fileoverview Client Analytics Manager\n *\n * Client-side analytics manager with static provider registry. Provides\n * factory functions for creating client analytics instances with support\n * for multiple providers (Console, HTTP, Segment, Vercel).\n *\n * **Providers Supported**:\n * - `console`: Console logging provider (development/debugging)\n * - `http`: HTTP provider for remote ingestion (oneapp-api)\n * - `segment`: Segment.io analytics provider\n * - `vercel`: Vercel Analytics provider\n *\n * @module @od-oneapp/analytics/client/manager\n */\n\nimport { SegmentClientProvider } from '@integrations/segment/analytics-provider/client';\nimport { VercelClientProvider } from '@integrations/vercel/analytics-provider/client';\n\nimport { ConsoleProvider } from '../providers/console/client';\nimport { HttpClientProvider } from '../providers/http/client';\nimport { createAnalyticsManager } from '../shared/utils/manager';\n\nimport type { AnalyticsConfig, AnalyticsManager, ProviderRegistry } from '../shared/types/types';\n\n// Static provider registry for client environments\nconst CLIENT_PROVIDERS: ProviderRegistry = {\n console: config => new ConsoleProvider(config),\n http: config => new HttpClientProvider(config),\n segment: config => new SegmentClientProvider(config),\n vercel: config => new VercelClientProvider(config),\n};\n\n/**\n * Create and initialize a client analytics instance\n * This is the primary way to create analytics for client-side applications\n *\n * @example\n * ```typescript\n * const analytics = await createClientAnalytics({\n * providers: {\n * http: { endpoint: '/api/v1/ingest' },\n * },\n * });\n * await analytics.track('Button Clicked', { variant: 'primary' });\n * ```\n * @param config - Analytics configuration including providers and settings\n * @returns Promise resolving to initialized analytics manager\n */\nexport async function createClientAnalytics(config: AnalyticsConfig): Promise<AnalyticsManager> {\n const manager = createAnalyticsManager(config, CLIENT_PROVIDERS);\n await manager.initialize();\n return manager;\n}\n\n/**\n * Create a client analytics instance without initializing\n * Useful when you need to control initialization timing\n *\n * @example\n * ```typescript\n * const analytics = createClientAnalyticsUninitialized(config);\n * // later inside a lazy effect\n * await analytics.initialize();\n * ```\n * @param config - Analytics configuration including providers and settings\n * @returns Uninitialized analytics manager instance\n */\nexport function createClientAnalyticsUninitialized(config: AnalyticsConfig): AnalyticsManager {\n return createAnalyticsManager(config, CLIENT_PROVIDERS);\n}\n","/**\n * @fileoverview Client-safe validation utilities for analytics configuration\n * Client-safe validation utilities for analytics configuration\n * This file contains only validation functions that are safe to use in browser environments\n */\n\nimport { PROVIDER_REQUIREMENTS } from './config';\n\nimport type { AnalyticsConfig, ProviderConfig } from '../types/types';\n\ninterface ValidationError {\n field: string;\n message: string;\n provider: string;\n}\n\ninterface ValidationResult {\n errors: ValidationError[];\n isValid: boolean;\n warnings: string[];\n}\n\n/**\n * Comprehensive configuration validation (client-safe version)\n * Accepts unknown input for defensive validation of potentially malformed configs\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 if (typedConfig.providers.mixpanel) {\n warnings.push(\n 'Mixpanel provider configured on client-side. Consider using server-side for better performance.',\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 */\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 * Helper functions for format validation\n */\nfunction isValidSegmentWriteKey(writeKey: string): boolean {\n // Segment write keys are typically 32 characters, alphanumeric\n return /^[\\dA-Za-z]{20,40}$/.test(writeKey);\n}\n\nfunction isValidPostHogApiKey(apiKey: string): boolean {\n // PostHog API keys start with 'phc_' followed by alphanumeric characters\n return /^phc_[\\dA-Za-z]{43}$/.test(apiKey);\n}\n\n/**\n * Utility to validate configuration (client-safe version without throwing)\n * Returns validation result instead of throwing errors\n */\nexport function validateConfig(config: AnalyticsConfig): ValidationResult {\n return validateAnalyticsConfig(config);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,mBAAqC;CACzC,UAAS,WAAU,IAAI,gBAAgB,OAAO;CAC9C,OAAM,WAAU,IAAI,mBAAmB,OAAO;CAC9C,UAAS,WAAU,IAAI,sBAAsB,OAAO;CACpD,SAAQ,WAAU,IAAI,qBAAqB,OAAO;CACnD;;;;;;;;;;;;;;;;;AAkBD,eAAsB,sBAAsB,QAAoD;CAC9F,MAAM,UAAU,uBAAuB,QAAQ,iBAAiB;AAChE,OAAM,QAAQ,YAAY;AAC1B,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,mCAAmC,QAA2C;AAC5F,QAAO,uBAAuB,QAAQ,iBAAiB;;;;;;;;;;;;;;AC3CzD,SAAgB,wBAAwB,QAAmC;CACzE,MAAM,SAA4B,EAAE;CACpC,MAAM,WAAqB,EAAE;AAG7B,KAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,SAAO,KAAK;GACV,UAAU;GACV,OAAO;GACP,SAAS;GACV,CAAC;AACF,SAAO;GAAE,SAAS;GAAO;GAAQ;GAAU;;CAG7C,MAAM,cAAc;AAGpB,KAAI,CAAC,YAAY,aAAa,OAAO,YAAY,cAAc,UAAU;AACvE,SAAO,KAAK;GACV,UAAU;GACV,OAAO;GACP,SAAS;GACV,CAAC;AACF,SAAO;GAAE,SAAS;GAAO;GAAQ;GAAU;;AAK7C,KADsB,OAAO,KAAK,YAAY,UAAU,CAAC,WACnC,EACpB,UAAS,KAAK,gEAAgE;AAIhF,MAAK,MAAM,CAAC,cAAc,mBAAmB,OAAO,QAAQ,YAAY,UAAU,EAAE;EAClF,MAAM,iBAAiB,iBAAiB,cAAc,eAAe;AACrE,SAAO,KAAK,GAAG,eAAe;;AAIhC,KAAI,YAAY,UAAU,SACxB,UAAS,KACP,kGACD;AAGH,QAAO;EACL,SAAS,OAAO,WAAW;EAC3B;EACA;EACD;;;;;AAMH,SAAgB,iBAAiB,cAAsB,QAA2C;CAChG,MAAM,SAA4B,EAAE;CAGpC,MAAM,iBAAiB;EAAC;EAAW;EAAW;EAAU;EAAW;EAAW;AAC9E,KAAI,CAAC,eAAe,SAAS,aAAa,EAAE;AAC1C,SAAO,KAAK;GACV,UAAU;GACV,OAAO;GACP,SAAS,qBAAqB,aAAa,sBAAsB,eAAe,KAAK,KAAK;GAC3F,CAAC;AACF,SAAO;;CAIT,MAAM,iBAAiB,sBAAsB,iBAAiB,EAAE;AAChE,MAAK,MAAM,SAAS,gBAAgB;EAClC,MAAM,QAAQ,OAAO;AAErB,MAAI,CAAC,MACH,QAAO,KAAK;GACV,UAAU;GACV;GACA,SAAS,mBAAmB,MAAM,6BAA6B,aAAa;GAC7E,CAAC;WACO,OAAO,UAAU,YAAY,MAAM,MAAM,KAAK,GACvD,QAAO,KAAK;GACV,UAAU;GACV;GACA,SAAS,mBAAmB,MAAM,kCAAkC,aAAa;GAClF,CAAC;;AAKN,SAAQ,cAAR;EACE,KAAK;AACH,OAAI,OAAO,YAAY,CAAC,uBAAuB,OAAO,SAAS,CAC7D,QAAO,KAAK;IACV,UAAU;IACV,OAAO;IACP,SAAS;IACV,CAAC;AAEJ;EAEF,KAAK;AACH,OAAI,OAAO,UAAU,CAAC,qBAAqB,OAAO,OAAO,CACvD,QAAO,KAAK;IACV,UAAU;IACV,OAAO;IACP,SAAS;IACV,CAAC;AAEJ;;AAGJ,QAAO;;;;;AAMT,SAAS,uBAAuB,UAA2B;AAEzD,QAAO,sBAAsB,KAAK,SAAS;;AAG7C,SAAS,qBAAqB,QAAyB;AAErD,QAAO,uBAAuB,KAAK,OAAO"}
@@ -0,0 +1,34 @@
1
+ import { c as ProviderConfig, r as AnalyticsManager, t as AnalyticsConfig, w as EmitterPayload } from "./types-BxBnNQ0V.mjs";
2
+
3
+ //#region src/shared/utils/emitter-adapter.d.ts
4
+ declare function processEmitterPayload(analytics: AnalyticsManager, payload: EmitterPayload): Promise<void>;
5
+ declare function createEmitterProcessor(analytics: AnalyticsManager): (payload: EmitterPayload) => Promise<void>;
6
+ declare function trackEcommerceEvent(analytics: AnalyticsManager, eventSpec: {
7
+ name: string;
8
+ properties: Record<string, any>;
9
+ }): Promise<void>;
10
+ //#endregion
11
+ //#region src/shared/utils/config.d.ts
12
+ type ConfigRequirements = Record<string, string[]>;
13
+ declare const PROVIDER_REQUIREMENTS: ConfigRequirements;
14
+ declare function validateConfig(config: unknown): void;
15
+ interface ConfigBuilder {
16
+ addConsole(options?: Record<string, unknown>): ConfigBuilder;
17
+ addPostHog(apiKey: string, options?: Record<string, unknown>): ConfigBuilder;
18
+ addProvider(name: string, config: ProviderConfig): ConfigBuilder;
19
+ addSegment(writeKey: string, options?: Record<string, unknown>): ConfigBuilder;
20
+ addVercel(options?: Record<string, unknown>): ConfigBuilder;
21
+ build(): AnalyticsConfig;
22
+ providers: Record<string, ProviderConfig>;
23
+ }
24
+ declare function createConfigBuilder(): ConfigBuilder;
25
+ interface AnalyticsConfigOptions {
26
+ isDevelopment?: boolean;
27
+ isStaging?: boolean;
28
+ segmentWriteKey?: string;
29
+ posthogApiKey?: string;
30
+ }
31
+ declare function getAnalyticsConfig(options?: AnalyticsConfigOptions): AnalyticsConfig;
32
+ //#endregion
33
+ export { createEmitterProcessor as a, validateConfig as i, createConfigBuilder as n, processEmitterPayload as o, getAnalyticsConfig as r, trackEcommerceEvent as s, PROVIDER_REQUIREMENTS as t };
34
+ //# sourceMappingURL=config-DPS6bSYo.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-DPS6bSYo.d.mts","names":[],"sources":["../src/shared/utils/emitter-adapter.ts","../src/shared/utils/config.ts"],"mappings":";;;iBAoCsB,qBAAA,CACpB,SAAA,EAAW,gBAAA,EACX,OAAA,EAAS,cAAA,GACR,OAAA;AAAA,iBAsJa,sBAAA,CAAuB,SAAA,EAAW,gBAAA,IACxC,OAAA,EAAS,cAAA,KAAc,OAAA;AAAA,iBAgBX,mBAAA,CACpB,SAAA,EAAW,gBAAA,EACX,SAAA;EAAa,IAAA;EAAc,UAAA,EAAY,MAAA;AAAA,IACtC,OAAA;;;KCzLS,kBAAA,GAAqB,MAAA;AAAA,cAQpB,qBAAA,EAAuB,kBAAA;AAAA,iBA0BpB,cAAA,CAAe,MAAA;AAAA,UA8Cd,aAAA;EACf,UAAA,CAAW,OAAA,GAAU,MAAA,oBAA0B,aAAA;EAC/C,UAAA,CAAW,MAAA,UAAgB,OAAA,GAAU,MAAA,oBAA0B,aAAA;EAC/D,WAAA,CAAY,IAAA,UAAc,MAAA,EAAQ,cAAA,GAAiB,aAAA;EACnD,UAAA,CAAW,QAAA,UAAkB,OAAA,GAAU,MAAA,oBAA0B,aAAA;EACjE,SAAA,CAAU,OAAA,GAAU,MAAA,oBAA0B,aAAA;EAC9C,KAAA,IAAS,eAAA;EACT,SAAA,EAAW,MAAA,SAAe,cAAA;AAAA;AAAA,iBAoBZ,mBAAA,CAAA,GAAuB,aAAA;AAAA,UA0CtB,sBAAA;EACf,aAAA;EACA,SAAA;EACA,eAAA;EACA,aAAA;AAAA;AAAA,iBAyBc,kBAAA,CAAmB,OAAA,GAAU,sBAAA,GAAyB,eAAA"}
@@ -0,0 +1,287 @@
1
+ //#region src/shared/utils/emitter-adapter.ts
2
+ /**
3
+ * Routes any emitter payload to the matching analytics manager method.
4
+ *
5
+ * This function is deliberately small so that Codex/OpenAI powered tooling can
6
+ * inspect a single switch statement and understand how each analytics verb maps
7
+ * to the strongly typed helper below.
8
+ *
9
+ * @deprecated Use `analytics.emit(payload)` instead for simpler API usage.
10
+ * This function remains available for compatibility and advanced use cases.
11
+ *
12
+ * @example Preferred approach:
13
+ * ```typescript
14
+ * await analytics.emit(track('Button Clicked', { color: 'blue' }));
15
+ * ```
16
+ *
17
+ * @param analytics - The analytics manager implementation (client or server)
18
+ * @param payload - Any emitter payload created by the Segment-style helpers
19
+ * @throws Error when the payload type is unknown, protecting against silent drops
20
+ */
21
+ async function processEmitterPayload(analytics, payload) {
22
+ switch (payload.type) {
23
+ case "identify": return processIdentifyPayload(analytics, payload);
24
+ case "track": return processTrackPayload(analytics, payload);
25
+ case "page": return processPagePayload(analytics, payload);
26
+ case "screen": return processScreenPayload(analytics, payload);
27
+ case "group": return processGroupPayload(analytics, payload);
28
+ case "alias": return processAliasPayload(analytics, payload);
29
+ default: {
30
+ const unknownPayload = payload;
31
+ throw new Error(`Unknown emitter payload type: ${unknownPayload.type}`);
32
+ }
33
+ }
34
+ }
35
+ /**
36
+ * Pipes an identify payload into `analytics.identify`, preserving context.
37
+ *
38
+ * @param analytics - Active analytics manager
39
+ * @param payload - Identify payload produced by the emitter factory
40
+ */
41
+ async function processIdentifyPayload(analytics, payload) {
42
+ const { traits, userId, ...options } = payload;
43
+ const trackingOptions = { context: options.context };
44
+ await analytics.identify(userId, traits, trackingOptions);
45
+ }
46
+ /**
47
+ * Pipes a track payload into `analytics.track`, preserving context metadata.
48
+ *
49
+ * @param analytics - Active analytics manager
50
+ * @param payload - Track payload produced by the emitter factory
51
+ */
52
+ async function processTrackPayload(analytics, payload) {
53
+ const { event, properties, ...options } = payload;
54
+ const trackingOptions = { context: options.context };
55
+ await analytics.track(event, properties, trackingOptions);
56
+ }
57
+ /**
58
+ * Pipes a page payload into `analytics.page`.
59
+ *
60
+ * @param analytics - Active analytics manager
61
+ * @param payload - Page payload produced by the emitter factory
62
+ */
63
+ async function processPagePayload(analytics, payload) {
64
+ const { name, properties, ...options } = payload;
65
+ const trackingOptions = { context: options.context };
66
+ await analytics.page(name, properties, trackingOptions);
67
+ }
68
+ /**
69
+ * Pipes a screen payload into `analytics.screen` (mobile equivalent of page).
70
+ *
71
+ * @param analytics - Active analytics manager
72
+ * @param payload - Screen payload produced by the emitter factory
73
+ */
74
+ async function processScreenPayload(analytics, payload) {
75
+ const { name, properties, ...options } = payload;
76
+ const trackingOptions = { context: options.context };
77
+ await analytics.screen?.(name, properties, trackingOptions);
78
+ }
79
+ /**
80
+ * Pipes a group payload into `analytics.group`.
81
+ *
82
+ * @param analytics - Active analytics manager
83
+ * @param payload - Group payload produced by the emitter factory
84
+ */
85
+ async function processGroupPayload(analytics, payload) {
86
+ const { groupId, traits, ...options } = payload;
87
+ const trackingOptions = { context: options.context };
88
+ await analytics.group(groupId, traits, trackingOptions);
89
+ }
90
+ /**
91
+ * Pipes an alias payload into `analytics.alias`.
92
+ *
93
+ * @param analytics - Active analytics manager
94
+ * @param payload - Alias payload produced by the emitter factory
95
+ */
96
+ async function processAliasPayload(analytics, payload) {
97
+ const { previousId, userId, ...options } = payload;
98
+ const trackingOptions = { context: options.context };
99
+ await analytics.alias(userId, previousId ?? "", trackingOptions);
100
+ }
101
+ /**
102
+ * Creates a pre-bound emitter processor for repeated usage.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * const processor = createEmitterProcessor(analytics);
107
+ * queue.forEach(processor);
108
+ * ```
109
+ *
110
+ * @param analytics - Active analytics manager
111
+ * @returns Function that accepts any emitter payload and routes it correctly
112
+ */
113
+ function createEmitterProcessor(analytics) {
114
+ return (payload) => processEmitterPayload(analytics, payload);
115
+ }
116
+ /**
117
+ * Minimal helper for wiring ecommerce event specs into analytics.track.
118
+ *
119
+ * @deprecated Use `analytics.emit(ecommerce.EVENT_NAME(...))` instead.
120
+ *
121
+ * @example Preferred approach:
122
+ * ```typescript
123
+ * await analytics.emit(ecommerce.productViewed({ product_id: '123' }));
124
+ * ```
125
+ *
126
+ * @param analytics - Active analytics manager
127
+ * @param eventSpec - Object that contains the `name` and `properties` fields
128
+ */
129
+ async function trackEcommerceEvent(analytics, eventSpec) {
130
+ await analytics.track(eventSpec.name, eventSpec.properties);
131
+ }
132
+
133
+ //#endregion
134
+ //#region src/shared/utils/config.ts
135
+ /**
136
+ * Provider requirements map - defines required fields for each provider.
137
+ *
138
+ * Used during configuration validation to ensure all required fields are present.
139
+ * Providers not listed here have no required fields.
140
+ */
141
+ const PROVIDER_REQUIREMENTS = {
142
+ console: [],
143
+ mixpanel: [],
144
+ posthog: ["apiKey"],
145
+ segment: ["writeKey"],
146
+ vercel: []
147
+ };
148
+ /**
149
+ * Validates analytics configuration.
150
+ *
151
+ * Accepts `unknown` for runtime validation of potentially malformed configs.
152
+ * Throws descriptive errors if configuration is invalid.
153
+ *
154
+ * @param {unknown} config - Configuration object to validate
155
+ * @throws {Error} If configuration is invalid or missing required fields
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * try {
160
+ * validateConfig(config);
161
+ * } catch (error) {
162
+ * console.error('Invalid config:', error.message);
163
+ * }
164
+ * ```
165
+ */
166
+ function validateConfig(config) {
167
+ if (!config || typeof config !== "object") throw new Error("Analytics config must be an object");
168
+ const typedConfig = config;
169
+ if (!typedConfig.providers || typeof typedConfig.providers !== "object") throw new Error("Analytics config must have a providers object");
170
+ for (const [providerName, providerConfig] of Object.entries(typedConfig.providers)) validateProviderConfig(providerName, providerConfig);
171
+ }
172
+ /**
173
+ * Validates a single provider configuration.
174
+ *
175
+ * Checks that all required fields for the provider are present in the configuration.
176
+ *
177
+ * @param {string} providerName - Name of the provider to validate
178
+ * @param {ProviderConfig} config - Provider configuration to validate
179
+ * @throws {Error} If required fields are missing
180
+ *
181
+ * @internal
182
+ */
183
+ function validateProviderConfig(providerName, config) {
184
+ const requiredFields = PROVIDER_REQUIREMENTS[providerName] ?? [];
185
+ for (const field of requiredFields) if (!config[field]) throw new Error(`Provider '${providerName}' missing required field '${field}'. Remove the provider from config or provide the required field.`);
186
+ }
187
+ /**
188
+ * Creates a fluent configuration builder.
189
+ *
190
+ * Returns a builder instance that allows chaining provider configuration methods.
191
+ * Call `build()` at the end to get the final configuration object.
192
+ *
193
+ * @returns {ConfigBuilder} Configuration builder instance
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const config = createConfigBuilder()
198
+ * .addPostHog('phc_xxx')
199
+ * .addSegment('xxx')
200
+ * .addConsole({ pretty: true })
201
+ * .build();
202
+ * ```
203
+ */
204
+ function createConfigBuilder() {
205
+ return {
206
+ providers: {},
207
+ addProvider(name, config) {
208
+ this.providers[name] = config;
209
+ return this;
210
+ },
211
+ addSegment(writeKey, options) {
212
+ return this.addProvider("segment", {
213
+ options,
214
+ writeKey
215
+ });
216
+ },
217
+ addPostHog(apiKey, options) {
218
+ return this.addProvider("posthog", {
219
+ apiKey,
220
+ options
221
+ });
222
+ },
223
+ addVercel(options) {
224
+ return this.addProvider("vercel", { options });
225
+ },
226
+ addConsole(options) {
227
+ return this.addProvider("console", { options });
228
+ },
229
+ build() {
230
+ const config = { providers: { ...this.providers } };
231
+ validateConfig(config);
232
+ return config;
233
+ }
234
+ };
235
+ }
236
+ /**
237
+ * Get analytics configuration
238
+ *
239
+ * When called with options (client-safe), uses the provided values.
240
+ * When called without options (server), reads from process.env.
241
+ *
242
+ * @param options - Optional configuration options for client-side usage
243
+ * @returns Analytics configuration object
244
+ *
245
+ * @example Server usage (reads from process.env):
246
+ * ```typescript
247
+ * const config = getAnalyticsConfig();
248
+ * ```
249
+ *
250
+ * @example Client usage (explicit options):
251
+ * ```typescript
252
+ * const config = getAnalyticsConfig({
253
+ * isDevelopment: process.env.NODE_ENV === 'development',
254
+ * posthogApiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY,
255
+ * });
256
+ * ```
257
+ */
258
+ function getAnalyticsConfig(options) {
259
+ const builder = createConfigBuilder();
260
+ const isDevelopment = options?.isDevelopment ?? true;
261
+ const isStaging = options?.isStaging ?? process.env.APP_ENV === "staging";
262
+ const posthogApiKey = options?.posthogApiKey ?? process.env.POSTHOG_API_KEY;
263
+ const segmentWriteKey = options?.segmentWriteKey ?? process.env.SEGMENT_WRITE_KEY;
264
+ if (isDevelopment) {
265
+ builder.addConsole({
266
+ prefix: "[Dev Analytics]",
267
+ pretty: true
268
+ });
269
+ return builder.build();
270
+ }
271
+ if (isStaging) {
272
+ if (posthogApiKey) builder.addPostHog(posthogApiKey);
273
+ builder.addConsole({
274
+ prefix: "[Staging Analytics]",
275
+ pretty: true
276
+ });
277
+ return builder.build();
278
+ }
279
+ if (segmentWriteKey) builder.addSegment(segmentWriteKey);
280
+ if (posthogApiKey) builder.addPostHog(posthogApiKey);
281
+ builder.addVercel();
282
+ return builder.build();
283
+ }
284
+
285
+ //#endregion
286
+ export { createEmitterProcessor as a, validateConfig as i, createConfigBuilder as n, processEmitterPayload as o, getAnalyticsConfig as r, trackEcommerceEvent as s, PROVIDER_REQUIREMENTS as t };
287
+ //# sourceMappingURL=config-P6P5adJg.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-P6P5adJg.mjs","names":[],"sources":["../src/shared/utils/emitter-adapter.ts","../src/shared/utils/config.ts"],"sourcesContent":["/**\n * @fileoverview Adapter functions to convert emitter payloads to analytics method calls\n * Adapter functions to convert emitter payloads to analytics method calls\n * This bridges the gap between the Segment.io spec emitters and the analytics manager\n */\n\nimport type {\n EmitterAliasPayload,\n EmitterGroupPayload,\n EmitterIdentifyPayload,\n EmitterPagePayload,\n EmitterPayload,\n EmitterScreenPayload,\n EmitterTrackPayload,\n} from '../emitters/emitter-types';\nimport type { AnalyticsManager } from '../types/types';\n\n/**\n * Routes any emitter payload to the matching analytics manager method.\n *\n * This function is deliberately small so that Codex/OpenAI powered tooling can\n * inspect a single switch statement and understand how each analytics verb maps\n * to the strongly typed helper below.\n *\n * @deprecated Use `analytics.emit(payload)` instead for simpler API usage.\n * This function remains available for compatibility and advanced use cases.\n *\n * @example Preferred approach:\n * ```typescript\n * await analytics.emit(track('Button Clicked', { color: 'blue' }));\n * ```\n *\n * @param analytics - The analytics manager implementation (client or server)\n * @param payload - Any emitter payload created by the Segment-style helpers\n * @throws Error when the payload type is unknown, protecting against silent drops\n */\nexport async function processEmitterPayload(\n analytics: AnalyticsManager,\n payload: EmitterPayload,\n): Promise<void> {\n switch (payload.type) {\n case 'identify':\n return processIdentifyPayload(analytics, payload);\n case 'track':\n return processTrackPayload(analytics, payload);\n case 'page':\n return processPagePayload(analytics, payload);\n case 'screen':\n return processScreenPayload(analytics, payload);\n case 'group':\n return processGroupPayload(analytics, payload);\n case 'alias':\n return processAliasPayload(analytics, payload);\n default: {\n // Runtime safety for unknown payload types (e.g., from untyped JavaScript code)\n const unknownPayload = payload as { type: string };\n throw new Error(`Unknown emitter payload type: ${unknownPayload.type}`);\n }\n }\n}\n\n/**\n * Pipes an identify payload into `analytics.identify`, preserving context.\n *\n * @param analytics - Active analytics manager\n * @param payload - Identify payload produced by the emitter factory\n */\nexport async function processIdentifyPayload(\n analytics: AnalyticsManager,\n payload: EmitterIdentifyPayload,\n): Promise<void> {\n const { traits, userId, ...options } = payload;\n\n // Convert emitter options to tracking options\n const trackingOptions = {\n context: options.context,\n // Add other options as needed\n };\n\n await analytics.identify(userId, traits, trackingOptions);\n}\n\n/**\n * Pipes a track payload into `analytics.track`, preserving context metadata.\n *\n * @param analytics - Active analytics manager\n * @param payload - Track payload produced by the emitter factory\n */\nexport async function processTrackPayload(\n analytics: AnalyticsManager,\n payload: EmitterTrackPayload,\n): Promise<void> {\n const { event, properties, ...options } = payload;\n\n const trackingOptions = {\n context: options.context,\n };\n\n await analytics.track(event, properties, trackingOptions);\n}\n\n/**\n * Pipes a page payload into `analytics.page`.\n *\n * @param analytics - Active analytics manager\n * @param payload - Page payload produced by the emitter factory\n */\nexport async function processPagePayload(\n analytics: AnalyticsManager,\n payload: EmitterPagePayload,\n): Promise<void> {\n const { name, properties, ...options } = payload;\n\n const trackingOptions = {\n context: options.context,\n };\n\n await analytics.page(name, properties, trackingOptions);\n}\n\n/**\n * Pipes a screen payload into `analytics.screen` (mobile equivalent of page).\n *\n * @param analytics - Active analytics manager\n * @param payload - Screen payload produced by the emitter factory\n */\nexport async function processScreenPayload(\n analytics: AnalyticsManager,\n payload: EmitterScreenPayload,\n): Promise<void> {\n const { name, properties, ...options } = payload;\n\n const trackingOptions = {\n context: options.context,\n };\n\n await analytics.screen?.(name, properties, trackingOptions);\n}\n\n/**\n * Pipes a group payload into `analytics.group`.\n *\n * @param analytics - Active analytics manager\n * @param payload - Group payload produced by the emitter factory\n */\nexport async function processGroupPayload(\n analytics: AnalyticsManager,\n payload: EmitterGroupPayload,\n): Promise<void> {\n const { groupId, traits, ...options } = payload;\n\n const trackingOptions = {\n context: options.context,\n };\n\n await analytics.group(groupId, traits, trackingOptions);\n}\n\n/**\n * Pipes an alias payload into `analytics.alias`.\n *\n * @param analytics - Active analytics manager\n * @param payload - Alias payload produced by the emitter factory\n */\nexport async function processAliasPayload(\n analytics: AnalyticsManager,\n payload: EmitterAliasPayload,\n): Promise<void> {\n const { previousId, userId, ...options } = payload;\n\n const trackingOptions = {\n context: options.context,\n };\n\n await analytics.alias(userId, previousId ?? '', trackingOptions);\n}\n\n/**\n * Creates a pre-bound emitter processor for repeated usage.\n *\n * @example\n * ```ts\n * const processor = createEmitterProcessor(analytics);\n * queue.forEach(processor);\n * ```\n *\n * @param analytics - Active analytics manager\n * @returns Function that accepts any emitter payload and routes it correctly\n */\nexport function createEmitterProcessor(analytics: AnalyticsManager) {\n return (payload: EmitterPayload) => processEmitterPayload(analytics, payload);\n}\n\n/**\n * Minimal helper for wiring ecommerce event specs into analytics.track.\n *\n * @deprecated Use `analytics.emit(ecommerce.EVENT_NAME(...))` instead.\n *\n * @example Preferred approach:\n * ```typescript\n * await analytics.emit(ecommerce.productViewed({ product_id: '123' }));\n * ```\n *\n * @param analytics - Active analytics manager\n * @param eventSpec - Object that contains the `name` and `properties` fields\n */\nexport async function trackEcommerceEvent(\n analytics: AnalyticsManager,\n eventSpec: { name: string; properties: Record<string, any> },\n): Promise<void> {\n await analytics.track(eventSpec.name, eventSpec.properties);\n}\n","/**\n * @fileoverview Configuration utilities for the analytics system\n *\n * This module provides configuration utilities that work in both client and server\n * environments. It includes:\n *\n * - **Provider Requirements**: Required fields for each provider type\n * - **Configuration Validation**: Validates provider configurations\n * - **Config Builder**: Fluent API for building configurations\n * - **Config Factory**: Environment-aware configuration factory\n *\n * **Usage**: Use `createConfigBuilder()` for programmatic config creation or\n * `getAnalyticsConfig()` for environment-aware configuration.\n *\n * @module @od-oneapp/analytics/shared/utils/config\n */\n\nimport type { AnalyticsConfig, ProviderConfig } from '../types/types';\n\n/**\n * Type for provider requirements mapping.\n *\n * Maps provider names to arrays of required configuration field names.\n */\nexport type ConfigRequirements = Record<string, string[]>;\n\n/**\n * Provider requirements map - defines required fields for each provider.\n *\n * Used during configuration validation to ensure all required fields are present.\n * Providers not listed here have no required fields.\n */\nexport const PROVIDER_REQUIREMENTS: ConfigRequirements = {\n console: [], // No required fields\n mixpanel: [], // Server-only provider\n posthog: ['apiKey'],\n segment: ['writeKey'],\n vercel: [], // No required fields\n};\n\n/**\n * Validates analytics configuration.\n *\n * Accepts `unknown` for runtime validation of potentially malformed configs.\n * Throws descriptive errors if configuration is invalid.\n *\n * @param {unknown} config - Configuration object to validate\n * @throws {Error} If configuration is invalid or missing required fields\n *\n * @example\n * ```typescript\n * try {\n * validateConfig(config);\n * } catch (error) {\n * console.error('Invalid config:', error.message);\n * }\n * ```\n */\nexport function validateConfig(config: unknown): void {\n if (!config || typeof config !== 'object') {\n throw new Error('Analytics config must be an object');\n }\n\n const typedConfig = config as AnalyticsConfig;\n\n if (!typedConfig.providers || typeof typedConfig.providers !== 'object') {\n throw new Error('Analytics config must have a providers object');\n }\n\n for (const [providerName, providerConfig] of Object.entries(typedConfig.providers)) {\n validateProviderConfig(providerName, providerConfig);\n }\n}\n\n/**\n * Validates a single provider configuration.\n *\n * Checks that all required fields for the provider are present in the configuration.\n *\n * @param {string} providerName - Name of the provider to validate\n * @param {ProviderConfig} config - Provider configuration to validate\n * @throws {Error} If required fields are missing\n *\n * @internal\n */\nfunction validateProviderConfig(providerName: string, config: ProviderConfig): void {\n const requiredFields = PROVIDER_REQUIREMENTS[providerName] ?? [];\n\n for (const field of requiredFields) {\n if (!config[field as keyof ProviderConfig]) {\n throw new Error(\n `Provider '${providerName}' missing required field '${field}'. ` +\n `Remove the provider from config or provide the required field.`,\n );\n }\n }\n}\n\n/**\n * Configuration builder interface.\n *\n * Provides a fluent API for building analytics configurations programmatically.\n * Methods return `this` to enable method chaining.\n */\nexport interface ConfigBuilder {\n addConsole(options?: Record<string, unknown>): ConfigBuilder;\n addPostHog(apiKey: string, options?: Record<string, unknown>): ConfigBuilder;\n addProvider(name: string, config: ProviderConfig): ConfigBuilder;\n addSegment(writeKey: string, options?: Record<string, unknown>): ConfigBuilder;\n addVercel(options?: Record<string, unknown>): ConfigBuilder;\n build(): AnalyticsConfig;\n providers: Record<string, ProviderConfig>;\n}\n\n/**\n * Creates a fluent configuration builder.\n *\n * Returns a builder instance that allows chaining provider configuration methods.\n * Call `build()` at the end to get the final configuration object.\n *\n * @returns {ConfigBuilder} Configuration builder instance\n *\n * @example\n * ```typescript\n * const config = createConfigBuilder()\n * .addPostHog('phc_xxx')\n * .addSegment('xxx')\n * .addConsole({ pretty: true })\n * .build();\n * ```\n */\nexport function createConfigBuilder(): ConfigBuilder {\n const builder: ConfigBuilder = {\n providers: {},\n\n addProvider(name: string, config: ProviderConfig): ConfigBuilder {\n this.providers[name] = config;\n return this;\n },\n\n addSegment(writeKey: string, options?: Record<string, unknown>): ConfigBuilder {\n return this.addProvider('segment', { options, writeKey });\n },\n\n addPostHog(apiKey: string, options?: Record<string, unknown>): ConfigBuilder {\n return this.addProvider('posthog', { apiKey, options });\n },\n\n addVercel(options?: Record<string, unknown>): ConfigBuilder {\n return this.addProvider('vercel', { options });\n },\n\n addConsole(options?: Record<string, unknown>): ConfigBuilder {\n return this.addProvider('console', { options });\n },\n\n build(): AnalyticsConfig {\n const config = { providers: { ...this.providers } };\n validateConfig(config);\n return config;\n },\n };\n\n return builder;\n}\n\n/**\n * Options for client-side configuration.\n *\n * Allows explicit configuration values to be passed instead of reading from\n * environment variables. Useful for client-side code where environment variables\n * may not be available.\n */\nexport interface AnalyticsConfigOptions {\n isDevelopment?: boolean;\n isStaging?: boolean;\n segmentWriteKey?: string;\n posthogApiKey?: string;\n}\n\n/**\n * Get analytics configuration\n *\n * When called with options (client-safe), uses the provided values.\n * When called without options (server), reads from process.env.\n *\n * @param options - Optional configuration options for client-side usage\n * @returns Analytics configuration object\n *\n * @example Server usage (reads from process.env):\n * ```typescript\n * const config = getAnalyticsConfig();\n * ```\n *\n * @example Client usage (explicit options):\n * ```typescript\n * const config = getAnalyticsConfig({\n * isDevelopment: process.env.NODE_ENV === 'development',\n * posthogApiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY,\n * });\n * ```\n */\nexport function getAnalyticsConfig(options?: AnalyticsConfigOptions): AnalyticsConfig {\n const builder = createConfigBuilder();\n\n // Determine environment from options or process.env\n const isDevelopment = options?.isDevelopment ?? process.env.NODE_ENV === 'development';\n const isStaging = options?.isStaging ?? process.env.APP_ENV === 'staging';\n\n // Get API keys from options or process.env\n const posthogApiKey = options?.posthogApiKey ?? process.env.POSTHOG_API_KEY;\n const segmentWriteKey = options?.segmentWriteKey ?? process.env.SEGMENT_WRITE_KEY;\n\n // Development - minimal providers\n if (isDevelopment) {\n builder.addConsole({\n prefix: '[Dev Analytics]',\n pretty: true,\n });\n return builder.build();\n }\n\n // Staging - selective providers\n if (isStaging) {\n if (posthogApiKey) {\n builder.addPostHog(posthogApiKey);\n }\n\n builder.addConsole({\n prefix: '[Staging Analytics]',\n pretty: true,\n });\n\n return builder.build();\n }\n\n // Production - multiple providers\n if (segmentWriteKey) {\n builder.addSegment(segmentWriteKey);\n }\n\n if (posthogApiKey) {\n builder.addPostHog(posthogApiKey);\n }\n\n // Add Vercel Analytics in production\n builder.addVercel();\n\n return builder.build();\n}\n"],"mappings":"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"}