@od-oneapp/analytics 2026.2.1701 → 2026.2.2301-canary
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.
- package/CHANGELOG.md +1 -1
- package/{ai-YMnynb-t.mjs → ai-Co8hBoEj.mjs} +2 -2
- package/{ai-YMnynb-t.mjs.map → ai-Co8hBoEj.mjs.map} +1 -1
- package/{client-D339NFJS.mjs → client-B8gfgflr.mjs} +1 -1
- package/{client-D339NFJS.mjs.map → client-B8gfgflr.mjs.map} +1 -1
- package/{client-CeOLjbac.mjs → client-C35AzV71.mjs} +21 -6
- package/client-C35AzV71.mjs.map +1 -0
- package/{client-CcFTauAh.mjs → client-DDehaDSz.mjs} +1 -1
- package/{client-CcFTauAh.mjs.map → client-DDehaDSz.mjs.map} +1 -1
- package/{client-CTzJVFU5.mjs → client-DK8twEdp.mjs} +2 -2
- package/{client-CTzJVFU5.mjs.map → client-DK8twEdp.mjs.map} +1 -1
- package/client-next.d.mts +7 -7
- package/client-next.d.mts.map +1 -1
- package/client-next.mjs +1615 -31
- package/client-next.mjs.map +1 -1
- package/client.d.mts +9 -9
- package/client.mjs +8 -116
- package/client.mjs.map +1 -1
- package/{config-P6P5adJg.mjs → config-6Mwe7b2O.mjs} +1 -1
- package/{config-P6P5adJg.mjs.map → config-6Mwe7b2O.mjs.map} +1 -1
- package/{config-DPS6bSYo.d.mts → config-Ciu7O6n1.d.mts} +2 -2
- package/{config-DPS6bSYo.d.mts.map → config-Ciu7O6n1.d.mts.map} +1 -1
- package/{console-8bND3mMU.mjs → console-BpU88FNF.mjs} +2 -2
- package/console-BpU88FNF.mjs.map +1 -0
- package/core-DBLE5iTF.mjs +95 -0
- package/core-DBLE5iTF.mjs.map +1 -0
- package/{ecommerce-Cgu4wlux.mjs → ecommerce-DGG1FbiH.mjs} +2 -2
- package/{ecommerce-Cgu4wlux.mjs.map → ecommerce-DGG1FbiH.mjs.map} +1 -1
- package/{emitters-DldkVSPp.d.mts → emitters-BDSsleo_.d.mts} +2 -2
- package/{emitters-DldkVSPp.d.mts.map → emitters-BDSsleo_.d.mts.map} +1 -1
- package/{emitters-6-nKo8i-.mjs → emitters-BvEelkxS.mjs} +1 -1
- package/{emitters-6-nKo8i-.mjs.map → emitters-BvEelkxS.mjs.map} +1 -1
- package/{index-jPzXRn52.d.mts → index-BWhDEs8u.d.mts} +3 -3
- package/{index-jPzXRn52.d.mts.map → index-BWhDEs8u.d.mts.map} +1 -1
- package/{index-BkIWe--N.d.mts → index-Cp-N57Zb.d.mts} +2 -2
- package/{index-BkIWe--N.d.mts.map → index-Cp-N57Zb.d.mts.map} +1 -1
- package/{index-BfNWgfa5.d.mts → index-DTvdqV7H.d.mts} +14 -2
- package/{index-BfNWgfa5.d.mts.map → index-DTvdqV7H.d.mts.map} +1 -1
- package/{manager-DvRRjza6.d.mts → manager-OJpSKwqb.d.mts} +3 -2
- package/manager-OJpSKwqb.d.mts.map +1 -0
- package/module-DVAU7zKb.mjs +5850 -0
- package/module-DVAU7zKb.mjs.map +1 -0
- package/package.json +42 -37
- package/{posthog-bootstrap-DWxFrxlt.d.mts → posthog-bootstrap-Bu1BfhVv.d.mts} +3 -3
- package/{posthog-bootstrap-DWxFrxlt.d.mts.map → posthog-bootstrap-Bu1BfhVv.d.mts.map} +1 -1
- package/{posthog-bootstrap-CYfIy_WS.mjs → posthog-bootstrap-DkPdn-hA.mjs} +81 -46
- package/posthog-bootstrap-DkPdn-hA.mjs.map +1 -0
- package/providers-http-client.d.mts +1 -1
- package/providers-http-client.d.mts.map +1 -1
- package/providers-http-client.mjs +35 -7
- package/providers-http-client.mjs.map +1 -1
- package/providers-http-server.d.mts +1 -1
- package/providers-http-server.d.mts.map +1 -1
- package/providers-http-server.mjs +19 -3
- package/providers-http-server.mjs.map +1 -1
- package/providers-http.d.mts +9 -1
- package/providers-http.d.mts.map +1 -1
- package/server-edge.d.mts +3 -3
- package/server-edge.mjs +4 -4
- package/server-edge.mjs.map +1 -1
- package/server-next.d.mts +9 -9
- package/server-next.mjs +5 -5
- package/server.d.mts +9 -9
- package/server.mjs +5 -5
- package/{service-Duqnlppl.mjs → service-NuHnv30x.mjs} +51 -119
- package/service-NuHnv30x.mjs.map +1 -0
- package/shared.d.mts +4 -4
- package/shared.mjs +3 -3
- package/{types-CBvxUEaF.d.mts → types-DEcTnnFe.d.mts} +1 -1
- package/{types-CBvxUEaF.d.mts.map → types-DEcTnnFe.d.mts.map} +1 -1
- package/{types-BxBnNQ0V.d.mts → types-cMMfHIpi.d.mts} +1 -1
- package/{types-BxBnNQ0V.d.mts.map → types-cMMfHIpi.d.mts.map} +1 -1
- package/types.d.mts +3 -3
- package/{vercel-types-lwakUfoI.d.mts → vercel-types-oM7Sn385.d.mts} +1 -1
- package/{vercel-types-lwakUfoI.d.mts.map → vercel-types-oM7Sn385.d.mts.map} +1 -1
- package/client-CeOLjbac.mjs.map +0 -1
- package/console-8bND3mMU.mjs.map +0 -1
- package/manager-DvRRjza6.d.mts.map +0 -1
- package/posthog-bootstrap-CYfIy_WS.mjs.map +0 -1
- package/service-Duqnlppl.mjs.map +0 -1
package/client.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":[],"sources":["../../../integrations/segment/src/analytics-provider/client.ts","../../../integrations/vercel/src/analytics-provider/client.ts","../src/client/manager.ts","../src/shared/utils/validation-client.ts"],"sourcesContent":["/**\n * @fileoverview Segment client-side (browser) analytics provider\n *\n * Provides client-side integration with Segment Analytics using @segment/analytics-next.\n * Implements the @od-oneapp/analytics AnalyticsProvider interface for use in the analytics\n * manager's provider registry.\n *\n * @module @integrations/segment/analytics-provider/client\n */\n\nimport type {\n AnalyticsContext,\n AnalyticsProvider,\n GroupTraits,\n PageProperties,\n Properties,\n ProviderConfig,\n SegmentConfig,\n UserTraits,\n} from './types';\n\n// Type for AnalyticsBrowser instance\ninterface AnalyticsBrowserInstance {\n track: (event: string, properties?: Properties) => Promise<unknown>;\n identify: (userId: string, traits?: UserTraits) => Promise<unknown>;\n page: (name?: string, properties?: PageProperties) => Promise<unknown>;\n group: (groupId: string, traits?: GroupTraits) => Promise<unknown>;\n alias: (userId: string, previousId: string) => Promise<unknown>;\n}\n\nexport class SegmentClientProvider implements AnalyticsProvider {\n readonly name = 'segment';\n private analytics: AnalyticsBrowserInstance | null = null;\n private config: SegmentConfig;\n private isInitialized = false;\n\n constructor(config: ProviderConfig) {\n if (!config.writeKey) {\n throw new Error('Segment writeKey is required');\n }\n\n this.config = {\n options: config.options as Record<string, unknown>,\n writeKey: config.writeKey,\n };\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n const { AnalyticsBrowser } = await import(\n /* webpackChunkName: \"segment-analytics-browser\" */\n '@segment/analytics-next'\n );\n\n this.analytics = AnalyticsBrowser.load({\n writeKey: this.config.writeKey,\n ...this.config.options,\n } as Parameters<typeof AnalyticsBrowser.load>[0]) as unknown as AnalyticsBrowserInstance;\n\n this.isInitialized = true;\n }\n\n async track(\n event: string,\n properties: Properties = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.analytics) return;\n await this.analytics.track(event, properties);\n }\n\n async identify(\n userId: string,\n traits: UserTraits = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.analytics) return;\n await this.analytics.identify(userId, traits);\n }\n\n async page(\n name?: string,\n properties: PageProperties = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.analytics) return;\n await this.analytics.page(name, properties);\n }\n\n async group(\n groupId: string,\n traits: GroupTraits = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.analytics) return;\n await this.analytics.group(groupId, traits);\n }\n\n async alias(userId: string, previousId: string, _context?: AnalyticsContext): Promise<void> {\n if (!this.analytics) return;\n await this.analytics.alias(userId, previousId);\n }\n}\n","/**\n * @fileoverview Vercel Analytics client-side (browser) provider\n *\n * Provides client-side integration with Vercel Analytics. Implements the\n * @od-oneapp/analytics AnalyticsProvider interface for use in the analytics\n * manager's provider registry.\n *\n * @module @integrations/vercel/analytics-provider/client\n */\n\nimport type {\n AnalyticsProvider,\n GroupTraits,\n PageProperties,\n Properties,\n ProviderConfig,\n UserTraits,\n VercelConfig,\n} from './types';\n\n/**\n * Converts internal Properties type to Vercel Analytics format.\n * Vercel Analytics requires Record<string, string | number | boolean>.\n */\nfunction normalizePropertiesToVercel(\n properties?: Properties,\n): Record<string, string | number | boolean> {\n if (!properties) return {};\n const normalized: Record<string, string | number | boolean> = {};\n for (const [key, value] of Object.entries(properties)) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n normalized[key] = value;\n }\n }\n return normalized;\n}\n\nexport class VercelClientProvider implements AnalyticsProvider {\n readonly name = 'vercel';\n private config: VercelConfig;\n private isInitialized = false;\n\n constructor(config: ProviderConfig) {\n this.config = {\n options: config.options,\n };\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n try {\n const { inject } = await import('@vercel/analytics');\n inject(this.config.options);\n this.isInitialized = true;\n } catch {\n throw new Error(\n 'Vercel Analytics not available. Install with: npm install @vercel/analytics',\n );\n }\n }\n\n async track(event: string, properties: Properties = {}): Promise<void> {\n if (!this.isInitialized) return;\n\n try {\n const { track } = await import('@vercel/analytics');\n track(event, normalizePropertiesToVercel(properties));\n } catch {\n // Silently fail to avoid disrupting app flow\n }\n }\n\n async identify(userId: string, traits: UserTraits = {}): Promise<void> {\n await this.track('User Identified', {\n userId,\n ...traits,\n });\n }\n\n async page(name?: string, properties: PageProperties = {}): Promise<void> {\n if (name || Object.keys(properties).length > 0) {\n await this.track('Page View', {\n page: name,\n ...properties,\n });\n }\n }\n\n async group(groupId: string, traits: GroupTraits = {}): Promise<void> {\n await this.track('Group Identified', {\n groupId,\n ...traits,\n });\n }\n\n async alias(userId: string, previousId: string): Promise<void> {\n await this.track('User Aliased', {\n previousId,\n userId,\n });\n }\n}\n","/**\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":"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"}
|
|
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 '@od-oneapp/integration-segment/analytics-provider/client';\nimport { VercelClientProvider } from '@od-oneapp/integration-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"}
|
|
@@ -284,4 +284,4 @@ function getAnalyticsConfig(options) {
|
|
|
284
284
|
|
|
285
285
|
//#endregion
|
|
286
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-
|
|
287
|
+
//# sourceMappingURL=config-6Mwe7b2O.mjs.map
|
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"config-6Mwe7b2O.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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ProviderConfig, r as AnalyticsManager, t as AnalyticsConfig, w as EmitterPayload } from "./types-
|
|
1
|
+
import { c as ProviderConfig, r as AnalyticsManager, t as AnalyticsConfig, w as EmitterPayload } from "./types-cMMfHIpi.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/shared/utils/emitter-adapter.d.ts
|
|
4
4
|
declare function processEmitterPayload(analytics: AnalyticsManager, payload: EmitterPayload): Promise<void>;
|
|
@@ -31,4 +31,4 @@ interface AnalyticsConfigOptions {
|
|
|
31
31
|
declare function getAnalyticsConfig(options?: AnalyticsConfigOptions): AnalyticsConfig;
|
|
32
32
|
//#endregion
|
|
33
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-
|
|
34
|
+
//# sourceMappingURL=config-Ciu7O6n1.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-
|
|
1
|
+
{"version":3,"file":"config-Ciu7O6n1.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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { i as logWarn, t as logDebug } from "./core-DBLE5iTF.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/providers/console/index.ts
|
|
5
5
|
/**
|
|
@@ -125,4 +125,4 @@ var ConsoleProvider = class {
|
|
|
125
125
|
|
|
126
126
|
//#endregion
|
|
127
127
|
export { console_exports as n, ConsoleProvider as t };
|
|
128
|
-
//# sourceMappingURL=console-
|
|
128
|
+
//# sourceMappingURL=console-BpU88FNF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-BpU88FNF.mjs","names":[],"sources":["../src/providers/console/index.ts"],"sourcesContent":["/**\n * @fileoverview Console provider - works in both client and server environments\n *\n * Provides console-based analytics logging for development and debugging.\n * Useful for testing analytics events without sending data to external services.\n *\n * @remarks\n * This provider:\n * - Logs analytics events to console\n * - Works in both browser and Node.js environments\n * - Useful for development and debugging\n * - Integrates with observability package for structured logging\n *\n * @module @od-oneapp/analytics/providers/console\n */\n\nimport { logDebug, logWarn } from '@od-oneapp/shared/logger';\n\nimport type { ConsoleConfig } from './types';\nimport type { AnalyticsProvider, ProviderConfig } from '../../shared/types/types';\n\nexport class ConsoleProvider implements AnalyticsProvider {\n readonly name = 'console';\n private config: ConsoleConfig;\n private isInitialized = false;\n\n constructor(config: ProviderConfig) {\n const options = config.options as ConsoleConfig | undefined;\n this.config = {\n prefix: '[Analytics]',\n logLevel: 'info',\n colorize: false,\n ...options,\n };\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n // Reduce noisy logs: only log in development or explicit debug\n const isDev = process.env.NODE_ENV !== 'production';\n const isDebug = process.env.NEXT_PUBLIC_OBSERVABILITY_DEBUG === 'true';\n if (isDev || isDebug) {\n this.log('Console Analytics Provider initialized', {\n config: this.config,\n });\n }\n\n this.isInitialized = true;\n }\n\n async track(event: string, properties: any = {}, _context?: any): Promise<void> {\n if (!this.isInitialized) {\n logWarn('Console provider not initialized', {\n provider: 'console',\n operation: 'track',\n event,\n });\n return;\n }\n\n this.log('TRACK', {\n event,\n properties,\n timestamp: new Date().toISOString(),\n });\n }\n\n async identify(userId: string, traits: any = {}, _context?: any): Promise<void> {\n if (!this.isInitialized) {\n logWarn('Console provider not initialized', {\n provider: 'console',\n operation: 'identify',\n userId,\n });\n return;\n }\n\n this.log('IDENTIFY', {\n timestamp: new Date().toISOString(),\n traits,\n userId,\n });\n }\n\n async page(name?: string, properties: any = {}, _context?: any): Promise<void> {\n if (!this.isInitialized) {\n logWarn('Console provider not initialized', {\n provider: 'console',\n operation: 'page',\n metadata: { name },\n });\n return;\n }\n\n this.log('PAGE', {\n name,\n properties,\n timestamp: new Date().toISOString(),\n });\n }\n\n async group(groupId: string, traits: any = {}, _context?: any): Promise<void> {\n if (!this.isInitialized) {\n logWarn('Console provider not initialized', {\n provider: 'console',\n operation: 'group',\n metadata: { groupId },\n });\n return;\n }\n\n this.log('GROUP', {\n groupId,\n timestamp: new Date().toISOString(),\n traits,\n });\n }\n\n async alias(userId: string, previousId: string, _context?: any): Promise<void> {\n if (!this.isInitialized) {\n logWarn('Console provider not initialized', {\n provider: 'console',\n operation: 'alias',\n userId,\n metadata: { previousId },\n });\n return;\n }\n\n this.log('ALIAS', {\n previousId,\n timestamp: new Date().toISOString(),\n userId,\n });\n }\n\n private log(action: string, data: any): void {\n const { logLevel, prefix } = this.config;\n\n if (logLevel === 'error') return; // Don't log analytics in error-only mode\n\n const message = `${prefix} ${action}`;\n\n // Use analytics logger instead of console directly\n logDebug(message, {\n provider: 'console',\n operation: action.toLowerCase(),\n metadata: data,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,IAAa,kBAAb,MAA0D;CACxD,AAAS,OAAO;CAChB,AAAQ;CACR,AAAQ,gBAAgB;CAExB,YAAY,QAAwB;AAElC,OAAK,SAAS;GACZ,QAAQ;GACR,UAAU;GACV,UAAU;GACV,GALc,OAAO;GAMtB;;CAGH,MAAM,aAA4B;AAChC,MAAI,KAAK,cAAe;AAIR,UAAQ,IAAI;AAE1B,OAAK,IAAI,0CAA0C,EACjD,QAAQ,KAAK,QACd,CAAC;AAGJ,OAAK,gBAAgB;;CAGvB,MAAM,MAAM,OAAe,aAAkB,EAAE,EAAE,UAA+B;AAC9E,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,oCAAoC;IAC1C,UAAU;IACV,WAAW;IACX;IACD,CAAC;AACF;;AAGF,OAAK,IAAI,SAAS;GAChB;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC,CAAC;;CAGJ,MAAM,SAAS,QAAgB,SAAc,EAAE,EAAE,UAA+B;AAC9E,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,oCAAoC;IAC1C,UAAU;IACV,WAAW;IACX;IACD,CAAC;AACF;;AAGF,OAAK,IAAI,YAAY;GACnB,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;GACA;GACD,CAAC;;CAGJ,MAAM,KAAK,MAAe,aAAkB,EAAE,EAAE,UAA+B;AAC7E,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,oCAAoC;IAC1C,UAAU;IACV,WAAW;IACX,UAAU,EAAE,MAAM;IACnB,CAAC;AACF;;AAGF,OAAK,IAAI,QAAQ;GACf;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC,CAAC;;CAGJ,MAAM,MAAM,SAAiB,SAAc,EAAE,EAAE,UAA+B;AAC5E,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,oCAAoC;IAC1C,UAAU;IACV,WAAW;IACX,UAAU,EAAE,SAAS;IACtB,CAAC;AACF;;AAGF,OAAK,IAAI,SAAS;GAChB;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;GACD,CAAC;;CAGJ,MAAM,MAAM,QAAgB,YAAoB,UAA+B;AAC7E,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,oCAAoC;IAC1C,UAAU;IACV,WAAW;IACX;IACA,UAAU,EAAE,YAAY;IACzB,CAAC;AACF;;AAGF,OAAK,IAAI,SAAS;GAChB;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;GACD,CAAC;;CAGJ,AAAQ,IAAI,QAAgB,MAAiB;EAC3C,MAAM,EAAE,UAAU,WAAW,KAAK;AAElC,MAAI,aAAa,QAAS;AAK1B,WAHgB,GAAG,OAAO,GAAG,UAGX;GAChB,UAAU;GACV,WAAW,OAAO,aAAa;GAC/B,UAAU;GACX,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//#region ../shared/src/logger/core.ts
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Canonical logger for the OneApp platform.
|
|
4
|
+
*
|
|
5
|
+
* This module provides isomorphic logging functions that work in any environment
|
|
6
|
+
* (Browser, Node.js, Edge). Logs directly to console with runtime information.
|
|
7
|
+
*
|
|
8
|
+
* Preferred usage is to import from '@od-oneapp/shared/logger'.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Get runtime environment information.
|
|
12
|
+
*
|
|
13
|
+
* Detects the current runtime environment (browser, Node.js, edge, Bun) and returns
|
|
14
|
+
* detailed information about the environment type, version, and capabilities.
|
|
15
|
+
*
|
|
16
|
+
* @returns Runtime information object with type, version, and environment-specific details
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const runtime = getRuntimeInfo();
|
|
21
|
+
* // Returns: { type: 'node', version: '22.0.0', major: 22, minor: 0, isNode22Plus: true, isNextJs: true }
|
|
22
|
+
* // or: { type: 'browser', isNextJs: true }
|
|
23
|
+
* // or: { type: 'edge', variant: 'vercel' }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
const getRuntimeInfo = () => {
|
|
27
|
+
if (typeof globalThis !== "undefined" && globalThis.EdgeRuntime) return {
|
|
28
|
+
type: "edge",
|
|
29
|
+
variant: "vercel"
|
|
30
|
+
};
|
|
31
|
+
if (typeof globalThis !== "undefined" && globalThis.caches && typeof globalThis.caches !== "undefined") return {
|
|
32
|
+
type: "edge",
|
|
33
|
+
variant: "cloudflare"
|
|
34
|
+
};
|
|
35
|
+
if (typeof globalThis !== "undefined" && "window" in globalThis && typeof globalThis.window !== "undefined" && typeof globalThis.window.document !== "undefined" && typeof globalThis.window.navigator !== "undefined") return {
|
|
36
|
+
type: "browser",
|
|
37
|
+
isNextJs: Boolean(globalThis.window.__NEXT_DATA__)
|
|
38
|
+
};
|
|
39
|
+
if (typeof process !== "undefined" && process.versions?.bun) return {
|
|
40
|
+
type: "bun",
|
|
41
|
+
version: process.versions.bun
|
|
42
|
+
};
|
|
43
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
44
|
+
const nodeVersion = parseInt(process.versions.node.split(".")[0] ?? "0");
|
|
45
|
+
const nodeVersionMinor = parseInt(process.versions.node.split(".")[1] ?? "0");
|
|
46
|
+
if (nodeVersion < 22) console.warn(`[Observability] Node ${process.versions.node} detected. Node 22+ is required for optimal performance and latest features.`);
|
|
47
|
+
return {
|
|
48
|
+
type: "node",
|
|
49
|
+
version: process.versions.node,
|
|
50
|
+
major: nodeVersion,
|
|
51
|
+
minor: nodeVersionMinor,
|
|
52
|
+
isNode22Plus: nodeVersion >= 22,
|
|
53
|
+
isNextJs: Boolean(process.env.NEXT_RUNTIME) || Boolean(process.env.__NEXT_RUNTIME) || Boolean(process.env.NEXT_PUBLIC_VERCEL_ENV)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return { type: "unknown" };
|
|
57
|
+
};
|
|
58
|
+
const runtimeInfo = getRuntimeInfo();
|
|
59
|
+
/**
|
|
60
|
+
* Create a generic log function factory.
|
|
61
|
+
*
|
|
62
|
+
* Factory function that creates log functions for different levels (debug, info, warn, error).
|
|
63
|
+
* Logs directly to console with runtime information.
|
|
64
|
+
*/
|
|
65
|
+
const createLogFunction = (level) => {
|
|
66
|
+
return (message, context) => {
|
|
67
|
+
if (message instanceof Error) if (context) console[level](`[${runtimeInfo.type}]`, message, context);
|
|
68
|
+
else console[level](`[${runtimeInfo.type}]`, message);
|
|
69
|
+
else {
|
|
70
|
+
const contextStr = context ? JSON.stringify(context) : "";
|
|
71
|
+
const logMessage = contextStr ? `${message} ${contextStr}` : message;
|
|
72
|
+
console[level](`[${runtimeInfo.type}]`, logMessage);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Log a debug message (isomorphic - works in any environment).
|
|
78
|
+
*/
|
|
79
|
+
const logDebug = createLogFunction("debug");
|
|
80
|
+
/**
|
|
81
|
+
* Log an info message (isomorphic - works in any environment).
|
|
82
|
+
*/
|
|
83
|
+
const logInfo = createLogFunction("info");
|
|
84
|
+
/**
|
|
85
|
+
* Log a warning message (isomorphic - works in any environment).
|
|
86
|
+
*/
|
|
87
|
+
const logWarn = createLogFunction("warn");
|
|
88
|
+
/**
|
|
89
|
+
* Log an error message (isomorphic - works in any environment).
|
|
90
|
+
*/
|
|
91
|
+
const logError = createLogFunction("error");
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
export { logWarn as i, logError as n, logInfo as r, logDebug as t };
|
|
95
|
+
//# sourceMappingURL=core-DBLE5iTF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-DBLE5iTF.mjs","names":[],"sources":["../../shared/src/logger/core.ts"],"sourcesContent":["/**\n * @fileoverview Canonical logger for the OneApp platform.\n *\n * This module provides isomorphic logging functions that work in any environment\n * (Browser, Node.js, Edge). Logs directly to console with runtime information.\n *\n * Preferred usage is to import from '@od-oneapp/shared/logger'.\n */\n\n/**\n * Get runtime environment information.\n *\n * Detects the current runtime environment (browser, Node.js, edge, Bun) and returns\n * detailed information about the environment type, version, and capabilities.\n *\n * @returns Runtime information object with type, version, and environment-specific details\n *\n * @example\n * ```typescript\n * const runtime = getRuntimeInfo();\n * // Returns: { type: 'node', version: '22.0.0', major: 22, minor: 0, isNode22Plus: true, isNextJs: true }\n * // or: { type: 'browser', isNextJs: true }\n * // or: { type: 'edge', variant: 'vercel' }\n * ```\n */\nexport const getRuntimeInfo = () => {\n // 1. Edge runtime detection (Vercel Edge, Cloudflare Workers)\n // Check these before browser because they might have a partial window mock\n if (typeof globalThis !== 'undefined' && (globalThis as any).EdgeRuntime) {\n return { type: 'edge', variant: 'vercel' };\n }\n if (\n typeof globalThis !== 'undefined' &&\n (globalThis as any).caches &&\n typeof (globalThis as any).caches !== 'undefined'\n ) {\n return { type: 'edge', variant: 'cloudflare' };\n }\n\n // 2. Browser detection\n if (\n typeof globalThis !== 'undefined' &&\n 'window' in globalThis &&\n typeof (globalThis as any).window !== 'undefined' &&\n typeof (globalThis as any).window.document !== 'undefined' &&\n typeof (globalThis as any).window.navigator !== 'undefined'\n ) {\n return { type: 'browser', isNextJs: Boolean((globalThis as any).window.__NEXT_DATA__) };\n }\n\n // 3. Bun detection\n if (typeof process !== 'undefined' && (process as any).versions?.bun) {\n return { type: 'bun', version: (process as any).versions.bun };\n }\n\n // 4. Node.js detection with version check\n if (typeof process !== 'undefined' && process.versions?.node) {\n const nodeVersion = parseInt(process.versions.node.split('.')[0] ?? '0');\n const nodeVersionMinor = parseInt(process.versions.node.split('.')[1] ?? '0');\n\n if (nodeVersion < 22) {\n // Note: Using console.warn here as observability system may not be initialized yet\n // eslint-disable-next-line no-console\n console.warn(\n `[Observability] Node ${process.versions.node} detected. Node 22+ is required for optimal performance and latest features.`,\n );\n }\n\n return {\n type: 'node',\n version: process.versions.node,\n major: nodeVersion,\n minor: nodeVersionMinor,\n isNode22Plus: nodeVersion >= 22,\n isNextJs:\n Boolean(process.env.NEXT_RUNTIME) ||\n Boolean(process.env.__NEXT_RUNTIME) ||\n Boolean(process.env.NEXT_PUBLIC_VERCEL_ENV),\n };\n }\n\n // Fallback\n return { type: 'unknown' };\n};\n\n// Cache the runtime info\nconst runtimeInfo = getRuntimeInfo();\n\n/**\n * Get cached runtime environment information.\n *\n * Returns the runtime information that was detected at module load time.\n * This is cached to avoid repeated detection checks.\n *\n * @returns Cached runtime information object\n */\nexport const getRuntimeEnvironment = () => runtimeInfo;\n\n/**\n * Detect if code is running in a browser environment\n * Extracted to shared utility to avoid duplication\n * @returns true if running in browser, false otherwise\n */\nexport function isBrowser(): boolean {\n return (\n typeof globalThis !== 'undefined' &&\n 'window' in globalThis &&\n typeof (globalThis as any).window !== 'undefined' &&\n typeof (globalThis as any).window.document !== 'undefined' &&\n typeof (globalThis as any).window.navigator !== 'undefined'\n );\n}\n\n/**\n * Determine if console logging should be enabled based on environment\n * Centralized logic to avoid duplication across entry points\n * @param envNodeEnv - The NEXT_PUBLIC_NODE_ENV value\n * @param consoleEnabled - The NEXT_PUBLIC_OBSERVABILITY_CONSOLE_ENABLED value (explicit control)\n * @param debugEnabled - The NEXT_PUBLIC_OBSERVABILITY_DEBUG value\n * @returns boolean indicating if console should be enabled\n */\nexport function shouldEnableConsole(\n envNodeEnv?: string,\n consoleEnabled?: boolean,\n debugEnabled?: boolean,\n): boolean {\n const isDevelopment = envNodeEnv === 'development' || process.env.NODE_ENV === 'development';\n\n // Priority: explicit control > development mode > debug mode\n if (consoleEnabled !== undefined) {\n return consoleEnabled;\n }\n if (isDevelopment) {\n return true;\n }\n return debugEnabled ?? false;\n}\n\n/**\n * Create a generic log function factory.\n *\n * Factory function that creates log functions for different levels (debug, info, warn, error).\n * Logs directly to console with runtime information.\n */\nconst createLogFunction = (level: 'debug' | 'info' | 'warn' | 'error') => {\n return (message: string | Error, context?: any): void => {\n if (message instanceof Error) {\n // For Error objects, log the error itself (console.error will show stack trace)\n // and include context as additional arguments\n if (context) {\n // eslint-disable-next-line no-console\n (console[level] as any)(`[${runtimeInfo.type}]`, message, context);\n } else {\n // eslint-disable-next-line no-console\n (console[level] as any)(`[${runtimeInfo.type}]`, message);\n }\n } else {\n // For string messages, format with context\n const contextStr = context ? JSON.stringify(context) : '';\n const logMessage = contextStr ? `${message} ${contextStr}` : message;\n // eslint-disable-next-line no-console\n (console[level] as any)(`[${runtimeInfo.type}]`, logMessage);\n }\n };\n};\n\n/**\n * Log a debug message (isomorphic - works in any environment).\n */\nexport const logDebug = createLogFunction('debug');\n\n/**\n * Log an info message (isomorphic - works in any environment).\n */\nexport const logInfo = createLogFunction('info');\n\n/**\n * Log a warning message (isomorphic - works in any environment).\n */\nexport const logWarn = createLogFunction('warn');\n\n/**\n * Log an error message (isomorphic - works in any environment).\n */\nexport const logError = createLogFunction('error');\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,uBAAuB;AAGlC,KAAI,OAAO,eAAe,eAAgB,WAAmB,YAC3D,QAAO;EAAE,MAAM;EAAQ,SAAS;EAAU;AAE5C,KACE,OAAO,eAAe,eACrB,WAAmB,UACpB,OAAQ,WAAmB,WAAW,YAEtC,QAAO;EAAE,MAAM;EAAQ,SAAS;EAAc;AAIhD,KACE,OAAO,eAAe,eACtB,YAAY,cACZ,OAAQ,WAAmB,WAAW,eACtC,OAAQ,WAAmB,OAAO,aAAa,eAC/C,OAAQ,WAAmB,OAAO,cAAc,YAEhD,QAAO;EAAE,MAAM;EAAW,UAAU,QAAS,WAAmB,OAAO,cAAc;EAAE;AAIzF,KAAI,OAAO,YAAY,eAAgB,QAAgB,UAAU,IAC/D,QAAO;EAAE,MAAM;EAAO,SAAU,QAAgB,SAAS;EAAK;AAIhE,KAAI,OAAO,YAAY,eAAe,QAAQ,UAAU,MAAM;EAC5D,MAAM,cAAc,SAAS,QAAQ,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI;EACxE,MAAM,mBAAmB,SAAS,QAAQ,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI;AAE7E,MAAI,cAAc,GAGhB,SAAQ,KACN,wBAAwB,QAAQ,SAAS,KAAK,8EAC/C;AAGH,SAAO;GACL,MAAM;GACN,SAAS,QAAQ,SAAS;GAC1B,OAAO;GACP,OAAO;GACP,cAAc,eAAe;GAC7B,UACE,QAAQ,QAAQ,IAAI,aAAa,IACjC,QAAQ,QAAQ,IAAI,eAAe,IACnC,QAAQ,QAAQ,IAAI,uBAAuB;GAC9C;;AAIH,QAAO,EAAE,MAAM,WAAW;;AAI5B,MAAM,cAAc,gBAAgB;;;;;;;AA0DpC,MAAM,qBAAqB,UAA+C;AACxE,SAAQ,SAAyB,YAAwB;AACvD,MAAI,mBAAmB,MAGrB,KAAI,QAEF,CAAC,QAAQ,OAAe,IAAI,YAAY,KAAK,IAAI,SAAS,QAAQ;MAGlE,CAAC,QAAQ,OAAe,IAAI,YAAY,KAAK,IAAI,QAAQ;OAEtD;GAEL,MAAM,aAAa,UAAU,KAAK,UAAU,QAAQ,GAAG;GACvD,MAAM,aAAa,aAAa,GAAG,QAAQ,GAAG,eAAe;AAE7D,GAAC,QAAQ,OAAe,IAAI,YAAY,KAAK,IAAI,WAAW;;;;;;;AAQlE,MAAa,WAAW,kBAAkB,QAAQ;;;;AAKlD,MAAa,UAAU,kBAAkB,OAAO;;;;AAKhD,MAAa,UAAU,kBAAkB,OAAO;;;;AAKhD,MAAa,WAAW,kBAAkB,QAAQ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
|
|
2
|
-
import { o as track } from "./emitters-
|
|
2
|
+
import { o as track } from "./emitters-BvEelkxS.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/shared/emitters/ecommerce/types.ts
|
|
5
5
|
const ECOMMERCE_EVENTS = {
|
|
@@ -990,4 +990,4 @@ var ecommerce_exports = /* @__PURE__ */ __exportAll({
|
|
|
990
990
|
|
|
991
991
|
//#endregion
|
|
992
992
|
export { ecommerce_exports as t };
|
|
993
|
-
//# sourceMappingURL=ecommerce-
|
|
993
|
+
//# sourceMappingURL=ecommerce-DGG1FbiH.mjs.map
|