{"version":3,"sources":["../src/config.ts","../src/context.ts","../src/api.ts","../src/client/validation.ts","../src/client/payloads.ts","../src/client/trackRequest.ts","../src/client/conversionRequest.ts","../src/client/identifyRequest.ts","../src/middleware/express.ts","../src/utils/identifier.ts","../src/utils/fingerprint.ts","../src/middleware/cookies.ts","../src/middleware/sessionEndpoint.ts","../src/droppedCall.ts","../src/mbuzz.ts"],"sourcesContent":["export interface MbuzzOptions {\n  apiKey: string;\n  enabled?: boolean;\n  debug?: boolean;\n  timeout?: number;\n  skipPaths?: string[];\n  skipExtensions?: string[];\n}\n\nconst DEFAULT_API_URL = 'https://api.mbuzz.co/api/v1';\nconst DEFAULT_TIMEOUT = 5000;\n\nconst DEFAULT_SKIP_PATHS = [\n  '/up',\n  '/health',\n  '/healthz',\n  '/ping',\n  '/cable',\n  '/assets',\n  '/packs',\n  '/rails/active_storage',\n  '/api',\n];\n\nconst DEFAULT_SKIP_EXTENSIONS = [\n  '.js',\n  '.css',\n  '.map',\n  '.png',\n  '.jpg',\n  '.jpeg',\n  '.gif',\n  '.ico',\n  '.svg',\n  '.woff',\n  '.woff2',\n  '.ttf',\n  '.eot',\n  '.webp',\n];\n\nclass Config {\n  private _apiKey = '';\n  private _apiUrl = DEFAULT_API_URL;\n  private _enabled = true;\n  private _debug = false;\n  private _timeout = DEFAULT_TIMEOUT;\n  private _skipPaths: string[] = [];\n  private _skipExtensions: string[] = [];\n  private _initialized = false;\n\n  get apiKey(): string {\n    return this._apiKey;\n  }\n\n  get apiUrl(): string {\n    return this._apiUrl;\n  }\n\n  get enabled(): boolean {\n    return this._enabled;\n  }\n\n  get debug(): boolean {\n    return this._debug;\n  }\n\n  get timeout(): number {\n    return this._timeout;\n  }\n\n  get skipPaths(): string[] {\n    return this._skipPaths;\n  }\n\n  get skipExtensions(): string[] {\n    return this._skipExtensions;\n  }\n\n  get isInitialized(): boolean {\n    return this._initialized;\n  }\n\n  init(options: MbuzzOptions): void {\n    if (!options.apiKey || options.apiKey.trim() === '') {\n      throw new Error('apiKey is required');\n    }\n\n    this._apiKey = options.apiKey;\n    this._apiUrl = DEFAULT_API_URL;\n    this._enabled = options.enabled ?? true;\n    this._debug = options.debug ?? false;\n    this._timeout = options.timeout ?? DEFAULT_TIMEOUT;\n    this._skipPaths = [...DEFAULT_SKIP_PATHS, ...(options.skipPaths ?? [])];\n    this._skipExtensions = [...DEFAULT_SKIP_EXTENSIONS, ...(options.skipExtensions ?? [])];\n    this._initialized = true;\n  }\n\n  /**\n   * Point the SDK at a different API host. For integration testing only.\n   *\n   * `apiUrl` was deliberately removed from init() in 0.8.2 so a production\n   * install can never be redirected away from api.mbuzz.co by configuration.\n   * That is still true: this refuses unless the configured key is `sk_test_`,\n   * so only a test account can be redirected.\n   */\n  setApiUrlForTesting(apiUrl: string): void {\n    if (!this._apiKey.startsWith('sk_test_')) {\n      throw new Error(\n        `setApiUrlForTesting() requires an sk_test_ key: a live install must never be redirected away from ${DEFAULT_API_URL}`\n      );\n    }\n\n    this._apiUrl = apiUrl.replace(/\\/+$/, '');\n  }\n\n  reset(): void {\n    this._apiKey = '';\n    this._apiUrl = DEFAULT_API_URL;\n    this._enabled = true;\n    this._debug = false;\n    this._timeout = DEFAULT_TIMEOUT;\n    this._skipPaths = [];\n    this._skipExtensions = [];\n    this._initialized = false;\n  }\n\n  shouldSkipPath(path: string): boolean {\n    // Check if path starts with any skip path\n    if (this._skipPaths.some((skipPath) => path.startsWith(skipPath))) {\n      return true;\n    }\n\n    // Check if path has a skipped extension\n    if (this._skipExtensions.some((ext) => path.endsWith(ext))) {\n      return true;\n    }\n\n    return false;\n  }\n}\n\n// Singleton instance\nexport const config = new Config();\n\n// Convenience exports\nexport const init = (options: MbuzzOptions): void => config.init(options);\nexport const reset = (): void => config.reset();\nexport const setApiUrlForTesting = (apiUrl: string): void => config.setApiUrlForTesting(apiUrl);\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\nexport interface RequestContextOptions {\n  visitorId: string;\n  ip: string;\n  userAgent: string;\n  userId?: string;\n  url?: string;\n  referrer?: string;\n}\n\n/**\n * Request context that holds visitor ID, request metadata, and fingerprint info.\n * Used to automatically enrich events with URL, referrer, ip, and user_agent.\n * NOTE: Session resolution is now handled server-side (v0.7.0+)\n */\nexport class RequestContext {\n  readonly visitorId: string;\n  readonly ip: string;\n  readonly userAgent: string;\n  userId?: string;\n  readonly url?: string;\n  readonly referrer?: string;\n\n  constructor(options: RequestContextOptions) {\n    this.visitorId = options.visitorId;\n    this.ip = options.ip;\n    this.userAgent = options.userAgent;\n    this.userId = options.userId;\n    this.url = options.url;\n    this.referrer = options.referrer;\n  }\n\n  /**\n   * Enrich custom properties with url and referrer from context.\n   * Custom properties override context properties.\n   */\n  enrichProperties(custom: Record<string, unknown>): Record<string, unknown> {\n    const base: Record<string, unknown> = {};\n\n    if (this.url) {\n      base.url = this.url;\n    }\n\n    if (this.referrer) {\n      base.referrer = this.referrer;\n    }\n\n    return { ...base, ...custom };\n  }\n}\n\n// AsyncLocalStorage for request context isolation\nconst asyncLocalStorage = new AsyncLocalStorage<RequestContext>();\n\n/**\n * Run a callback with the given request context.\n * Context is automatically available via getContext() within the callback.\n */\nexport function withContext<T>(\n  context: RequestContext,\n  callback: () => T | Promise<T>\n): Promise<T> {\n  return new Promise((resolve, reject) => {\n    asyncLocalStorage.run(context, async () => {\n      try {\n        const result = await callback();\n        resolve(result);\n      } catch (error) {\n        reject(error);\n      }\n    });\n  });\n}\n\n/**\n * Get the current request context.\n * Returns undefined if called outside of withContext.\n */\nexport function getContext(): RequestContext | undefined {\n  return asyncLocalStorage.getStore();\n}\n\n/**\n * Clear the current context.\n * Useful for testing or manual cleanup.\n */\nexport function clearContext(): void {\n  // AsyncLocalStorage doesn't have a direct clear method,\n  // but we can exit the store by running outside of it.\n  // For testing, this effectively makes getStore() return undefined.\n  asyncLocalStorage.disable();\n}\n","import * as https from 'node:https';\nimport * as http from 'node:http';\nimport { config } from './config';\n\nconst VERSION = '0.11.0';\n\nfunction debugLog(message: string, data?: unknown): void {\n  if (config.debug) {\n    console.log(`[mbuzz] ${message}`, data ?? '');\n  }\n}\n\nfunction makeRequest(\n  path: string,\n  payload: Record<string, unknown>\n): Promise<{ statusCode: number; body: string }> {\n  return new Promise((resolve, reject) => {\n    // Ensure base URL ends with / and path doesn't start with /\n    const baseUrl = config.apiUrl.endsWith('/') ? config.apiUrl : `${config.apiUrl}/`;\n    const cleanPath = path.startsWith('/') ? path.slice(1) : path;\n    const url = new URL(cleanPath, baseUrl);\n    const body = JSON.stringify(payload);\n\n    const options: https.RequestOptions = {\n      method: 'POST',\n      headers: {\n        'Authorization': `Bearer ${config.apiKey}`,\n        'Content-Type': 'application/json',\n        'User-Agent': `mbuzz-node/${VERSION}`,\n        'Content-Length': Buffer.byteLength(body),\n      },\n      timeout: config.timeout,\n    };\n\n    debugLog(`POST ${url.toString()}`, payload);\n\n    // Use http or https based on the URL protocol\n    const requestModule = url.protocol === 'https:' ? https : http;\n    const req = requestModule.request(url, options, (res) => {\n      let responseBody = '';\n\n      res.on('data', (chunk) => {\n        responseBody += chunk;\n      });\n\n      res.on('end', () => {\n        debugLog(`Response ${res.statusCode}`, responseBody);\n        resolve({ statusCode: res.statusCode ?? 0, body: responseBody });\n      });\n    });\n\n    req.on('error', (error) => {\n      debugLog('Request error', error.message);\n      reject(error);\n    });\n\n    req.on('timeout', () => {\n      req.destroy();\n      debugLog('Request timeout');\n      reject(new Error('Request timeout'));\n    });\n\n    req.write(body);\n    req.end();\n  });\n}\n\n/**\n * Make a POST request to the API.\n * Returns true on success (2xx), false on any failure.\n * Never throws exceptions.\n */\nexport async function post(\n  path: string,\n  payload: Record<string, unknown>\n): Promise<boolean> {\n  if (!config.isInitialized) {\n    debugLog('SDK not initialized');\n    return false;\n  }\n\n  if (!config.enabled) {\n    debugLog('SDK disabled');\n    return false;\n  }\n\n  try {\n    const { statusCode } = await makeRequest(path, payload);\n    return statusCode >= 200 && statusCode < 300;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Make a POST request to the API and return the parsed response.\n * Returns the parsed JSON on success, null on any failure.\n * Never throws exceptions.\n */\nexport async function postWithResponse<T = Record<string, unknown>>(\n  path: string,\n  payload: Record<string, unknown>\n): Promise<T | null> {\n  if (!config.isInitialized) {\n    debugLog('SDK not initialized');\n    return null;\n  }\n\n  if (!config.enabled) {\n    debugLog('SDK disabled');\n    return null;\n  }\n\n  try {\n    const { statusCode, body } = await makeRequest(path, payload);\n\n    if (statusCode < 200 || statusCode >= 300) {\n      return null;\n    }\n\n    return JSON.parse(body) as T;\n  } catch {\n    return null;\n  }\n}\n","// Pure validation functions\n// NOTE: Session validation removed in v0.7.0 - server handles session resolution\n\nimport type { TrackOptions, ConversionOptions, IdentifyOptions } from './types';\n\nconst isPresent = (value: unknown): boolean =>\n  value !== undefined && value !== null && String(value).trim() !== '';\n\nconst hasIdentifier = (visitorId?: string, userId?: string | number): boolean =>\n  isPresent(visitorId) || isPresent(userId);\n\nexport const validateTrack = (options: TrackOptions): boolean =>\n  isPresent(options.eventType) && hasIdentifier(options.visitorId, options.userId);\n\nexport const validateConversion = (options: ConversionOptions): boolean =>\n  isPresent(options.conversionType) &&\n  (isPresent(options.eventId) || isPresent(options.visitorId) || isPresent(options.userId));\n\nexport const validateIdentify = (options: IdentifyOptions): boolean =>\n  isPresent(options.userId);\n","// Pure payload builder functions\n// NOTE: Session ID removed in v0.7.0 - server handles session resolution\n\nimport type { TrackOptions, ConversionOptions, IdentifyOptions } from './types';\n\nconst timestamp = (): string => new Date().toISOString();\n\nconst compact = <T extends Record<string, unknown>>(obj: T): Partial<T> =>\n  Object.fromEntries(\n    Object.entries(obj).filter(([, v]) => v !== undefined)\n  ) as Partial<T>;\n\nexport const buildTrackPayload = (options: TrackOptions) => ({\n  events: [\n    compact({\n      visitor_id: options.visitorId,\n      user_id: options.userId,\n      event_type: options.eventType,\n      properties: options.properties ?? {},\n      timestamp: timestamp(),\n      ip: options.ip,\n      user_agent: options.userAgent,\n      identifier: options.identifier,\n    }),\n  ],\n});\n\nexport const buildConversionPayload = (options: ConversionOptions) => ({\n  conversion: compact({\n    event_id: options.eventId,\n    visitor_id: options.visitorId,\n    user_id: options.userId,\n    conversion_type: options.conversionType,\n    revenue: options.revenue,\n    currency: options.currency ?? 'USD',\n    is_acquisition: options.isAcquisition,\n    inherit_acquisition: options.inheritAcquisition,\n    properties: options.properties ?? {},\n    timestamp: timestamp(),\n    ip: options.ip,\n    user_agent: options.userAgent,\n    identifier: options.identifier,\n  }),\n});\n\nexport const buildIdentifyPayload = (options: IdentifyOptions) => ({\n  user_id: String(options.userId),\n  visitor_id: options.visitorId,\n  traits: options.traits ?? {},\n  timestamp: timestamp(),\n});\n","import { postWithResponse } from '../api';\nimport { validateTrack } from './validation';\nimport { buildTrackPayload } from './payloads';\nimport type { TrackOptions, TrackResult } from './types';\n\nexport type { TrackResult } from './types';\n\ninterface EventsResponse {\n  events: Array<{ id: string }>;\n}\n\nconst isProxyAccepted = (response: unknown): boolean =>\n  !!response && typeof response === 'object' && 'status' in response &&\n  (response as Record<string, unknown>).status === 'accepted';\n\nconst parseResponse = (\n  response: EventsResponse | null,\n  options: TrackOptions\n): TrackResult | false => {\n  if (!response?.events?.[0]?.id) {\n    if (isProxyAccepted(response)) {\n      return { success: true, eventType: options.eventType, visitorId: options.visitorId };\n    }\n    return false;\n  }\n\n  return {\n    success: true,\n    eventId: response.events[0].id,\n    eventType: options.eventType,\n    visitorId: options.visitorId,\n  };\n};\n\nexport const track = async (options: TrackOptions): Promise<TrackResult | false> => {\n  if (!validateTrack(options)) {\n    return false;\n  }\n\n  const payload = buildTrackPayload(options);\n  const response = await postWithResponse<EventsResponse>('/events', payload);\n\n  return parseResponse(response, options);\n};\n","import { postWithResponse } from '../api';\nimport { validateConversion } from './validation';\nimport { buildConversionPayload } from './payloads';\nimport type { ConversionOptions, ConversionResult } from './types';\n\nexport type { ConversionResult } from './types';\n\ninterface ConversionResponse {\n  conversion: { id?: string };\n  attribution?: Record<string, unknown>;\n}\n\nconst isProxyAccepted = (response: unknown): boolean =>\n  !!response && typeof response === 'object' && 'status' in response &&\n  (response as Record<string, unknown>).status === 'accepted';\n\nconst parseResponse = (response: ConversionResponse | null): ConversionResult | false => {\n  if (!response?.conversion?.id) {\n    if (isProxyAccepted(response)) {\n      return { success: true };\n    }\n    return false;\n  }\n\n  return {\n    success: true,\n    conversionId: response.conversion.id,\n    attribution: response.attribution,\n  };\n};\n\nlet identifierDeprecationWarned = false;\nconst warnIdentifierDeprecated = (): void => {\n  if (identifierDeprecationWarned) return;\n  identifierDeprecationWarned = true;\n  // Surface once per process, matching Node's standard deprecation pattern.\n  // Can be silenced with --no-deprecation or filtered via process.on('warning', …).\n  if (typeof process !== 'undefined' && typeof process.emitWarning === 'function') {\n    process.emitWarning(\n      'The `identifier` option on conversion() is deprecated and ignored by the backend on /conversions. Pass the email or external ID as `userId` instead.',\n      'DeprecationWarning',\n      'MBUZZ_CONVERSION_IDENTIFIER'\n    );\n  }\n};\n\nexport const conversion = async (\n  options: ConversionOptions\n): Promise<ConversionResult | false> => {\n  if (options.identifier !== undefined) {\n    warnIdentifierDeprecated();\n  }\n\n  if (!validateConversion(options)) {\n    return false;\n  }\n\n  const payload = buildConversionPayload(options);\n  const response = await postWithResponse<ConversionResponse>('/conversions', payload);\n\n  return parseResponse(response);\n};\n","import { post } from '../api';\nimport { validateIdentify } from './validation';\nimport { buildIdentifyPayload } from './payloads';\nimport type { IdentifyOptions } from './types';\n\nexport const identify = async (options: IdentifyOptions): Promise<boolean> => {\n  if (!validateIdentify(options)) {\n    return false;\n  }\n\n  const payload = buildIdentifyPayload(options);\n  return post('/identify', payload);\n};\n","import type { Request, Response, NextFunction } from 'express';\nimport { randomUUID } from 'node:crypto';\nimport { config } from '../config';\nimport { post } from '../api';\nimport { generateId } from '../utils/identifier';\nimport { deviceFingerprint } from '../utils/fingerprint';\nimport { VISITOR_COOKIE, FBP_COOKIE, readFbp } from './cookies';\nimport { isSessionRequest, handleSessionRequest } from './sessionEndpoint';\n\nexport interface MbuzzRequest {\n  visitorId: string;\n  ip: string;\n  userAgent: string;\n  userId?: string;\n}\n\ndeclare global {\n  // eslint-disable-next-line @typescript-eslint/no-namespace\n  namespace Express {\n    interface Request {\n      mbuzz?: MbuzzRequest;\n    }\n  }\n}\n\ntype ExpressMiddleware = (req: Request, res: Response, next: NextFunction) => void;\n\nconst getFullUrl = (req: Request): string => {\n  const protocol = req.protocol;\n  const host = req.get('host') ?? 'localhost';\n  return `${protocol}://${host}${req.url}`;\n};\n\nconst getReferrer = (req: Request): string | undefined => req.get('referer');\n\nconst isSecure = (req: Request): boolean => req.protocol === 'https';\n\nconst getVisitorId = (req: Request): { id: string; isNew: boolean } => {\n  const existing = req.cookies?.[VISITOR_COOKIE];\n  return existing ? { id: existing, isNew: false } : { id: generateId(), isNew: true };\n};\n\nconst getClientIp = (req: Request): string => {\n  const forwarded = req.headers?.['x-forwarded-for'];\n  if (typeof forwarded === 'string') {\n    return forwarded.split(',')[0].trim();\n  }\n  return req.ip ?? req.socket?.remoteAddress ?? 'unknown';\n};\n\nconst getUserAgent = (req: Request): string => {\n  return req.headers?.['user-agent'] ?? 'unknown';\n};\n\nconst attachMbuzz = (req: Request, visitorId: string, ip: string, userAgent: string): void => {\n  req.mbuzz = { visitorId, ip, userAgent, userId: undefined };\n};\n\n/**\n * Determine whether the request is a real page navigation that should\n * create a server-side session.\n *\n * Primary signal: Sec-Fetch-* headers (modern browsers).\n * Fallback: blacklist known sub-request framework headers (old browsers).\n */\nexport const shouldCreateSession = (req: Request): boolean => {\n  const mode = req.headers['sec-fetch-mode'];\n  const dest = req.headers['sec-fetch-dest'];\n\n  if (mode) {\n    return mode === 'navigate' &&\n      dest === 'document' &&\n      !req.headers['sec-purpose'];\n  }\n\n  // Fallback for old browsers / bots: blacklist known sub-requests\n  return !req.headers['turbo-frame'] &&\n    !req.headers['hx-request'] &&\n    !req.headers['x-up-version'] &&\n    req.headers['x-requested-with'] !== 'XMLHttpRequest';\n};\n\nconst createSessionAsync = (\n  visitorId: string,\n  url: string,\n  referrer: string | undefined,\n  ip: string,\n  userAgent: string,\n  fbp?: string\n): void => {\n  const payload = {\n    session: {\n      visitor_id: visitorId,\n      session_id: randomUUID(),\n      url,\n      referrer,\n      device_fingerprint: deviceFingerprint(ip, userAgent),\n      user_agent: userAgent,\n      // The visitor's address. mbuzz sends it to Meta as\n      // `client_ip_address`, which Meta documents as required for website\n      // events. It was already computed for the fingerprint above and then\n      // omitted here until 0.10.1.\n      ip,\n      started_at: new Date().toISOString(),\n      // Omitted, not null, when the visitor has none.\n      ...(fbp ? { fbp } : {}),\n    },\n  };\n\n  // Fire and forget — post() never throws\n  void post('/sessions', payload);\n};\n\nexport const createMiddleware = (): ExpressMiddleware => {\n  return (req: Request, res: Response, next: NextFunction): void => {\n    if (!config.enabled) {\n      return next();\n    }\n\n    const visitor = getVisitorId(req);\n    const ip = getClientIp(req);\n    const userAgent = getUserAgent(req);\n    const secure = isSecure(req);\n\n    // Ahead of shouldSkipPath: on a cached page this is the only request that\n    // reaches the app at all, so a skipPaths entry must not be able to swallow\n    // it. It answers here rather than calling next() — there is no route behind\n    // it.\n    if (isSessionRequest(req)) {\n      return handleSessionRequest(req, res, visitor.id, ip, userAgent, secure);\n    }\n\n    if (config.shouldSkipPath(req.path)) {\n      return next();\n    }\n\n    // Only a visitor the browser already holds. This response may be stored by\n    // a full-page cache and replayed to everyone, so setting a cookie here\n    // would put it in that cache and hand every later visitor the same id —\n    // unrelated people merged into one journey. Corruption, not loss: every row\n    // still exists, each attributed to the wrong person, and nothing looks\n    // missing. A first-time visitor is established a moment later by the\n    // session endpoint above, whose POST no cache stores.\n    if (visitor.isNew) {\n      return next();\n    }\n\n    attachMbuzz(req, visitor.id, ip, userAgent);\n\n    if (shouldCreateSession(req)) {\n      createSessionAsync(\n        visitor.id,\n        getFullUrl(req),\n        getReferrer(req),\n        ip,\n        userAgent,\n        readFbp(req.cookies?.[FBP_COOKIE])\n      );\n    }\n\n    next();\n  };\n};\n","import { randomBytes } from 'node:crypto';\n\n/**\n * Generate a random 64-character hex string for use as visitor/session ID.\n * Uses cryptographically secure random bytes.\n */\nexport function generateId(): string {\n  return randomBytes(32).toString('hex');\n}\n","import { createHash } from 'node:crypto';\n\n/**\n * Compute a device fingerprint from IP and User-Agent.\n * Matches server-side: SHA256(\"ip|userAgent\")[0:32]\n */\nexport function deviceFingerprint(ip: string, userAgent: string): string {\n  return createHash('sha256')\n    .update(`${ip}|${userAgent}`)\n    .digest('hex')\n    .substring(0, 32);\n}\n","// Cookie constants and utilities\n// NOTE: Session cookie removed in 0.7.0 - server handles session resolution\n\nexport const VISITOR_COOKIE = '_mbuzz_vid';\n\nexport const VISITOR_MAX_AGE = 63072000000; // 2 years in ms\n\nexport interface CookieOptions {\n  maxAge: number;\n  httpOnly: boolean;\n  sameSite: 'lax' | 'strict' | 'none';\n  path: string;\n  secure?: boolean;\n}\n\nexport const visitorCookieOptions = (secure: boolean): CookieOptions => ({\n  maxAge: VISITOR_MAX_AGE,\n  httpOnly: true,\n  sameSite: 'lax',\n  path: '/',\n  secure,\n});\n\n// The one request that always reaches the app on a cached page. A cache never\n// stores a POST, so this path is the only place the server can still mint.\nexport const SESSION_ENDPOINT_PATH = '/_mbuzz/session';\n\n// Meta's browser id, written client-side by the customer's Meta Pixel. Read\n// only, never set: forwarded on the session call so Meta can merge mbuzz's\n// server event with the Pixel's browser event.\nexport const FBP_COOKIE = '_fbp';\n\n// Meta's documented shape, fb.<subdomainIndex>.<creationTime>.<random>, plus\n// the optional appendix Meta's server-side Parameter Builder adds\n// (fb.1.<ts>.<random>.AQECAQIB). Both are valid to Meta. No `m` flag, so `$`\n// anchors at the true end of the string and a trailing newline is rejected.\nconst FBP_FORMAT = /^fb\\.\\d+\\.\\d+\\.\\d+(?:\\.[A-Za-z0-9_-]+)?$/;\n\n/**\n * The Pixel's _fbp, or undefined when absent or not in Meta's format. mbuzz\n * never invents one and never rewrites what it forwards.\n */\nexport const readFbp = (value: unknown): string | undefined =>\n  typeof value === 'string' && FBP_FORMAT.test(value) ? value : undefined;\n","import type { Request, Response } from 'express';\nimport { randomUUID } from 'node:crypto';\nimport { post } from '../api';\nimport { generateId } from '../utils/identifier';\nimport { deviceFingerprint } from '../utils/fingerprint';\nimport {\n  VISITOR_COOKIE,\n  FBP_COOKIE,\n  SESSION_ENDPOINT_PATH,\n  readFbp,\n  visitorCookieOptions,\n} from './cookies';\n\n/**\n * Establishes the visitor from a page a cache served.\n *\n * A cached page never enters the Express stack, so the tracking middleware\n * never runs and no visitor cookie is set — every later event is then rejected\n * for having no one to attribute it to, silently, while the page renders\n * perfectly.\n *\n * This endpoint is the one request on such a page that always reaches the app.\n * A small script on the page POSTs here; the SERVER mints the cookie on the\n * response. The id is never created or read in JS, so it stays HttpOnly and\n * keeps its full two-year life — a cookie written by document.cookie is capped\n * at 7 days under Safari's ITP, and 24 hours after an ad click.\n */\n\n// Nothing to return: the response exists for its Set-Cookie header.\nconst NO_CONTENT_STATUS = 204;\n\nconst NO_STORE = 'no-store, no-cache, must-revalidate, private';\n\ninterface SessionBody {\n  url?: string;\n  referrer?: string;\n}\n\n/**\n * POST only: a GET is cacheable by an intermediary, which would reintroduce the\n * very bug this endpoint exists to fix.\n */\nexport const isSessionRequest = (req: Request): boolean =>\n  req.method === 'POST' && req.path === SESSION_ENDPOINT_PATH;\n\n// Express only populates req.body when a body parser is mounted. The endpoint\n// must work without one — the customer's parser config is not something the fix\n// can depend on.\nconst parseBody = (req: Request): SessionBody => {\n  const body = req.body as unknown;\n  return body && typeof body === 'object' ? (body as SessionBody) : {};\n};\n\nconst createSessionAsync = (\n  visitorId: string,\n  body: SessionBody,\n  ip: string,\n  userAgent: string,\n  fbp?: string\n): void => {\n  const payload = {\n    session: {\n      visitor_id: visitorId,\n      session_id: randomUUID(),\n      // The page's URL, not ours — a script on the page called us, so our own\n      // path would attribute every session to this endpoint.\n      url: body.url,\n      referrer: body.referrer,\n      device_fingerprint: deviceFingerprint(ip, userAgent),\n      user_agent: userAgent,\n      // The visitor's address. mbuzz sends it to Meta as\n      // `client_ip_address`, which Meta documents as required for website\n      // events. It was already computed for the fingerprint above and then\n      // omitted here until 0.10.1.\n      ip,\n      started_at: new Date().toISOString(),\n      // Omitted, not null, when the visitor has none.\n      ...(fbp ? { fbp } : {}),\n    },\n  };\n\n  // Fire and forget — post() never throws\n  void post('/sessions', payload);\n};\n\n/**\n * Answer the session request: mint the cookie, record the session against the\n * page, and return an empty, uncacheable 204.\n */\nexport const handleSessionRequest = (\n  req: Request,\n  res: Response,\n  visitorId: string,\n  ip: string,\n  userAgent: string,\n  secure: boolean\n): void => {\n  createSessionAsync(visitorId, parseBody(req), ip, userAgent, readFbp(req.cookies?.[FBP_COOKIE]));\n\n  res.cookie(VISITOR_COOKIE, visitorId, visitorCookieOptions(secure));\n  res.set('Cache-Control', NO_STORE);\n  res.status(NO_CONTENT_STATUS).end();\n};\n\nexport { SESSION_ENDPOINT_PATH, generateId };\n","import { SESSION_ENDPOINT_PATH } from './middleware/cookies';\n\n/**\n * Says out loud when a call is dropped for having nothing to attribute it to.\n *\n * Every SDK guarded its send with a bare `return false`: no request, no log,\n * nothing. Behind a full-page cache that is the whole failure — the cookie is\n * never minted, so every later event fails this guard and vanishes. It cost a\n * full day on a live account precisely because the silence was total from both\n * sides.\n *\n * Deliberately NOT behind config.debug. The customers who hit this are exactly\n * the ones not running in debug, so a debug-gated warning would be silent for\n * everyone who needs it.\n */\n\nconst MISSING_IDENTITY =\n  'no visitorId and no userId. If your pages are served from a full-page cache, ' +\n  `mount mbuzz.middleware() and call POST ${SESSION_ENDPOINT_PATH} from the page ` +\n  \"— see the README's \\\"Full-page caching\\\" section.\";\n\nconst emit = (message: string): void => {\n  // eslint-disable-next-line no-console\n  console.warn(`[mbuzz] ${message}`);\n};\n\nexport const warnMissingIdentity = (kind: string, name: string): void => {\n  emit(`dropped ${kind} \"${name}\": ${MISSING_IDENTITY}`);\n};\n\nexport const warnInvalid = (kind: string, name: string, reason: string): void => {\n  emit(`dropped ${kind} \"${name}\": ${reason}.`);\n};\n","import { init as initConfig, MbuzzOptions } from './config';\nimport { getContext } from './context';\nimport { track } from './client/trackRequest';\nimport { conversion as createConversion } from './client/conversionRequest';\nimport { identify as identifyUser } from './client/identifyRequest';\nimport { createMiddleware } from './middleware/express';\nimport type { TrackResult } from './client/trackRequest';\nimport type { ConversionResult } from './client/conversionRequest';\nimport type { Identifier } from './client/types';\nimport { warnMissingIdentity, warnInvalid } from './droppedCall';\n\n// Re-export types\nexport type { MbuzzOptions, TrackResult, ConversionResult, Identifier };\n\nconst isPresent = (value: unknown): boolean =>\n  value !== undefined && value !== null && String(value).trim() !== '';\n\n// Initialize SDK\nexport const init = (options: MbuzzOptions): void => initConfig(options);\n\n// Context accessors\n// NOTE: sessionId removed in v0.7.0 - server handles session resolution\nexport const visitorId = (): string | undefined => getContext()?.visitorId;\nexport const userId = (): string | undefined => getContext()?.userId;\n\n// Middleware\nexport const middleware = createMiddleware;\n\n// Event tracking\nexport interface EventOptions {\n  visitorId?: string;\n  userId?: string;\n  identifier?: Identifier;\n  [key: string]: unknown;\n}\n\nexport const event = async (\n  eventType: string,\n  properties: Record<string, unknown> = {}\n): Promise<TrackResult | false> => {\n  const ctx = getContext();\n  const resolvedVisitorId = ctx?.visitorId;\n  const resolvedUserId = ctx?.userId;\n\n  if (!isPresent(eventType)) {\n    warnInvalid('event', eventType, 'eventType is required');\n    return false;\n  }\n\n  // Must have at least one identifier. Warn rather than drop in silence: with\n  // no visitor and no user there is nothing to attribute this to, and behind a\n  // full-page cache that is the normal case, not an edge one.\n  if (!resolvedVisitorId && !resolvedUserId) {\n    warnMissingIdentity('event', eventType);\n    return false;\n  }\n\n  const enrichedProps = ctx ? ctx.enrichProperties(properties) : properties;\n\n  return track({\n    visitorId: resolvedVisitorId,\n    userId: resolvedUserId,\n    eventType,\n    properties: enrichedProps,\n    ip: ctx?.ip,\n    userAgent: ctx?.userAgent,\n  });\n};\n\n// Conversion tracking\nexport interface ConversionOptions {\n  eventId?: string;\n  visitorId?: string;\n  userId?: string;\n  revenue?: number;\n  currency?: string;\n  isAcquisition?: boolean;\n  inheritAcquisition?: boolean;\n  properties?: Record<string, unknown>;\n  identifier?: Identifier;\n}\n\nexport const conversion = async (\n  conversionType: string,\n  options: ConversionOptions = {}\n): Promise<ConversionResult | false> => {\n  const ctx = getContext();\n  const resolvedVisitorId = options.visitorId ?? ctx?.visitorId;\n  const resolvedUserId = options.userId ?? ctx?.userId;\n\n  if (!isPresent(conversionType)) {\n    warnInvalid('conversion', conversionType, 'conversionType is required');\n    return false;\n  }\n\n  // A conversion dropped here is lost revenue attribution, so it is never\n  // silent. An eventId alone is enough — it carries its own attribution.\n  if (!resolvedVisitorId && !resolvedUserId && !isPresent(options.eventId)) {\n    warnMissingIdentity('conversion', conversionType);\n    return false;\n  }\n\n  return createConversion({\n    conversionType,\n    visitorId: resolvedVisitorId,\n    userId: resolvedUserId,\n    eventId: options.eventId,\n    revenue: options.revenue,\n    currency: options.currency,\n    isAcquisition: options.isAcquisition,\n    inheritAcquisition: options.inheritAcquisition,\n    properties: options.properties,\n    ip: ctx?.ip,\n    userAgent: ctx?.userAgent,\n    identifier: options.identifier,\n  });\n};\n\n// User identification\nexport interface IdentifyOptions {\n  visitorId?: string;\n  traits?: Record<string, unknown>;\n}\n\nexport const identify = async (\n  userIdValue: string | number,\n  options: IdentifyOptions = {}\n): Promise<boolean> => {\n  const ctx = getContext();\n\n  if (!isPresent(userIdValue)) {\n    warnInvalid('identify', String(userIdValue), 'userId is required');\n    return false;\n  }\n\n  const result = await identifyUser({\n    userId: userIdValue,\n    visitorId: options.visitorId ?? ctx?.visitorId,\n    traits: options.traits,\n  });\n\n  if (result && ctx) {\n    ctx.userId = String(userIdValue);\n  }\n\n  return result;\n};\n"],"mappings":"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","names":["visitorId","userId","isProxyAccepted","parseResponse","randomUUID","visitorId","visitorId","createSessionAsync","randomUUID","isPresent","init","conversion","identify"]}