@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,329 @@
1
+ /**
2
+ * @fileoverview PostHog server-side (Node.js) provider implementation
3
+ *
4
+ * Provides server-side integration with PostHog Analytics including feature flags support.
5
+ * Supports full PostHog tracking including capture, identify, group, alias, and feature flags.
6
+ *
7
+ * @remarks
8
+ * This provider:
9
+ * - Uses PostHog Node.js SDK for server-side tracking
10
+ * - Supports feature flags and experiments
11
+ * - Optimized for Next.js server components
12
+ * - Integrates with PostHog's API endpoint
13
+ *
14
+ * @module @repo/analytics/providers/posthog/server
15
+ */
16
+
17
+ import type {
18
+ BootstrapData,
19
+ EnhancedPostHogProvider,
20
+ ExperimentInfo,
21
+ PostHogConfig,
22
+ } from './types';
23
+ import type { AnalyticsProvider, ProviderConfig } from '../../shared/types/types';
24
+
25
+ export class PostHogServerProvider implements AnalyticsProvider, Partial<EnhancedPostHogProvider> {
26
+ readonly name = 'posthog';
27
+ private config: PostHogConfig;
28
+ private client: any = null;
29
+ private isInitialized = false;
30
+
31
+ constructor(config: ProviderConfig) {
32
+ if (!config.apiKey) {
33
+ throw new Error('PostHog apiKey is required');
34
+ }
35
+
36
+ this.config = {
37
+ apiKey: config.apiKey,
38
+ options: {
39
+ // Server-side optimizations for Next.js
40
+ flushAt: 1,
41
+ flushInterval: 0,
42
+ ...config.options,
43
+ },
44
+ };
45
+ }
46
+
47
+ async initialize(): Promise<void> {
48
+ if (this.isInitialized) return;
49
+
50
+ try {
51
+ // Dynamically import PostHog Node.js SDK
52
+ const { PostHog } = await import('posthog-node');
53
+
54
+ // Extract client-side only options that don't apply to server
55
+ const {
56
+ api_host: _api_host,
57
+ autocapture: _autocapture,
58
+ bootstrap: _bootstrap,
59
+ capture_pageview: _capture_pageview,
60
+ cross_subdomain_cookie: _cross_subdomain_cookie,
61
+ disable_session_recording: _disable_session_recording,
62
+ fetch_options: _fetch_options,
63
+ loaded: _loaded,
64
+ persistence: _persistence,
65
+ ui_host: _ui_host,
66
+ ...serverOptions
67
+ } = this.config.options ?? {};
68
+
69
+ this.client = new PostHog(this.config.apiKey, {
70
+ host: 'https://app.posthog.com',
71
+ ...serverOptions,
72
+ });
73
+
74
+ this.isInitialized = true;
75
+ } catch {
76
+ throw new Error('PostHog Node.js SDK not available. Install with: npm install posthog-node');
77
+ }
78
+ }
79
+
80
+ async track(event: string, properties: any = {}): Promise<void> {
81
+ if (!this.isInitialized || !this.client) {
82
+ return;
83
+ }
84
+
85
+ try {
86
+ this.client.capture({
87
+ distinctId: properties.userId ?? properties.distinctId ?? 'anonymous',
88
+ event,
89
+ properties,
90
+ });
91
+ } catch {
92
+ // Silently fail to avoid disrupting app flow
93
+ }
94
+ }
95
+
96
+ async identify(userId: string, traits: any = {}): Promise<void> {
97
+ if (!this.isInitialized || !this.client) {
98
+ return;
99
+ }
100
+
101
+ try {
102
+ this.client.identify({
103
+ distinctId: userId,
104
+ properties: traits,
105
+ });
106
+ } catch {
107
+ // Silently fail to avoid disrupting app flow
108
+ }
109
+ }
110
+
111
+ async page(name?: string, properties: any = {}): Promise<void> {
112
+ if (!this.isInitialized || !this.client) {
113
+ return;
114
+ }
115
+
116
+ try {
117
+ this.client.capture({
118
+ distinctId: properties.userId ?? properties.distinctId ?? 'anonymous',
119
+ event: '$pageview',
120
+ properties: {
121
+ $current_url: properties.url,
122
+ $title: name,
123
+ ...properties,
124
+ },
125
+ });
126
+ } catch {
127
+ // Silently fail to avoid disrupting app flow
128
+ }
129
+ }
130
+
131
+ async group(groupId: string, traits: any = {}): Promise<void> {
132
+ if (!this.isInitialized || !this.client) {
133
+ return;
134
+ }
135
+
136
+ try {
137
+ this.client.groupIdentify({
138
+ groupKey: groupId,
139
+ groupType: 'company',
140
+ properties: traits,
141
+ });
142
+ } catch {
143
+ // Silently fail to avoid disrupting app flow
144
+ }
145
+ }
146
+
147
+ async alias(userId: string, previousId: string): Promise<void> {
148
+ if (!this.isInitialized || !this.client) {
149
+ return;
150
+ }
151
+
152
+ try {
153
+ this.client.alias({
154
+ alias: previousId,
155
+ distinctId: userId,
156
+ });
157
+ } catch {
158
+ // Silently fail to avoid disrupting app flow
159
+ }
160
+ }
161
+
162
+ // Feature Flag Methods (Server-Side)
163
+ async getAllFlags(userId: string): Promise<Record<string, any>> {
164
+ if (!this.isInitialized || !this.client) {
165
+ return {};
166
+ }
167
+
168
+ if (!userId) {
169
+ return {};
170
+ }
171
+
172
+ try {
173
+ const flags = await this.client.getAllFlags(userId);
174
+ return flags ?? {};
175
+ } catch {
176
+ return {};
177
+ }
178
+ }
179
+
180
+ async getFeatureFlag(flag: string, userId: string): Promise<any> {
181
+ if (!this.isInitialized || !this.client) {
182
+ return false;
183
+ }
184
+
185
+ if (!userId) {
186
+ return false;
187
+ }
188
+
189
+ try {
190
+ return await this.client.getFeatureFlag(flag, userId);
191
+ } catch {
192
+ return false;
193
+ }
194
+ }
195
+
196
+ async isFeatureEnabled(flag: string, userId: string): Promise<boolean> {
197
+ if (!this.isInitialized || !this.client) {
198
+ return false;
199
+ }
200
+
201
+ if (!userId) {
202
+ return false;
203
+ }
204
+
205
+ try {
206
+ const flagValue = await this.client.isFeatureEnabled(flag, userId);
207
+ return Boolean(flagValue);
208
+ } catch {
209
+ return false;
210
+ }
211
+ }
212
+
213
+ async getFeatureFlagPayload(flag: string, userId?: string): Promise<any | null> {
214
+ if (!this.isInitialized || !this.client) {
215
+ return null;
216
+ }
217
+
218
+ if (!userId) {
219
+ return null;
220
+ }
221
+
222
+ try {
223
+ const payload = await this.client.getFeatureFlagPayload(flag, userId);
224
+ return payload ?? null;
225
+ } catch {
226
+ return null;
227
+ }
228
+ }
229
+
230
+ async getActiveExperiments(userId: string): Promise<ExperimentInfo[]> {
231
+ if (!this.isInitialized || !this.client) {
232
+ return [];
233
+ }
234
+
235
+ if (!userId) {
236
+ return [];
237
+ }
238
+
239
+ try {
240
+ const flags = await this.getAllFlags(userId);
241
+ const experiments: ExperimentInfo[] = [];
242
+
243
+ for (const [key, variant] of Object.entries(flags)) {
244
+ if (variant !== false) {
245
+ const payload = await this.getFeatureFlagPayload(key, userId);
246
+ experiments.push({
247
+ key,
248
+ payload: payload ?? undefined,
249
+ variant: typeof variant === 'object' ? JSON.stringify(variant) : String(variant),
250
+ });
251
+ }
252
+ }
253
+
254
+ return experiments;
255
+ } catch {
256
+ return [];
257
+ }
258
+ }
259
+
260
+ // Bootstrap method - primary use case for server-side
261
+ async getBootstrapData(distinctId: string): Promise<BootstrapData> {
262
+ if (!this.isInitialized || !this.client) {
263
+ return { distinctID: distinctId };
264
+ }
265
+
266
+ try {
267
+ // Get all flags for the user
268
+ const featureFlags = await this.getAllFlags(distinctId);
269
+
270
+ // Get payloads for flags that have them
271
+ const featureFlagPayloads: Record<string, any> = {};
272
+
273
+ for (const [flagKey, flagValue] of Object.entries(featureFlags)) {
274
+ if (flagValue !== false) {
275
+ try {
276
+ const payload = await this.getFeatureFlagPayload(flagKey, distinctId);
277
+ if (payload) {
278
+ featureFlagPayloads[flagKey] = payload;
279
+ }
280
+ } catch {
281
+ // Continue if individual payload fetch fails - silently ignore
282
+ }
283
+ }
284
+ }
285
+
286
+ return {
287
+ distinctID: distinctId,
288
+ };
289
+ } catch {
290
+ return { distinctID: distinctId };
291
+ }
292
+ }
293
+
294
+ // Utility Methods
295
+ reset(): void {
296
+ // Server-side reset doesn't make sense in the same way as client-side
297
+ // But we can provide a method for consistency
298
+ }
299
+
300
+ async shutdown(): Promise<void> {
301
+ if (!this.isInitialized || !this.client) {
302
+ return;
303
+ }
304
+
305
+ try {
306
+ await this.client.shutdown();
307
+ } catch {
308
+ // Silently fail
309
+ }
310
+ }
311
+
312
+ // Server-specific helper methods
313
+ async forceFlush(): Promise<void> {
314
+ if (!this.isInitialized || !this.client) {
315
+ return;
316
+ }
317
+
318
+ try {
319
+ await this.client.flush();
320
+ } catch {
321
+ // Silently fail
322
+ }
323
+ }
324
+
325
+ // Get the PostHog client for advanced usage
326
+ getClient(): any {
327
+ return this.client;
328
+ }
329
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @fileoverview PostHog provider type definitions
3
+ *
4
+ * Defines TypeScript types and interfaces for PostHog Analytics provider configuration.
5
+ * Includes feature flags, experiments, and bootstrap data types.
6
+ *
7
+ * @module @repo/analytics/providers/posthog/types
8
+ */
9
+
10
+ export interface PostHogConfig {
11
+ apiKey: string;
12
+ options?: PostHogOptions | undefined;
13
+ }
14
+
15
+ interface PostHogOptions {
16
+ host?: string;
17
+ autocapture?: boolean;
18
+ capture_pageview?: boolean;
19
+ capture_pageleave?: boolean;
20
+ session_recording?: boolean;
21
+ debug?: boolean;
22
+ bootstrap?: BootstrapData;
23
+ person_profiles?: 'always' | 'never' | 'identified_only';
24
+ api?: {
25
+ host?: string;
26
+ };
27
+ ui?: {
28
+ host?: string;
29
+ };
30
+ feature_flag_request_timeout_ms?: number;
31
+ advanced_disable_decide?: boolean;
32
+ disable_surveys?: boolean;
33
+ disable_toolbar?: boolean;
34
+ disable_session_recording?: boolean;
35
+ property_blacklist?: string[];
36
+ sanitize_properties?: (properties: any, event: string) => any;
37
+ request_headers?: Record<string, string>;
38
+ respect_dnt?: boolean;
39
+ opt_out_capturing_by_default?: boolean;
40
+ opt_out_persistence_by_default?: boolean;
41
+ opt_out_useragent_filter?: boolean;
42
+ cross_subdomain_cookie?: boolean;
43
+ persistence?: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie';
44
+ persistence_name?: string;
45
+ cookie_name?: string;
46
+ loaded?: (posthog: any) => void;
47
+ on_xhr_error?: (failedRequest: XMLHttpRequest) => void;
48
+ mask_all_element_attributes?: boolean;
49
+ mask_all_text?: boolean;
50
+ advanced_disable_feature_flags?: boolean;
51
+ advanced_disable_feature_flags_on_first_load?: boolean;
52
+ advanced_disable_toolbar_metrics?: boolean;
53
+ segment?: any;
54
+ name?: string;
55
+
56
+ // Server-specific options
57
+ flushAt?: number;
58
+ flushInterval?: number;
59
+ api_host?: string;
60
+ ui_host?: string;
61
+ fetch_options?: any;
62
+ }
63
+
64
+ export interface BootstrapData {
65
+ distinctID?: string;
66
+ isIdentifiedID?: boolean;
67
+ featureFlags?: Record<string, any>;
68
+ featureFlagPayloads?: Record<string, any>;
69
+ sessionRecording?: {
70
+ endpoint?: string;
71
+ };
72
+ surveys?: any[];
73
+ toolbarParams?: Record<string, any>;
74
+ }
75
+
76
+ export interface ExperimentInfo {
77
+ key: string;
78
+ variant: string | boolean;
79
+ payload?: any;
80
+ }
81
+
82
+ export interface EnhancedPostHogProvider {
83
+ // Feature flag methods
84
+ isFeatureEnabled(flag: string, userId?: string): Promise<boolean>;
85
+ getFeatureFlag(flag: string, userId?: string): Promise<any>;
86
+ getFeatureFlagPayload(flag: string): any;
87
+ reloadFeatureFlags(): Promise<void>;
88
+ getAllFlags(userId?: string): Promise<Record<string, any>>;
89
+
90
+ // Experiment methods
91
+ getActiveExperiments(userId?: string): Promise<ExperimentInfo[]>;
92
+
93
+ // Bootstrap methods
94
+ getBootstrapData(distinctId: string): Promise<BootstrapData>;
95
+
96
+ // Session methods
97
+ startSessionRecording(): void;
98
+ stopSessionRecording(): void;
99
+
100
+ // Advanced methods
101
+ reset(): void;
102
+ register(properties: Record<string, any>): void;
103
+ unregister(property: string): void;
104
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @fileoverview Segment client-side (browser) provider implementation
3
+ *
4
+ * Provides client-side integration with Segment Analytics using @segment/analytics-next.
5
+ * Supports full Segment.io spec tracking including track, identify, page, group, and alias.
6
+ *
7
+ * @remarks
8
+ * This provider:
9
+ * - Uses @segment/analytics-next for browser tracking
10
+ * - Supports dynamic imports to avoid SSR issues
11
+ * - Handles initialization and event tracking
12
+ * - Integrates with Segment's CDN and API
13
+ *
14
+ * @module @repo/analytics/providers/segment/client
15
+ */
16
+
17
+ import { BaseAnalyticsProvider } from '../base-provider';
18
+
19
+ import type { SegmentConfig } from './types';
20
+ import type {
21
+ AnalyticsContext,
22
+ GroupTraits,
23
+ PageProperties,
24
+ Properties,
25
+ ProviderConfig,
26
+ UserTraits,
27
+ } from '../../shared/types/types';
28
+
29
+ // Type for AnalyticsBrowser instance
30
+ interface AnalyticsBrowserInstance {
31
+ track: (event: string, properties?: Properties) => Promise<unknown>;
32
+ identify: (userId: string, traits?: UserTraits) => Promise<unknown>;
33
+ page: (name?: string, properties?: PageProperties) => Promise<unknown>;
34
+ group: (groupId: string, traits?: GroupTraits) => Promise<unknown>;
35
+ alias: (userId: string, previousId: string) => Promise<unknown>;
36
+ }
37
+
38
+ export class SegmentClientProvider extends BaseAnalyticsProvider<SegmentConfig> {
39
+ readonly name = 'segment';
40
+ private analytics: AnalyticsBrowserInstance | null = null;
41
+
42
+ constructor(config: ProviderConfig) {
43
+ super(config);
44
+
45
+ if (!config.writeKey) {
46
+ throw new Error('Segment writeKey is required');
47
+ }
48
+
49
+ this.config = {
50
+ options: config.options as Record<string, unknown>,
51
+ writeKey: config.writeKey,
52
+ };
53
+ }
54
+
55
+ protected async doInitialize(): Promise<void> {
56
+ // Dynamically import Segment Analytics Next
57
+ const { AnalyticsBrowser } = await import(
58
+ /* webpackChunkName: "segment-analytics-browser" */
59
+ '@segment/analytics-next'
60
+ );
61
+
62
+ // Initialize Analytics Browser
63
+ this.analytics = AnalyticsBrowser.load({
64
+ writeKey: this.config.writeKey,
65
+ ...this.config.options,
66
+ }) as unknown as AnalyticsBrowserInstance;
67
+ }
68
+
69
+ protected async doTrack(
70
+ event: string,
71
+ properties: Properties,
72
+ _context?: AnalyticsContext,
73
+ ): Promise<void> {
74
+ if (!this.analytics) return;
75
+ await this.analytics.track(event, properties);
76
+ }
77
+
78
+ protected async doIdentify(
79
+ userId: string,
80
+ traits: UserTraits,
81
+ _context?: AnalyticsContext,
82
+ ): Promise<void> {
83
+ if (!this.analytics) return;
84
+ await this.analytics.identify(userId, traits);
85
+ }
86
+
87
+ protected async doPage(
88
+ name: string | undefined,
89
+ properties: PageProperties,
90
+ _context?: AnalyticsContext,
91
+ ): Promise<void> {
92
+ if (!this.analytics) return;
93
+ await this.analytics.page(name, properties);
94
+ }
95
+
96
+ protected async doGroup(
97
+ groupId: string,
98
+ traits: GroupTraits,
99
+ _context?: AnalyticsContext,
100
+ ): Promise<void> {
101
+ if (!this.analytics) return;
102
+ await this.analytics.group(groupId, traits);
103
+ }
104
+
105
+ protected async doAlias(
106
+ userId: string,
107
+ previousId: string,
108
+ _context?: AnalyticsContext,
109
+ ): Promise<void> {
110
+ if (!this.analytics) return;
111
+ await this.analytics.alias(userId, previousId);
112
+ }
113
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview Segment provider shared logic and exports
3
+ *
4
+ * Barrel export file for Segment Analytics provider implementations and types.
5
+ *
6
+ * @module @repo/analytics/providers/segment
7
+ */
8
+
9
+ // Export provider implementations
10
+ // Export types
11
+ export type * from './types';
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @fileoverview Segment server-side (Node.js) provider implementation
3
+ *
4
+ * Provides server-side integration with Segment Analytics using @segment/analytics-next.
5
+ * Note: analytics-next supports universal runtime environments including Node.js.
6
+ *
7
+ * @remarks
8
+ * This provider:
9
+ * - Uses @segment/analytics-next for server-side tracking
10
+ * - Supports Node.js runtime with flushAt: 1 for immediate sending
11
+ * - Handles initialization and event tracking
12
+ * - Integrates with Segment's API endpoint
13
+ *
14
+ * @module @repo/analytics/providers/segment/server
15
+ */
16
+
17
+ import { BaseAnalyticsProvider } from '../base-provider';
18
+
19
+ import type { SegmentConfig } from './types';
20
+ import type {
21
+ AnalyticsContext,
22
+ GroupTraits,
23
+ PageProperties,
24
+ Properties,
25
+ ProviderConfig,
26
+ UserTraits,
27
+ } from '../../shared/types/types';
28
+
29
+ // Type for Analytics server instance
30
+ interface AnalyticsServerInstance {
31
+ track: (params: { event: string; properties?: Properties }) => Promise<unknown>;
32
+ identify: (params: { userId: string; traits?: UserTraits }) => Promise<unknown>;
33
+ page: (params: { name?: string; properties?: PageProperties }) => Promise<unknown>;
34
+ group: (params: { groupId: string; traits?: GroupTraits }) => Promise<unknown>;
35
+ alias: (params: { userId: string; previousId: string }) => Promise<unknown>;
36
+ }
37
+
38
+ export class SegmentServerProvider extends BaseAnalyticsProvider<SegmentConfig> {
39
+ readonly name = 'segment';
40
+ private analytics: AnalyticsServerInstance | null = null;
41
+
42
+ constructor(config: ProviderConfig) {
43
+ super(config);
44
+
45
+ if (!config.writeKey) {
46
+ throw new Error('Segment writeKey is required');
47
+ }
48
+
49
+ this.config = {
50
+ options: config.options as Record<string, unknown>,
51
+ writeKey: config.writeKey,
52
+ };
53
+ }
54
+
55
+ protected async doInitialize(): Promise<void> {
56
+ // Dynamically import Segment Analytics Next
57
+ // analytics-next supports Node.js runtime with flushAt: 1 for server environments
58
+ const { Analytics } = await import(
59
+ /* webpackChunkName: "segment-analytics" */
60
+ '@segment/analytics-next'
61
+ );
62
+
63
+ this.analytics = new Analytics({
64
+ writeKey: this.config.writeKey,
65
+ // Note: flushAt is not supported in @segment/analytics-next
66
+ // Server-side events are sent immediately by default
67
+ ...this.config.options,
68
+ }) as unknown as AnalyticsServerInstance;
69
+ }
70
+
71
+ protected async doTrack(
72
+ event: string,
73
+ properties: Properties,
74
+ _context?: AnalyticsContext,
75
+ ): Promise<void> {
76
+ if (!this.analytics) return;
77
+ await this.analytics.track({ event, properties });
78
+ }
79
+
80
+ protected async doIdentify(
81
+ userId: string,
82
+ traits: UserTraits,
83
+ _context?: AnalyticsContext,
84
+ ): Promise<void> {
85
+ if (!this.analytics) return;
86
+ await this.analytics.identify({ userId, traits });
87
+ }
88
+
89
+ protected async doPage(
90
+ name: string | undefined,
91
+ properties: PageProperties,
92
+ _context?: AnalyticsContext,
93
+ ): Promise<void> {
94
+ if (!this.analytics) return;
95
+ await this.analytics.page({ ...(name && { name }), properties });
96
+ }
97
+
98
+ protected async doGroup(
99
+ groupId: string,
100
+ traits: GroupTraits,
101
+ _context?: AnalyticsContext,
102
+ ): Promise<void> {
103
+ if (!this.analytics) return;
104
+ await this.analytics.group({ groupId, traits });
105
+ }
106
+
107
+ protected async doAlias(
108
+ userId: string,
109
+ previousId: string,
110
+ _context?: AnalyticsContext,
111
+ ): Promise<void> {
112
+ if (!this.analytics) return;
113
+ await this.analytics.alias({ userId, previousId });
114
+ }
115
+ }