@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers-http-server.mjs","names":[],"sources":["../src/providers/http/server.ts"],"sourcesContent":["/**\n * @fileoverview HTTP provider for server/Node.js environments\n *\n * Provides HTTP-based analytics event sending for server-side applications.\n * Sends events to a remote ingestion endpoint (e.g., oneapp-api/ingest).\n *\n * Features:\n * - Event batching for efficiency\n * - Automatic flush on interval or batch size\n * - Retry with exponential backoff\n * - Graceful shutdown with final flush\n *\n * @module @od-oneapp/analytics/providers/http/server\n */\n\nimport { logDebug, logError, logWarn } from '@repo/shared/logs';\n\nimport type { HttpProviderConfig, IngestionResponse, QueuedEvent } from './types';\nimport type {\n AnalyticsContext,\n AnalyticsProvider,\n GroupTraits,\n PageProperties,\n Properties,\n ProviderConfig,\n UserTraits,\n} from '../../shared/types/types';\n\n/** Default configuration values */\nconst DEFAULTS = {\n batchSize: 10,\n flushInterval: 5000,\n timeout: 10000,\n retries: 3,\n} as const;\n\n/** Base delay for exponential backoff in ms */\nconst BACKOFF_BASE_MS = 1000;\n\n/**\n * HTTP Analytics Provider for server environments.\n *\n * Sends analytics events to a remote endpoint via HTTP POST requests.\n * Events are batched and flushed periodically for efficiency.\n *\n * @example\n * ```typescript\n * const provider = new HttpServerProvider({\n * options: {\n * endpoint: 'https://api.oneapp.dev/v1/ingest',\n * apiKey: process.env.ANALYTICS_API_KEY,\n * },\n * });\n * await provider.initialize();\n * await provider.track('Button Clicked', { button: 'signup' });\n * await provider.flush(); // Send queued events\n * ```\n */\nexport class HttpServerProvider implements AnalyticsProvider {\n readonly name = 'http';\n\n private config: Required<\n Pick<HttpProviderConfig, 'batchSize' | 'flushInterval' | 'timeout' | 'retries'>\n > &\n HttpProviderConfig;\n private isInitialized = false;\n private queue: QueuedEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private userId?: string;\n private anonymousId: string;\n private isFlushing = false;\n\n constructor(providerConfig: ProviderConfig) {\n const options = (providerConfig.options ?? {}) as unknown as HttpProviderConfig;\n\n if (!options.endpoint) {\n throw new Error('HttpProvider requires an endpoint URL');\n }\n\n this.config = {\n ...options,\n batchSize: options.batchSize ?? DEFAULTS.batchSize,\n flushInterval: options.flushInterval ?? DEFAULTS.flushInterval,\n timeout: options.timeout ?? DEFAULTS.timeout,\n retries: options.retries ?? DEFAULTS.retries,\n };\n\n this.userId = options.userId;\n this.anonymousId = options.anonymousId ?? this.generateAnonymousId();\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n // Start auto-flush timer if interval > 0\n if (this.config.flushInterval > 0) {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n\n // Unref the timer so it doesn't prevent Node.js from exiting\n if (typeof this.flushTimer.unref === 'function') {\n this.flushTimer.unref();\n }\n }\n\n if (this.config.debug) {\n logDebug('HTTP Analytics Provider initialized', {\n provider: 'http',\n endpoint: this.config.endpoint,\n batchSize: this.config.batchSize,\n flushInterval: this.config.flushInterval,\n });\n }\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.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'track', event });\n return;\n }\n\n this.enqueue({\n type: 'track',\n event,\n properties,\n timestamp: new Date().toISOString(),\n userId: this.userId,\n anonymousId: this.anonymousId,\n });\n }\n\n async identify(\n userId: string,\n traits: UserTraits = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'identify', userId });\n return;\n }\n\n // Update stored user ID\n this.userId = userId;\n\n this.enqueue({\n type: 'identify',\n userId,\n traits,\n timestamp: new Date().toISOString(),\n anonymousId: this.anonymousId,\n });\n }\n\n async page(\n name?: string,\n properties: PageProperties = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'page', name });\n return;\n }\n\n this.enqueue({\n type: 'page',\n name,\n properties,\n timestamp: new Date().toISOString(),\n userId: this.userId,\n anonymousId: this.anonymousId,\n });\n }\n\n async group(\n groupId: string,\n traits: GroupTraits = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'group', groupId });\n return;\n }\n\n this.enqueue({\n type: 'group',\n groupId,\n traits,\n timestamp: new Date().toISOString(),\n userId: this.userId,\n anonymousId: this.anonymousId,\n });\n }\n\n async alias(userId: string, previousId: string, _context?: AnalyticsContext): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', {\n provider: 'http',\n operation: 'alias',\n userId,\n previousId,\n });\n return;\n }\n\n this.enqueue({\n type: 'alias',\n userId,\n previousId,\n timestamp: new Date().toISOString(),\n anonymousId: this.anonymousId,\n });\n }\n\n /**\n * Flush all queued events to the remote endpoint.\n * Called automatically on interval or when batch size is reached.\n */\n async flush(): Promise<void> {\n if (this.queue.length === 0 || this.isFlushing) return;\n\n this.isFlushing = true;\n\n // Take all events from queue\n const events = [...this.queue];\n this.queue = [];\n\n try {\n await this.sendBatch(events);\n } catch (error) {\n // Re-queue events on failure (they'll be retried on next flush)\n this.queue.unshift(...events);\n logError('Failed to flush events, re-queued for retry', {\n provider: 'http',\n eventCount: events.length,\n error: error instanceof Error ? error.message : String(error),\n });\n } finally {\n this.isFlushing = false;\n }\n }\n\n /**\n * Shutdown the provider gracefully.\n * Flushes remaining events and stops the flush timer.\n */\n async shutdown(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n\n // Final flush\n await this.flush();\n this.isInitialized = false;\n }\n\n /**\n * Get the current queue length (for testing/monitoring).\n */\n getQueueLength(): number {\n return this.queue.length;\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n private enqueue(event: QueuedEvent): void {\n this.queue.push(event);\n\n if (this.config.debug) {\n logDebug('Event queued', {\n provider: 'http',\n type: event.type,\n queueLength: this.queue.length,\n });\n }\n\n // Flush if batch size reached\n if (this.queue.length >= this.config.batchSize) {\n void this.flush();\n }\n }\n\n private async sendBatch(events: QueuedEvent[]): Promise<void> {\n const payload = { batch: events };\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.retries; attempt++) {\n try {\n const response = await this.sendRequest(payload);\n\n if (response.success) {\n if (this.config.debug) {\n logDebug('Batch sent successfully', {\n provider: 'http',\n accepted: response.accepted,\n rejected: response.rejected,\n });\n }\n return;\n }\n\n // Request succeeded but ingestion failed\n logWarn('Batch partially rejected', {\n provider: 'http',\n accepted: response.accepted,\n rejected: response.rejected,\n error: response.error,\n });\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt < this.config.retries) {\n // Exponential backoff: 1s, 2s, 4s, ...\n const delay = BACKOFF_BASE_MS * Math.pow(2, attempt);\n\n if (this.config.debug) {\n logDebug('Retrying batch send', {\n provider: 'http',\n attempt: attempt + 1,\n maxRetries: this.config.retries,\n delayMs: delay,\n });\n }\n\n await this.sleep(delay);\n }\n }\n }\n\n // All retries exhausted\n throw lastError ?? new Error('Failed to send batch after retries');\n }\n\n private async sendRequest(payload: { batch: QueuedEvent[] }): Promise<IngestionResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.config.headers,\n };\n\n if (this.config.apiKey) {\n headers['X-API-Key'] = this.config.apiKey;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(this.config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n throw new Error(`Rate limited. Retry after ${retryAfter ?? 'unknown'} seconds`);\n }\n\n const errorBody = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorBody}`);\n }\n\n return (await response.json()) as IngestionResponse;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private generateAnonymousId(): string {\n // Use crypto.randomUUID if available (Node 19+), otherwise fallback\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for older Node versions\n return `anon_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"providers-http-server.mjs","names":[],"sources":["../src/providers/http/server.ts"],"sourcesContent":["/**\n * @fileoverview HTTP provider for server/Node.js environments\n *\n * Provides HTTP-based analytics event sending for server-side applications.\n * Sends events to a remote ingestion endpoint (e.g., oneapp-api/ingest).\n *\n * Features:\n * - Event batching for efficiency\n * - Automatic flush on interval or batch size\n * - Retry with exponential backoff\n * - Graceful shutdown with final flush\n *\n * @module @od-oneapp/analytics/providers/http/server\n */\n\nimport { logDebug, logError, logWarn } from '@od-oneapp/shared/logs';\n\nimport type { HttpProviderConfig, IngestionResponse, QueuedEvent } from './types';\nimport type {\n AnalyticsContext,\n AnalyticsProvider,\n GroupTraits,\n PageProperties,\n Properties,\n ProviderConfig,\n UserTraits,\n} from '../../shared/types/types';\n\n/** Default configuration values */\nconst DEFAULTS = {\n batchSize: 10,\n flushInterval: 5000,\n timeout: 10000,\n retries: 3,\n maxQueueSize: 10000,\n} as const;\n\n/** Base delay for exponential backoff in ms */\nconst BACKOFF_BASE_MS = 1000;\n\n/**\n * HTTP Analytics Provider for server environments.\n *\n * Sends analytics events to a remote endpoint via HTTP POST requests.\n * Events are batched and flushed periodically for efficiency.\n *\n * @example\n * ```typescript\n * const provider = new HttpServerProvider({\n * options: {\n * endpoint: 'https://api.oneapp.dev/v1/ingest',\n * apiKey: process.env.ANALYTICS_API_KEY,\n * },\n * });\n * await provider.initialize();\n * await provider.track('Button Clicked', { button: 'signup' });\n * await provider.flush(); // Send queued events\n * ```\n */\nexport class HttpServerProvider implements AnalyticsProvider {\n readonly name = 'http';\n\n private config: Required<\n Pick<\n HttpProviderConfig,\n 'batchSize' | 'flushInterval' | 'timeout' | 'retries' | 'maxQueueSize'\n >\n > &\n HttpProviderConfig;\n private isInitialized = false;\n private queue: QueuedEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private userId?: string;\n private anonymousId: string;\n private isFlushing = false;\n\n constructor(providerConfig: ProviderConfig) {\n const options = (providerConfig.options ?? {}) as unknown as HttpProviderConfig;\n\n if (!options.endpoint) {\n throw new Error('HttpProvider requires an endpoint URL');\n }\n\n try {\n const parsed = new URL(options.endpoint);\n if (parsed.protocol !== 'https:') {\n throw new Error('HttpProvider endpoint must use HTTPS');\n }\n } catch {\n throw new Error('HttpProvider endpoint must be a valid HTTPS URL');\n }\n\n const resolvedQueueSize = options.maxQueueSize ?? DEFAULTS.maxQueueSize;\n if (!Number.isInteger(resolvedQueueSize) || resolvedQueueSize <= 0) {\n throw new Error('HttpProvider maxQueueSize must be a positive integer');\n }\n\n this.config = {\n ...options,\n batchSize: options.batchSize ?? DEFAULTS.batchSize,\n flushInterval: options.flushInterval ?? DEFAULTS.flushInterval,\n timeout: options.timeout ?? DEFAULTS.timeout,\n retries: options.retries ?? DEFAULTS.retries,\n maxQueueSize: resolvedQueueSize,\n };\n\n this.userId = options.userId;\n this.anonymousId = options.anonymousId ?? this.generateAnonymousId();\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n // Start auto-flush timer if interval > 0\n if (this.config.flushInterval > 0) {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n\n // Unref the timer so it doesn't prevent Node.js from exiting\n if (typeof this.flushTimer.unref === 'function') {\n this.flushTimer.unref();\n }\n }\n\n if (this.config.debug) {\n logDebug('HTTP Analytics Provider initialized', {\n provider: 'http',\n endpoint: this.config.endpoint,\n batchSize: this.config.batchSize,\n flushInterval: this.config.flushInterval,\n });\n }\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.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'track', event });\n return;\n }\n\n this.enqueue({\n type: 'track',\n event,\n properties,\n timestamp: new Date().toISOString(),\n userId: this.userId,\n anonymousId: this.anonymousId,\n });\n }\n\n async identify(\n userId: string,\n traits: UserTraits = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'identify', userId });\n return;\n }\n\n // Update stored user ID\n this.userId = userId;\n\n this.enqueue({\n type: 'identify',\n userId,\n traits,\n timestamp: new Date().toISOString(),\n anonymousId: this.anonymousId,\n });\n }\n\n async page(\n name?: string,\n properties: PageProperties = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'page', name });\n return;\n }\n\n this.enqueue({\n type: 'page',\n name,\n properties,\n timestamp: new Date().toISOString(),\n userId: this.userId,\n anonymousId: this.anonymousId,\n });\n }\n\n async group(\n groupId: string,\n traits: GroupTraits = {},\n _context?: AnalyticsContext,\n ): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', { provider: 'http', operation: 'group', groupId });\n return;\n }\n\n this.enqueue({\n type: 'group',\n groupId,\n traits,\n timestamp: new Date().toISOString(),\n userId: this.userId,\n anonymousId: this.anonymousId,\n });\n }\n\n async alias(userId: string, previousId: string, _context?: AnalyticsContext): Promise<void> {\n if (!this.isInitialized) {\n logWarn('HTTP provider not initialized', {\n provider: 'http',\n operation: 'alias',\n userId,\n previousId,\n });\n return;\n }\n\n this.enqueue({\n type: 'alias',\n userId,\n previousId,\n timestamp: new Date().toISOString(),\n anonymousId: this.anonymousId,\n });\n }\n\n /**\n * Flush all queued events to the remote endpoint.\n * Called automatically on interval or when batch size is reached.\n */\n async flush(): Promise<void> {\n if (this.queue.length === 0 || this.isFlushing) return;\n\n this.isFlushing = true;\n\n // Take all events from queue\n const events = [...this.queue];\n this.queue = [];\n\n try {\n await this.sendBatch(events);\n } catch (error) {\n // Re-queue events on failure (they'll be retried on next flush)\n this.queue.unshift(...events);\n logError('Failed to flush events, re-queued for retry', {\n provider: 'http',\n eventCount: events.length,\n error: error instanceof Error ? error.message : String(error),\n });\n } finally {\n this.isFlushing = false;\n }\n }\n\n /**\n * Shutdown the provider gracefully.\n * Flushes remaining events and stops the flush timer.\n */\n async shutdown(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n\n // Final flush\n await this.flush();\n this.isInitialized = false;\n }\n\n /**\n * Get the current queue length (for testing/monitoring).\n */\n getQueueLength(): number {\n return this.queue.length;\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n private enqueue(event: QueuedEvent): void {\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift();\n logWarn('Http provider queue full. Dropping oldest event to maintain bounded memory.', {\n provider: 'http',\n queueSize: this.config.maxQueueSize,\n });\n }\n\n this.queue.push(event);\n\n if (this.config.debug) {\n logDebug('Event queued', {\n provider: 'http',\n type: event.type,\n queueLength: this.queue.length,\n });\n }\n\n // Flush if batch size reached\n if (this.queue.length >= this.config.batchSize) {\n void this.flush();\n }\n }\n\n private async sendBatch(events: QueuedEvent[]): Promise<void> {\n const payload = { batch: events };\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.retries; attempt++) {\n try {\n const response = await this.sendRequest(payload);\n\n if (response.success) {\n if (this.config.debug) {\n logDebug('Batch sent successfully', {\n provider: 'http',\n accepted: response.accepted,\n rejected: response.rejected,\n });\n }\n return;\n }\n\n // Request succeeded but ingestion failed\n logWarn('Batch partially rejected', {\n provider: 'http',\n accepted: response.accepted,\n rejected: response.rejected,\n error: response.error,\n });\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt < this.config.retries) {\n // Exponential backoff: 1s, 2s, 4s, ...\n const delay = BACKOFF_BASE_MS * Math.pow(2, attempt);\n\n if (this.config.debug) {\n logDebug('Retrying batch send', {\n provider: 'http',\n attempt: attempt + 1,\n maxRetries: this.config.retries,\n delayMs: delay,\n });\n }\n\n await this.sleep(delay);\n }\n }\n }\n\n // All retries exhausted\n throw lastError ?? new Error('Failed to send batch after retries');\n }\n\n private async sendRequest(payload: { batch: QueuedEvent[] }): Promise<IngestionResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.config.headers,\n };\n\n if (this.config.apiKey) {\n headers['X-API-Key'] = this.config.apiKey;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(this.config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n throw new Error(`Rate limited. Retry after ${retryAfter ?? 'unknown'} seconds`);\n }\n\n const errorBody = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorBody}`);\n }\n\n return (await response.json()) as IngestionResponse;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private generateAnonymousId(): string {\n // Use crypto.randomUUID if available (Node 19+), otherwise fallback\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for older Node versions\n return `anon_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n"],"mappings":"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"}
|
package/providers-http.d.mts
CHANGED
|
@@ -9,6 +9,7 @@ interface HttpProviderConfig {
|
|
|
9
9
|
flushInterval?: number;
|
|
10
10
|
timeout?: number;
|
|
11
11
|
retries?: number;
|
|
12
|
+
maxQueueSize?: number;
|
|
12
13
|
headers?: Record<string, string>;
|
|
13
14
|
debug?: boolean;
|
|
14
15
|
userId?: string;
|
|
@@ -27,6 +28,12 @@ interface QueuedEvent {
|
|
|
27
28
|
groupId?: string;
|
|
28
29
|
previousId?: string;
|
|
29
30
|
}
|
|
31
|
+
interface IngestionDispatchResult {
|
|
32
|
+
scheduled: number;
|
|
33
|
+
attempted: number;
|
|
34
|
+
failed: number;
|
|
35
|
+
status: 'skipped' | 'pending' | 'completed' | 'completed_with_failures';
|
|
36
|
+
}
|
|
30
37
|
interface IngestionResponse {
|
|
31
38
|
success: boolean;
|
|
32
39
|
accepted?: number;
|
|
@@ -37,10 +44,11 @@ interface IngestionResponse {
|
|
|
37
44
|
status: 'accepted' | 'rejected';
|
|
38
45
|
error?: string;
|
|
39
46
|
}>;
|
|
47
|
+
dispatch?: IngestionDispatchResult;
|
|
40
48
|
receivedAt?: string;
|
|
41
49
|
error?: string;
|
|
42
50
|
code?: string;
|
|
43
51
|
}
|
|
44
52
|
//#endregion
|
|
45
|
-
export { HttpClientProvider, HttpServerProvider as HttpProvider, HttpServerProvider, type HttpProviderConfig, type IngestionResponse, type QueuedEvent };
|
|
53
|
+
export { HttpClientProvider, HttpServerProvider as HttpProvider, HttpServerProvider, type HttpProviderConfig, type IngestionDispatchResult, type IngestionResponse, type QueuedEvent };
|
|
46
54
|
//# sourceMappingURL=providers-http.d.mts.map
|
package/providers-http.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers-http.d.mts","names":[],"sources":["../src/providers/http/types.ts"],"mappings":";;;;UAsBiB,kBAAA;EAOf,QAAA;EAOA,MAAA;EAQA,SAAA;EAQA,aAAA;EAOA,OAAA;EAQA,OAAA;EAMA,OAAA,GAAU,MAAA;EAOV,KAAA;EAMA,MAAA;EAMA,WAAA;AAAA;AAAA,UAOe,WAAA;EACf,IAAA;EACA,SAAA;EACA,MAAA;EACA,WAAA;EAEA,KAAA;EACA,UAAA,GAAa,MAAA;EAEb,MAAA,GAAS,MAAA;EAET,IAAA;EACA,QAAA;EAEA,OAAA;EAEA,UAAA;AAAA;AAAA,UAMe,iBAAA;EACf,OAAA;EACA,QAAA;EACA,QAAA;EACA,OAAA,GAAU,KAAA;IACR,EAAA;IACA,IAAA;IACA,MAAA;IACA,KAAA;EAAA;EAEF,UAAA;EACA,KAAA;EACA,IAAA;AAAA"}
|
|
1
|
+
{"version":3,"file":"providers-http.d.mts","names":[],"sources":["../src/providers/http/types.ts"],"mappings":";;;;UAsBiB,kBAAA;EAOf,QAAA;EAOA,MAAA;EAQA,SAAA;EAQA,aAAA;EAOA,OAAA;EAQA,OAAA;EAOA,YAAA;EAMA,OAAA,GAAU,MAAA;EAOV,KAAA;EAMA,MAAA;EAMA,WAAA;AAAA;AAAA,UAOe,WAAA;EACf,IAAA;EACA,SAAA;EACA,MAAA;EACA,WAAA;EAEA,KAAA;EACA,UAAA,GAAa,MAAA;EAEb,MAAA,GAAS,MAAA;EAET,IAAA;EACA,QAAA;EAEA,OAAA;EAEA,UAAA;AAAA;AAAA,UAMe,uBAAA;EAEf,SAAA;EAGA,SAAA;EAGA,MAAA;EAGA,MAAA;AAAA;AAAA,UAMe,iBAAA;EACf,OAAA;EACA,QAAA;EACA,QAAA;EACA,OAAA,GAAU,KAAA;IACR,EAAA;IACA,IAAA;IACA,MAAA;IACA,KAAA;EAAA;EAEF,QAAA,GAAW,uBAAA;EACX,UAAA;EACA,KAAA;EACA,IAAA;AAAA"}
|
package/server-edge.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as GroupTraits, C as EmitterPagePayload, D as EmitterTrackPayload, E as EmitterScreenPayload, F as UserTraits, M as Properties, N as PropertyObject, O as EmitterUserTraits, P as PropertyValue, S as EmitterOptions, T as EmitterProduct, _ as EmitterEventProperties, a as EcommerceEventSpec, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, f as AnalyticsEmitter, g as EmitterContext, h as EmitterConfig, i as AnalyticsProvider, j as PageProperties, k as IntegrationConfig, l as ProviderFactory, m as EmitterBasePayload, n as AnalyticsContext, o as ErrorContext, p as EmitterAliasPayload, r as AnalyticsManager, s as PostHogBootstrap, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload, x as EmitterIntegrations, y as EmitterGroupTraits } from "./types-
|
|
2
|
-
import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-
|
|
3
|
-
import { a as createEmitterProcessor, r as getAnalyticsConfig } from "./config-
|
|
1
|
+
import { A as GroupTraits, C as EmitterPagePayload, D as EmitterTrackPayload, E as EmitterScreenPayload, F as UserTraits, M as Properties, N as PropertyObject, O as EmitterUserTraits, P as PropertyValue, S as EmitterOptions, T as EmitterProduct, _ as EmitterEventProperties, a as EcommerceEventSpec, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, f as AnalyticsEmitter, g as EmitterContext, h as EmitterConfig, i as AnalyticsProvider, j as PageProperties, k as IntegrationConfig, l as ProviderFactory, m as EmitterBasePayload, n as AnalyticsContext, o as ErrorContext, p as EmitterAliasPayload, r as AnalyticsManager, s as PostHogBootstrap, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload, x as EmitterIntegrations, y as EmitterGroupTraits } from "./types-cMMfHIpi.mjs";
|
|
2
|
+
import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-BDSsleo_.mjs";
|
|
3
|
+
import { a as createEmitterProcessor, r as getAnalyticsConfig } from "./config-Ciu7O6n1.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/server-edge.d.ts
|
|
6
6
|
declare function createServerAnalytics(config?: AnalyticsConfig): Promise<AnalyticsManager>;
|
package/server-edge.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { i as logWarn } from "./core-DBLE5iTF.mjs";
|
|
2
|
+
import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-BvEelkxS.mjs";
|
|
3
|
+
import { a as createEmitterProcessor, r as getAnalyticsConfig } from "./config-6Mwe7b2O.mjs";
|
|
4
4
|
import { createEnv } from "@t3-oss/env-core";
|
|
5
5
|
import { z } from "zod/v4";
|
|
6
6
|
|
|
@@ -140,7 +140,7 @@ async function createServerAnalytics(config = defaultConfig) {
|
|
|
140
140
|
const providers = [];
|
|
141
141
|
let context = {};
|
|
142
142
|
if (config.providers.console) {
|
|
143
|
-
const { ConsoleProvider } = await import("./console-
|
|
143
|
+
const { ConsoleProvider } = await import("./console-BpU88FNF.mjs").then((n) => n.n);
|
|
144
144
|
const consoleProvider = new ConsoleProvider(config.providers.console);
|
|
145
145
|
await consoleProvider.initialize();
|
|
146
146
|
providers.push(consoleProvider);
|
package/server-edge.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-edge.mjs","names":[],"sources":["../env.ts","../src/server-edge.ts"],"sourcesContent":["/**\n * @fileoverview Environment variable configuration for analytics package\n * Environment variable configuration for analytics package\n */\n\nimport { logWarn } from '@repo/shared/logger';\nimport { createEnv } from '@t3-oss/env-core';\nimport { z } from 'zod/v4';\n\nexport const env = createEnv({\n server: {\n // PostHog server configuration for feature flags and analytics\n POSTHOG_HOST: z.string().url().default('https://app.posthog.com'),\n POSTHOG_KEY: z.string().optional(),\n POSTHOG_API_KEY: z.string().optional(), // Additional key used in source code\n POSTHOG_PERSONAL_API_KEY: z.string().optional(),\n POSTHOG_PROJECT_ID: z.string().optional(),\n\n // Segment server configuration\n SEGMENT_WRITE_KEY: z.string().optional(),\n\n // Analytics logging configuration\n ANALYTICS_LOG_PROVIDER: z.enum(['console', 'sentry']).default('console'),\n\n // Environment detection\n NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),\n APP_ENV: z.enum(['development', 'staging', 'production']).optional(),\n NEXT_RUNTIME: z.enum(['nodejs', 'edge']).optional(),\n },\n clientPrefix: 'NEXT_PUBLIC_',\n client: {\n // PostHog client configuration\n NEXT_PUBLIC_POSTHOG_HOST: z.string().url().default('https://app.posthog.com'),\n NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),\n\n // Segment client configuration\n NEXT_PUBLIC_SEGMENT_WRITE_KEY: z.string().optional(),\n\n // Vercel Analytics\n NEXT_PUBLIC_VERCEL_ANALYTICS_ID: z.string().optional(),\n\n // App environment for client\n NEXT_PUBLIC_APP_ENV: z.enum(['development', 'staging', 'production']).optional(),\n NEXT_PUBLIC_NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),\n },\n runtimeEnv: process.env,\n emptyStringAsUndefined: true,\n onInvalidAccess: (variable: string) => {\n throw new Error(\n `❌ Attempted to access a server-side environment variable on the client: ${variable}`,\n );\n },\n onValidationError: (error: unknown) => {\n logWarn('Analytics environment validation failed:', { error: String(error) });\n // Don't throw in packages - use fallbacks for resilience\n return undefined as never;\n },\n});\n\n/**\n * Returns a resilient env object for non-Next.js runtimes (CLI scripts, tests, workers).\n *\n * Codex/OpenAI models can rely on this helper when generating examples because it always\n * returns a fully populated object, using process.env fallbacks when the strongly typed\n * `createEnv` instance is unavailable.\n */\nexport function safeEnv() {\n // env is always defined, but may have validation errors\n // Return env directly, fallback only if access throws\n try {\n return env;\n } catch {\n // Return fallback if env access fails\n return {\n // Server variables\n POSTHOG_HOST: process.env.POSTHOG_HOST ?? 'https://app.posthog.com',\n POSTHOG_KEY: process.env.POSTHOG_KEY ?? '',\n POSTHOG_API_KEY: process.env.POSTHOG_API_KEY ?? '',\n POSTHOG_PERSONAL_API_KEY: process.env.POSTHOG_PERSONAL_API_KEY ?? '',\n POSTHOG_PROJECT_ID: process.env.POSTHOG_PROJECT_ID ?? '',\n SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY ?? '',\n ANALYTICS_LOG_PROVIDER:\n (process.env.ANALYTICS_LOG_PROVIDER as 'console' | 'sentry' | undefined) ?? 'console',\n NODE_ENV: (process.env.NODE_ENV as string | undefined) ?? 'development',\n APP_ENV: process.env.APP_ENV as 'development' | 'staging' | 'production' | undefined,\n NEXT_RUNTIME: process.env.NEXT_RUNTIME as 'nodejs' | 'edge' | undefined,\n\n // Client variables\n NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST ?? 'https://app.posthog.com',\n NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY ?? '',\n NEXT_PUBLIC_SEGMENT_WRITE_KEY: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY ?? '',\n NEXT_PUBLIC_VERCEL_ANALYTICS_ID: process.env.NEXT_PUBLIC_VERCEL_ANALYTICS_ID ?? '',\n NEXT_PUBLIC_APP_ENV: process.env.NEXT_PUBLIC_APP_ENV as\n | 'development'\n | 'staging'\n | 'production'\n | undefined,\n NEXT_PUBLIC_NODE_ENV:\n (process.env.NEXT_PUBLIC_NODE_ENV as 'development' | 'test' | 'production' | undefined) ??\n 'development',\n };\n }\n}\n\n// Export type for better DX\nexport type Env = typeof env;\n","/**\n * @fileoverview Edge Runtime Analytics Module\n *\n * Provides edge-compatible analytics for Next.js middleware and edge API routes.\n * Uses Web APIs and HTTP-based implementations compatible with edge runtime.\n *\n * **Supported Features**:\n * - Basic event tracking (track, identify, page, group, alias)\n * - Console provider (uses console API)\n * - PostHog provider (HTTP-based, no SDK dependency)\n * - Emitter pattern support via `emit()`\n *\n * **Limitations (Edge Runtime Constraints)**:\n * - No Node.js APIs (fs, crypto, etc.)\n * - No native modules or SDK dependencies\n * - No event deduplication (no LRU cache)\n * - No rate limiting (100 req/s limit not enforced)\n * - No batch processing optimization\n * - No performance metrics tracking\n * - No feature flags (PostHog flags require server SDK)\n * - Context is per-request only (not persisted)\n *\n * **For full analytics features**, use `@od-oneapp/analytics/server` in Node.js environments.\n *\n * **Usage**: Import from `@od-oneapp/analytics/server/edge` for Next.js middleware and edge API routes.\n *\n * @example\n * ```typescript\n * // In Next.js middleware\n * import { createServerAnalytics, track } from '@od-oneapp/analytics/server/edge';\n *\n * export async function middleware(request: NextRequest) {\n * const analytics = await createServerAnalytics({\n * providers: {\n * posthog: { apiKey: process.env.POSTHOG_API_KEY }\n * }\n * });\n *\n * await analytics.emit(track('Middleware Hit', { path: request.nextUrl.pathname }));\n * return NextResponse.next();\n * }\n * ```\n *\n * @module @od-oneapp/analytics/server/edge\n */\n\nimport { env } from '../env';\n\nimport type {\n EmitterAliasPayload,\n EmitterGroupPayload,\n EmitterIdentifyPayload,\n EmitterPagePayload,\n EmitterPayload,\n EmitterTrackPayload,\n} from './shared/emitters/emitter-types';\nimport type {\n AnalyticsConfig,\n AnalyticsContext,\n AnalyticsManager,\n AnalyticsProvider,\n GroupTraits,\n PageProperties,\n Properties,\n UserTraits,\n} from './shared/types/types';\n\n// Type aliases for clarity\ntype IdentifyTraits = UserTraits;\ntype TrackProperties = Properties;\n\n// Re-export types for consumers\nexport type * from './shared/emitters/emitter-types';\nexport type * from './shared/types/types';\n\n// Re-export emitter utilities\nexport { createEmitterProcessor } from './shared/utils/emitter-adapter';\n\n// Re-export core emitters for edge usage\nexport { alias, group, identify, page, track } from './shared/emitters';\n\nconst defaultConfig: AnalyticsConfig = { providers: {} };\n\n/**\n * Creates an edge-compatible analytics manager.\n *\n * This is a simplified implementation optimized for edge runtime constraints.\n * It provides basic analytics functionality without Node.js-specific features.\n *\n * **Supported Providers**:\n * - Console (always available)\n * - PostHog (HTTP-based, requires API key)\n *\n * **Not Supported in Edge**:\n * - Segment SDK (requires Node.js)\n * - Vercel Analytics SDK (requires Node.js)\n * - Rate limiting\n * - Event deduplication\n * - Batch processing optimization\n *\n * @param {AnalyticsConfig} [config] - Analytics configuration with provider settings\n * @returns {Promise<AnalyticsManager>} Promise resolving to AnalyticsManager instance\n *\n * @example\n * ```typescript\n * const analytics = await createServerAnalytics({\n * providers: {\n * posthog: { apiKey: process.env.POSTHOG_API_KEY }\n * }\n * });\n *\n * await analytics.track('Event Name', { property: 'value' });\n * ```\n */\nexport async function createServerAnalytics(\n config: AnalyticsConfig = defaultConfig,\n): Promise<AnalyticsManager> {\n const providers: AnalyticsProvider[] = [];\n let context: AnalyticsContext = {};\n\n // Initialize Console provider (edge-compatible)\n if (config.providers.console) {\n const { ConsoleProvider } = await import('./providers/console');\n const consoleProvider = new ConsoleProvider(config.providers.console);\n await consoleProvider.initialize();\n providers.push(consoleProvider);\n }\n\n // Initialize PostHog HTTP provider (edge-compatible)\n if (config.providers.posthog?.apiKey) {\n const posthogProvider = createPostHogEdgeProvider(config);\n providers.push(posthogProvider);\n }\n\n // Process emitter payload by type\n const processPayload = async (payload: EmitterPayload): Promise<void> => {\n switch (payload.type) {\n case 'track': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.track(p.event, p.properties ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'identify': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.identify?.(p.userId, p.traits ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'page': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.page?.(p.name ?? '', p.properties ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'screen': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.screen?.(p.name ?? '', p.properties ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'group': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.group?.(p.groupId, p.traits ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'alias': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.alias?.(p.userId, p.previousId, { ...context, ...p.context }),\n ),\n );\n break;\n }\n }\n };\n\n // Create emitter function at outer scope (within createServerAnalytics)\n function createEmitterFunction(payload: EmitterPayload): Promise<void> {\n return processPayload(payload);\n }\n\n // Return edge-compatible analytics manager\n const manager: AnalyticsManager = {\n getContext: () => ({ ...context }),\n\n initialize: async () => {\n // Providers already initialized above\n },\n\n setContext: (newContext: AnalyticsContext) => {\n context = { ...context, ...newContext };\n },\n\n createEmitter: () => createEmitterFunction,\n\n emit: async (payload: EmitterPayload) => {\n await processPayload(payload);\n },\n\n emitBatch: async (payloads: EmitterPayload[]) => {\n // Process sequentially in edge (no concurrency optimization)\n for (const payload of payloads) {\n await processPayload(payload);\n }\n },\n\n // Overloaded track method\n track: async (eventOrPayload: string | EmitterTrackPayload, properties?: Properties) => {\n if (typeof eventOrPayload === 'object') {\n await processPayload(eventOrPayload);\n } else if (typeof eventOrPayload === 'string') {\n await Promise.allSettled(\n providers.map(p => p.track(eventOrPayload, properties ?? {}, context)),\n );\n }\n },\n\n // Overloaded identify method\n identify: async (userIdOrPayload: string | EmitterIdentifyPayload, traits?: IdentifyTraits) => {\n if (typeof userIdOrPayload === 'object') {\n await processPayload(userIdOrPayload);\n } else if (typeof userIdOrPayload === 'string') {\n await Promise.allSettled(\n providers.map(p => p.identify?.(userIdOrPayload, traits ?? {}, context)),\n );\n }\n },\n\n // Overloaded page method\n page: async (nameOrPayload?: string | EmitterPagePayload, properties?: PageProperties) => {\n if (typeof nameOrPayload === 'object') {\n await processPayload(nameOrPayload);\n } else {\n const pageName = typeof nameOrPayload === 'string' ? nameOrPayload : '';\n await Promise.allSettled(providers.map(p => p.page?.(pageName, properties ?? {}, context)));\n }\n },\n\n // Overloaded group method\n group: async (groupIdOrPayload: string | EmitterGroupPayload, traits?: GroupTraits) => {\n if (typeof groupIdOrPayload === 'object') {\n await processPayload(groupIdOrPayload);\n } else if (typeof groupIdOrPayload === 'string') {\n await Promise.allSettled(\n providers.map(p => p.group?.(groupIdOrPayload, traits ?? {}, context)),\n );\n }\n },\n\n // Overloaded alias method\n alias: async (userIdOrPayload: string | EmitterAliasPayload, previousId?: string) => {\n if (typeof userIdOrPayload === 'object') {\n await processPayload(userIdOrPayload);\n } else if (typeof userIdOrPayload === 'string' && previousId) {\n await Promise.allSettled(\n providers.map(p => p.alias?.(userIdOrPayload, previousId, context)),\n );\n }\n },\n\n getActiveProviders: () => providers.map(p => p.name),\n getProvider: (name: string) => providers.find(p => p.name === name),\n\n reset: () => {\n context = {};\n },\n\n shutdown: async () => {\n // In edge, we don't have complex shutdown logic usually\n providers.length = 0;\n },\n\n // Deprecated methods (no-ops with warning)\n processEmitterPayload: async (payload: EmitterPayload) => {\n await processPayload(payload);\n },\n trackEcommerce: async () => {\n if (config.debug && config.onInfo) {\n config.onInfo('trackEcommerce is deprecated, use emit(ecommerce.EVENT_NAME(...))');\n }\n },\n };\n\n return manager;\n}\n\n/**\n * Creates a PostHog provider that uses HTTP API (edge-compatible).\n *\n * This provider uses PostHog's HTTP capture API instead of the Node.js SDK,\n * making it compatible with edge runtime constraints.\n *\n * **Features**:\n * - HTTP-based event tracking\n * - 5-second timeout per request\n * - Error handling via config callbacks\n * - Supports all standard analytics methods (track, identify, page, group, alias)\n *\n * @param {AnalyticsConfig} config - Analytics configuration\n * @returns {AnalyticsProvider} PostHog provider instance\n *\n * @throws {Error} If PostHog API key is not provided\n *\n * @internal\n */\nfunction createPostHogEdgeProvider(config: AnalyticsConfig): AnalyticsProvider {\n const posthogConfig = config.providers?.posthog;\n if (!posthogConfig?.apiKey) {\n throw new Error('PostHog apiKey is required');\n }\n\n const posthogHost =\n (posthogConfig.options as { api_host?: string } | undefined)?.api_host ??\n env.POSTHOG_HOST ??\n 'https://app.posthog.com';\n const posthogUrl = `${posthogHost}/capture/`;\n const { apiKey } = posthogConfig;\n const timeout = 5000;\n\n // Safe fetch with timeout and error handling\n const safeFetch = async (body: Record<string, unknown>, method: string): Promise<void> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(posthogUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok && config.onError) {\n config.onError(\n new Error(`PostHog ${method} failed: ${response.status} ${response.statusText}`),\n { provider: 'posthog-edge', method, status: response.status },\n );\n }\n } catch (error) {\n if (config.onError) {\n config.onError(error instanceof Error ? error : new Error('Unknown error'), {\n provider: 'posthog-edge',\n method,\n });\n }\n } finally {\n clearTimeout(timeoutId);\n }\n };\n\n return {\n name: 'posthog-edge',\n\n async initialize() {\n // No initialization needed for HTTP-based PostHog\n },\n\n async track(event: string, properties?: TrackProperties, context?: AnalyticsContext) {\n const distinctId = context?.userId ?? properties?.distinctId ?? 'anonymous';\n await safeFetch(\n {\n api_key: apiKey,\n event,\n distinct_id: distinctId,\n properties: { ...properties, ...context },\n timestamp: new Date().toISOString(),\n },\n 'track',\n );\n },\n\n async identify(userId: string, traits?: IdentifyTraits) {\n await safeFetch(\n {\n api_key: apiKey,\n event: '$identify',\n distinct_id: userId,\n properties: { $set: traits },\n },\n 'identify',\n );\n },\n\n async page(name?: string, properties?: PageProperties, context?: AnalyticsContext) {\n const distinctId = context?.userId ?? 'anonymous';\n await safeFetch(\n {\n api_key: apiKey,\n event: '$pageview',\n distinct_id: distinctId,\n properties: { $current_url: properties?.url, $title: name, ...properties },\n },\n 'page',\n );\n },\n\n async group(groupId: string, traits?: GroupTraits, context?: AnalyticsContext) {\n const distinctId = context?.userId ?? 'anonymous';\n await safeFetch(\n {\n api_key: apiKey,\n event: '$groupidentify',\n distinct_id: distinctId,\n properties: { $group_type: 'company', $group_key: groupId, $group_set: traits },\n },\n 'group',\n );\n },\n\n async alias(userId: string, previousId: string) {\n await safeFetch(\n {\n api_key: apiKey,\n event: '$create_alias',\n properties: { distinct_id: userId, alias: previousId },\n },\n 'alias',\n );\n },\n };\n}\n\n// Export edge-compatible configuration utilities\nexport { getAnalyticsConfig } from './shared/utils/config';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server-edge.mjs","names":[],"sources":["../env.ts","../src/server-edge.ts"],"sourcesContent":["/**\n * @fileoverview Environment variable configuration for analytics package\n * Environment variable configuration for analytics package\n */\n\nimport { logWarn } from '@od-oneapp/shared/logger';\nimport { createEnv } from '@t3-oss/env-core';\nimport { z } from 'zod/v4';\n\nexport const env = createEnv({\n server: {\n // PostHog server configuration for feature flags and analytics\n POSTHOG_HOST: z.string().url().default('https://app.posthog.com'),\n POSTHOG_KEY: z.string().optional(),\n POSTHOG_API_KEY: z.string().optional(), // Additional key used in source code\n POSTHOG_PERSONAL_API_KEY: z.string().optional(),\n POSTHOG_PROJECT_ID: z.string().optional(),\n\n // Segment server configuration\n SEGMENT_WRITE_KEY: z.string().optional(),\n\n // Analytics logging configuration\n ANALYTICS_LOG_PROVIDER: z.enum(['console', 'sentry']).default('console'),\n\n // Environment detection\n NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),\n APP_ENV: z.enum(['development', 'staging', 'production']).optional(),\n NEXT_RUNTIME: z.enum(['nodejs', 'edge']).optional(),\n },\n clientPrefix: 'NEXT_PUBLIC_',\n client: {\n // PostHog client configuration\n NEXT_PUBLIC_POSTHOG_HOST: z.string().url().default('https://app.posthog.com'),\n NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),\n\n // Segment client configuration\n NEXT_PUBLIC_SEGMENT_WRITE_KEY: z.string().optional(),\n\n // Vercel Analytics\n NEXT_PUBLIC_VERCEL_ANALYTICS_ID: z.string().optional(),\n\n // App environment for client\n NEXT_PUBLIC_APP_ENV: z.enum(['development', 'staging', 'production']).optional(),\n NEXT_PUBLIC_NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),\n },\n runtimeEnv: process.env,\n emptyStringAsUndefined: true,\n onInvalidAccess: (variable: string) => {\n throw new Error(\n `❌ Attempted to access a server-side environment variable on the client: ${variable}`,\n );\n },\n onValidationError: (error: unknown) => {\n logWarn('Analytics environment validation failed:', { error: String(error) });\n // Don't throw in packages - use fallbacks for resilience\n return undefined as never;\n },\n});\n\n/**\n * Returns a resilient env object for non-Next.js runtimes (CLI scripts, tests, workers).\n *\n * Codex/OpenAI models can rely on this helper when generating examples because it always\n * returns a fully populated object, using process.env fallbacks when the strongly typed\n * `createEnv` instance is unavailable.\n */\nexport function safeEnv() {\n // env is always defined, but may have validation errors\n // Return env directly, fallback only if access throws\n try {\n return env;\n } catch {\n // Return fallback if env access fails\n return {\n // Server variables\n POSTHOG_HOST: process.env.POSTHOG_HOST ?? 'https://app.posthog.com',\n POSTHOG_KEY: process.env.POSTHOG_KEY ?? '',\n POSTHOG_API_KEY: process.env.POSTHOG_API_KEY ?? '',\n POSTHOG_PERSONAL_API_KEY: process.env.POSTHOG_PERSONAL_API_KEY ?? '',\n POSTHOG_PROJECT_ID: process.env.POSTHOG_PROJECT_ID ?? '',\n SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY ?? '',\n ANALYTICS_LOG_PROVIDER:\n (process.env.ANALYTICS_LOG_PROVIDER as 'console' | 'sentry' | undefined) ?? 'console',\n NODE_ENV: (process.env.NODE_ENV as string | undefined) ?? 'development',\n APP_ENV: process.env.APP_ENV as 'development' | 'staging' | 'production' | undefined,\n NEXT_RUNTIME: process.env.NEXT_RUNTIME as 'nodejs' | 'edge' | undefined,\n\n // Client variables\n NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST ?? 'https://app.posthog.com',\n NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY ?? '',\n NEXT_PUBLIC_SEGMENT_WRITE_KEY: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY ?? '',\n NEXT_PUBLIC_VERCEL_ANALYTICS_ID: process.env.NEXT_PUBLIC_VERCEL_ANALYTICS_ID ?? '',\n NEXT_PUBLIC_APP_ENV: process.env.NEXT_PUBLIC_APP_ENV as\n | 'development'\n | 'staging'\n | 'production'\n | undefined,\n NEXT_PUBLIC_NODE_ENV:\n (process.env.NEXT_PUBLIC_NODE_ENV as 'development' | 'test' | 'production' | undefined) ??\n 'development',\n };\n }\n}\n\n// Export type for better DX\nexport type Env = typeof env;\n","/**\n * @fileoverview Edge Runtime Analytics Module\n *\n * Provides edge-compatible analytics for Next.js middleware and edge API routes.\n * Uses Web APIs and HTTP-based implementations compatible with edge runtime.\n *\n * **Supported Features**:\n * - Basic event tracking (track, identify, page, group, alias)\n * - Console provider (uses console API)\n * - PostHog provider (HTTP-based, no SDK dependency)\n * - Emitter pattern support via `emit()`\n *\n * **Limitations (Edge Runtime Constraints)**:\n * - No Node.js APIs (fs, crypto, etc.)\n * - No native modules or SDK dependencies\n * - No event deduplication (no LRU cache)\n * - No rate limiting (100 req/s limit not enforced)\n * - No batch processing optimization\n * - No performance metrics tracking\n * - No feature flags (PostHog flags require server SDK)\n * - Context is per-request only (not persisted)\n *\n * **For full analytics features**, use `@od-oneapp/analytics/server` in Node.js environments.\n *\n * **Usage**: Import from `@od-oneapp/analytics/server/edge` for Next.js middleware and edge API routes.\n *\n * @example\n * ```typescript\n * // In Next.js middleware\n * import { createServerAnalytics, track } from '@od-oneapp/analytics/server/edge';\n *\n * export async function middleware(request: NextRequest) {\n * const analytics = await createServerAnalytics({\n * providers: {\n * posthog: { apiKey: process.env.POSTHOG_API_KEY }\n * }\n * });\n *\n * await analytics.emit(track('Middleware Hit', { path: request.nextUrl.pathname }));\n * return NextResponse.next();\n * }\n * ```\n *\n * @module @od-oneapp/analytics/server/edge\n */\n\nimport { env } from '../env';\n\nimport type {\n EmitterAliasPayload,\n EmitterGroupPayload,\n EmitterIdentifyPayload,\n EmitterPagePayload,\n EmitterPayload,\n EmitterTrackPayload,\n} from './shared/emitters/emitter-types';\nimport type {\n AnalyticsConfig,\n AnalyticsContext,\n AnalyticsManager,\n AnalyticsProvider,\n GroupTraits,\n PageProperties,\n Properties,\n UserTraits,\n} from './shared/types/types';\n\n// Type aliases for clarity\ntype IdentifyTraits = UserTraits;\ntype TrackProperties = Properties;\n\n// Re-export types for consumers\nexport type * from './shared/emitters/emitter-types';\nexport type * from './shared/types/types';\n\n// Re-export emitter utilities\nexport { createEmitterProcessor } from './shared/utils/emitter-adapter';\n\n// Re-export core emitters for edge usage\nexport { alias, group, identify, page, track } from './shared/emitters';\n\nconst defaultConfig: AnalyticsConfig = { providers: {} };\n\n/**\n * Creates an edge-compatible analytics manager.\n *\n * This is a simplified implementation optimized for edge runtime constraints.\n * It provides basic analytics functionality without Node.js-specific features.\n *\n * **Supported Providers**:\n * - Console (always available)\n * - PostHog (HTTP-based, requires API key)\n *\n * **Not Supported in Edge**:\n * - Segment SDK (requires Node.js)\n * - Vercel Analytics SDK (requires Node.js)\n * - Rate limiting\n * - Event deduplication\n * - Batch processing optimization\n *\n * @param {AnalyticsConfig} [config] - Analytics configuration with provider settings\n * @returns {Promise<AnalyticsManager>} Promise resolving to AnalyticsManager instance\n *\n * @example\n * ```typescript\n * const analytics = await createServerAnalytics({\n * providers: {\n * posthog: { apiKey: process.env.POSTHOG_API_KEY }\n * }\n * });\n *\n * await analytics.track('Event Name', { property: 'value' });\n * ```\n */\nexport async function createServerAnalytics(\n config: AnalyticsConfig = defaultConfig,\n): Promise<AnalyticsManager> {\n const providers: AnalyticsProvider[] = [];\n let context: AnalyticsContext = {};\n\n // Initialize Console provider (edge-compatible)\n if (config.providers.console) {\n const { ConsoleProvider } = await import('./providers/console');\n const consoleProvider = new ConsoleProvider(config.providers.console);\n await consoleProvider.initialize();\n providers.push(consoleProvider);\n }\n\n // Initialize PostHog HTTP provider (edge-compatible)\n if (config.providers.posthog?.apiKey) {\n const posthogProvider = createPostHogEdgeProvider(config);\n providers.push(posthogProvider);\n }\n\n // Process emitter payload by type\n const processPayload = async (payload: EmitterPayload): Promise<void> => {\n switch (payload.type) {\n case 'track': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.track(p.event, p.properties ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'identify': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.identify?.(p.userId, p.traits ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'page': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.page?.(p.name ?? '', p.properties ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'screen': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.screen?.(p.name ?? '', p.properties ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'group': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.group?.(p.groupId, p.traits ?? {}, { ...context, ...p.context }),\n ),\n );\n break;\n }\n case 'alias': {\n const p = payload;\n await Promise.allSettled(\n providers.map(provider =>\n provider.alias?.(p.userId, p.previousId, { ...context, ...p.context }),\n ),\n );\n break;\n }\n }\n };\n\n // Create emitter function at outer scope (within createServerAnalytics)\n function createEmitterFunction(payload: EmitterPayload): Promise<void> {\n return processPayload(payload);\n }\n\n // Return edge-compatible analytics manager\n const manager: AnalyticsManager = {\n getContext: () => ({ ...context }),\n\n initialize: async () => {\n // Providers already initialized above\n },\n\n setContext: (newContext: AnalyticsContext) => {\n context = { ...context, ...newContext };\n },\n\n createEmitter: () => createEmitterFunction,\n\n emit: async (payload: EmitterPayload) => {\n await processPayload(payload);\n },\n\n emitBatch: async (payloads: EmitterPayload[]) => {\n // Process sequentially in edge (no concurrency optimization)\n for (const payload of payloads) {\n await processPayload(payload);\n }\n },\n\n // Overloaded track method\n track: async (eventOrPayload: string | EmitterTrackPayload, properties?: Properties) => {\n if (typeof eventOrPayload === 'object') {\n await processPayload(eventOrPayload);\n } else if (typeof eventOrPayload === 'string') {\n await Promise.allSettled(\n providers.map(p => p.track(eventOrPayload, properties ?? {}, context)),\n );\n }\n },\n\n // Overloaded identify method\n identify: async (userIdOrPayload: string | EmitterIdentifyPayload, traits?: IdentifyTraits) => {\n if (typeof userIdOrPayload === 'object') {\n await processPayload(userIdOrPayload);\n } else if (typeof userIdOrPayload === 'string') {\n await Promise.allSettled(\n providers.map(p => p.identify?.(userIdOrPayload, traits ?? {}, context)),\n );\n }\n },\n\n // Overloaded page method\n page: async (nameOrPayload?: string | EmitterPagePayload, properties?: PageProperties) => {\n if (typeof nameOrPayload === 'object') {\n await processPayload(nameOrPayload);\n } else {\n const pageName = typeof nameOrPayload === 'string' ? nameOrPayload : '';\n await Promise.allSettled(providers.map(p => p.page?.(pageName, properties ?? {}, context)));\n }\n },\n\n // Overloaded group method\n group: async (groupIdOrPayload: string | EmitterGroupPayload, traits?: GroupTraits) => {\n if (typeof groupIdOrPayload === 'object') {\n await processPayload(groupIdOrPayload);\n } else if (typeof groupIdOrPayload === 'string') {\n await Promise.allSettled(\n providers.map(p => p.group?.(groupIdOrPayload, traits ?? {}, context)),\n );\n }\n },\n\n // Overloaded alias method\n alias: async (userIdOrPayload: string | EmitterAliasPayload, previousId?: string) => {\n if (typeof userIdOrPayload === 'object') {\n await processPayload(userIdOrPayload);\n } else if (typeof userIdOrPayload === 'string' && previousId) {\n await Promise.allSettled(\n providers.map(p => p.alias?.(userIdOrPayload, previousId, context)),\n );\n }\n },\n\n getActiveProviders: () => providers.map(p => p.name),\n getProvider: (name: string) => providers.find(p => p.name === name),\n\n reset: () => {\n context = {};\n },\n\n shutdown: async () => {\n // In edge, we don't have complex shutdown logic usually\n providers.length = 0;\n },\n\n // Deprecated methods (no-ops with warning)\n processEmitterPayload: async (payload: EmitterPayload) => {\n await processPayload(payload);\n },\n trackEcommerce: async () => {\n if (config.debug && config.onInfo) {\n config.onInfo('trackEcommerce is deprecated, use emit(ecommerce.EVENT_NAME(...))');\n }\n },\n };\n\n return manager;\n}\n\n/**\n * Creates a PostHog provider that uses HTTP API (edge-compatible).\n *\n * This provider uses PostHog's HTTP capture API instead of the Node.js SDK,\n * making it compatible with edge runtime constraints.\n *\n * **Features**:\n * - HTTP-based event tracking\n * - 5-second timeout per request\n * - Error handling via config callbacks\n * - Supports all standard analytics methods (track, identify, page, group, alias)\n *\n * @param {AnalyticsConfig} config - Analytics configuration\n * @returns {AnalyticsProvider} PostHog provider instance\n *\n * @throws {Error} If PostHog API key is not provided\n *\n * @internal\n */\nfunction createPostHogEdgeProvider(config: AnalyticsConfig): AnalyticsProvider {\n const posthogConfig = config.providers?.posthog;\n if (!posthogConfig?.apiKey) {\n throw new Error('PostHog apiKey is required');\n }\n\n const posthogHost =\n (posthogConfig.options as { api_host?: string } | undefined)?.api_host ??\n env.POSTHOG_HOST ??\n 'https://app.posthog.com';\n const posthogUrl = `${posthogHost}/capture/`;\n const { apiKey } = posthogConfig;\n const timeout = 5000;\n\n // Safe fetch with timeout and error handling\n const safeFetch = async (body: Record<string, unknown>, method: string): Promise<void> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(posthogUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok && config.onError) {\n config.onError(\n new Error(`PostHog ${method} failed: ${response.status} ${response.statusText}`),\n { provider: 'posthog-edge', method, status: response.status },\n );\n }\n } catch (error) {\n if (config.onError) {\n config.onError(error instanceof Error ? error : new Error('Unknown error'), {\n provider: 'posthog-edge',\n method,\n });\n }\n } finally {\n clearTimeout(timeoutId);\n }\n };\n\n return {\n name: 'posthog-edge',\n\n async initialize() {\n // No initialization needed for HTTP-based PostHog\n },\n\n async track(event: string, properties?: TrackProperties, context?: AnalyticsContext) {\n const distinctId = context?.userId ?? properties?.distinctId ?? 'anonymous';\n await safeFetch(\n {\n api_key: apiKey,\n event,\n distinct_id: distinctId,\n properties: { ...properties, ...context },\n timestamp: new Date().toISOString(),\n },\n 'track',\n );\n },\n\n async identify(userId: string, traits?: IdentifyTraits) {\n await safeFetch(\n {\n api_key: apiKey,\n event: '$identify',\n distinct_id: userId,\n properties: { $set: traits },\n },\n 'identify',\n );\n },\n\n async page(name?: string, properties?: PageProperties, context?: AnalyticsContext) {\n const distinctId = context?.userId ?? 'anonymous';\n await safeFetch(\n {\n api_key: apiKey,\n event: '$pageview',\n distinct_id: distinctId,\n properties: { $current_url: properties?.url, $title: name, ...properties },\n },\n 'page',\n );\n },\n\n async group(groupId: string, traits?: GroupTraits, context?: AnalyticsContext) {\n const distinctId = context?.userId ?? 'anonymous';\n await safeFetch(\n {\n api_key: apiKey,\n event: '$groupidentify',\n distinct_id: distinctId,\n properties: { $group_type: 'company', $group_key: groupId, $group_set: traits },\n },\n 'group',\n );\n },\n\n async alias(userId: string, previousId: string) {\n await safeFetch(\n {\n api_key: apiKey,\n event: '$create_alias',\n properties: { distinct_id: userId, alias: previousId },\n },\n 'alias',\n );\n },\n };\n}\n\n// Export edge-compatible configuration utilities\nexport { getAnalyticsConfig } from './shared/utils/config';\n"],"mappings":"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"}
|
package/server-next.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { C as EmitterPagePayload, D as EmitterTrackPayload, S as EmitterOptions, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, g as EmitterContext, i as AnalyticsProvider, n as AnalyticsContext, p as EmitterAliasPayload, r as AnalyticsManager, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload } from "./types-
|
|
2
|
-
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-
|
|
3
|
-
import { a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload } from "./posthog-bootstrap-
|
|
4
|
-
import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-
|
|
5
|
-
import { t as index_d_exports } from "./index-
|
|
6
|
-
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-
|
|
7
|
-
import { a as ConsoleConfig, c as PostHogConfig, i as SegmentOptions, l as PostHogOptions, n as VercelOptions, o as ConsoleOptions, r as SegmentConfig, s as BootstrapData, t as VercelConfig } from "./vercel-types-
|
|
8
|
-
import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-
|
|
9
|
-
import { a as createIngestionService, c as IngestionErrorResponse, d as validateAnalyticsConfig, f as validateConfigOrThrow, h as createServerAnalyticsUninitialized, i as IngestionServiceConfig, l as IngestionSuccessResponse, m as createServerAnalytics, n as IngestionMetrics, o as validateBatchPayload, p as validateProvider, r as IngestionService, s as validateEventPayload, t as IngestionContext, u as debugConfig } from "./index-
|
|
1
|
+
import { C as EmitterPagePayload, D as EmitterTrackPayload, S as EmitterOptions, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, g as EmitterContext, i as AnalyticsProvider, n as AnalyticsContext, p as EmitterAliasPayload, r as AnalyticsManager, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload } from "./types-cMMfHIpi.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-BDSsleo_.mjs";
|
|
3
|
+
import { a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload } from "./posthog-bootstrap-Bu1BfhVv.mjs";
|
|
4
|
+
import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-DEcTnnFe.mjs";
|
|
5
|
+
import { t as index_d_exports } from "./index-BWhDEs8u.mjs";
|
|
6
|
+
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-Ciu7O6n1.mjs";
|
|
7
|
+
import { a as ConsoleConfig, c as PostHogConfig, i as SegmentOptions, l as PostHogOptions, n as VercelOptions, o as ConsoleOptions, r as SegmentConfig, s as BootstrapData, t as VercelConfig } from "./vercel-types-oM7Sn385.mjs";
|
|
8
|
+
import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-OJpSKwqb.mjs";
|
|
9
|
+
import { a as createIngestionService, c as IngestionErrorResponse, d as validateAnalyticsConfig, f as validateConfigOrThrow, h as createServerAnalyticsUninitialized, i as IngestionServiceConfig, l as IngestionSuccessResponse, m as createServerAnalytics, n as IngestionMetrics, o as validateBatchPayload, p as validateProvider, r as IngestionService, s as validateEventPayload, t as IngestionContext, u as debugConfig } from "./index-DTvdqV7H.mjs";
|
|
10
10
|
import "./server.mjs";
|
|
11
11
|
|
|
12
12
|
//#region src/next/middleware.d.ts
|
package/server-next.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { _ as AnalyticsManager, a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, i as getDistinctIdFromCookies, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload, v as createAnalyticsManager } from "./posthog-bootstrap-
|
|
2
|
-
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-
|
|
3
|
-
import { t as ecommerce_exports } from "./ecommerce-
|
|
4
|
-
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-
|
|
5
|
-
import { a as debugConfig, c as validateProvider, i as validateEventPayload, l as createServerAnalytics, n as createIngestionService, o as validateAnalyticsConfig, r as validateBatchPayload, s as validateConfigOrThrow, t as IngestionService, u as createServerAnalyticsUninitialized } from "./service-
|
|
1
|
+
import { _ as AnalyticsManager, a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, i as getDistinctIdFromCookies, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload, v as createAnalyticsManager } from "./posthog-bootstrap-DkPdn-hA.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-BvEelkxS.mjs";
|
|
3
|
+
import { t as ecommerce_exports } from "./ecommerce-DGG1FbiH.mjs";
|
|
4
|
+
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-6Mwe7b2O.mjs";
|
|
5
|
+
import { a as debugConfig, c as validateProvider, i as validateEventPayload, l as createServerAnalytics, n as createIngestionService, o as validateAnalyticsConfig, r as validateBatchPayload, s as validateConfigOrThrow, t as IngestionService, u as createServerAnalyticsUninitialized } from "./service-NuHnv30x.mjs";
|
|
6
6
|
|
|
7
7
|
//#region src/next/middleware.ts
|
|
8
8
|
/**
|
package/server.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { C as EmitterPagePayload, D as EmitterTrackPayload, S as EmitterOptions, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, g as EmitterContext, i as AnalyticsProvider, n as AnalyticsContext, p as EmitterAliasPayload, r as AnalyticsManager, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload } from "./types-
|
|
2
|
-
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-
|
|
3
|
-
import { a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload } from "./posthog-bootstrap-
|
|
4
|
-
import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-
|
|
5
|
-
import { t as index_d_exports } from "./index-
|
|
6
|
-
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-
|
|
7
|
-
import { a as ConsoleConfig, c as PostHogConfig, i as SegmentOptions, l as PostHogOptions, n as VercelOptions, o as ConsoleOptions, r as SegmentConfig, s as BootstrapData, t as VercelConfig } from "./vercel-types-
|
|
8
|
-
import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-
|
|
9
|
-
import { a as createIngestionService, c as IngestionErrorResponse, d as validateAnalyticsConfig, f as validateConfigOrThrow, h as createServerAnalyticsUninitialized, i as IngestionServiceConfig, l as IngestionSuccessResponse, m as createServerAnalytics, n as IngestionMetrics, o as validateBatchPayload, p as validateProvider, r as IngestionService, s as validateEventPayload, t as IngestionContext, u as debugConfig } from "./index-
|
|
1
|
+
import { C as EmitterPagePayload, D as EmitterTrackPayload, S as EmitterOptions, b as EmitterIdentifyPayload, c as ProviderConfig, d as TrackingOptions, g as EmitterContext, i as AnalyticsProvider, n as AnalyticsContext, p as EmitterAliasPayload, r as AnalyticsManager, t as AnalyticsConfig, u as ProviderRegistry, v as EmitterGroupPayload, w as EmitterPayload } from "./types-cMMfHIpi.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-BDSsleo_.mjs";
|
|
3
|
+
import { a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload } from "./posthog-bootstrap-Bu1BfhVv.mjs";
|
|
4
|
+
import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-DEcTnnFe.mjs";
|
|
5
|
+
import { t as index_d_exports } from "./index-BWhDEs8u.mjs";
|
|
6
|
+
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-Ciu7O6n1.mjs";
|
|
7
|
+
import { a as ConsoleConfig, c as PostHogConfig, i as SegmentOptions, l as PostHogOptions, n as VercelOptions, o as ConsoleOptions, r as SegmentConfig, s as BootstrapData, t as VercelConfig } from "./vercel-types-oM7Sn385.mjs";
|
|
8
|
+
import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-OJpSKwqb.mjs";
|
|
9
|
+
import { a as createIngestionService, c as IngestionErrorResponse, d as validateAnalyticsConfig, f as validateConfigOrThrow, h as createServerAnalyticsUninitialized, i as IngestionServiceConfig, l as IngestionSuccessResponse, m as createServerAnalytics, n as IngestionMetrics, o as validateBatchPayload, p as validateProvider, r as IngestionService, s as validateEventPayload, t as IngestionContext, u as debugConfig } from "./index-DTvdqV7H.mjs";
|
|
10
10
|
export { AnalyticsConfig, AnalyticsContext, AnalyticsManager, AnalyticsManager$1 as AnalyticsManagerClass, AnalyticsProvider, BaseProductProperties, BootstrapData, CartProperties, ConsoleConfig, ConsoleOptions, ContextBuilder, EcommerceEventSpec, EmitterAliasPayload, EmitterContext, EmitterGroupPayload, EmitterIdentifyPayload, EmitterOptions, EmitterPagePayload, EmitterPayload, EmitterTrackPayload, EventBatch, ExtendedProductProperties, type IngestionContext, type IngestionErrorResponse, type IngestionMetrics, IngestionService, type IngestionServiceConfig, type IngestionSuccessResponse, OrderProperties, PROVIDER_REQUIREMENTS, PayloadBuilder, PostHogConfig, PostHogOptions, ProviderConfig, ProviderRegistry, SegmentConfig, SegmentOptions, TrackingOptions, VercelConfig, VercelOptions, alias, createAnalyticsManager, createAnonymousSession, createBootstrapData, createConfigBuilder, createEmitterProcessor, createIngestionService, createMinimalBootstrapData, createServerAnalytics, createServerAnalyticsUninitialized, createUserSession, debugConfig, index_d_exports as ecommerce, generateDistinctId, getAnalyticsConfig, group, identify, isAliasPayload, isGroupPayload, isIdentifyPayload, isPagePayload, isTrackPayload, page, processEmitterPayload, screen, track, trackEcommerceEvent, validateAnalyticsConfig, validateBatchPayload, validateConfig, validateConfigOrThrow, validateEventPayload, validateProvider, withMetadata, withUTM };
|
package/server.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { _ as AnalyticsManager, a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload, v as createAnalyticsManager } from "./posthog-bootstrap-
|
|
2
|
-
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-
|
|
3
|
-
import { t as ecommerce_exports } from "./ecommerce-
|
|
4
|
-
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-
|
|
5
|
-
import { a as debugConfig, c as validateProvider, i as validateEventPayload, l as createServerAnalytics, n as createIngestionService, o as validateAnalyticsConfig, r as validateBatchPayload, s as validateConfigOrThrow, t as IngestionService, u as createServerAnalyticsUninitialized } from "./service-
|
|
1
|
+
import { _ as AnalyticsManager, a as ContextBuilder, c as createAnonymousSession, d as isGroupPayload, f as isIdentifyPayload, g as withUTM, h as withMetadata, l as createUserSession, m as isTrackPayload, n as createMinimalBootstrapData, o as EventBatch, p as isPagePayload, r as generateDistinctId, s as PayloadBuilder, t as createBootstrapData, u as isAliasPayload, v as createAnalyticsManager } from "./posthog-bootstrap-DkPdn-hA.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-BvEelkxS.mjs";
|
|
3
|
+
import { t as ecommerce_exports } from "./ecommerce-DGG1FbiH.mjs";
|
|
4
|
+
import { a as createEmitterProcessor, i as validateConfig, n as createConfigBuilder, o as processEmitterPayload, r as getAnalyticsConfig, s as trackEcommerceEvent, t as PROVIDER_REQUIREMENTS } from "./config-6Mwe7b2O.mjs";
|
|
5
|
+
import { a as debugConfig, c as validateProvider, i as validateEventPayload, l as createServerAnalytics, n as createIngestionService, o as validateAnalyticsConfig, r as validateBatchPayload, s as validateConfigOrThrow, t as IngestionService, u as createServerAnalyticsUninitialized } from "./service-NuHnv30x.mjs";
|
|
6
6
|
|
|
7
7
|
export { AnalyticsManager as AnalyticsManagerClass, ContextBuilder, EventBatch, IngestionService, PROVIDER_REQUIREMENTS, PayloadBuilder, alias, createAnalyticsManager, createAnonymousSession, createBootstrapData, createConfigBuilder, createEmitterProcessor, createIngestionService, createMinimalBootstrapData, createServerAnalytics, createServerAnalyticsUninitialized, createUserSession, debugConfig, ecommerce_exports as ecommerce, generateDistinctId, getAnalyticsConfig, group, identify, isAliasPayload, isGroupPayload, isIdentifyPayload, isPagePayload, isTrackPayload, page, processEmitterPayload, screen, track, trackEcommerceEvent, validateAnalyticsConfig, validateBatchPayload, validateConfig, validateConfigOrThrow, validateEventPayload, validateProvider, withMetadata, withUTM };
|
|
@@ -1,117 +1,12 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { i as logWarn, n as logError, r as logInfo, t as logDebug } from "./core-DBLE5iTF.mjs";
|
|
2
|
+
import { t as ConsoleProvider } from "./console-BpU88FNF.mjs";
|
|
3
|
+
import { b as validateEventName, v as createAnalyticsManager, y as sanitizeProperties } from "./posthog-bootstrap-DkPdn-hA.mjs";
|
|
4
|
+
import { t as PROVIDER_REQUIREMENTS } from "./config-6Mwe7b2O.mjs";
|
|
4
5
|
import { HttpServerProvider } from "./providers-http-server.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
6
|
+
import { SegmentServerProvider } from "@od-oneapp/integration-segment/analytics-provider/server";
|
|
7
|
+
import { VercelServerProvider } from "@od-oneapp/integration-vercel/analytics-provider/server";
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
|
|
9
|
-
//#region ../../integrations/segment/src/analytics-provider/server.ts
|
|
10
|
-
var SegmentServerProvider = class {
|
|
11
|
-
name = "segment";
|
|
12
|
-
analytics = null;
|
|
13
|
-
config;
|
|
14
|
-
isInitialized = false;
|
|
15
|
-
constructor(config) {
|
|
16
|
-
if (!config.writeKey) throw new Error("Segment writeKey is required");
|
|
17
|
-
this.config = {
|
|
18
|
-
options: config.options,
|
|
19
|
-
writeKey: config.writeKey
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
async initialize() {
|
|
23
|
-
if (this.isInitialized) return;
|
|
24
|
-
const { Analytics } = await import(
|
|
25
|
-
/* webpackChunkName: "segment-analytics" */
|
|
26
|
-
"@segment/analytics-next"
|
|
27
|
-
);
|
|
28
|
-
this.analytics = new Analytics({
|
|
29
|
-
writeKey: this.config.writeKey,
|
|
30
|
-
...this.config.options
|
|
31
|
-
});
|
|
32
|
-
this.isInitialized = true;
|
|
33
|
-
}
|
|
34
|
-
async track(event, properties = {}, _context) {
|
|
35
|
-
if (!this.analytics) return;
|
|
36
|
-
await this.analytics.track({
|
|
37
|
-
event,
|
|
38
|
-
properties
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
async identify(userId, traits = {}, _context) {
|
|
42
|
-
if (!this.analytics) return;
|
|
43
|
-
await this.analytics.identify({
|
|
44
|
-
userId,
|
|
45
|
-
traits
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
async page(name, properties = {}, _context) {
|
|
49
|
-
if (!this.analytics) return;
|
|
50
|
-
await this.analytics.page({
|
|
51
|
-
...name && { name },
|
|
52
|
-
properties
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
async group(groupId, traits = {}, _context) {
|
|
56
|
-
if (!this.analytics) return;
|
|
57
|
-
await this.analytics.group({
|
|
58
|
-
groupId,
|
|
59
|
-
traits
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
async alias(userId, previousId, _context) {
|
|
63
|
-
if (!this.analytics) return;
|
|
64
|
-
await this.analytics.alias({
|
|
65
|
-
userId,
|
|
66
|
-
previousId
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
//#endregion
|
|
72
|
-
//#region ../../integrations/vercel/src/analytics-provider/server.ts
|
|
73
|
-
var VercelServerProvider = class {
|
|
74
|
-
name = "vercel";
|
|
75
|
-
isInitialized = false;
|
|
76
|
-
config;
|
|
77
|
-
constructor(config) {
|
|
78
|
-
this.config = config;
|
|
79
|
-
}
|
|
80
|
-
async initialize() {
|
|
81
|
-
if (this.isInitialized) return;
|
|
82
|
-
this.isInitialized = true;
|
|
83
|
-
}
|
|
84
|
-
async track(event, properties = {}) {
|
|
85
|
-
if (!this.isInitialized) return;
|
|
86
|
-
this.config;
|
|
87
|
-
}
|
|
88
|
-
async identify(userId, traits = {}) {
|
|
89
|
-
await this.track("User Identified", {
|
|
90
|
-
userId,
|
|
91
|
-
...traits
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
async page(name, properties = {}) {
|
|
95
|
-
await this.track("Page View (Server)", {
|
|
96
|
-
page: name,
|
|
97
|
-
...properties
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
async group(groupId, traits = {}) {
|
|
101
|
-
await this.track("Group Identified", {
|
|
102
|
-
groupId,
|
|
103
|
-
...traits
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
async alias(userId, previousId) {
|
|
107
|
-
await this.track("User Aliased", {
|
|
108
|
-
previousId,
|
|
109
|
-
userId
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
//#endregion
|
|
115
10
|
//#region src/server/manager.ts
|
|
116
11
|
/**
|
|
117
12
|
* @fileoverview Server analytics manager with static provider registry
|
|
@@ -631,6 +526,20 @@ const EventResultSchema = z.object({
|
|
|
631
526
|
error: z.string().optional()
|
|
632
527
|
});
|
|
633
528
|
/**
|
|
529
|
+
* Dispatch outcome for analytics forwarding.
|
|
530
|
+
*/
|
|
531
|
+
const IngestionDispatchResultSchema = z.object({
|
|
532
|
+
scheduled: z.number().int().nonnegative(),
|
|
533
|
+
attempted: z.number().int().nonnegative(),
|
|
534
|
+
failed: z.number().int().nonnegative(),
|
|
535
|
+
status: z.enum([
|
|
536
|
+
"skipped",
|
|
537
|
+
"pending",
|
|
538
|
+
"completed",
|
|
539
|
+
"completed_with_failures"
|
|
540
|
+
])
|
|
541
|
+
});
|
|
542
|
+
/**
|
|
634
543
|
* Successful ingestion response schema.
|
|
635
544
|
*/
|
|
636
545
|
const IngestionSuccessResponseSchema = z.object({
|
|
@@ -638,6 +547,7 @@ const IngestionSuccessResponseSchema = z.object({
|
|
|
638
547
|
accepted: z.number().int().nonnegative(),
|
|
639
548
|
rejected: z.number().int().nonnegative(),
|
|
640
549
|
results: z.array(EventResultSchema),
|
|
550
|
+
dispatch: IngestionDispatchResultSchema.optional(),
|
|
641
551
|
receivedAt: z.string().datetime()
|
|
642
552
|
});
|
|
643
553
|
/**
|
|
@@ -680,7 +590,8 @@ const DEFAULT_CONFIG = {
|
|
|
680
590
|
stripPII: true,
|
|
681
591
|
stripHTML: true,
|
|
682
592
|
eventTimeout: 5e3,
|
|
683
|
-
batchConcurrency: 10
|
|
593
|
+
batchConcurrency: 10,
|
|
594
|
+
awaitDispatch: false
|
|
684
595
|
};
|
|
685
596
|
/**
|
|
686
597
|
* Generate a UUID v4.
|
|
@@ -901,7 +812,7 @@ var IngestionService = class {
|
|
|
901
812
|
allowDangerousKeys: false
|
|
902
813
|
});
|
|
903
814
|
normalized.properties = sanitized.data;
|
|
904
|
-
if (sanitized.warnings.length > 0) logDebug
|
|
815
|
+
if (sanitized.warnings.length > 0) logDebug("Event properties sanitized", {
|
|
905
816
|
eventId,
|
|
906
817
|
warnings: sanitized.warnings
|
|
907
818
|
});
|
|
@@ -931,31 +842,51 @@ var IngestionService = class {
|
|
|
931
842
|
error: errorMessage
|
|
932
843
|
});
|
|
933
844
|
metrics.rejected++;
|
|
934
|
-
logWarn
|
|
845
|
+
logWarn("Event processing failed", {
|
|
935
846
|
eventId,
|
|
936
847
|
type: event.type,
|
|
937
848
|
error: errorMessage
|
|
938
849
|
});
|
|
939
850
|
}
|
|
940
851
|
}
|
|
941
|
-
|
|
852
|
+
const dispatch = {
|
|
853
|
+
scheduled: 0,
|
|
854
|
+
attempted: 0,
|
|
855
|
+
failed: 0,
|
|
856
|
+
status: processedEvents.length > 0 ? "pending" : "skipped"
|
|
857
|
+
};
|
|
858
|
+
const forwardEvents = async () => {
|
|
942
859
|
try {
|
|
943
860
|
await this.analyticsManager.emitBatch(processedEvents, {
|
|
944
861
|
timeout: this.config.eventTimeout,
|
|
945
862
|
concurrency: this.config.batchConcurrency,
|
|
946
863
|
failFast: false
|
|
947
864
|
});
|
|
865
|
+
if (this.config.awaitDispatch) {
|
|
866
|
+
dispatch.status = "completed";
|
|
867
|
+
dispatch.attempted = processedEvents.length;
|
|
868
|
+
}
|
|
948
869
|
} catch (error) {
|
|
949
|
-
|
|
870
|
+
if (this.config.awaitDispatch) {
|
|
871
|
+
dispatch.status = "completed_with_failures";
|
|
872
|
+
dispatch.attempted = processedEvents.length;
|
|
873
|
+
dispatch.failed = processedEvents.length;
|
|
874
|
+
}
|
|
875
|
+
logError("Failed to emit events to analytics manager", {
|
|
950
876
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
951
877
|
eventCount: processedEvents.length,
|
|
952
878
|
traceId: context.traceId
|
|
953
879
|
});
|
|
954
880
|
}
|
|
955
|
-
}
|
|
881
|
+
};
|
|
882
|
+
if (processedEvents.length > 0) {
|
|
883
|
+
dispatch.scheduled = processedEvents.length;
|
|
884
|
+
if (this.config.awaitDispatch) await forwardEvents();
|
|
885
|
+
else forwardEvents();
|
|
886
|
+
}
|
|
956
887
|
const endTime = process.hrtime.bigint();
|
|
957
888
|
metrics.processingTimeMs = Number(endTime - startTime) / 1e6;
|
|
958
|
-
logInfo
|
|
889
|
+
logInfo("Event ingestion completed", {
|
|
959
890
|
traceId: context.traceId,
|
|
960
891
|
source: context.source,
|
|
961
892
|
tenantId: context.tenantId,
|
|
@@ -970,6 +901,7 @@ var IngestionService = class {
|
|
|
970
901
|
accepted: metrics.accepted,
|
|
971
902
|
rejected: metrics.rejected,
|
|
972
903
|
results,
|
|
904
|
+
dispatch,
|
|
973
905
|
receivedAt
|
|
974
906
|
};
|
|
975
907
|
}
|
|
@@ -1046,4 +978,4 @@ function validateBatchPayload(payloads) {
|
|
|
1046
978
|
|
|
1047
979
|
//#endregion
|
|
1048
980
|
export { debugConfig as a, validateProvider as c, validateEventPayload as i, createServerAnalytics as l, createIngestionService as n, validateAnalyticsConfig as o, validateBatchPayload as r, validateConfigOrThrow as s, IngestionService as t, createServerAnalyticsUninitialized as u };
|
|
1049
|
-
//# sourceMappingURL=service-
|
|
981
|
+
//# sourceMappingURL=service-NuHnv30x.mjs.map
|