{"version":3,"file":"index.cjs","names":[],"sources":["../src/event-protocol.ts","../src/index.ts"],"sourcesContent":["/**\n * Event Protocol Types\n *\n * These types define the canonical event structures used across the Entrolytics ecosystem.\n * Used by: API Server, SDKs, CLI, worker processes.\n *\n * This file was extracted from the internal @entrolytics/protocol package to enable\n * sharing with external packages.\n */\n\n/**\n * Core event types supported by the analytics platform\n */\nexport const EventType = {\n  PageView: \"pageview\",\n  Custom: \"custom_event\",\n  Click: \"click\",\n} as const;\n\nexport type EventType = (typeof EventType)[keyof typeof EventType];\n\n/**\n * Event payload as sent from client SDKs\n */\nexport interface EventPayload {\n  websiteId: string;\n  eventId: string;\n  timestamp: string;\n  sessionId: string;\n  visitorId: string;\n  url: string;\n  referrer?: string;\n  eventType: EventType;\n  eventName?: string;\n  consent?: boolean;\n  properties?: Record<string, unknown>;\n\n  // Device info\n  screenWidth?: number;\n  screenHeight?: number;\n\n  // Performance metrics\n  loadTime?: number;\n  domInteractive?: number;\n  domComplete?: number;\n\n  // UTM parameters\n  utmSource?: string;\n  utmMedium?: string;\n  utmCampaign?: string;\n  utmTerm?: string;\n  utmContent?: string;\n}\n\n/**\n * Event DB row structure as stored in ClickHouse\n * Uses snake_case to match database column naming convention\n */\nexport interface EventDBRow {\n  id: string; // UUID - Maps to 'id' in ClickHouse\n  website_id: string; // UUID\n  session_id: string; // UUID\n  visitor_id: string; // UUID\n  timestamp: string; // ISO String\n  event_type: EventType;\n  event_name: string | null;\n  url: string;\n  path: string;\n  referrer: string | null;\n  referrer_domain: string | null;\n  browser: string;\n  browser_version: string | null;\n  os: string;\n  os_version: string | null;\n  device_type: \"desktop\" | \"mobile\" | \"tablet\" | \"server\" | \"unknown\";\n  screen_width: number | null;\n  screen_height: number | null;\n  country: string | null;\n  city: string | null;\n  region: string | null;\n  load_time: number | null;\n  dom_interactive: number | null;\n  dom_complete: number | null;\n  utm_source: string | null;\n  utm_medium: string | null;\n  utm_campaign: string | null;\n  utm_term: string | null;\n  utm_content: string | null;\n  properties: string; // JSON string in database\n}\n\n/**\n * Device types for analytics segmentation\n */\nexport type DeviceType = \"desktop\" | \"mobile\" | \"tablet\" | \"server\" | \"unknown\";\n","/**\n * Shared constants across Entrolytics ecosystem\n * Used by: CLI, SDKs, Dashboard, Integrations\n */\n\n/**\n * Plan definitions and limits\n */\nexport const PLANS = {\n  starter: {\n    id: \"starter\",\n    name: \"Starter\",\n    price: 0,\n    limits: {\n      pageviewsPerMonth: 25_000,\n      websites: 2,\n      retentionDays: 30,\n      seats: 1,\n    },\n    features: {\n      funnels: false,\n      attribution: false,\n      revenue: false,\n      customDashboards: false,\n      apiAccess: false,\n      weeklyReports: true,\n      support: \"community\",\n    },\n  },\n  pro: {\n    id: \"pro\",\n    name: \"Pro\",\n    price: 29,\n    limits: {\n      pageviewsPerMonth: 250_000,\n      websites: 10,\n      retentionDays: 365,\n      seats: 5,\n    },\n    features: {\n      funnels: true,\n      attribution: true,\n      revenue: true,\n      customDashboards: false,\n      apiAccess: true,\n      weeklyReports: true,\n      support: \"email\",\n    },\n  },\n  business: {\n    id: \"business\",\n    name: \"Business\",\n    price: 99,\n    limits: {\n      pageviewsPerMonth: 1_000_000,\n      websites: -1, // unlimited\n      retentionDays: 730, // 2 years\n      seats: -1, // unlimited\n    },\n    features: {\n      funnels: true,\n      attribution: true,\n      revenue: true,\n      customDashboards: true,\n      apiAccess: true,\n      weeklyReports: true,\n      support: \"priority\",\n    },\n  },\n  enterprise: {\n    id: \"enterprise\",\n    name: \"Enterprise\",\n    price: -1, // custom\n    limits: {\n      pageviewsPerMonth: -1, // custom\n      websites: -1,\n      retentionDays: -1, // custom\n      seats: -1,\n    },\n    features: {\n      funnels: true,\n      attribution: true,\n      revenue: true,\n      customDashboards: true,\n      apiAccess: true,\n      weeklyReports: true,\n      support: \"dedicated\",\n      sso: true,\n      auditLogs: true,\n      customRetention: true,\n    },\n  },\n} as const;\n\n/**\n * Plan feature names for display\n */\nexport const PLAN_FEATURES = {\n  funnels: \"Funnel Analytics\",\n  attribution: \"Attribution Reports\",\n  revenue: \"Revenue Tracking\",\n  customDashboards: \"Custom Dashboards\",\n  apiAccess: \"API Access\",\n  weeklyReports: \"Weekly Email Reports\",\n  sso: \"SSO/SAML\",\n  auditLogs: \"Audit Logs\",\n  customRetention: \"Custom Data Retention\",\n} as const;\n\n/**\n * Usage warning thresholds (percentages)\n */\nexport const USAGE_THRESHOLDS = {\n  warning: 90,\n  critical: 95,\n} as const;\n\n/**\n * Billing-related error codes\n */\nexport const BILLING_ERRORS = {\n  quotaExceeded: \"QUOTA_EXCEEDED\",\n  planRequired: \"PLAN_REQUIRED\",\n  featureNotAvailable: \"FEATURE_NOT_AVAILABLE\",\n  subscriptionInactive: \"SUBSCRIPTION_INACTIVE\",\n  paymentFailed: \"PAYMENT_FAILED\",\n} as const;\n\n/**\n * API endpoint configuration\n */\nexport const API_ENDPOINTS = {\n  production: \"https://api.entrolytics.click\",\n  development: \"http://localhost:3001\",\n} as const;\n\n/**\n * Default API host\n */\nexport const DEFAULT_API_HOST: string =\n  getEnv()?.NODE_ENV === \"production\" ? API_ENDPOINTS.production : API_ENDPOINTS.development;\n\n/**\n * Environment variable naming conventions by framework\n */\nexport const ENV_VAR_NAMES = {\n  nextjs: {\n    websiteId: \"NEXT_PUBLIC_ENTROLYTICS_WEBSITE_ID\",\n    host: \"NEXT_PUBLIC_ENTROLYTICS_HOST\",\n    envFile: \".env.local\",\n  },\n  react: {\n    websiteId: \"VITE_ENTROLYTICS_WEBSITE_ID\",\n    host: \"VITE_ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  vue: {\n    websiteId: \"VITE_ENTROLYTICS_WEBSITE_ID\",\n    host: \"VITE_ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  svelte: {\n    websiteId: \"PUBLIC_ENTROLYTICS_WEBSITE_ID\",\n    host: \"PUBLIC_ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  astro: {\n    websiteId: \"PUBLIC_ENTROLYTICS_WEBSITE_ID\",\n    host: \"PUBLIC_ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  html: {\n    websiteId: \"ENTROLYTICS_WEBSITE_ID\",\n    host: \"ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  node: {\n    websiteId: \"ENTROLYTICS_WEBSITE_ID\",\n    host: \"ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  php: {\n    websiteId: \"ENTROLYTICS_WEBSITE_ID\",\n    host: \"ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  python: {\n    websiteId: \"ENTROLYTICS_WEBSITE_ID\",\n    host: \"ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n  go: {\n    websiteId: \"ENTROLYTICS_WEBSITE_ID\",\n    host: \"ENTROLYTICS_HOST\",\n    envFile: \".env\",\n  },\n} as const;\n\n/**\n * CLI configuration constants\n */\nexport const CLI_CONFIG = {\n  tokenExpiryMinutes: 15,\n  maxTokensPerUser: 10,\n  pollIntervalMs: 2000,\n  setupTimeoutMs: 300000, // 5 minutes\n  minCliVersion: \"1.0.0\",\n} as const;\n\n/**\n * Core event types - matches backend protocol values exactly\n * Used by: API Server, SDKs, CLI, worker processes\n * See: entrolytics/packages/protocol/src/events.ts\n */\nexport const EVENT_TYPES = {\n  pageView: \"pageview\",\n  custom: \"custom_event\",\n  click: \"click\",\n} as const;\n\n/**\n * Extended event types for SDK-level semantics\n * These are higher-level event categories used by SDKs\n * They map to the core EVENT_TYPES when sent to the backend\n */\nexport const SDK_EVENT_TYPES = {\n  pageView: \"pageview\",\n  click: \"click\",\n  formSubmit: \"form_submit\",\n  custom: \"custom_event\",\n  error: \"error\",\n  performance: \"performance\",\n} as const;\n\n/**\n * Web Vitals metric types (Phase 2)\n * Core Web Vitals: LCP, INP, CLS\n * Additional: TTFB, FCP\n */\nexport const VITAL_TYPES = {\n  LCP: \"LCP\", // Largest Contentful Paint\n  INP: \"INP\", // Interaction to Next Paint (replaced FID)\n  CLS: \"CLS\", // Cumulative Layout Shift\n  TTFB: \"TTFB\", // Time to First Byte\n  FCP: \"FCP\", // First Contentful Paint\n} as const;\n\n/**\n * Web Vitals rating thresholds\n */\nexport const VITAL_RATINGS = {\n  good: \"good\",\n  needsImprovement: \"needs-improvement\",\n  poor: \"poor\",\n} as const;\n\n/**\n * Web Vitals thresholds by metric (in milliseconds, except CLS which is unitless)\n */\nexport const VITAL_THRESHOLDS = {\n  LCP: { good: 2500, poor: 4000 },\n  INP: { good: 200, poor: 500 },\n  CLS: { good: 0.1, poor: 0.25 },\n  TTFB: { good: 800, poor: 1800 },\n  FCP: { good: 1800, poor: 3000 },\n} as const;\n\n/**\n * Navigation types for Web Vitals context\n */\nexport const NAVIGATION_TYPES = {\n  navigate: \"navigate\",\n  reload: \"reload\",\n  backForward: \"back-forward\",\n  backForwardCache: \"back-forward-cache\",\n  prerender: \"prerender\",\n  restore: \"restore\",\n  softNavigation: \"soft-navigation\",\n} as const;\n\n/**\n * Form event types (Phase 2)\n */\nexport const FORM_EVENT_TYPES = {\n  start: \"start\", // Form interaction started\n  fieldFocus: \"field_focus\", // Field received focus\n  fieldBlur: \"field_blur\", // Field lost focus\n  fieldError: \"field_error\", // Field validation error\n  submit: \"submit\", // Form submitted\n  abandon: \"abandon\", // Form abandoned (left page)\n} as const;\n\n/**\n * Form field types\n */\nexport const FORM_FIELD_TYPES = {\n  text: \"text\",\n  email: \"email\",\n  password: \"password\",\n  tel: \"tel\",\n  number: \"number\",\n  url: \"url\",\n  textarea: \"textarea\",\n  select: \"select\",\n  checkbox: \"checkbox\",\n  radio: \"radio\",\n  date: \"date\",\n  file: \"file\",\n  hidden: \"hidden\",\n  submit: \"submit\",\n  other: \"other\",\n} as const;\n\n/**\n * Deployment platform sources (Phase 2)\n */\nexport const DEPLOYMENT_SOURCES = {\n  vercel: \"vercel\",\n  netlify: \"netlify\",\n  cloudflare: \"cloudflare\",\n  railway: \"railway\",\n  render: \"render\",\n  fly: \"fly\",\n  heroku: \"heroku\",\n  aws: \"aws\",\n  gcp: \"gcp\",\n  azure: \"azure\",\n  custom: \"custom\",\n} as const;\n\n/**\n * Deployment environment variables by platform\n */\nexport const DEPLOYMENT_ENV_VARS = {\n  vercel: {\n    deployId: \"VERCEL_DEPLOYMENT_ID\",\n    gitSha: \"VERCEL_GIT_COMMIT_SHA\",\n    gitBranch: \"VERCEL_GIT_COMMIT_REF\",\n    url: \"VERCEL_URL\",\n  },\n  netlify: {\n    deployId: \"DEPLOY_ID\",\n    gitSha: \"COMMIT_REF\",\n    gitBranch: \"BRANCH\",\n    url: \"DEPLOY_URL\",\n  },\n  cloudflare: {\n    deployId: \"CF_PAGES_COMMIT_SHA\",\n    gitSha: \"CF_PAGES_COMMIT_SHA\",\n    gitBranch: \"CF_PAGES_BRANCH\",\n    url: \"CF_PAGES_URL\",\n  },\n} as const;\n\n/**\n * HTTP status codes\n */\nexport const HTTP_STATUS = {\n  ok: 200,\n  created: 201,\n  accepted: 202,\n  noContent: 204,\n  badRequest: 400,\n  unauthorized: 401,\n  forbidden: 403,\n  notFound: 404,\n  conflict: 409,\n  tooManyRequests: 429,\n  internalServerError: 500,\n  serviceUnavailable: 503,\n} as const;\n\n/**\n * API route paths\n */\nexport const API_ROUTES = {\n  // CLI Auth routes\n  cliAuthToken: \"/api/auth/cli/token\",\n  cliAuthTokens: \"/api/auth/cli/tokens\",\n  cliValidate: \"/api/auth/cli/validate\",\n\n  // Share routes\n  shareToken: (shareId: string) => `/api/share/${shareId}`,\n\n  // Links routes\n  links: \"/api/links\",\n  linkRedirect: (slug: string) => `/q/${slug}`,\n\n  // Website routes\n  websites: \"/api/websites\",\n  websiteById: (id: string) => `/api/websites/${id}`,\n  websiteEvents: (id: string) => `/api/websites/${id}/events`,\n  websiteRecentEvents: (id: string) => `/api/websites/${id}/recent-events`,\n\n  // User routes\n  userOnboarding: \"/api/user/onboarding\",\n  userProfile: \"/api/user/profile\",\n  userEmailPreferences: \"/api/me/email-preferences\",\n\n  // Billing routes\n  billingUsage: \"/api/billing/usage\",\n  billingCheckout: \"/api/billing/checkout\",\n  billingPortal: \"/api/billing/portal\",\n  billingWebhook: \"/api/billing/webhook\",\n\n  // Analytics routes (REST)\n  analyticsOverview: (websiteId: string) => `/api/analytics/${websiteId}/overview`,\n  analyticsTimeseries: (websiteId: string) => `/api/analytics/${websiteId}/timeseries`,\n  analyticsTopPages: (websiteId: string) => `/api/analytics/${websiteId}/top-pages`,\n  analyticsTopReferrers: (websiteId: string) => `/api/analytics/${websiteId}/top-referrers`,\n  analyticsGeography: (websiteId: string) => `/api/analytics/${websiteId}/geography`,\n  analyticsDevices: (websiteId: string) => `/api/analytics/${websiteId}/devices`,\n\n  // Event collection\n  collect: \"/collect\",\n  collectBatch: \"/collect/batch\",\n  send: \"/collect\",\n\n  // Phase 2: Web Vitals, Forms, Deployments\n  collectVitals: \"/api/collect/vitals\",\n  collectVitalsBatch: \"/api/collect/vitals/batch\",\n  collectForms: \"/api/collect/forms\",\n  collectFormsBatch: \"/api/collect/forms/batch\",\n  vitalsOverview: \"/api/vitals/overview\",\n  vitalsByPage: \"/api/vitals/by-page\",\n  vitalsTrend: \"/api/vitals/trend\",\n  vitalsRecent: \"/api/vitals/recent\",\n  vitalsPageBreakdown: \"/api/vitals/page-breakdown\",\n  formsConversions: \"/api/forms/conversions\",\n  formsFieldMetrics: \"/api/forms/field-metrics\",\n  formsFunnel: \"/api/forms/funnel\",\n  formsRecent: \"/api/forms/recent\",\n  deployments: \"/api/deployments\",\n  deploymentByWebsite: (id: string) => `/api/deployments/${id}`,\n  deploymentCompare: (id: string) => `/api/deployments/${id}/compare`,\n  deploymentLatest: (id: string) => `/api/deployments/${id}/latest`,\n\n  // Health checks\n  health: \"/api/health\",\n  healthIntegrations: \"/api/health/integrations\",\n} as const;\n\n/**\n * Onboarding step identifiers\n */\nexport const ONBOARDING_STEPS = {\n  welcome: \"welcome\",\n  createWebsite: \"create-website\",\n  installTracking: \"install-tracking\",\n  verify: \"verify\",\n  complete: \"complete\",\n  skipped: \"skipped\",\n} as const;\n\n/**\n * CLI token statuses\n */\nexport const CLI_TOKEN_STATUS = {\n  pending: \"pending\",\n  used: \"used\",\n  expired: \"expired\",\n  revoked: \"revoked\",\n} as const;\n\n/**\n * User roles\n */\nexport const USER_ROLES = {\n  admin: \"admin\",\n  user: \"user\",\n  viewer: \"viewer\",\n} as const;\n\n/**\n * Framework package names\n */\nexport const FRAMEWORK_PACKAGES = {\n  nextjs: \"@entrolytics/nextjs-sdk\",\n  react: \"@entrolytics/react-sdk\",\n  vue: \"@entrolytics/vue-sdk\",\n  svelte: \"@entrolytics/svelte-sdk\",\n  astro: \"@entrolytics/astro-sdk\",\n  node: \"@entrolytics/node-sdk\",\n} as const;\n\n/**\n * Framework detection patterns\n */\nexport const FRAMEWORK_PATTERNS = {\n  nextjs: {\n    files: [\"next.config.js\", \"next.config.mjs\", \"next.config.ts\"],\n    dependencies: [\"next\"],\n  },\n  react: {\n    files: [\"vite.config.js\", \"vite.config.ts\"],\n    dependencies: [\"react\", \"vite\"],\n  },\n  vue: {\n    files: [\"vite.config.js\", \"vite.config.ts\"],\n    dependencies: [\"vue\", \"vite\"],\n  },\n  svelte: {\n    files: [\"svelte.config.js\", \"svelte.config.ts\"],\n    dependencies: [\"svelte\"],\n  },\n  astro: {\n    files: [\"astro.config.mjs\", \"astro.config.ts\"],\n    dependencies: [\"astro\"],\n  },\n} as const;\n\n/**\n * Rate limiting configuration\n * Updated to match server-side implementation\n */\nexport const RATE_LIMITS = {\n  cliTokenExchange: {\n    windowSeconds: 60, // 1 minute\n    maxRequests: 5,\n  },\n  shareTokenGeneration: {\n    windowSeconds: 60, // 1 minute\n    maxRequests: 10,\n  },\n  linkCreation: {\n    windowSeconds: 60, // 1 minute\n    maxRequests: 20,\n  },\n  linkRedirect: {\n    windowSeconds: 60, // 1 minute\n    maxRequests: 100,\n  },\n  apiGeneral: {\n    windowSeconds: 60, // 1 minute\n    maxRequests: 100,\n  },\n} as const;\n\n/**\n * Error messages\n */\nexport const ERROR_MESSAGES = {\n  // Authentication\n  unauthorized: \"Unauthorized access\",\n  forbidden: \"Access forbidden\",\n  tokenExpired: \"Token has expired\",\n  tokenInvalid: \"Invalid token\",\n  tokenNotFound: \"Token not found\",\n  tokenAlreadyUsed: \"Token has already been used\",\n  tokenRevoked: \"Token has been revoked\",\n  tokenMissingJti: \"Token missing JTI - please re-authenticate\",\n  userBanned: \"User account has been banned\",\n  userDeleted: \"User account has been deleted\",\n\n  // Share tokens\n  shareTokenExpired: \"Share token has expired\",\n  shareTokenRevoked: \"Share has been revoked\",\n  shareTokenInvalid: \"Invalid share token\",\n\n  // URL Validation\n  invalidUrl: \"Invalid URL provided\",\n  invalidUrlProtocol: \"URL must use http or https protocol\",\n  openRedirectBlocked: \"Open redirect attempt blocked\",\n\n  // Validation\n  invalidInput: \"Invalid input provided\",\n  missingRequired: \"Missing required fields\",\n  invalidFormat: \"Invalid format\",\n\n  // Resources\n  notFound: \"Resource not found\",\n  websiteNotFound: \"Website not found\",\n  userNotFound: \"User not found\",\n  linkNotFound: \"Link not found\",\n\n  // Rate limiting\n  tooManyRequests: \"Too many requests. Please try again later.\",\n  rateLimitExceeded: \"Rate limit exceeded\",\n\n  // Server\n  internalError: \"Internal server error\",\n  serviceUnavailable: \"Service temporarily unavailable\",\n} as const;\n\n/**\n * Success messages\n */\nexport const SUCCESS_MESSAGES = {\n  tokenGenerated: \"Setup token generated successfully\",\n  tokenValidated: \"Token validated successfully\",\n  tokenRevoked: \"Token revoked successfully\",\n  allTokensRevoked: \"All tokens revoked successfully\",\n  websiteCreated: \"Website created successfully\",\n  linkCreated: \"Link created successfully\",\n  shareCreated: \"Share created successfully\",\n  onboardingComplete: \"Onboarding completed successfully\",\n  setupComplete: \"Setup completed successfully\",\n} as const;\n\n/**\n * CLI Access Token metadata\n */\nexport interface CliAccessTokenMetadata {\n  jti: string;\n  createdAt: string;\n  expiresAt: string;\n  lastUsedAt: string | null;\n  ipAddress: string | null;\n  userAgent: string | null;\n}\n\n// Type exports\nexport type Framework = keyof typeof ENV_VAR_NAMES;\nexport type EventType = (typeof EVENT_TYPES)[keyof typeof EVENT_TYPES];\nexport type SdkEventType = (typeof SDK_EVENT_TYPES)[keyof typeof SDK_EVENT_TYPES];\nexport type OnboardingStep = (typeof ONBOARDING_STEPS)[keyof typeof ONBOARDING_STEPS];\nexport type CliTokenStatus = (typeof CLI_TOKEN_STATUS)[keyof typeof CLI_TOKEN_STATUS];\nexport type UserRole = (typeof USER_ROLES)[keyof typeof USER_ROLES];\nexport type PlanId = keyof typeof PLANS;\nexport type Plan = (typeof PLANS)[PlanId];\nexport type PlanFeature = keyof typeof PLAN_FEATURES;\nexport type BillingError = (typeof BILLING_ERRORS)[keyof typeof BILLING_ERRORS];\n\n// Phase 2 type exports\nexport type VitalType = (typeof VITAL_TYPES)[keyof typeof VITAL_TYPES];\nexport type VitalRating = (typeof VITAL_RATINGS)[keyof typeof VITAL_RATINGS];\nexport type NavigationType = (typeof NAVIGATION_TYPES)[keyof typeof NAVIGATION_TYPES];\nexport type FormEventType = (typeof FORM_EVENT_TYPES)[keyof typeof FORM_EVENT_TYPES];\nexport type FormFieldType = (typeof FORM_FIELD_TYPES)[keyof typeof FORM_FIELD_TYPES];\nexport type DeploymentSource = (typeof DEPLOYMENT_SOURCES)[keyof typeof DEPLOYMENT_SOURCES];\n\nexport const EVENT_TYPE_VALUES = Object.values(EVENT_TYPES) as [EventType, ...EventType[]];\nexport const SDK_EVENT_TYPE_VALUES = Object.values(SDK_EVENT_TYPES) as [\n  SdkEventType,\n  ...SdkEventType[],\n];\nexport const VITAL_TYPE_VALUES = Object.values(VITAL_TYPES) as [VitalType, ...VitalType[]];\nexport const VITAL_RATING_VALUES = Object.values(VITAL_RATINGS) as [VitalRating, ...VitalRating[]];\nexport const NAVIGATION_TYPE_VALUES = Object.values(NAVIGATION_TYPES) as [\n  NavigationType,\n  ...NavigationType[],\n];\nexport const FORM_EVENT_TYPE_VALUES = Object.values(FORM_EVENT_TYPES) as [\n  FormEventType,\n  ...FormEventType[],\n];\nexport const FORM_FIELD_TYPE_VALUES = Object.values(FORM_FIELD_TYPES) as [\n  FormFieldType,\n  ...FormFieldType[],\n];\nexport const DEPLOYMENT_SOURCE_VALUES = Object.values(DEPLOYMENT_SOURCES) as [\n  DeploymentSource,\n  ...DeploymentSource[],\n];\n\nexport function isEventType(value: string): value is EventType {\n  return EVENT_TYPE_VALUES.includes(value as EventType);\n}\n\nexport function isSdkEventType(value: string): value is SdkEventType {\n  return SDK_EVENT_TYPE_VALUES.includes(value as SdkEventType);\n}\n\nexport function isVitalType(value: string): value is VitalType {\n  return VITAL_TYPE_VALUES.includes(value as VitalType);\n}\n\nexport function isVitalRating(value: string): value is VitalRating {\n  return VITAL_RATING_VALUES.includes(value as VitalRating);\n}\n\nexport function isNavigationType(value: string): value is NavigationType {\n  return NAVIGATION_TYPE_VALUES.includes(value as NavigationType);\n}\n\nexport function isFormEventType(value: string): value is FormEventType {\n  return FORM_EVENT_TYPE_VALUES.includes(value as FormEventType);\n}\n\nexport function isFormFieldType(value: string): value is FormFieldType {\n  return FORM_FIELD_TYPE_VALUES.includes(value as FormFieldType);\n}\n\nexport function isDeploymentSource(value: string): value is DeploymentSource {\n  return DEPLOYMENT_SOURCE_VALUES.includes(value as DeploymentSource);\n}\n\nexport function normalizeDeploymentSource(value: string | null | undefined): DeploymentSource {\n  if (!value) {\n    return \"custom\";\n  }\n\n  return isDeploymentSource(value) ? value : \"custom\";\n}\n\n/**\n * Web Vital data structure for SDK tracking\n */\nexport interface WebVitalData {\n  metric: VitalType;\n  value: number;\n  rating: VitalRating;\n  delta?: number;\n  id?: string;\n  navigationType?: NavigationType;\n  attribution?: Record<string, unknown>;\n  url?: string;\n  path?: string;\n}\n\n/**\n * Form event data structure for SDK tracking\n */\nexport interface FormEventData {\n  eventType: FormEventType;\n  formId: string;\n  formName?: string;\n  urlPath: string;\n  fieldName?: string;\n  fieldType?: FormFieldType;\n  fieldIndex?: number;\n  timeOnField?: number;\n  timeSinceStart?: number;\n  errorMessage?: string;\n  success?: boolean;\n}\n\n/**\n * Deployment context for SDK tracking\n */\nexport interface DeploymentContext {\n  deployId: string;\n  gitSha?: string;\n  gitBranch?: string;\n  deployUrl?: string;\n  source?: DeploymentSource;\n}\n\n/**\n * Utility functions\n */\nexport function getEnvVarNames(framework: Framework): (typeof ENV_VAR_NAMES)[Framework] {\n  return ENV_VAR_NAMES[framework];\n}\n\nexport function getFrameworkPackage(framework: Framework): string | null {\n  return FRAMEWORK_PACKAGES[framework as keyof typeof FRAMEWORK_PACKAGES] || null;\n}\n\nexport function isValidFramework(framework: string): framework is Framework {\n  return framework in ENV_VAR_NAMES;\n}\n\nexport function getApiRoute(route: keyof typeof API_ROUTES, ...args: string[]): string {\n  const routeFn = API_ROUTES[route];\n  if (typeof routeFn === \"function\") {\n    return (routeFn as (...args: string[]) => string)(...args);\n  }\n  return routeFn;\n}\n\n/**\n * Get plan by ID\n */\nexport function getPlan(planId: PlanId): Plan {\n  return PLANS[planId];\n}\n\n/**\n * Check if a feature is available for a plan\n */\nexport function isPlanFeatureEnabled(planId: PlanId, feature: PlanFeature): boolean {\n  const plan = PLANS[planId];\n  return plan?.features?.[feature as keyof typeof plan.features] === true;\n}\n\n/**\n * Get plan limit value (-1 means unlimited)\n */\nexport function getPlanLimit(planId: PlanId, limit: keyof Plan[\"limits\"]): number {\n  return PLANS[planId]?.limits?.[limit] ?? 0;\n}\n\n/**\n * Check if usage is at warning threshold\n */\nexport function isUsageWarning(current: number, limit: number): boolean {\n  if (limit <= 0) return false; // unlimited\n  return (current / limit) * 100 >= USAGE_THRESHOLDS.warning;\n}\n\n/**\n * Check if usage is at critical threshold\n */\nexport function isUsageCritical(current: number, limit: number): boolean {\n  if (limit <= 0) return false; // unlimited\n  return (current / limit) * 100 >= USAGE_THRESHOLDS.critical;\n}\n\n/**\n * Calculate Web Vital rating from value (Phase 2)\n */\nexport function getVitalRating(metric: VitalType, value: number): VitalRating {\n  const thresholds = VITAL_THRESHOLDS[metric];\n  if (value <= thresholds.good) return \"good\";\n  if (value <= thresholds.poor) return \"needs-improvement\";\n  return \"poor\";\n}\n\n/**\n * Detect deployment context from environment variables (Phase 2)\n * Works in Node.js environments only - returns null in browser\n */\nexport function detectDeploymentContext(): DeploymentContext | null {\n  // Safe access to process.env in any environment\n  const env = getEnv();\n  if (!env) return null;\n\n  // Vercel\n  if (env.VERCEL_DEPLOYMENT_ID) {\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      source: \"vercel\",\n    };\n  }\n\n  // Netlify\n  if (env.DEPLOY_ID) {\n    return {\n      deployId: env.DEPLOY_ID,\n      gitSha: env.COMMIT_REF,\n      gitBranch: env.BRANCH,\n      deployUrl: env.DEPLOY_URL,\n      source: \"netlify\",\n    };\n  }\n\n  // Cloudflare Pages\n  if (env.CF_PAGES_COMMIT_SHA) {\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      source: \"cloudflare\",\n    };\n  }\n\n  return null;\n}\n\n/**\n * Safe environment variable access (works in browser and Node.js)\n */\nfunction getEnv(): Record<string, string | undefined> | null {\n  try {\n    // Check if we're in a Node.js-like environment\n    if (typeof globalThis !== \"undefined\" && \"process\" in globalThis) {\n      const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n        .process;\n      return proc?.env ?? null;\n    }\n    return null;\n  } catch {\n    return null;\n  }\n}\n// Export analytics types\nexport * from \"./analytics-types\";\n// Export event protocol types (canonical event structures)\nexport * from \"./event-protocol\";\n"],"mappings":"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"}