{"version":3,"file":"index.cjs","names":["API_ROUTES","API_ROUTES","isVitalType","isVitalRating","isNavigationType"],"sources":["../../src/server/deployment.ts","../../src/server/identity.ts","../../src/server/forms.ts","../../src/server/middleware.ts","../../src/server/proxy.ts","../../src/server/track.ts","../../src/server/vitals.ts"],"sourcesContent":["/**\n * Deployment detection utilities for Next.js\n * Auto-detects deployment info from Vercel, Netlify, Cloudflare, and other platforms\n */\n\n// Declare process for environments where it exists\ndeclare const process: { env: Record<string, string | undefined> } | undefined;\n\nexport interface DeploymentInfo {\n  /** Deployment ID from platform */\n  deployId?: string;\n  /** Git commit SHA */\n  gitSha?: string;\n  /** Git branch */\n  gitBranch?: string;\n  /** Deployment URL */\n  deployUrl?: string;\n  /** Platform name */\n  platform?:\n    | 'vercel'\n    | 'netlify'\n    | 'cloudflare'\n    | 'railway'\n    | 'render'\n    | 'github-actions'\n    | 'unknown';\n}\n\n/**\n * Detect deployment information from environment variables.\n * Works on both client and server.\n */\nexport function detectDeployment(): DeploymentInfo {\n  // Server-side detection\n  if (typeof process !== 'undefined' && process.env) {\n    const env = process.env;\n\n    // Vercel\n    if (env.VERCEL) {\n      return {\n        deployId: env.VERCEL_DEPLOYMENT_ID,\n        gitSha: env.VERCEL_GIT_COMMIT_SHA,\n        gitBranch: env.VERCEL_GIT_COMMIT_REF,\n        deployUrl: env.VERCEL_URL ? `https://${env.VERCEL_URL}` : undefined,\n        platform: 'vercel',\n      };\n    }\n\n    // Netlify\n    if (env.NETLIFY) {\n      return {\n        deployId: env.DEPLOY_ID,\n        gitSha: env.COMMIT_REF,\n        gitBranch: env.BRANCH,\n        deployUrl: env.DEPLOY_URL,\n        platform: 'netlify',\n      };\n    }\n\n    // Cloudflare Pages\n    if (env.CF_PAGES) {\n      return {\n        deployId: env.CF_PAGES_COMMIT_SHA,\n        gitSha: env.CF_PAGES_COMMIT_SHA,\n        gitBranch: env.CF_PAGES_BRANCH,\n        deployUrl: env.CF_PAGES_URL,\n        platform: 'cloudflare',\n      };\n    }\n\n    // Railway\n    if (env.RAILWAY_ENVIRONMENT) {\n      return {\n        deployId: env.RAILWAY_DEPLOYMENT_ID,\n        gitSha: env.RAILWAY_GIT_COMMIT_SHA,\n        gitBranch: env.RAILWAY_GIT_BRANCH,\n        platform: 'railway',\n      };\n    }\n\n    // Render\n    if (env.RENDER) {\n      return {\n        deployId: env.RENDER_SERVICE_ID,\n        gitSha: env.RENDER_GIT_COMMIT,\n        gitBranch: env.RENDER_GIT_BRANCH,\n        platform: 'render',\n      };\n    }\n\n    // GitHub Actions\n    if (env.GITHUB_ACTIONS) {\n      return {\n        deployId: env.GITHUB_RUN_ID,\n        gitSha: env.GITHUB_SHA,\n        gitBranch: env.GITHUB_REF_NAME,\n        platform: 'github-actions',\n      };\n    }\n\n    // Generic fallback\n    if (env.DEPLOY_ID || env.GIT_COMMIT) {\n      return {\n        deployId: env.DEPLOY_ID,\n        gitSha: env.GIT_COMMIT || env.COMMIT_SHA,\n        gitBranch: env.GIT_BRANCH || env.BRANCH,\n        platform: 'unknown',\n      };\n    }\n  }\n\n  return { platform: 'unknown' };\n}\n\n/**\n * Get deployment info as a string for display\n */\nexport function getDeploymentLabel(info: DeploymentInfo): string {\n  if (!info.deployId && !info.gitSha) return 'Unknown';\n\n  const parts: string[] = [];\n  if (info.gitBranch) parts.push(info.gitBranch);\n  if (info.gitSha) parts.push(info.gitSha.slice(0, 7));\n  if (info.deployId && !parts.length) parts.push(info.deployId.slice(0, 12));\n\n  return parts.join(' - ') || 'Unknown';\n}\n","export interface SessionVisitorInput {\n  sessionId?: string;\n  visitorId?: string;\n}\n\nexport interface SessionVisitorIds {\n  sessionId: string;\n  visitorId: string;\n}\n\nexport function generateUuid(): string {\n  if (\n    typeof globalThis.crypto !== 'undefined' &&\n    typeof globalThis.crypto.randomUUID === 'function'\n  ) {\n    return globalThis.crypto.randomUUID();\n  }\n\n  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n    const r = Math.floor(Math.random() * 16);\n    const v = c === 'x' ? r : (r & 0x3) | 0x8;\n    return v.toString(16);\n  });\n}\n\nexport function resolveSessionVisitorIds(input: SessionVisitorInput = {}): SessionVisitorIds {\n  return {\n    sessionId: input.sessionId || generateUuid(),\n    visitorId: input.visitorId || generateUuid(),\n  };\n}\n","import { API_ROUTES } from '@entrolytics/shared';\nimport type { FormEventType } from '@entrolytics/shared';\n/**\n * Server-side Form tracking for Next.js\n * Track form submissions from Server Actions and API routes\n */\n\nimport { resolveSessionVisitorIds } from './identity';\n\nexport type { FormEventType };\n\nexport interface FormEventPayload {\n  /** Form event type */\n  eventType: FormEventType;\n  /** Form identifier */\n  formId: string;\n  /** Human-readable form name */\n  formName?: string;\n  /** Page path where form exists */\n  urlPath: string;\n  /** Field name (for field events) */\n  fieldName?: string;\n  /** Field type */\n  fieldType?: string;\n  /** Field position */\n  fieldIndex?: number;\n  /** Time spent on field (ms) */\n  timeOnField?: number;\n  /** Time since form start (ms) */\n  timeSinceStart?: number;\n  /** Error message */\n  errorMessage?: string;\n  /** Whether submission was successful */\n  success?: boolean;\n}\n\nexport interface TrackFormConfig {\n  /** Entrolytics host URL */\n  host: string;\n  /** Public collection API key */\n  apiKey: string;\n  /** Website ID */\n  websiteId: string;\n  /** Optional stable session ID */\n  sessionId?: string;\n  /** Optional stable visitor ID */\n  visitorId?: string;\n}\n\n/**\n * Track a form event from server side (Server Actions, API routes)\n *\n * @example\n * ```ts\n * // In a Server Action\n * 'use server';\n * import { trackServerFormEvent } from '@entrolytics/nextjs/server';\n *\n * export async function submitContactForm(formData: FormData) {\n *   const result = await saveToDatabase(formData);\n *\n *   await trackServerFormEvent(\n *     {\n *       host: process.env.ENTROLYTICS_HOST!,\n *       websiteId: process.env.ENTROLYTICS_WEBSITE_ID!,\n *     },\n *     {\n *       eventType: 'submit',\n *       formId: 'contact-form',\n *       formName: 'Contact Form',\n *       urlPath: '/contact',\n *       success: result.ok,\n *     }\n *   );\n *\n *   return result;\n * }\n * ```\n */\nexport async function trackServerFormEvent(\n  config: TrackFormConfig,\n  event: FormEventPayload,\n): Promise<{ ok: boolean; error?: string }> {\n  const { host, websiteId, apiKey } = config;\n  const baseUrl = host.replace(/\\/$/, '');\n  const { sessionId, visitorId } = resolveSessionVisitorIds(config);\n\n  const payload = {\n    websiteId,\n    sessionId,\n    visitorId,\n    ...event,\n  };\n\n  try {\n    const response = await fetch(`${baseUrl}${API_ROUTES.collectForms}`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'x-api-key': apiKey,\n      },\n      body: JSON.stringify(payload),\n    });\n\n    if (!response.ok) {\n      return { ok: false, error: `HTTP ${response.status}` };\n    }\n\n    return { ok: true };\n  } catch (error) {\n    return {\n      ok: false,\n      error: error instanceof Error ? error.message : 'Unknown error',\n    };\n  }\n}\n\n/**\n * Track multiple form events at once\n */\nexport async function trackServerFormEventsBatch(\n  config: TrackFormConfig,\n  events: FormEventPayload[],\n): Promise<{ ok: boolean; error?: string }> {\n  const { host, websiteId, apiKey } = config;\n  const baseUrl = host.replace(/\\/$/, '');\n  const { sessionId, visitorId } = resolveSessionVisitorIds(config);\n\n  const payload = {\n    websiteId,\n    sessionId,\n    visitorId,\n    events,\n  };\n\n  try {\n    const response = await fetch(`${baseUrl}${API_ROUTES.collectFormsBatch}`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'x-api-key': apiKey,\n      },\n      body: JSON.stringify(payload),\n    });\n\n    if (!response.ok) {\n      return { ok: false, error: `HTTP ${response.status}` };\n    }\n\n    return { ok: true };\n  } catch (error) {\n    return {\n      ok: false,\n      error: error instanceof Error ? error.message : 'Unknown error',\n    };\n  }\n}\n\n/**\n * Helper to create a form submission tracker\n * Wraps a Server Action to automatically track submit events\n *\n * @example\n * ```ts\n * 'use server';\n * import { withFormTracking } from '@entrolytics/nextjs/server';\n *\n * const trackedAction = withFormTracking(\n *   { host: '...', websiteId: '...' },\n *   { formId: 'signup', formName: 'Signup Form', urlPath: '/signup' }\n * );\n *\n * export async function signup(formData: FormData) {\n *   return trackedAction(async () => {\n *     const result = await createUser(formData);\n *     return { success: result.ok };\n *   });\n * }\n * ```\n */\nexport function withFormTracking(\n  config: TrackFormConfig,\n  formInfo: { formId: string; formName?: string; urlPath: string },\n) {\n  return async <T extends { success?: boolean }>(action: () => Promise<T>): Promise<T> => {\n    const startTime = Date.now();\n\n    try {\n      const result = await action();\n\n      await trackServerFormEvent(config, {\n        eventType: 'submit',\n        formId: formInfo.formId,\n        formName: formInfo.formName,\n        urlPath: formInfo.urlPath,\n        success: result.success ?? true,\n        timeSinceStart: Date.now() - startTime,\n      });\n\n      return result;\n    } catch (error) {\n      await trackServerFormEvent(config, {\n        eventType: 'submit',\n        formId: formInfo.formId,\n        formName: formInfo.formName,\n        urlPath: formInfo.urlPath,\n        success: false,\n        timeSinceStart: Date.now() - startTime,\n        errorMessage: error instanceof Error ? error.message : 'Unknown error',\n      });\n\n      throw error;\n    }\n  };\n}\n","import type { NextRequest, NextResponse } from 'next/server';\nimport { resolveSessionVisitorIds } from './identity';\n\ninterface MiddlewareConfig {\n  /** Entrolytics host URL */\n  host: string;\n  /** Public collection API key */\n  apiKey: string;\n  /** Website ID */\n  websiteId: string;\n  /** Route patterns to track (glob patterns) */\n  trackRoutes?: string[];\n  /** Route patterns to exclude */\n  excludeRoutes?: string[];\n  /** Tag for segmentation */\n  tag?: string;\n}\n\ntype MiddlewareHandler = (\n  request: NextRequest,\n  response?: NextResponse | Response,\n) => Promise<NextResponse | Response | undefined> | NextResponse | Response | undefined;\n\nfunction routeToRegex(pattern: string): RegExp {\n  const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n  return new RegExp(`^${escaped}$`);\n}\n\n/**\n * Creates a middleware wrapper that tracks requests to specified routes.\n *\n * @example\n * ```ts\n * // middleware.ts\n * import { withEntrolyticsMiddleware } from '@entrolytics/nextjs/server';\n * import { NextResponse } from 'next/server';\n *\n * const entrolyticsMiddleware = withEntrolyticsMiddleware({\n *   host: process.env.ENTROLYTICS_HOST!,\n *   websiteId: process.env.ENTROLYTICS_WEBSITE_ID!,\n *   trackRoutes: ['/api/*'],\n *   excludeRoutes: ['/api/health', '/api/collect/*'],\n * });\n *\n * export async function middleware(request: NextRequest) {\n *   // Your custom middleware logic\n *   const response = NextResponse.next();\n *\n *   // Track with Entrolytics\n *   return entrolyticsMiddleware(request, response);\n * }\n *\n * export const config = {\n *   matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],\n * };\n * ```\n */\nexport function withEntrolyticsMiddleware(config: MiddlewareConfig): MiddlewareHandler {\n  const {\n    host,\n    apiKey,\n    websiteId,\n    trackRoutes = [],\n    excludeRoutes = ['/api/collect', '/_next', '/favicon.ico'],\n    tag,\n  } = config;\n\n  const baseUrl = host.replace(/\\/$/, '');\n\n  const trackPatterns = trackRoutes.map(routeToRegex);\n  const excludePatterns = excludeRoutes.map(routeToRegex);\n\n  const shouldTrack = (pathname: string): boolean => {\n    // Check exclusions first\n    if (excludePatterns.some(pattern => pattern.test(pathname))) {\n      return false;\n    }\n\n    // If no track patterns specified, track all (except excluded)\n    if (trackPatterns.length === 0) {\n      return false; // Default to not tracking unless specified\n    }\n\n    return trackPatterns.some(pattern => pattern.test(pathname));\n  };\n\n  return async (request: NextRequest, response?: NextResponse | Response) => {\n    const { pathname } = request.nextUrl;\n\n    if (shouldTrack(pathname)) {\n      // Track asynchronously without blocking the response\n      const headers = request.headers;\n      const hostname = headers.get('host') || 'server';\n      const language = headers.get('accept-language')?.split(',')[0] || 'en';\n      const userAgent = headers.get('user-agent') || '';\n      const { sessionId, visitorId } = resolveSessionVisitorIds();\n      const pageUrl = request.nextUrl.toString();\n      const referrer = headers.get('referer');\n\n      const properties: Record<string, string> = {\n        method: request.method,\n        pathname,\n        hostname,\n        language,\n      };\n\n      if (tag) {\n        properties.tag = tag;\n      }\n\n      const payload = {\n        websiteId,\n        eventId: crypto.randomUUID(),\n        timestamp: new Date().toISOString(),\n        sessionId,\n        visitorId,\n        url: pageUrl,\n        eventType: 'custom_event',\n        eventName: 'middleware-request',\n        ...(referrer && { referrer }),\n        properties,\n      };\n\n      // Fire and forget - don't await\n      fetch(`${baseUrl}/collect`, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'x-api-key': apiKey,\n          ...(userAgent && { 'User-Agent': userAgent }),\n        },\n        body: JSON.stringify(payload),\n      }).catch(error => {\n        console.error('[Entrolytics Middleware] tracking error:', error);\n      });\n    }\n\n    return response;\n  };\n}\n\n/**\n * Compose multiple middleware functions.\n *\n * @example\n * ```ts\n * import { composeMiddleware, withEntrolyticsMiddleware } from '@entrolytics/nextjs/server';\n *\n * const entrolytics = withEntrolyticsMiddleware({ ... });\n * const auth = withAuthMiddleware({ ... });\n *\n * export const middleware = composeMiddleware(entrolytics, auth);\n * ```\n */\nexport function composeMiddleware(...middlewares: MiddlewareHandler[]): MiddlewareHandler {\n  return async (request: NextRequest, initialResponse?: NextResponse | Response) => {\n    let response: NextResponse | Response | undefined = initialResponse;\n\n    for (const middleware of middlewares) {\n      const result = await middleware(request, response);\n      if (result) {\n        response = result;\n      }\n    }\n\n    return response;\n  };\n}\n","import type { NextRequest } from 'next/server';\nimport { resolveSessionVisitorIds } from './identity';\n\ninterface ProxyHandlerConfig {\n  /** Entrolytics host URL */\n  host: string;\n  /** Public collection API key */\n  apiKey: string;\n  /** Website ID (required for cloak mode) */\n  websiteId?: string;\n  /** Proxy mode: 'direct' passes through, 'cloak' hides websiteId server-side */\n  mode?: 'direct' | 'cloak';\n}\n\ninterface ProxyHandlers {\n  GET: (request: NextRequest) => Promise<Response>;\n  POST: (request: NextRequest) => Promise<Response>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Creates proxy route handlers for ad-blocker bypass.\n *\n * @example\n * ```ts\n * // app/api/collect/[...path]/route.ts\n * import { createProxyHandler } from '@entrolytics/nextjs/server';\n *\n * export const { GET, POST } = createProxyHandler({\n *   host: process.env.ENTROLYTICS_HOST!,\n *   websiteId: process.env.ENTROLYTICS_WEBSITE_ID,\n *   mode: 'cloak',\n * });\n * ```\n */\nexport function createProxyHandler(config: ProxyHandlerConfig): ProxyHandlers {\n  const { host, apiKey, websiteId, mode = 'direct' } = config;\n  const baseUrl = host.replace(/\\/$/, '');\n\n  const GET = async (request: NextRequest): Promise<Response> => {\n    const url = new URL(request.url);\n    const path = url.pathname.replace(/^\\/api\\/collect/, '');\n\n    try {\n      const response = await fetch(`${baseUrl}${path || '/script.js'}`, {\n        headers: {\n          'User-Agent': request.headers.get('user-agent') || '',\n          Accept: request.headers.get('accept') || '*/*',\n        },\n      });\n\n      let content = await response.text();\n\n      // In cloak mode, inject websiteId into the script\n      if (mode === 'cloak' && websiteId && path.endsWith('.js')) {\n        // Replace placeholder or inject websiteId\n        content = content.replace(/data-website-id=\"[^\"]*\"/g, `data-website-id=\"${websiteId}\"`);\n      }\n\n      return new Response(content, {\n        status: response.status,\n        headers: {\n          'Content-Type': response.headers.get('content-type') || 'application/javascript',\n          'Cache-Control': 'public, max-age=86400',\n        },\n      });\n    } catch (error) {\n      console.error('[Entrolytics Proxy] GET error:', error);\n      return new Response('Proxy error', { status: 502 });\n    }\n  };\n\n  const POST = async (request: NextRequest): Promise<Response> => {\n    try {\n      const body: unknown = await request.json();\n      if (!isRecord(body)) {\n        return Response.json({ error: 'Request body must be a JSON object' }, { status: 400 });\n      }\n\n      if ('type' in body && 'payload' in body) {\n        return Response.json(\n          {\n            error:\n              'Legacy /api/send envelope is not supported in proxy mode. Send collect payload directly.',\n          },\n          { status: 400 },\n        );\n      }\n\n      const normalizedPayload: Record<string, unknown> = { ...body };\n\n      // In cloak mode, inject websiteId into the payload\n      if (mode === 'cloak' && websiteId) {\n        normalizedPayload.websiteId = websiteId;\n      }\n\n      if (!normalizedPayload.websiteId || typeof normalizedPayload.websiteId !== 'string') {\n        return Response.json({ error: 'websiteId is required' }, { status: 400 });\n      }\n\n      if (!normalizedPayload.sessionId || !normalizedPayload.visitorId) {\n        const { sessionId, visitorId } = resolveSessionVisitorIds({\n          sessionId:\n            typeof normalizedPayload.sessionId === 'string'\n              ? normalizedPayload.sessionId\n              : undefined,\n          visitorId:\n            typeof normalizedPayload.visitorId === 'string'\n              ? normalizedPayload.visitorId\n              : undefined,\n        });\n        normalizedPayload.sessionId = sessionId;\n        normalizedPayload.visitorId = visitorId;\n      }\n\n      const clientIp =\n        request.headers.get('x-forwarded-for')?.split(',')[0].trim() ||\n        request.headers.get('x-real-ip') ||\n        '';\n\n      const response = await fetch(`${baseUrl}/collect`, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'x-api-key': apiKey,\n          'User-Agent': request.headers.get('user-agent') || '',\n          'X-Forwarded-For': clientIp,\n          'X-Real-IP': clientIp,\n        },\n        body: JSON.stringify(normalizedPayload),\n      });\n\n      let data: unknown;\n      try {\n        data = await response.json();\n      } catch {\n        data = { error: 'Upstream response was not valid JSON' };\n      }\n\n      return Response.json(data, {\n        status: response.status,\n        headers: {\n          'Cache-Control': 'no-store',\n        },\n      });\n    } catch (error) {\n      console.error('[Entrolytics Proxy] POST error:', error);\n      return new Response('Proxy error', { status: 502 });\n    }\n  };\n\n  return { GET, POST };\n}\n\n/**\n * Creates a script proxy handler that serves the tracking script.\n *\n * @example\n * ```ts\n * // app/analytics.js/route.ts\n * import { createScriptProxy } from '@entrolytics/nextjs/server';\n *\n * export const GET = createScriptProxy({\n *   host: process.env.ENTROLYTICS_HOST!,\n * });\n * ```\n */\nexport function createScriptProxy(config: Pick<ProxyHandlerConfig, 'host'>) {\n  const { host } = config;\n  const baseUrl = host.replace(/\\/$/, '');\n\n  return async (_request: NextRequest): Promise<Response> => {\n    try {\n      const response = await fetch(`${baseUrl}/script.js`);\n      const content = await response.text();\n\n      return new Response(content, {\n        status: response.status,\n        headers: {\n          'Content-Type': 'application/javascript',\n          'Cache-Control': 'public, max-age=86400',\n        },\n      });\n    } catch (error) {\n      console.error('[Entrolytics Script Proxy] error:', error);\n      return new Response('// Script unavailable', {\n        status: 502,\n        headers: { 'Content-Type': 'application/javascript' },\n      });\n    }\n  };\n}\n","import type { NextRequest } from 'next/server';\nimport type { EventData } from '../types';\nimport { resolveSessionVisitorIds } from './identity';\n\ninterface ServerTrackConfig {\n  /** Entrolytics host URL */\n  host: string;\n  /** Public collection API key */\n  apiKey: string;\n  /** Website ID */\n  websiteId?: string;\n  /** Optional stable session ID */\n  sessionId?: string;\n  /** Optional stable visitor ID */\n  visitorId?: string;\n}\n\ninterface ServerTrackOptions {\n  /** Event name */\n  event?: string;\n  /** Event data */\n  data?: EventData;\n  /** URL to track */\n  url?: string;\n  /** Page title */\n  title?: string;\n  /** Referrer */\n  referrer?: string;\n  /** Distinct ID for user tracking */\n  id?: string;\n  /** Tag for segmentation */\n  tag?: string;\n  /** Extract info from request */\n  request?: NextRequest | Request;\n}\n\ninterface RequestMetadata {\n  hostname: string;\n  ip: string;\n  language: string;\n  referrer: string;\n  requestUrl: string;\n  userAgent: string;\n}\n\nfunction extractRequestMetadata(request?: NextRequest | Request): RequestMetadata {\n  if (!request) {\n    return {\n      hostname: 'server',\n      ip: '',\n      language: 'en',\n      referrer: '',\n      requestUrl: '/',\n      userAgent: '',\n    };\n  }\n\n  const headers = request.headers;\n  const host = headers.get('host') || 'server';\n  const protocol = headers.get('x-forwarded-proto') || 'https';\n\n  let requestUrl = '/';\n  try {\n    const parsed = new URL(request.url);\n    requestUrl = parsed.pathname + parsed.search;\n  } catch {\n    // Keep default\n  }\n\n  return {\n    hostname: host,\n    ip: headers.get('x-forwarded-for')?.split(',')[0]?.trim() || headers.get('x-real-ip') || '',\n    language: headers.get('accept-language')?.split(',')[0] || 'en',\n    referrer: headers.get('referer') || '',\n    requestUrl,\n    userAgent: headers.get('user-agent') || `${protocol} server`,\n  };\n}\n\nfunction toAbsoluteUrl(\n  rawUrl: string,\n  request?: NextRequest | Request,\n  fallbackHost = 'server',\n): string {\n  if (/^https?:\\/\\//i.test(rawUrl)) {\n    return rawUrl;\n  }\n\n  const cleanPath = rawUrl.startsWith('/') ? rawUrl : `/${rawUrl}`;\n\n  if (request) {\n    try {\n      const parsed = new URL(request.url);\n      return `${parsed.origin}${cleanPath}`;\n    } catch {\n      // Continue to host-based fallback\n    }\n  }\n\n  const normalizedHost = fallbackHost || 'localhost';\n  return `https://${normalizedHost}${cleanPath}`;\n}\n\nfunction toValidReferrer(rawReferrer: string | undefined): string | undefined {\n  if (!rawReferrer) return undefined;\n\n  if (/^https?:\\/\\//i.test(rawReferrer)) {\n    return rawReferrer;\n  }\n\n  return undefined;\n}\n\n/**\n * Track an event from the server side (API routes, Server Actions, middleware).\n *\n * @example\n * ```ts\n * // In an API route or Server Action\n * import { trackServerEvent } from '@entrolytics/nextjs/server';\n *\n * export async function POST(request: Request) {\n *   await trackServerEvent(\n *     {\n *       host: process.env.ENTROLYTICS_HOST!,\n *       websiteId: process.env.ENTROLYTICS_WEBSITE_ID!,\n *     },\n *     {\n *       event: 'api-call',\n *       data: { endpoint: '/api/users' },\n *       request,\n *     }\n *   );\n *\n *   return Response.json({ success: true });\n * }\n * ```\n */\nexport async function trackServerEvent(\n  config: ServerTrackConfig,\n  options: ServerTrackOptions = {},\n): Promise<{ ok: boolean; error?: string }> {\n  const { host, websiteId, apiKey } = config;\n  const { event, data, url, title, referrer, id, tag, request } = options;\n\n  if (!websiteId) {\n    return {\n      ok: false,\n      error: 'websiteId is required for collect contract',\n    };\n  }\n\n  const baseUrl = host.replace(/\\/$/, '');\n  const metadata = extractRequestMetadata(request);\n  const { sessionId, visitorId } = resolveSessionVisitorIds(config);\n\n  const payloadProperties: EventData = {\n    ...data,\n  };\n\n  if (title) payloadProperties.title = title;\n  if (tag) payloadProperties.tag = tag;\n  if (id) payloadProperties.distinctId = id;\n  payloadProperties.hostname = metadata.hostname;\n  payloadProperties.language = metadata.language;\n\n  const eventUrl = toAbsoluteUrl(url || metadata.requestUrl || '/', request, metadata.hostname);\n  const eventReferrer = toValidReferrer(referrer || metadata.referrer);\n\n  const payload = {\n    websiteId,\n    eventId: crypto.randomUUID(),\n    timestamp: new Date().toISOString(),\n    sessionId,\n    visitorId,\n    url: eventUrl,\n    eventType: event ? 'custom_event' : 'pageview',\n    ...(event && { eventName: event }),\n    ...(eventReferrer && { referrer: eventReferrer }),\n    ...(Object.keys(payloadProperties).length > 0 && { properties: payloadProperties }),\n  };\n\n  try {\n    const response = await fetch(`${baseUrl}/collect`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'x-api-key': apiKey,\n        ...(metadata.userAgent && { 'User-Agent': metadata.userAgent }),\n        ...(metadata.ip && { 'X-Forwarded-For': metadata.ip }),\n      },\n      body: JSON.stringify(payload),\n    });\n\n    if (!response.ok) {\n      return { ok: false, error: `HTTP ${response.status}` };\n    }\n\n    return { ok: true };\n  } catch (error) {\n    return {\n      ok: false,\n      error: error instanceof Error ? error.message : 'Unknown error',\n    };\n  }\n}\n\n/**\n * Track an identify event from the server side.\n *\n * @example\n * ```ts\n * import { identifyServerSession } from '@entrolytics/nextjs/server';\n *\n * await identifyServerSession(\n *   { host: '...', websiteId: '...' },\n *   {\n *     id: 'user-123',\n *     data: { plan: 'premium', region: 'us-west' },\n *   }\n * );\n * ```\n */\nexport async function identifyServerSession(\n  config: ServerTrackConfig,\n  options: Pick<ServerTrackOptions, 'id' | 'data' | 'request'>,\n): Promise<{ ok: boolean; error?: string }> {\n  const identifyData: EventData = {\n    ...options.data,\n  };\n\n  if (options.id) {\n    identifyData.distinctId = options.id;\n  }\n\n  return trackServerEvent(config, {\n    event: 'identify',\n    data: identifyData,\n    request: options.request,\n  });\n}\n","import { API_ROUTES, isNavigationType, isVitalRating, isVitalType } from '@entrolytics/shared';\nimport type { NavigationType, VitalRating, VitalType } from '@entrolytics/shared';\n/**\n * Server-side Web Vitals tracking for Next.js\n * Receives vitals from client and forwards to Entrolytics\n */\n\nimport { detectDeployment } from './deployment';\nimport { resolveSessionVisitorIds } from './identity';\n\n// Declare process for environments where it exists\n\nexport type WebVitalMetric = VitalType;\nexport type WebVitalRating = VitalRating;\nexport type { NavigationType };\n\nexport interface WebVitalPayload {\n  /** Metric name (LCP, INP, CLS, TTFB, FCP) */\n  metric: WebVitalMetric;\n  /** Metric value */\n  value: number;\n  /** Performance rating */\n  rating: WebVitalRating;\n  /** Delta from previous measurement */\n  delta?: number;\n  /** Unique metric ID for deduplication */\n  id?: string;\n  /** Navigation type */\n  navigationType?: NavigationType;\n  /** Attribution data */\n  attribution?: Record<string, unknown>;\n  /** Page URL */\n  url?: string;\n  /** Page path */\n  path?: string;\n}\n\nexport interface TrackVitalsConfig {\n  /** Entrolytics host URL */\n  host: string;\n  /** Public collection API key */\n  apiKey: string;\n  /** Website ID */\n  websiteId: string;\n  /** Optional stable session ID */\n  sessionId?: string;\n  /** Optional stable visitor ID */\n  visitorId?: string;\n}\n\n/**\n * Track a Web Vital metric from server side (e.g., from an API route that receives client vitals)\n *\n * @example\n * ```ts\n * // In app/api/vitals/route.ts\n * import { trackServerVital } from '@entrolytics/nextjs/server';\n *\n * export async function POST(request: Request) {\n *   const vital = await request.json();\n *\n *   await trackServerVital(\n *     {\n *       host: process.env.ENTROLYTICS_HOST!,\n *       websiteId: process.env.ENTROLYTICS_WEBSITE_ID!,\n *     },\n *     vital\n *   );\n *\n *   return Response.json({ ok: true });\n * }\n * ```\n */\nexport async function trackServerVital(\n  config: TrackVitalsConfig,\n  vital: WebVitalPayload,\n): Promise<{ ok: boolean; error?: string }> {\n  const { host, websiteId, apiKey } = config;\n  const baseUrl = host.replace(/\\/$/, '');\n  const { sessionId, visitorId } = resolveSessionVisitorIds(config);\n\n  // Auto-detect deployment info\n  const deployment = detectDeployment();\n\n  const payload = {\n    websiteId,\n    sessionId,\n    visitorId,\n    metricName: vital.metric,\n    metricValue: vital.value,\n    rating: vital.rating,\n    delta: vital.delta,\n    id: vital.id,\n    navigationType: vital.navigationType,\n    attribution: vital.attribution,\n    url: vital.url,\n    path: vital.path,\n    // Add deployment info if available\n    deployId: deployment.deployId,\n  };\n\n  try {\n    const response = await fetch(`${baseUrl}${API_ROUTES.collectVitals}`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'x-api-key': apiKey,\n      },\n      body: JSON.stringify(payload),\n    });\n\n    if (!response.ok) {\n      return { ok: false, error: `HTTP ${response.status}` };\n    }\n\n    return { ok: true };\n  } catch (error) {\n    return {\n      ok: false,\n      error: error instanceof Error ? error.message : 'Unknown error',\n    };\n  }\n}\n\n/**\n * Track multiple Web Vitals at once\n */\nexport async function trackServerVitalsBatch(\n  config: TrackVitalsConfig,\n  vitals: WebVitalPayload[],\n): Promise<{ ok: boolean; error?: string }> {\n  const { host, websiteId, apiKey } = config;\n  const baseUrl = host.replace(/\\/$/, '');\n  const { sessionId, visitorId } = resolveSessionVisitorIds(config);\n\n  // Auto-detect deployment info\n  const deployment = detectDeployment();\n\n  const payload = {\n    websiteId,\n    sessionId,\n    visitorId,\n    vitals: vitals.map(v => ({\n      attribution: v.attribution,\n      delta: v.delta,\n      deployId: deployment.deployId,\n      id: v.id,\n      metricName: v.metric,\n      metricValue: v.value,\n      navigationType: v.navigationType,\n      path: v.path,\n      rating: v.rating,\n      url: v.url,\n    })),\n  };\n\n  try {\n    const response = await fetch(`${baseUrl}${API_ROUTES.collectVitalsBatch}`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'x-api-key': apiKey,\n      },\n      body: JSON.stringify(payload),\n    });\n\n    if (!response.ok) {\n      return { ok: false, error: `HTTP ${response.status}` };\n    }\n\n    return { ok: true };\n  } catch (error) {\n    return {\n      ok: false,\n      error: error instanceof Error ? error.message : 'Unknown error',\n    };\n  }\n}\n\n/**\n * Create a reportWebVitals handler for Next.js\n * Use this in your custom _app.tsx or layout.tsx\n *\n * @example\n * ```ts\n * // In pages/_app.tsx (Pages Router)\n * import { createWebVitalsReporter } from '@entrolytics/nextjs/server';\n *\n * export function reportWebVitals(metric) {\n *   const reporter = createWebVitalsReporter({\n *     host: process.env.NEXT_PUBLIC_ENTROLYTICS_HOST!,\n *     websiteId: process.env.NEXT_PUBLIC_ENTROLYTICS_WEBSITE_ID!,\n *   });\n *   reporter(metric);\n * }\n * ```\n */\nexport function createWebVitalsReporter(config: TrackVitalsConfig) {\n  // Queue for batching\n  let queue: WebVitalPayload[] = [];\n  let timeout: ReturnType<typeof setTimeout> | null = null;\n\n  const flush = async () => {\n    if (queue.length === 0) return;\n\n    const vitals = [...queue];\n    queue = [];\n\n    await trackServerVitalsBatch(config, vitals);\n  };\n\n  return (metric: {\n    name: string;\n    value: number;\n    rating?: string;\n    delta?: number;\n    id?: string;\n    navigationType?: string;\n    attribution?: Record<string, unknown>;\n  }) => {\n    // Only track Core Web Vitals\n    if (!isVitalType(metric.name)) return;\n\n    const rating = metric.rating && isVitalRating(metric.rating) ? metric.rating : 'good';\n    const navigationType =\n      metric.navigationType && isNavigationType(metric.navigationType)\n        ? metric.navigationType\n        : undefined;\n\n    queue.push({\n      metric: metric.name,\n      value: metric.value,\n      rating,\n      delta: metric.delta,\n      id: metric.id,\n      navigationType,\n      attribution: metric.attribution,\n      url: typeof window !== 'undefined' ? window.location.href : undefined,\n      path: typeof window !== 'undefined' ? window.location.pathname : undefined,\n    });\n\n    // Debounce sending\n    if (timeout) clearTimeout(timeout);\n    timeout = setTimeout(flush, 100);\n  };\n}\n"],"mappings":"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"}