@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,442 @@
1
+ /**
2
+ * @fileoverview Edge Runtime Analytics Module
3
+ *
4
+ * Provides edge-compatible analytics for Next.js middleware and edge API routes.
5
+ * Uses Web APIs and HTTP-based implementations compatible with edge runtime.
6
+ *
7
+ * **Supported Features**:
8
+ * - Basic event tracking (track, identify, page, group, alias)
9
+ * - Console provider (uses console API)
10
+ * - PostHog provider (HTTP-based, no SDK dependency)
11
+ * - Emitter pattern support via `emit()`
12
+ *
13
+ * **Limitations (Edge Runtime Constraints)**:
14
+ * - No Node.js APIs (fs, crypto, etc.)
15
+ * - No native modules or SDK dependencies
16
+ * - No event deduplication (no LRU cache)
17
+ * - No rate limiting (100 req/s limit not enforced)
18
+ * - No batch processing optimization
19
+ * - No performance metrics tracking
20
+ * - No feature flags (PostHog flags require server SDK)
21
+ * - Context is per-request only (not persisted)
22
+ *
23
+ * **For full analytics features**, use `@od-oneapp/analytics/server` in Node.js environments.
24
+ *
25
+ * **Usage**: Import from `@od-oneapp/analytics/server/edge` for Next.js middleware and edge API routes.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // In Next.js middleware
30
+ * import { createServerAnalytics, track } from '@od-oneapp/analytics/server/edge';
31
+ *
32
+ * export async function middleware(request: NextRequest) {
33
+ * const analytics = await createServerAnalytics({
34
+ * providers: {
35
+ * posthog: { apiKey: process.env.POSTHOG_API_KEY }
36
+ * }
37
+ * });
38
+ *
39
+ * await analytics.emit(track('Middleware Hit', { path: request.nextUrl.pathname }));
40
+ * return NextResponse.next();
41
+ * }
42
+ * ```
43
+ *
44
+ * @module @od-oneapp/analytics/server/edge
45
+ */
46
+
47
+ import { env } from '../env';
48
+
49
+ import type {
50
+ EmitterAliasPayload,
51
+ EmitterGroupPayload,
52
+ EmitterIdentifyPayload,
53
+ EmitterPagePayload,
54
+ EmitterPayload,
55
+ EmitterTrackPayload,
56
+ } from './shared/emitters/emitter-types';
57
+ import type {
58
+ AnalyticsConfig,
59
+ AnalyticsContext,
60
+ AnalyticsManager,
61
+ AnalyticsProvider,
62
+ GroupTraits,
63
+ PageProperties,
64
+ Properties,
65
+ UserTraits,
66
+ } from './shared/types/types';
67
+
68
+ // Type aliases for clarity
69
+ type IdentifyTraits = UserTraits;
70
+ type TrackProperties = Properties;
71
+
72
+ // Re-export types for consumers
73
+ export type * from './shared/emitters/emitter-types';
74
+ export type * from './shared/types/types';
75
+
76
+ // Re-export emitter utilities
77
+ export { createEmitterProcessor } from './shared/utils/emitter-adapter';
78
+
79
+ // Re-export core emitters for edge usage
80
+ export { alias, group, identify, page, track } from './shared/emitters';
81
+
82
+ const defaultConfig: AnalyticsConfig = { providers: {} };
83
+
84
+ /**
85
+ * Creates an edge-compatible analytics manager.
86
+ *
87
+ * This is a simplified implementation optimized for edge runtime constraints.
88
+ * It provides basic analytics functionality without Node.js-specific features.
89
+ *
90
+ * **Supported Providers**:
91
+ * - Console (always available)
92
+ * - PostHog (HTTP-based, requires API key)
93
+ *
94
+ * **Not Supported in Edge**:
95
+ * - Segment SDK (requires Node.js)
96
+ * - Vercel Analytics SDK (requires Node.js)
97
+ * - Rate limiting
98
+ * - Event deduplication
99
+ * - Batch processing optimization
100
+ *
101
+ * @param {AnalyticsConfig} [config] - Analytics configuration with provider settings
102
+ * @returns {Promise<AnalyticsManager>} Promise resolving to AnalyticsManager instance
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const analytics = await createServerAnalytics({
107
+ * providers: {
108
+ * posthog: { apiKey: process.env.POSTHOG_API_KEY }
109
+ * }
110
+ * });
111
+ *
112
+ * await analytics.track('Event Name', { property: 'value' });
113
+ * ```
114
+ */
115
+ export async function createServerAnalytics(
116
+ config: AnalyticsConfig = defaultConfig,
117
+ ): Promise<AnalyticsManager> {
118
+ const providers: AnalyticsProvider[] = [];
119
+ let context: AnalyticsContext = {};
120
+
121
+ // Initialize Console provider (edge-compatible)
122
+ if (config.providers.console) {
123
+ const { ConsoleProvider } = await import('./providers/console');
124
+ const consoleProvider = new ConsoleProvider(config.providers.console);
125
+ await consoleProvider.initialize();
126
+ providers.push(consoleProvider);
127
+ }
128
+
129
+ // Initialize PostHog HTTP provider (edge-compatible)
130
+ if (config.providers.posthog?.apiKey) {
131
+ const posthogProvider = createPostHogEdgeProvider(config);
132
+ providers.push(posthogProvider);
133
+ }
134
+
135
+ // Process emitter payload by type
136
+ const processPayload = async (payload: EmitterPayload): Promise<void> => {
137
+ switch (payload.type) {
138
+ case 'track': {
139
+ const p = payload;
140
+ await Promise.allSettled(
141
+ providers.map(provider =>
142
+ provider.track(p.event, p.properties ?? {}, { ...context, ...p.context }),
143
+ ),
144
+ );
145
+ break;
146
+ }
147
+ case 'identify': {
148
+ const p = payload;
149
+ await Promise.allSettled(
150
+ providers.map(provider =>
151
+ provider.identify?.(p.userId, p.traits ?? {}, { ...context, ...p.context }),
152
+ ),
153
+ );
154
+ break;
155
+ }
156
+ case 'page': {
157
+ const p = payload;
158
+ await Promise.allSettled(
159
+ providers.map(provider =>
160
+ provider.page?.(p.name ?? '', p.properties ?? {}, { ...context, ...p.context }),
161
+ ),
162
+ );
163
+ break;
164
+ }
165
+ case 'screen': {
166
+ const p = payload;
167
+ await Promise.allSettled(
168
+ providers.map(provider =>
169
+ provider.screen?.(p.name ?? '', p.properties ?? {}, { ...context, ...p.context }),
170
+ ),
171
+ );
172
+ break;
173
+ }
174
+ case 'group': {
175
+ const p = payload;
176
+ await Promise.allSettled(
177
+ providers.map(provider =>
178
+ provider.group?.(p.groupId, p.traits ?? {}, { ...context, ...p.context }),
179
+ ),
180
+ );
181
+ break;
182
+ }
183
+ case 'alias': {
184
+ const p = payload;
185
+ await Promise.allSettled(
186
+ providers.map(provider =>
187
+ provider.alias?.(p.userId, p.previousId, { ...context, ...p.context }),
188
+ ),
189
+ );
190
+ break;
191
+ }
192
+ }
193
+ };
194
+
195
+ // Create emitter function at outer scope (within createServerAnalytics)
196
+ function createEmitterFunction(payload: EmitterPayload): Promise<void> {
197
+ return processPayload(payload);
198
+ }
199
+
200
+ // Return edge-compatible analytics manager
201
+ const manager: AnalyticsManager = {
202
+ getContext: () => ({ ...context }),
203
+
204
+ initialize: async () => {
205
+ // Providers already initialized above
206
+ },
207
+
208
+ setContext: (newContext: AnalyticsContext) => {
209
+ context = { ...context, ...newContext };
210
+ },
211
+
212
+ createEmitter: () => createEmitterFunction,
213
+
214
+ emit: async (payload: EmitterPayload) => {
215
+ await processPayload(payload);
216
+ },
217
+
218
+ emitBatch: async (payloads: EmitterPayload[]) => {
219
+ // Process sequentially in edge (no concurrency optimization)
220
+ for (const payload of payloads) {
221
+ await processPayload(payload);
222
+ }
223
+ },
224
+
225
+ // Overloaded track method
226
+ track: async (eventOrPayload: string | EmitterTrackPayload, properties?: Properties) => {
227
+ if (typeof eventOrPayload === 'object') {
228
+ await processPayload(eventOrPayload);
229
+ } else if (typeof eventOrPayload === 'string') {
230
+ await Promise.allSettled(
231
+ providers.map(p => p.track(eventOrPayload, properties ?? {}, context)),
232
+ );
233
+ }
234
+ },
235
+
236
+ // Overloaded identify method
237
+ identify: async (userIdOrPayload: string | EmitterIdentifyPayload, traits?: IdentifyTraits) => {
238
+ if (typeof userIdOrPayload === 'object') {
239
+ await processPayload(userIdOrPayload);
240
+ } else if (typeof userIdOrPayload === 'string') {
241
+ await Promise.allSettled(
242
+ providers.map(p => p.identify?.(userIdOrPayload, traits ?? {}, context)),
243
+ );
244
+ }
245
+ },
246
+
247
+ // Overloaded page method
248
+ page: async (nameOrPayload?: string | EmitterPagePayload, properties?: PageProperties) => {
249
+ if (typeof nameOrPayload === 'object') {
250
+ await processPayload(nameOrPayload);
251
+ } else {
252
+ const pageName = typeof nameOrPayload === 'string' ? nameOrPayload : '';
253
+ await Promise.allSettled(providers.map(p => p.page?.(pageName, properties ?? {}, context)));
254
+ }
255
+ },
256
+
257
+ // Overloaded group method
258
+ group: async (groupIdOrPayload: string | EmitterGroupPayload, traits?: GroupTraits) => {
259
+ if (typeof groupIdOrPayload === 'object') {
260
+ await processPayload(groupIdOrPayload);
261
+ } else if (typeof groupIdOrPayload === 'string') {
262
+ await Promise.allSettled(
263
+ providers.map(p => p.group?.(groupIdOrPayload, traits ?? {}, context)),
264
+ );
265
+ }
266
+ },
267
+
268
+ // Overloaded alias method
269
+ alias: async (userIdOrPayload: string | EmitterAliasPayload, previousId?: string) => {
270
+ if (typeof userIdOrPayload === 'object') {
271
+ await processPayload(userIdOrPayload);
272
+ } else if (typeof userIdOrPayload === 'string' && previousId) {
273
+ await Promise.allSettled(
274
+ providers.map(p => p.alias?.(userIdOrPayload, previousId, context)),
275
+ );
276
+ }
277
+ },
278
+
279
+ getActiveProviders: () => providers.map(p => p.name),
280
+ getProvider: (name: string) => providers.find(p => p.name === name),
281
+
282
+ reset: () => {
283
+ context = {};
284
+ },
285
+
286
+ shutdown: async () => {
287
+ // In edge, we don't have complex shutdown logic usually
288
+ providers.length = 0;
289
+ },
290
+
291
+ // Deprecated methods (no-ops with warning)
292
+ processEmitterPayload: async (payload: EmitterPayload) => {
293
+ await processPayload(payload);
294
+ },
295
+ trackEcommerce: async () => {
296
+ if (config.debug && config.onInfo) {
297
+ config.onInfo('trackEcommerce is deprecated, use emit(ecommerce.EVENT_NAME(...))');
298
+ }
299
+ },
300
+ };
301
+
302
+ return manager;
303
+ }
304
+
305
+ /**
306
+ * Creates a PostHog provider that uses HTTP API (edge-compatible).
307
+ *
308
+ * This provider uses PostHog's HTTP capture API instead of the Node.js SDK,
309
+ * making it compatible with edge runtime constraints.
310
+ *
311
+ * **Features**:
312
+ * - HTTP-based event tracking
313
+ * - 5-second timeout per request
314
+ * - Error handling via config callbacks
315
+ * - Supports all standard analytics methods (track, identify, page, group, alias)
316
+ *
317
+ * @param {AnalyticsConfig} config - Analytics configuration
318
+ * @returns {AnalyticsProvider} PostHog provider instance
319
+ *
320
+ * @throws {Error} If PostHog API key is not provided
321
+ *
322
+ * @internal
323
+ */
324
+ function createPostHogEdgeProvider(config: AnalyticsConfig): AnalyticsProvider {
325
+ const posthogConfig = config.providers?.posthog;
326
+ if (!posthogConfig?.apiKey) {
327
+ throw new Error('PostHog apiKey is required');
328
+ }
329
+
330
+ const posthogHost =
331
+ (posthogConfig.options as { api_host?: string } | undefined)?.api_host ??
332
+ env.POSTHOG_HOST ??
333
+ 'https://app.posthog.com';
334
+ const posthogUrl = `${posthogHost}/capture/`;
335
+ const { apiKey } = posthogConfig;
336
+ const timeout = 5000;
337
+
338
+ // Safe fetch with timeout and error handling
339
+ const safeFetch = async (body: Record<string, unknown>, method: string): Promise<void> => {
340
+ const controller = new AbortController();
341
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
342
+
343
+ try {
344
+ const response = await fetch(posthogUrl, {
345
+ method: 'POST',
346
+ headers: { 'Content-Type': 'application/json' },
347
+ body: JSON.stringify(body),
348
+ signal: controller.signal,
349
+ });
350
+
351
+ if (!response.ok && config.onError) {
352
+ config.onError(
353
+ new Error(`PostHog ${method} failed: ${response.status} ${response.statusText}`),
354
+ { provider: 'posthog-edge', method, status: response.status },
355
+ );
356
+ }
357
+ } catch (error) {
358
+ if (config.onError) {
359
+ config.onError(error instanceof Error ? error : new Error('Unknown error'), {
360
+ provider: 'posthog-edge',
361
+ method,
362
+ });
363
+ }
364
+ } finally {
365
+ clearTimeout(timeoutId);
366
+ }
367
+ };
368
+
369
+ return {
370
+ name: 'posthog-edge',
371
+
372
+ async initialize() {
373
+ // No initialization needed for HTTP-based PostHog
374
+ },
375
+
376
+ async track(event: string, properties?: TrackProperties, context?: AnalyticsContext) {
377
+ const distinctId = context?.userId ?? properties?.distinctId ?? 'anonymous';
378
+ await safeFetch(
379
+ {
380
+ api_key: apiKey,
381
+ event,
382
+ distinct_id: distinctId,
383
+ properties: { ...properties, ...context },
384
+ timestamp: new Date().toISOString(),
385
+ },
386
+ 'track',
387
+ );
388
+ },
389
+
390
+ async identify(userId: string, traits?: IdentifyTraits) {
391
+ await safeFetch(
392
+ {
393
+ api_key: apiKey,
394
+ event: '$identify',
395
+ distinct_id: userId,
396
+ properties: { $set: traits },
397
+ },
398
+ 'identify',
399
+ );
400
+ },
401
+
402
+ async page(name?: string, properties?: PageProperties, context?: AnalyticsContext) {
403
+ const distinctId = context?.userId ?? 'anonymous';
404
+ await safeFetch(
405
+ {
406
+ api_key: apiKey,
407
+ event: '$pageview',
408
+ distinct_id: distinctId,
409
+ properties: { $current_url: properties?.url, $title: name, ...properties },
410
+ },
411
+ 'page',
412
+ );
413
+ },
414
+
415
+ async group(groupId: string, traits?: GroupTraits, context?: AnalyticsContext) {
416
+ const distinctId = context?.userId ?? 'anonymous';
417
+ await safeFetch(
418
+ {
419
+ api_key: apiKey,
420
+ event: '$groupidentify',
421
+ distinct_id: distinctId,
422
+ properties: { $group_type: 'company', $group_key: groupId, $group_set: traits },
423
+ },
424
+ 'group',
425
+ );
426
+ },
427
+
428
+ async alias(userId: string, previousId: string) {
429
+ await safeFetch(
430
+ {
431
+ api_key: apiKey,
432
+ event: '$create_alias',
433
+ properties: { distinct_id: userId, alias: previousId },
434
+ },
435
+ 'alias',
436
+ );
437
+ },
438
+ };
439
+ }
440
+
441
+ // Export edge-compatible configuration utilities
442
+ export { getAnalyticsConfig } from './shared/utils/config';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @fileoverview Next.js server exports
3
+ *
4
+ * This module provides Next.js-specific server-side analytics functionality.
5
+ * It exports:
6
+ *
7
+ * - **Server Analytics**: All server exports from `./server`
8
+ * - **Middleware**: Framework-agnostic analytics middleware utilities
9
+ * - **Types**: Analytics middleware types and configurations
10
+ *
11
+ * **Middleware Usage**: For Next.js middleware, use the framework-agnostic middleware
12
+ * from `./next/middleware` and provide Next.js-specific adapters in your Next.js app.
13
+ *
14
+ * **Usage**: Import from `@od-oneapp/analytics/server/next` for Next.js server components,
15
+ * API routes, and server actions.
16
+ *
17
+ * @module @od-oneapp/analytics/server/next
18
+ */
19
+
20
+ // Re-export everything from server
21
+ export * from './server';
22
+
23
+ // Export framework-agnostic middleware (use with Next.js adapters in app)
24
+ export {
25
+ composeMiddleware,
26
+ conditionalAnalyticsMiddleware,
27
+ createAnalyticsMiddleware,
28
+ createAnalyticsMiddlewareConfig,
29
+ getAnalyticsContextFromHeaders,
30
+ getDistinctIdFromHeaders,
31
+ } from './next/middleware';
32
+ export type {
33
+ AnalyticsMiddlewareConfig,
34
+ MiddlewareRequest,
35
+ MiddlewareResponse,
36
+ } from './next/middleware';
37
+
38
+ // Export types
39
+ export type * from './types';
package/src/server.ts ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @fileoverview Server exports for Node.js environments (non-Next.js)
3
+ *
4
+ * This module provides server-side analytics functionality for non-Next.js Node.js
5
+ * environments. It exports:
6
+ *
7
+ * - **Analytics Managers**: `createServerAnalytics()`, `createServerAnalyticsUninitialized()`
8
+ * - **Emitters**: Type-safe event tracking functions (track, identify, page, screen, group, alias)
9
+ * - **Ecommerce Emitters**: Comprehensive ecommerce event tracking
10
+ * - **AI Emitters**: AI product analytics tracking
11
+ * - **Emitter Utilities**: ContextBuilder, EventBatch, PayloadBuilder
12
+ * - **Adapter Utilities**: Emitter processing and ecommerce event tracking
13
+ * - **Configuration**: Full configuration utilities with validation
14
+ * - **Validation**: Server-side validation utilities including `validateConfigOrThrow()`
15
+ * - **PostHog Utilities**: Bootstrap data and distinct ID generation
16
+ *
17
+ * **Usage**: Import from `@od-oneapp/analytics/server` for Node.js server applications.
18
+ * For Next.js applications, use `@od-oneapp/analytics/server/next` instead.
19
+ *
20
+ * @module @od-oneapp/analytics/server
21
+ */
22
+
23
+ // Export core server functions
24
+ export { createServerAnalytics, createServerAnalyticsUninitialized } from './server/manager';
25
+
26
+ // Export all emitters - these are the preferred way to track events
27
+ export {
28
+ // Emitter utilities
29
+ ContextBuilder,
30
+ EventBatch,
31
+ PayloadBuilder,
32
+ alias,
33
+ createAnonymousSession,
34
+ createUserSession,
35
+ // Ecommerce emitters namespace
36
+ ecommerce,
37
+ group,
38
+ // Core Segment.io spec emitters
39
+ identify,
40
+ isAliasPayload,
41
+ isGroupPayload,
42
+ isIdentifyPayload,
43
+ isPagePayload,
44
+ // Type guards
45
+ isTrackPayload,
46
+ page,
47
+ screen,
48
+ track,
49
+ withMetadata,
50
+ withUTM,
51
+ } from './shared/emitters';
52
+
53
+ // Export adapter utilities
54
+ export {
55
+ createEmitterProcessor,
56
+ // Emitter processing utilities
57
+ processEmitterPayload,
58
+ trackEcommerceEvent,
59
+ } from './shared/utils/emitter-adapter';
60
+
61
+ // Export configuration utilities
62
+ export {
63
+ PROVIDER_REQUIREMENTS,
64
+ createConfigBuilder,
65
+ getAnalyticsConfig,
66
+ validateConfig,
67
+ } from './shared/utils/config';
68
+
69
+ // Export validation utilities
70
+ export {
71
+ debugConfig,
72
+ validateAnalyticsConfig,
73
+ validateConfigOrThrow,
74
+ validateProvider,
75
+ } from './shared/utils/validation';
76
+
77
+ // Export manager utilities
78
+ export {
79
+ AnalyticsManager as AnalyticsManagerClass,
80
+ createAnalyticsManager,
81
+ } from './shared/utils/manager';
82
+
83
+ // Export PostHog utilities
84
+ export {
85
+ createBootstrapData,
86
+ createMinimalBootstrapData,
87
+ generateDistinctId,
88
+ } from './shared/utils/posthog-bootstrap';
89
+
90
+ // Export ingestion service
91
+ export {
92
+ createIngestionService,
93
+ IngestionService,
94
+ validateEventPayload,
95
+ validateBatchPayload,
96
+ } from './shared/ingestion';
97
+ export type {
98
+ IngestionContext,
99
+ IngestionServiceConfig,
100
+ IngestionMetrics,
101
+ IngestionSuccessResponse,
102
+ IngestionErrorResponse,
103
+ } from './shared/ingestion';
104
+
105
+ // Export types
106
+ export type * from './types';