@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,220 @@
1
+ /**
2
+ * @fileoverview TypeScript declarations for Next.js 15 analytics integration
3
+ *
4
+ * Provides type definitions for Next.js analytics integration, including:
5
+ * - Next.js request/response type augmentations
6
+ * - Analytics event types
7
+ * - Server action types
8
+ * - Provider props types
9
+ * - Hook return types
10
+ *
11
+ * @remarks
12
+ * Type-only imports are used to avoid contamination. Runtime Next.js
13
+ * dependencies should be provided via dependency injection in implementation files.
14
+ *
15
+ * @module @od-oneapp/analytics/next/types
16
+ */
17
+
18
+ /// <reference types="react" />
19
+ /// <reference types="next" />
20
+
21
+ // Type-only import - no runtime dependency
22
+ import type { BootstrapData } from '../shared/types/posthog-types';
23
+ import type { AnalyticsConfig } from '../shared/types/types';
24
+ import type { ReadonlyRequestCookies } from 'next/dist/server/web/spec-extension/adapters/request-cookies';
25
+
26
+ declare module 'next/server' {
27
+ interface NextRequest {
28
+ analytics?: {
29
+ distinctId?: string;
30
+ context?: Record<string, any>;
31
+ };
32
+ }
33
+ }
34
+
35
+ declare module 'next/headers' {
36
+ interface ReadonlyHeaders {
37
+ getAnalyticsContext(): Record<string, any>;
38
+ getDistinctId(): string | null;
39
+ }
40
+ }
41
+
42
+ // Augment global types for edge runtime
43
+ declare global {
44
+ namespace NodeJS {
45
+ interface ProcessEnv {
46
+ NEXT_PUBLIC_POSTHOG_HOST?: string;
47
+ NEXT_PUBLIC_POSTHOG_KEY?: string;
48
+ NEXT_PUBLIC_SEGMENT_WRITE_KEY?: string;
49
+ NEXT_PUBLIC_VERCEL_ANALYTICS_ID?: string;
50
+ }
51
+ }
52
+
53
+ interface Window {
54
+ // PostHog types
55
+ posthog?: any;
56
+
57
+ // Segment types
58
+ analytics?: any;
59
+
60
+ // Custom analytics events
61
+ analyticsReady?: boolean;
62
+ onAnalyticsReady?: (callback: () => void) => void;
63
+ }
64
+ }
65
+
66
+ // Server Action types
67
+ export type ServerActionResult<T = void> = Promise<{
68
+ success: boolean;
69
+ data?: T;
70
+ error?: string;
71
+ }>;
72
+
73
+ // Feature flag types with proper typing
74
+ export type TypedFeatureFlags<T extends Record<string, boolean>> = {
75
+ [K in keyof T]: T[K];
76
+ };
77
+
78
+ // Analytics event types
79
+ export interface AnalyticsEvent {
80
+ context?: Record<string, any>;
81
+ name: string;
82
+ properties?: Record<string, any>;
83
+ timestamp?: string;
84
+ }
85
+
86
+ // Page view event
87
+ export interface PageViewEvent extends AnalyticsEvent {
88
+ name: 'Page View';
89
+ properties: {
90
+ path: string;
91
+ url: string;
92
+ title: string;
93
+ referrer?: string;
94
+ search?: string;
95
+ search_params?: Record<string, string>;
96
+ route_params?: Record<string, string | string[]>;
97
+ };
98
+ }
99
+
100
+ // E-commerce event types
101
+ export interface ProductViewEvent extends AnalyticsEvent {
102
+ name: 'Product Viewed';
103
+ properties: {
104
+ product_id: string;
105
+ product_name: string;
106
+ price?: number;
107
+ category?: string;
108
+ [key: string]: any;
109
+ };
110
+ }
111
+
112
+ export interface AddToCartEvent extends AnalyticsEvent {
113
+ name: 'Product Added to Cart';
114
+ properties: {
115
+ product_id: string;
116
+ product_name: string;
117
+ price?: number;
118
+ quantity: number;
119
+ [key: string]: any;
120
+ };
121
+ }
122
+
123
+ export interface CheckoutEvent extends AnalyticsEvent {
124
+ name: 'Checkout Started';
125
+ properties: {
126
+ total: number;
127
+ item_count: number;
128
+ [key: string]: any;
129
+ };
130
+ }
131
+
132
+ export interface PurchaseEvent extends AnalyticsEvent {
133
+ name: 'Order Completed';
134
+ properties: {
135
+ order_id: string;
136
+ total: number;
137
+ item_count: number;
138
+ [key: string]: any;
139
+ };
140
+ }
141
+
142
+ // Form tracking event types
143
+ export interface FormStartEvent extends AnalyticsEvent {
144
+ name: 'Form Started';
145
+ properties: {
146
+ form_name: string;
147
+ };
148
+ }
149
+
150
+ export interface FormSubmitEvent extends AnalyticsEvent {
151
+ name: 'Form Submitted';
152
+ properties: {
153
+ form_name: string;
154
+ field_count?: number;
155
+ };
156
+ }
157
+
158
+ export interface FormErrorEvent extends AnalyticsEvent {
159
+ name: 'Form Error';
160
+ properties: {
161
+ form_name: string;
162
+ error_message: string;
163
+ };
164
+ }
165
+
166
+ // Middleware types
167
+ export interface AnalyticsMiddlewareContext {
168
+ cookies: ReadonlyRequestCookies;
169
+ geo?: {
170
+ country?: string;
171
+ region?: string;
172
+ city?: string;
173
+ };
174
+ headers: Headers;
175
+ method: string;
176
+ pathname: string;
177
+ searchParams: URLSearchParams;
178
+ }
179
+
180
+ // React component props types
181
+ export interface TrackedComponentProps {
182
+ 'data-analytics-event'?: string;
183
+ 'data-analytics-properties'?: string | Record<string, any>;
184
+ }
185
+
186
+ // Hook return types
187
+ export interface UseAnalyticsReturn {
188
+ identify: (userId: string, traits?: any) => void;
189
+ page: (name?: string, properties?: any) => void;
190
+ ready: boolean;
191
+ track: (event: string, properties?: any) => void;
192
+ }
193
+
194
+ // Provider props types
195
+ export interface AnalyticsProviderProps {
196
+ autoPageTracking?: boolean;
197
+ bootstrapData?: BootstrapData;
198
+ children: React.ReactNode;
199
+ config: AnalyticsConfig;
200
+ consentRequired?: boolean;
201
+ onReady?: () => void;
202
+ pageTrackingOptions?: {
203
+ trackSearch?: boolean;
204
+ trackParams?: boolean;
205
+ properties?: Record<string, any>;
206
+ skip?: boolean;
207
+ };
208
+ }
209
+
210
+ // Utility types for type-safe event tracking
211
+ export type EventProperties<T extends AnalyticsEvent> = T extends { properties: infer P }
212
+ ? P
213
+ : never;
214
+
215
+ export type EventName<T extends AnalyticsEvent> = T extends { name: infer N } ? N : never;
216
+
217
+ // Helper type for creating typed track functions
218
+ export type TypedTrackFunction<T extends AnalyticsEvent> = (
219
+ properties: EventProperties<T>,
220
+ ) => void | Promise<void>;
@@ -0,0 +1,419 @@
1
+ /**
2
+ * @fileoverview Base Analytics Provider
3
+ *
4
+ * Abstract base class that implements common provider patterns:
5
+ * - Initialization state management
6
+ * - Safe method execution with error handling
7
+ * - Consistent interface implementation
8
+ * - Error handling and logging
9
+ *
10
+ * **Provider Development**: Providers should extend this class and implement
11
+ * the abstract methods (`doInitialize`, `doTrack`, `doIdentify`, etc.).
12
+ *
13
+ * **Benefits**:
14
+ * - Consistent error handling across all providers
15
+ * - Initialization state management
16
+ * - Safe method execution (checks initialization before calling)
17
+ * - Error callbacks for logging/reporting
18
+ *
19
+ * @module @od-oneapp/analytics/providers/base-provider
20
+ */
21
+
22
+ import type {
23
+ AnalyticsContext,
24
+ AnalyticsProvider,
25
+ GroupTraits,
26
+ PageProperties,
27
+ Properties,
28
+ ProviderConfig,
29
+ UserTraits,
30
+ } from '../shared/types/types';
31
+
32
+ /**
33
+ * Error handler type for provider operations.
34
+ *
35
+ * Called when an error occurs during provider operations. Receives the error
36
+ * and context about which provider and method failed.
37
+ *
38
+ * @param {unknown} error - The error that occurred
39
+ * @param {object} context - Context about the error (provider name, method name, metadata)
40
+ */
41
+ export type ProviderErrorHandler = (
42
+ error: unknown,
43
+ context: {
44
+ provider: string;
45
+ method: string;
46
+ [key: string]: unknown;
47
+ },
48
+ ) => void;
49
+
50
+ /**
51
+ * Base configuration for all providers.
52
+ *
53
+ * Common configuration options that all providers support.
54
+ */
55
+ export interface BaseProviderConfig {
56
+ /** Error handler callback */
57
+ onError?: ProviderErrorHandler;
58
+ /** Enable debug mode */
59
+ debug?: boolean;
60
+ }
61
+
62
+ /**
63
+ * Abstract base class for analytics providers
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * class MyProvider extends BaseAnalyticsProvider<MyConfig> {
68
+ * readonly name = 'my-provider';
69
+ *
70
+ * protected async doInitialize(): Promise<void> {
71
+ * // Load SDK and set up client
72
+ * }
73
+ *
74
+ * protected async doTrack(event: string, properties: Properties): Promise<void> {
75
+ * // Call SDK track method
76
+ * }
77
+ *
78
+ * // ... implement other abstract methods
79
+ * }
80
+ * ```
81
+ */
82
+ export abstract class BaseAnalyticsProvider<
83
+ TConfig extends BaseProviderConfig = BaseProviderConfig,
84
+ > implements AnalyticsProvider {
85
+ /** Provider name used for identification and logging */
86
+ abstract readonly name: string;
87
+
88
+ /** Provider-specific configuration */
89
+ protected config: TConfig;
90
+
91
+ /** Whether the provider has been initialized */
92
+ protected isInitialized = false;
93
+
94
+ /** Error handler for logging/reporting errors */
95
+ protected onError?: ProviderErrorHandler | undefined;
96
+
97
+ constructor(config: ProviderConfig, defaultConfig: Partial<TConfig> = {}) {
98
+ this.config = {
99
+ ...defaultConfig,
100
+ ...config,
101
+ ...(config.options as Partial<TConfig>),
102
+ } as TConfig;
103
+ this.onError = this.config.onError ?? undefined;
104
+ }
105
+
106
+ /**
107
+ * Initialize the provider.
108
+ *
109
+ * This is called by the analytics manager before any tracking calls.
110
+ * Calls the abstract `doInitialize()` method and handles errors.
111
+ *
112
+ * @param {ProviderConfig} [config] - Optional provider configuration
113
+ * @returns {Promise<void>} Promise that resolves when initialization is complete
114
+ * @throws {Error} If initialization fails
115
+ */
116
+ async initialize(config?: ProviderConfig): Promise<void> {
117
+ if (this.isInitialized) return;
118
+
119
+ try {
120
+ await this.doInitialize(config);
121
+ this.isInitialized = true;
122
+ } catch (error) {
123
+ this.handleError(error, 'initialize');
124
+ throw error; // Re-throw to let manager know initialization failed
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Track an event.
130
+ *
131
+ * Validates that the provider is initialized, then calls the abstract
132
+ * `doTrack()` method. Handles errors gracefully without throwing.
133
+ *
134
+ * @param {string} event - Event name
135
+ * @param {Properties} [properties] - Event properties
136
+ * @param {AnalyticsContext} [context] - Analytics context
137
+ * @returns {Promise<void>} Promise that resolves when tracking is complete
138
+ */
139
+ async track(
140
+ event: string,
141
+ properties: Properties = {},
142
+ context?: AnalyticsContext,
143
+ ): Promise<void> {
144
+ if (!this.isInitialized) {
145
+ this.handleError(new Error('Provider not initialized'), 'track', { event });
146
+ return;
147
+ }
148
+
149
+ try {
150
+ await this.doTrack(event, properties, context);
151
+ } catch (error) {
152
+ this.handleError(error, 'track', { event, properties });
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Identify a user.
158
+ *
159
+ * Validates that the provider is initialized, then calls the abstract
160
+ * `doIdentify()` method. Handles errors gracefully without throwing.
161
+ *
162
+ * @param {string} userId - User identifier
163
+ * @param {UserTraits} [traits] - User traits
164
+ * @param {AnalyticsContext} [context] - Analytics context
165
+ * @returns {Promise<void>} Promise that resolves when identification is complete
166
+ */
167
+ async identify(
168
+ userId: string,
169
+ traits: UserTraits = {},
170
+ context?: AnalyticsContext,
171
+ ): Promise<void> {
172
+ if (!this.isInitialized) {
173
+ this.handleError(new Error('Provider not initialized'), 'identify', { userId });
174
+ return;
175
+ }
176
+
177
+ try {
178
+ await this.doIdentify(userId, traits, context);
179
+ } catch (error) {
180
+ this.handleError(error, 'identify', { userId });
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Track a page view.
186
+ *
187
+ * Validates that the provider is initialized, then calls the abstract
188
+ * `doPage()` method. Handles errors gracefully.
189
+ *
190
+ * @param {string} [name] - Page name
191
+ * @param {PageProperties} [properties] - Page properties
192
+ * @param {AnalyticsContext} [context] - Analytics context
193
+ * @returns {Promise<void>} Promise that resolves when page tracking is complete
194
+ */
195
+ async page(
196
+ name?: string,
197
+ properties: PageProperties = {},
198
+ context?: AnalyticsContext,
199
+ ): Promise<void> {
200
+ if (!this.isInitialized) {
201
+ this.handleError(new Error('Provider not initialized'), 'page', { name });
202
+ return;
203
+ }
204
+
205
+ try {
206
+ await this.doPage(name, properties, context);
207
+ } catch (error) {
208
+ this.handleError(error, 'page', { name });
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Associate user with a group.
214
+ *
215
+ * Validates that the provider is initialized, then calls the abstract
216
+ * `doGroup()` method. Handles errors gracefully.
217
+ *
218
+ * @param {string} groupId - Group identifier
219
+ * @param {GroupTraits} [traits] - Group traits
220
+ * @param {AnalyticsContext} [context] - Analytics context
221
+ * @returns {Promise<void>} Promise that resolves when group association is complete
222
+ */
223
+ async group(
224
+ groupId: string,
225
+ traits: GroupTraits = {},
226
+ context?: AnalyticsContext,
227
+ ): Promise<void> {
228
+ if (!this.isInitialized) {
229
+ this.handleError(new Error('Provider not initialized'), 'group', { groupId });
230
+ return;
231
+ }
232
+
233
+ try {
234
+ await this.doGroup(groupId, traits, context);
235
+ } catch (error) {
236
+ this.handleError(error, 'group', { groupId });
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Alias one user ID to another.
242
+ *
243
+ * Validates that the provider is initialized, then calls the abstract
244
+ * `doAlias()` method. Handles errors gracefully.
245
+ *
246
+ * @param {string} userId - New user identifier
247
+ * @param {string} previousId - Previous user identifier
248
+ * @param {AnalyticsContext} [context] - Analytics context
249
+ * @returns {Promise<void>} Promise that resolves when aliasing is complete
250
+ */
251
+ async alias(userId: string, previousId: string, context?: AnalyticsContext): Promise<void> {
252
+ if (!this.isInitialized) {
253
+ this.handleError(new Error('Provider not initialized'), 'alias', { userId, previousId });
254
+ return;
255
+ }
256
+
257
+ try {
258
+ await this.doAlias(userId, previousId, context);
259
+ } catch (error) {
260
+ this.handleError(error, 'alias', { userId, previousId });
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Set global context for the provider
266
+ */
267
+ setContext?(context: AnalyticsContext): void;
268
+
269
+ /**
270
+ * Handle errors consistently across all methods.
271
+ *
272
+ * Calls the error handler callback if configured. Errors are swallowed
273
+ * in production to not disrupt app flow, but logged via callback.
274
+ *
275
+ * @param {unknown} error - The error that occurred
276
+ * @param {string} method - Method name where error occurred
277
+ * @param {Record<string, unknown>} [metadata] - Additional error metadata
278
+ *
279
+ * @internal
280
+ */
281
+ protected handleError(error: unknown, method: string, metadata?: Record<string, unknown>): void {
282
+ if (this.onError) {
283
+ this.onError(error, {
284
+ provider: this.name,
285
+ method,
286
+ ...metadata,
287
+ });
288
+ }
289
+ // In production, errors are swallowed to not disrupt app flow
290
+ // Logging happens via onError callback if provided
291
+ }
292
+
293
+ /**
294
+ * Check if provider is ready to accept tracking calls.
295
+ *
296
+ * @returns {boolean} `true` if provider is initialized and ready, `false` otherwise
297
+ */
298
+ isReady(): boolean {
299
+ return this.isInitialized;
300
+ }
301
+
302
+ // ============================================================================
303
+ // ABSTRACT METHODS - Must be implemented by subclasses
304
+ // ============================================================================
305
+
306
+ /**
307
+ * Perform provider-specific initialization.
308
+ *
309
+ * Called by `initialize()` after checking `isInitialized` flag.
310
+ * Subclasses must implement this to perform actual provider initialization.
311
+ *
312
+ * @param {ProviderConfig} [config] - Optional provider configuration
313
+ * @returns {Promise<void>} Promise that resolves when initialization is complete
314
+ *
315
+ * @protected
316
+ * @abstract
317
+ */
318
+ protected abstract doInitialize(config?: ProviderConfig): Promise<void>;
319
+
320
+ /**
321
+ * Perform provider-specific track call.
322
+ *
323
+ * Called by `track()` after validation. Subclasses must implement this
324
+ * to perform actual event tracking.
325
+ *
326
+ * @param {string} event - Event name
327
+ * @param {Properties} properties - Event properties
328
+ * @param {AnalyticsContext} [context] - Analytics context
329
+ * @returns {Promise<void>} Promise that resolves when tracking is complete
330
+ *
331
+ * @protected
332
+ * @abstract
333
+ */
334
+ protected abstract doTrack(
335
+ event: string,
336
+ properties: Properties,
337
+ context?: AnalyticsContext,
338
+ ): Promise<void>;
339
+
340
+ /**
341
+ * Perform provider-specific identify call.
342
+ *
343
+ * Called by `identify()` after validation. Subclasses must implement this
344
+ * to perform actual user identification.
345
+ *
346
+ * @param {string} userId - User identifier
347
+ * @param {UserTraits} traits - User traits
348
+ * @param {AnalyticsContext} [context] - Analytics context
349
+ * @returns {Promise<void>} Promise that resolves when identification is complete
350
+ *
351
+ * @protected
352
+ * @abstract
353
+ */
354
+ protected abstract doIdentify(
355
+ userId: string,
356
+ traits: UserTraits,
357
+ context?: AnalyticsContext,
358
+ ): Promise<void>;
359
+
360
+ /**
361
+ * Perform provider-specific page call.
362
+ *
363
+ * Called by `page()` after validation. Subclasses must implement this
364
+ * to perform actual page view tracking.
365
+ *
366
+ * @param {string | undefined} name - Page name
367
+ * @param {PageProperties} properties - Page properties
368
+ * @param {AnalyticsContext} [context] - Analytics context
369
+ * @returns {Promise<void>} Promise that resolves when page tracking is complete
370
+ *
371
+ * @protected
372
+ * @abstract
373
+ */
374
+ protected abstract doPage(
375
+ name: string | undefined,
376
+ properties: PageProperties,
377
+ context?: AnalyticsContext,
378
+ ): Promise<void>;
379
+
380
+ /**
381
+ * Perform provider-specific group call.
382
+ *
383
+ * Called by `group()` after validation. Subclasses must implement this
384
+ * to perform actual group association.
385
+ *
386
+ * @param {string} groupId - Group identifier
387
+ * @param {GroupTraits} traits - Group traits
388
+ * @param {AnalyticsContext} [context] - Analytics context
389
+ * @returns {Promise<void>} Promise that resolves when group association is complete
390
+ *
391
+ * @protected
392
+ * @abstract
393
+ */
394
+ protected abstract doGroup(
395
+ groupId: string,
396
+ traits: GroupTraits,
397
+ context?: AnalyticsContext,
398
+ ): Promise<void>;
399
+
400
+ /**
401
+ * Perform provider-specific alias call.
402
+ *
403
+ * Called by `alias()` after validation. Subclasses must implement this
404
+ * to perform actual user ID aliasing.
405
+ *
406
+ * @param {string} userId - New user identifier
407
+ * @param {string} previousId - Previous user identifier
408
+ * @param {AnalyticsContext} [context] - Analytics context
409
+ * @returns {Promise<void>} Promise that resolves when aliasing is complete
410
+ *
411
+ * @protected
412
+ * @abstract
413
+ */
414
+ protected abstract doAlias(
415
+ userId: string,
416
+ previousId: string,
417
+ context?: AnalyticsContext,
418
+ ): Promise<void>;
419
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Console provider for client/browser environments
3
+ *
4
+ * Provides console-based analytics logging for development and debugging.
5
+ * Useful for testing analytics events without sending data to external services.
6
+ *
7
+ * @module @od-oneapp/analytics/providers/console/client
8
+ */
9
+
10
+ export { ConsoleProvider } from '.';