@od-oneapp/analytics 2026.2.1701 → 2026.2.2001-canary.1
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-BSaTnqoc.mjs} +2 -2
- package/{ai-YMnynb-t.mjs.map → ai-BSaTnqoc.mjs.map} +1 -1
- package/{client-D339NFJS.mjs → client-B0v807xN.mjs} +1 -1
- package/{client-D339NFJS.mjs.map → client-B0v807xN.mjs.map} +1 -1
- package/{client-CcFTauAh.mjs → client-BrLI6DF9.mjs} +1 -1
- package/{client-CcFTauAh.mjs.map → client-BrLI6DF9.mjs.map} +1 -1
- package/{client-CeOLjbac.mjs → client-ClA-Qeks.mjs} +21 -6
- package/client-ClA-Qeks.mjs.map +1 -0
- package/client-next.d.mts +7 -7
- package/client-next.d.mts.map +1 -1
- package/client-next.mjs +1616 -31
- package/client-next.mjs.map +1 -1
- package/{client-CTzJVFU5.mjs → client-uX7stpb0.mjs} +2 -2
- package/{client-CTzJVFU5.mjs.map → client-uX7stpb0.mjs.map} +1 -1
- package/client.d.mts +9 -9
- package/client.mjs +8 -116
- package/client.mjs.map +1 -1
- package/{config-DPS6bSYo.d.mts → config-BA1zbRTh.d.mts} +2 -2
- package/{config-DPS6bSYo.d.mts.map → config-BA1zbRTh.d.mts.map} +1 -1
- package/{config-P6P5adJg.mjs → config-DKN8G0TI.mjs} +1 -1
- package/{config-P6P5adJg.mjs.map → config-DKN8G0TI.mjs.map} +1 -1
- package/{console-8bND3mMU.mjs → console-CDP0gY0K.mjs} +2 -2
- package/console-CDP0gY0K.mjs.map +1 -0
- package/core-C3oFD9Vr.mjs +95 -0
- package/core-C3oFD9Vr.mjs.map +1 -0
- package/{ecommerce-Cgu4wlux.mjs → ecommerce-DAo98u3I.mjs} +2 -2
- package/{ecommerce-Cgu4wlux.mjs.map → ecommerce-DAo98u3I.mjs.map} +1 -1
- package/{emitters-DldkVSPp.d.mts → emitters-B2gDJtjd.d.mts} +2 -2
- package/{emitters-DldkVSPp.d.mts.map → emitters-B2gDJtjd.d.mts.map} +1 -1
- package/{emitters-6-nKo8i-.mjs → emitters-RheHbeX2.mjs} +1 -1
- package/{emitters-6-nKo8i-.mjs.map → emitters-RheHbeX2.mjs.map} +1 -1
- package/{index-jPzXRn52.d.mts → index-Bq051UsT.d.mts} +3 -3
- package/{index-jPzXRn52.d.mts.map → index-Bq051UsT.d.mts.map} +1 -1
- package/{index-BfNWgfa5.d.mts → index-CuDXrdLY.d.mts} +14 -2
- package/{index-BfNWgfa5.d.mts.map → index-CuDXrdLY.d.mts.map} +1 -1
- package/{index-BkIWe--N.d.mts → index-uQHwlV0P.d.mts} +2 -2
- package/{index-BkIWe--N.d.mts.map → index-uQHwlV0P.d.mts.map} +1 -1
- package/logs-8LsA--uG.mjs +112 -0
- package/logs-8LsA--uG.mjs.map +1 -0
- package/{manager-DvRRjza6.d.mts → manager-Dh9loalA.d.mts} +3 -2
- package/manager-Dh9loalA.d.mts.map +1 -0
- package/module-D5xR4CAy.mjs +5808 -0
- package/module-D5xR4CAy.mjs.map +1 -0
- package/package.json +21 -27
- package/{posthog-bootstrap-DWxFrxlt.d.mts → posthog-bootstrap-D7Ot--Qc.d.mts} +3 -3
- package/{posthog-bootstrap-DWxFrxlt.d.mts.map → posthog-bootstrap-D7Ot--Qc.d.mts.map} +1 -1
- package/{posthog-bootstrap-CYfIy_WS.mjs → posthog-bootstrap-DkDBbvMJ.mjs} +81 -46
- package/posthog-bootstrap-DkDBbvMJ.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-tn0JFfVH.mjs} +49 -116
- package/service-tn0JFfVH.mjs.map +1 -0
- package/shared.d.mts +4 -4
- package/shared.mjs +3 -3
- package/{types-BxBnNQ0V.d.mts → types-BbXOa_UL.d.mts} +1 -1
- package/{types-BxBnNQ0V.d.mts.map → types-BbXOa_UL.d.mts.map} +1 -1
- package/{types-CBvxUEaF.d.mts → types-DC5uYgdR.d.mts} +1 -1
- package/{types-CBvxUEaF.d.mts.map → types-DC5uYgdR.d.mts.map} +1 -1
- package/types.d.mts +3 -3
- package/{vercel-types-lwakUfoI.d.mts → vercel-types-tUdlBxJ-.d.mts} +1 -1
- package/{vercel-types-lwakUfoI.d.mts.map → vercel-types-tUdlBxJ-.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":";;;;;;;;;;;;;;;;;;AA6BA,MAAM,WAAW;CACf,WAAW;CACX,eAAe;CACf,SAAS;CACT,SAAS;CACV;;AAGD,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;AAqBxB,IAAa,qBAAb,MAA6D;CAC3D,AAAS,OAAO;CAEhB,AAAQ;CAIR,AAAQ,gBAAgB;CACxB,AAAQ,QAAuB,EAAE;CACjC,AAAQ,aAAoD;CAC5D,AAAQ;CACR,AAAQ;CACR,AAAQ,aAAa;CAErB,YAAY,gBAAgC;EAC1C,MAAM,UAAW,eAAe,WAAW,EAAE;AAE7C,MAAI,CAAC,QAAQ,SACX,OAAM,IAAI,MAAM,wCAAwC;AAG1D,OAAK,SAAS;GACZ,GAAG;GACH,WAAW,QAAQ,aAAa,SAAS;GACzC,eAAe,QAAQ,iBAAiB,SAAS;GACjD,SAAS,QAAQ,WAAW,SAAS;GACrC,SAAS,QAAQ,WAAW,SAAS;GACtC;AAED,OAAK,SAAS,QAAQ;AACtB,OAAK,cAAc,QAAQ,eAAe,KAAK,qBAAqB;;CAGtE,MAAM,aAA4B;AAChC,MAAI,KAAK,cAAe;AAGxB,MAAI,KAAK,OAAO,gBAAgB,GAAG;AACjC,QAAK,aAAa,kBAAkB;AAClC,IAAK,KAAK,OAAO;MAChB,KAAK,OAAO,cAAc;AAG7B,OAAI,OAAO,KAAK,WAAW,UAAU,WACnC,MAAK,WAAW,OAAO;;AAI3B,MAAI,KAAK,OAAO,MACd,UAAS,uCAAuC;GAC9C,UAAU;GACV,UAAU,KAAK,OAAO;GACtB,WAAW,KAAK,OAAO;GACvB,eAAe,KAAK,OAAO;GAC5B,CAAC;AAGJ,OAAK,gBAAgB;;CAGvB,MAAM,MACJ,OACA,aAAyB,EAAE,EAC3B,UACe;AACf,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,iCAAiC;IAAE,UAAU;IAAQ,WAAW;IAAS;IAAO,CAAC;AACzF;;AAGF,OAAK,QAAQ;GACX,MAAM;GACN;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,QAAQ,KAAK;GACb,aAAa,KAAK;GACnB,CAAC;;CAGJ,MAAM,SACJ,QACA,SAAqB,EAAE,EACvB,UACe;AACf,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,iCAAiC;IAAE,UAAU;IAAQ,WAAW;IAAY;IAAQ,CAAC;AAC7F;;AAIF,OAAK,SAAS;AAEd,OAAK,QAAQ;GACX,MAAM;GACN;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,aAAa,KAAK;GACnB,CAAC;;CAGJ,MAAM,KACJ,MACA,aAA6B,EAAE,EAC/B,UACe;AACf,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,iCAAiC;IAAE,UAAU;IAAQ,WAAW;IAAQ;IAAM,CAAC;AACvF;;AAGF,OAAK,QAAQ;GACX,MAAM;GACN;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,QAAQ,KAAK;GACb,aAAa,KAAK;GACnB,CAAC;;CAGJ,MAAM,MACJ,SACA,SAAsB,EAAE,EACxB,UACe;AACf,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,iCAAiC;IAAE,UAAU;IAAQ,WAAW;IAAS;IAAS,CAAC;AAC3F;;AAGF,OAAK,QAAQ;GACX,MAAM;GACN;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,QAAQ,KAAK;GACb,aAAa,KAAK;GACnB,CAAC;;CAGJ,MAAM,MAAM,QAAgB,YAAoB,UAA4C;AAC1F,MAAI,CAAC,KAAK,eAAe;AACvB,WAAQ,iCAAiC;IACvC,UAAU;IACV,WAAW;IACX;IACA;IACD,CAAC;AACF;;AAGF,OAAK,QAAQ;GACX,MAAM;GACN;GACA;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,aAAa,KAAK;GACnB,CAAC;;;;;;CAOJ,MAAM,QAAuB;AAC3B,MAAI,KAAK,MAAM,WAAW,KAAK,KAAK,WAAY;AAEhD,OAAK,aAAa;EAGlB,MAAM,SAAS,CAAC,GAAG,KAAK,MAAM;AAC9B,OAAK,QAAQ,EAAE;AAEf,MAAI;AACF,SAAM,KAAK,UAAU,OAAO;WACrB,OAAO;AAEd,QAAK,MAAM,QAAQ,GAAG,OAAO;AAC7B,YAAS,+CAA+C;IACtD,UAAU;IACV,YAAY,OAAO;IACnB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D,CAAC;YACM;AACR,QAAK,aAAa;;;;;;;CAQtB,MAAM,WAA0B;AAC9B,MAAI,KAAK,YAAY;AACnB,iBAAc,KAAK,WAAW;AAC9B,QAAK,aAAa;;AAIpB,QAAM,KAAK,OAAO;AAClB,OAAK,gBAAgB;;;;;CAMvB,iBAAyB;AACvB,SAAO,KAAK,MAAM;;CAOpB,AAAQ,QAAQ,OAA0B;AACxC,OAAK,MAAM,KAAK,MAAM;AAEtB,MAAI,KAAK,OAAO,MACd,UAAS,gBAAgB;GACvB,UAAU;GACV,MAAM,MAAM;GACZ,aAAa,KAAK,MAAM;GACzB,CAAC;AAIJ,MAAI,KAAK,MAAM,UAAU,KAAK,OAAO,UACnC,CAAK,KAAK,OAAO;;CAIrB,MAAc,UAAU,QAAsC;EAC5D,MAAM,UAAU,EAAE,OAAO,QAAQ;EAEjC,IAAI,YAA0B;AAE9B,OAAK,IAAI,UAAU,GAAG,WAAW,KAAK,OAAO,SAAS,UACpD,KAAI;GACF,MAAM,WAAW,MAAM,KAAK,YAAY,QAAQ;AAEhD,OAAI,SAAS,SAAS;AACpB,QAAI,KAAK,OAAO,MACd,UAAS,2BAA2B;KAClC,UAAU;KACV,UAAU,SAAS;KACnB,UAAU,SAAS;KACpB,CAAC;AAEJ;;AAIF,WAAQ,4BAA4B;IAClC,UAAU;IACV,UAAU,SAAS;IACnB,UAAU,SAAS;IACnB,OAAO,SAAS;IACjB,CAAC;AACF;WACO,OAAO;AACd,eAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AAErE,OAAI,UAAU,KAAK,OAAO,SAAS;IAEjC,MAAM,QAAQ,kBAAkB,KAAK,IAAI,GAAG,QAAQ;AAEpD,QAAI,KAAK,OAAO,MACd,UAAS,uBAAuB;KAC9B,UAAU;KACV,SAAS,UAAU;KACnB,YAAY,KAAK,OAAO;KACxB,SAAS;KACV,CAAC;AAGJ,UAAM,KAAK,MAAM,MAAM;;;AAM7B,QAAM,6BAAa,IAAI,MAAM,qCAAqC;;CAGpE,MAAc,YAAY,SAA+D;EACvF,MAAM,UAAkC;GACtC,gBAAgB;GAChB,GAAG,KAAK,OAAO;GAChB;AAED,MAAI,KAAK,OAAO,OACd,SAAQ,eAAe,KAAK,OAAO;EAGrC,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,YAAY,iBAAiB,WAAW,OAAO,EAAE,KAAK,OAAO,QAAQ;AAE3E,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,KAAK,OAAO,UAAU;IACjD,QAAQ;IACR;IACA,MAAM,KAAK,UAAU,QAAQ;IAC7B,QAAQ,WAAW;IACpB,CAAC;AAEF,OAAI,CAAC,SAAS,IAAI;AAEhB,QAAI,SAAS,WAAW,KAAK;KAC3B,MAAM,aAAa,SAAS,QAAQ,IAAI,cAAc;AACtD,WAAM,IAAI,MAAM,6BAA6B,cAAc,UAAU,UAAU;;IAGjF,MAAM,YAAY,MAAM,SAAS,MAAM;AACvC,UAAM,IAAI,MAAM,QAAQ,SAAS,OAAO,IAAI,YAAY;;AAG1D,UAAQ,MAAM,SAAS,MAAM;YACrB;AACR,gBAAa,UAAU;;;CAI3B,AAAQ,sBAA8B;AAEpC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAChE,QAAO,OAAO,YAAY;AAI5B,SAAO,QAAQ,KAAK,KAAK,CAAC,SAAS,GAAG,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;;CAGjF,AAAQ,MAAM,IAA2B;AACvC,SAAO,IAAI,SAAQ,YAAW,WAAW,SAAS,GAAG,CAAC"}
|
|
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-BbXOa_UL.mjs";
|
|
2
|
+
import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-B2gDJtjd.mjs";
|
|
3
|
+
import { a as createEmitterProcessor, r as getAnalyticsConfig } from "./config-BA1zbRTh.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-C3oFD9Vr.mjs";
|
|
2
|
+
import { i as page, n as group, o as track, r as identify, t as alias } from "./emitters-RheHbeX2.mjs";
|
|
3
|
+
import { a as createEmitterProcessor, r as getAnalyticsConfig } from "./config-DKN8G0TI.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-CDP0gY0K.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-BbXOa_UL.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-B2gDJtjd.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-D7Ot--Qc.mjs";
|
|
4
|
+
import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-DC5uYgdR.mjs";
|
|
5
|
+
import { t as index_d_exports } from "./index-Bq051UsT.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-BA1zbRTh.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-tUdlBxJ-.mjs";
|
|
8
|
+
import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-Dh9loalA.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-CuDXrdLY.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-DkDBbvMJ.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-RheHbeX2.mjs";
|
|
3
|
+
import { t as ecommerce_exports } from "./ecommerce-DAo98u3I.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-DKN8G0TI.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-tn0JFfVH.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-BbXOa_UL.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-B2gDJtjd.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-D7Ot--Qc.mjs";
|
|
4
|
+
import { d as EcommerceEventSpec, m as OrderProperties, p as ExtendedProductProperties, r as CartProperties, t as BaseProductProperties } from "./types-DC5uYgdR.mjs";
|
|
5
|
+
import { t as index_d_exports } from "./index-Bq051UsT.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-BA1zbRTh.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-tUdlBxJ-.mjs";
|
|
8
|
+
import { n as createAnalyticsManager, t as AnalyticsManager$1 } from "./manager-Dh9loalA.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-CuDXrdLY.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-DkDBbvMJ.mjs";
|
|
2
|
+
import { a as screen, i as page, n as group, o as track, r as identify, t as alias } from "./emitters-RheHbeX2.mjs";
|
|
3
|
+
import { t as ecommerce_exports } from "./ecommerce-DAo98u3I.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-DKN8G0TI.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-tn0JFfVH.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,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
1
|
+
import { i as logWarn, n as logError, r as logInfo } from "./core-C3oFD9Vr.mjs";
|
|
2
|
+
import { t as ConsoleProvider } from "./console-CDP0gY0K.mjs";
|
|
3
|
+
import { i as logWarn$1, n as logError$1, r as logInfo$1, t as logDebug } from "./logs-8LsA--uG.mjs";
|
|
4
|
+
import { b as validateEventName, v as createAnalyticsManager, y as sanitizeProperties } from "./posthog-bootstrap-DkDBbvMJ.mjs";
|
|
5
|
+
import { t as PROVIDER_REQUIREMENTS } from "./config-DKN8G0TI.mjs";
|
|
4
6
|
import { HttpServerProvider } from "./providers-http-server.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
+
import { SegmentServerProvider } from "@od-oneapp/integration-segment/analytics-provider/server";
|
|
8
|
+
import { VercelServerProvider } from "@od-oneapp/integration-vercel/analytics-provider/server";
|
|
7
9
|
import { z } from "zod";
|
|
8
10
|
|
|
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
11
|
//#region src/server/manager.ts
|
|
116
12
|
/**
|
|
117
13
|
* @fileoverview Server analytics manager with static provider registry
|
|
@@ -631,6 +527,20 @@ const EventResultSchema = z.object({
|
|
|
631
527
|
error: z.string().optional()
|
|
632
528
|
});
|
|
633
529
|
/**
|
|
530
|
+
* Dispatch outcome for analytics forwarding.
|
|
531
|
+
*/
|
|
532
|
+
const IngestionDispatchResultSchema = z.object({
|
|
533
|
+
scheduled: z.number().int().nonnegative(),
|
|
534
|
+
attempted: z.number().int().nonnegative(),
|
|
535
|
+
failed: z.number().int().nonnegative(),
|
|
536
|
+
status: z.enum([
|
|
537
|
+
"skipped",
|
|
538
|
+
"pending",
|
|
539
|
+
"completed",
|
|
540
|
+
"completed_with_failures"
|
|
541
|
+
])
|
|
542
|
+
});
|
|
543
|
+
/**
|
|
634
544
|
* Successful ingestion response schema.
|
|
635
545
|
*/
|
|
636
546
|
const IngestionSuccessResponseSchema = z.object({
|
|
@@ -638,6 +548,7 @@ const IngestionSuccessResponseSchema = z.object({
|
|
|
638
548
|
accepted: z.number().int().nonnegative(),
|
|
639
549
|
rejected: z.number().int().nonnegative(),
|
|
640
550
|
results: z.array(EventResultSchema),
|
|
551
|
+
dispatch: IngestionDispatchResultSchema.optional(),
|
|
641
552
|
receivedAt: z.string().datetime()
|
|
642
553
|
});
|
|
643
554
|
/**
|
|
@@ -680,7 +591,8 @@ const DEFAULT_CONFIG = {
|
|
|
680
591
|
stripPII: true,
|
|
681
592
|
stripHTML: true,
|
|
682
593
|
eventTimeout: 5e3,
|
|
683
|
-
batchConcurrency: 10
|
|
594
|
+
batchConcurrency: 10,
|
|
595
|
+
awaitDispatch: false
|
|
684
596
|
};
|
|
685
597
|
/**
|
|
686
598
|
* Generate a UUID v4.
|
|
@@ -901,7 +813,7 @@ var IngestionService = class {
|
|
|
901
813
|
allowDangerousKeys: false
|
|
902
814
|
});
|
|
903
815
|
normalized.properties = sanitized.data;
|
|
904
|
-
if (sanitized.warnings.length > 0) logDebug
|
|
816
|
+
if (sanitized.warnings.length > 0) logDebug("Event properties sanitized", {
|
|
905
817
|
eventId,
|
|
906
818
|
warnings: sanitized.warnings
|
|
907
819
|
});
|
|
@@ -938,21 +850,41 @@ var IngestionService = class {
|
|
|
938
850
|
});
|
|
939
851
|
}
|
|
940
852
|
}
|
|
941
|
-
|
|
853
|
+
const dispatch = {
|
|
854
|
+
scheduled: 0,
|
|
855
|
+
attempted: 0,
|
|
856
|
+
failed: 0,
|
|
857
|
+
status: processedEvents.length > 0 ? "pending" : "skipped"
|
|
858
|
+
};
|
|
859
|
+
const forwardEvents = async () => {
|
|
942
860
|
try {
|
|
943
861
|
await this.analyticsManager.emitBatch(processedEvents, {
|
|
944
862
|
timeout: this.config.eventTimeout,
|
|
945
863
|
concurrency: this.config.batchConcurrency,
|
|
946
864
|
failFast: false
|
|
947
865
|
});
|
|
866
|
+
if (this.config.awaitDispatch) {
|
|
867
|
+
dispatch.status = "completed";
|
|
868
|
+
dispatch.attempted = processedEvents.length;
|
|
869
|
+
}
|
|
948
870
|
} catch (error) {
|
|
871
|
+
if (this.config.awaitDispatch) {
|
|
872
|
+
dispatch.status = "completed_with_failures";
|
|
873
|
+
dispatch.attempted = processedEvents.length;
|
|
874
|
+
dispatch.failed = processedEvents.length;
|
|
875
|
+
}
|
|
949
876
|
logError$1("Failed to emit events to analytics manager", {
|
|
950
877
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
951
878
|
eventCount: processedEvents.length,
|
|
952
879
|
traceId: context.traceId
|
|
953
880
|
});
|
|
954
881
|
}
|
|
955
|
-
}
|
|
882
|
+
};
|
|
883
|
+
if (processedEvents.length > 0) {
|
|
884
|
+
dispatch.scheduled = processedEvents.length;
|
|
885
|
+
if (this.config.awaitDispatch) await forwardEvents();
|
|
886
|
+
else forwardEvents();
|
|
887
|
+
}
|
|
956
888
|
const endTime = process.hrtime.bigint();
|
|
957
889
|
metrics.processingTimeMs = Number(endTime - startTime) / 1e6;
|
|
958
890
|
logInfo$1("Event ingestion completed", {
|
|
@@ -970,6 +902,7 @@ var IngestionService = class {
|
|
|
970
902
|
accepted: metrics.accepted,
|
|
971
903
|
rejected: metrics.rejected,
|
|
972
904
|
results,
|
|
905
|
+
dispatch,
|
|
973
906
|
receivedAt
|
|
974
907
|
};
|
|
975
908
|
}
|
|
@@ -1046,4 +979,4 @@ function validateBatchPayload(payloads) {
|
|
|
1046
979
|
|
|
1047
980
|
//#endregion
|
|
1048
981
|
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-
|
|
982
|
+
//# sourceMappingURL=service-tn0JFfVH.mjs.map
|