{"version":3,"sources":["../src/parse.ts","../src/map.ts","../src/defaults.ts","../src/merge.ts","../src/transformer.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport type {\n  GA4Event,\n  GA4EventParams,\n  GA4Hit,\n  GA4HitParams,\n  GA4Item,\n  GA4Request,\n} from './types';\n\nexport function parseQuery(url: string): Record<string, string> {\n  const out: Record<string, string> = {};\n  const qIdx = url.indexOf('?');\n  if (qIdx === -1) return out;\n  const usp = new URLSearchParams(url.slice(qIdx + 1));\n  usp.forEach((value, key) => {\n    out[key] = value;\n  });\n  return out;\n}\n\nexport function parseBody(body: string): Record<string, string>[] {\n  if (!body) return [];\n  return body\n    .split(/\\r?\\n/)\n    .map((line) => line.trim())\n    .filter((line) => line.length > 0)\n    .map((line) => {\n      const out: Record<string, string> = {};\n      const usp = new URLSearchParams(line);\n      usp.forEach((v, k) => {\n        out[k] = v;\n      });\n      return out;\n    });\n}\n\n// Two separate dispatch maps keyed by 2-char prefix.\n// Split by type so the assignment site stays type-safe (no cast).\nconst ITEM_STRING_FIELDS: Readonly<Record<string, keyof GA4Item>> = {\n  id: 'id',\n  nm: 'name',\n  br: 'brand',\n  ca: 'category',\n  c2: 'category2',\n  c3: 'category3',\n  c4: 'category4',\n  c5: 'category5',\n  va: 'variant',\n  cp: 'coupon',\n  ln: 'listName',\n  li: 'listId',\n  lo: 'locationId',\n  af: 'affiliation',\n  cn: 'creativeName',\n  cs: 'creativeSlot',\n  pi: 'promotionId',\n  pn: 'promotionName',\n};\n\nconst ITEM_NUMBER_FIELDS: Readonly<Record<string, keyof GA4Item>> = {\n  pr: 'price',\n  qt: 'quantity',\n  ds: 'discount',\n  lp: 'listPosition',\n};\n\nfunction setItemString(item: GA4Item, key: keyof GA4Item, value: string): void {\n  // Narrow assignment by key — these are the string-typed fields.\n  switch (key) {\n    case 'id':\n      item.id = value;\n      return;\n    case 'name':\n      item.name = value;\n      return;\n    case 'brand':\n      item.brand = value;\n      return;\n    case 'category':\n      item.category = value;\n      return;\n    case 'category2':\n      item.category2 = value;\n      return;\n    case 'category3':\n      item.category3 = value;\n      return;\n    case 'category4':\n      item.category4 = value;\n      return;\n    case 'category5':\n      item.category5 = value;\n      return;\n    case 'variant':\n      item.variant = value;\n      return;\n    case 'coupon':\n      item.coupon = value;\n      return;\n    case 'listName':\n      item.listName = value;\n      return;\n    case 'listId':\n      item.listId = value;\n      return;\n    case 'locationId':\n      item.locationId = value;\n      return;\n    case 'affiliation':\n      item.affiliation = value;\n      return;\n    case 'creativeName':\n      item.creativeName = value;\n      return;\n    case 'creativeSlot':\n      item.creativeSlot = value;\n      return;\n    case 'promotionId':\n      item.promotionId = value;\n      return;\n    case 'promotionName':\n      item.promotionName = value;\n      return;\n  }\n}\n\nfunction setItemNumber(item: GA4Item, key: keyof GA4Item, value: number): void {\n  switch (key) {\n    case 'price':\n      item.price = value;\n      return;\n    case 'quantity':\n      item.quantity = value;\n      return;\n    case 'discount':\n      item.discount = value;\n      return;\n    case 'listPosition':\n      item.listPosition = value;\n      return;\n  }\n}\n\nexport function parseItem(value: string): GA4Item {\n  const item: GA4Item = { custom: {} };\n  const customKeys = new Map<string, string>();\n  const customVals = new Map<string, string>();\n\n  for (const raw of value.split('~')) {\n    if (raw.length === 0) continue;\n\n    // Variable-length k<N>/v<N> (must match before 2-char prefix lookup\n    // because k10/v10 etc are wider than 2 chars).\n    const kvMatch = /^([kv])(\\d+)(.*)$/.exec(raw);\n    if (kvMatch) {\n      const [, kind, idx, val] = kvMatch;\n      if (kind === 'k') customKeys.set(idx, val);\n      else customVals.set(idx, val);\n      continue;\n    }\n\n    if (raw.length < 2) continue;\n    const prefix = raw.slice(0, 2);\n    const val = raw.slice(2);\n\n    const stringKey = ITEM_STRING_FIELDS[prefix];\n    if (stringKey !== undefined) {\n      setItemString(item, stringKey, val);\n      continue;\n    }\n    const numberKey = ITEM_NUMBER_FIELDS[prefix];\n    if (numberKey !== undefined) {\n      const n = Number(val);\n      if (!Number.isNaN(n)) setItemNumber(item, numberKey, n);\n      continue;\n    }\n  }\n\n  // Pair k<N> with v<N>; drop unmatched.\n  for (const [idx, key] of customKeys) {\n    const v = customVals.get(idx);\n    if (v !== undefined) item.custom[key] = v;\n  }\n  return item;\n}\n\nexport function parseConsent(hit: { gcs?: string }): WalkerOS.Consent {\n  const gcs = hit.gcs;\n  if (!gcs || !/^G[01]{3}$/.test(gcs)) return {};\n  // gcs[1] is reserved (always '1' for current consent mode v2)\n  return {\n    marketing: gcs[2] === '1', // ad_storage\n    analytics: gcs[3] === '1', // analytics_storage\n  };\n}\n\nconst HIT_PARAM_KEYS = new Set([\n  'v',\n  'tid',\n  'cid',\n  'sid',\n  'sct',\n  'seg',\n  '_p',\n  '_z',\n  'gtm',\n  'dl',\n  'dt',\n  'dr',\n  'ul',\n  'sr',\n  'uid',\n  '_dbg',\n  '_s',\n  '_ss',\n  '_fv',\n  'gcs',\n  'gcd',\n  'dma',\n  'dma_cps',\n  'npa',\n  'p',\n]);\n\nexport function parseRequest(req: GA4Request): GA4Hit {\n  const queryParams = parseQuery(req.url);\n  const hit: GA4HitParams = {};\n  const queryEventParams: Record<string, string> = {};\n\n  // Split URL params into hit-level vs event-level.\n  for (const [k, v] of Object.entries(queryParams)) {\n    if (HIT_PARAM_KEYS.has(k)) hit[k] = v;\n    else queryEventParams[k] = v;\n  }\n\n  // GET: event params live in the URL alongside hit params.\n  // POST: in body lines.\n  const bodyLines = req.body ? parseBody(req.body) : [];\n  const rawEvents =\n    bodyLines.length > 0\n      ? bodyLines\n      : Object.keys(queryEventParams).length > 0\n        ? [queryEventParams]\n        : [];\n\n  const events: GA4Event[] = rawEvents\n    .filter((raw) => typeof raw.en === 'string' && raw.en.length > 0)\n    .map((raw) => buildEvent(raw));\n\n  return { hit, events };\n}\n\nfunction buildEvent(raw: Record<string, string>): GA4Event {\n  const params: GA4EventParams = { ep: {}, epn: {}, up: {}, upn: {} };\n  const itemEntries: Array<[number, string]> = [];\n\n  for (const [k, v] of Object.entries(raw)) {\n    if (k === 'en') continue;\n\n    // pr<N> items\n    const prMatch = /^pr(\\d+)$/.exec(k);\n    if (prMatch) {\n      itemEntries.push([Number(prMatch[1]), v]);\n      continue;\n    }\n\n    // Dotted-key nesting\n    if (k.startsWith('ep.')) {\n      params.ep[k.slice(3)] = v;\n      continue;\n    }\n    if (k.startsWith('epn.')) {\n      const n = Number(v);\n      if (!Number.isNaN(n)) params.epn[k.slice(4)] = n;\n      continue;\n    }\n    if (k.startsWith('up.')) {\n      params.up[k.slice(3)] = v;\n      continue;\n    }\n    if (k.startsWith('upn.')) {\n      const n = Number(v);\n      if (!Number.isNaN(n)) params.upn[k.slice(4)] = n;\n      continue;\n    }\n\n    // Standalone numeric keys\n    if (k === '_et') {\n      const n = Number(v);\n      if (!Number.isNaN(n)) params._et = n;\n      continue;\n    }\n    if (k === '_c') {\n      params._c = v;\n      continue;\n    }\n    // Unknown standalone keys: drop. Add to GA4EventParams type if a future\n    // need surfaces.\n  }\n\n  itemEntries.sort((a, b) => a[0] - b[0]);\n  const items = itemEntries.map(([, v]) => parseItem(v));\n\n  return { en: raw.en, params, items };\n}\n","import type { Mapping, WalkerOS } from '@walkeros/core';\nimport { getByPath, getId, deleteByPath, isObject } from '@walkeros/core';\nimport type {\n  GA4Event,\n  GA4Hit,\n  GA4HitParams,\n  GA4Item,\n  GA4Mapping,\n} from './types';\nimport { parseConsent } from './parse';\n\n/**\n * Lookup root for mapping path resolution. Mapping rules reference keys via\n * dotted paths: `hit.dl`, `params.ep.transaction_id`, `params.epn.value`, `items`.\n *\n * `en` exposes the GA4 event name (used by the `*` fallback so unknown events\n * can carry their original name through). `firstItem` exposes `items[0]` so\n * promotion-style mappings can resolve `firstItem.promotionId` etc. without\n * needing array-index syntax in `getByPath`.\n *\n * Typed as `Record<string, unknown> & { ... }` so `getByPath` (which accepts\n * unknown) is happy without any narrowing cast on the call site.\n */\ntype LookupRoot = Record<string, unknown> & {\n  hit: GA4HitParams;\n  params: GA4Event['params'];\n  items: GA4Event['items'];\n  en: string;\n  firstItem?: GA4Item;\n};\n\n/**\n * Convert a parsed GA4 hit into zero or more walkerOS events.\n * One GA4 hit may carry several events (POST batch); each is mapped\n * independently with hit-level metadata merged in.\n */\nexport function mapHitToEvents(\n  hit: GA4Hit,\n  mapping: GA4Mapping,\n): WalkerOS.DeepPartialEvent[] {\n  const out: WalkerOS.DeepPartialEvent[] = [];\n  for (const event of hit.events) {\n    const mapped = mapOneEvent(hit.hit, event, mapping);\n    if (mapped) out.push(mapped);\n  }\n  return out;\n}\n\nfunction mapOneEvent(\n  hitParams: GA4HitParams,\n  event: GA4Event,\n  mapping: GA4Mapping,\n): WalkerOS.DeepPartialEvent | null {\n  const ruleEntry = mapping[event.en] ?? mapping['*'];\n  if (!ruleEntry) return null;\n  // For v1, only single-rule entries are supported (no array fan-out).\n  const rule: Mapping.Rule = Array.isArray(ruleEntry)\n    ? ruleEntry[0]\n    : ruleEntry;\n  if (!rule || rule.ignore) return null;\n\n  const lookup: LookupRoot = {\n    hit: hitParams,\n    params: event.params,\n    items: event.items,\n    en: event.en,\n    ...(event.items.length > 0 ? { firstItem: event.items[0] } : {}),\n  };\n\n  const evaluated: WalkerOS.DeepPartialEvent = {};\n\n  if (rule.name) {\n    const [entity, ...rest] = rule.name.split(' ');\n    evaluated.name = rule.name;\n    evaluated.entity = entity;\n    evaluated.action = rest.join(' ');\n  }\n\n  if (rule.data !== undefined) {\n    let data = evalValue(rule.data, lookup);\n    if (rule.remove && isObject(data)) {\n      for (const path of rule.remove) data = deleteByPath(data, path);\n    }\n    if (data !== undefined) {\n      evaluated.data = data as WalkerOS.Properties;\n    }\n  }\n\n  // Hit-level merge: user / globals / source.\n  evaluated.user = {\n    ...(hitParams.uid !== undefined ? { id: hitParams.uid } : {}),\n    ...(hitParams.cid !== undefined ? { device: hitParams.cid } : {}),\n    ...(hitParams.sid !== undefined ? { session: hitParams.sid } : {}),\n  };\n  evaluated.globals = {\n    ...(hitParams.ul !== undefined ? { language: hitParams.ul } : {}),\n    ...(hitParams.sr !== undefined ? { screen: hitParams.sr } : {}),\n  };\n  evaluated.source = {\n    type: 'ga4',\n    ...(hitParams.p !== undefined ? { platform: hitParams.p } : {}),\n  };\n\n  // Consent from gcs string, id from hit._p (fallback to generated string),\n  // timestamp from sid (epoch seconds → ms; falls back to wall-clock now),\n  // timing from event._et (ms; 0 if absent), trigger hard-coded to \"ga4\" for v1.\n  evaluated.consent = parseConsent(hitParams);\n  evaluated.id = hitParams._p ?? getId();\n  const sidNum = hitParams.sid ? Number(hitParams.sid) : NaN;\n  evaluated.timestamp =\n    !Number.isNaN(sidNum) && sidNum > 0 ? sidNum * 1000 : Date.now();\n  evaluated.timing = event.params._et ?? 0;\n  evaluated.trigger = 'ga4';\n\n  if (event.items.length > 0) {\n    evaluated.nested = itemsToNested(event.items);\n  }\n\n  return evaluated;\n}\n\n/**\n * GA4 items → walkerOS nested product entities.\n * Field naming: camelCase GA4Item keys are emitted as snake_case data keys\n * (`listName` → `list_name`, `promotionId` → `promotion_id`, etc).\n * Custom k<N>/v<N> pairs are spread as-is.\n *\n * Returns `WalkerOS.Entities` (i.e. `Array<WalkerOS.Entity>`). Note that the\n * canonical `WalkerOS.Entity` interface uses `entity: string` as the kind\n * discriminator (not `type`).\n */\nfunction itemsToNested(items: GA4Item[]): WalkerOS.Entities {\n  return items.map((item): WalkerOS.Entity => {\n    const data: WalkerOS.Properties = {};\n    if (item.id !== undefined) data.id = item.id;\n    if (item.name !== undefined) data.name = item.name;\n    if (item.brand !== undefined) data.brand = item.brand;\n    if (item.category !== undefined) data.category = item.category;\n    if (item.category2 !== undefined) data.category2 = item.category2;\n    if (item.category3 !== undefined) data.category3 = item.category3;\n    if (item.category4 !== undefined) data.category4 = item.category4;\n    if (item.category5 !== undefined) data.category5 = item.category5;\n    if (item.variant !== undefined) data.variant = item.variant;\n    if (item.price !== undefined) data.price = item.price;\n    if (item.quantity !== undefined) data.quantity = item.quantity;\n    if (item.coupon !== undefined) data.coupon = item.coupon;\n    if (item.discount !== undefined) data.discount = item.discount;\n    if (item.listName !== undefined) data.list_name = item.listName;\n    if (item.listId !== undefined) data.list_id = item.listId;\n    if (item.listPosition !== undefined) data.list_position = item.listPosition;\n    if (item.locationId !== undefined) data.location_id = item.locationId;\n    if (item.affiliation !== undefined) data.affiliation = item.affiliation;\n    if (item.creativeName !== undefined) data.creative_name = item.creativeName;\n    if (item.creativeSlot !== undefined) data.creative_slot = item.creativeSlot;\n    if (item.promotionId !== undefined) data.promotion_id = item.promotionId;\n    if (item.promotionName !== undefined)\n      data.promotion_name = item.promotionName;\n    for (const [k, v] of Object.entries(item.custom)) data[k] = v;\n    return { entity: 'product', data, nested: [], context: {} };\n  });\n}\n\n/**\n * Minimal mapping evaluator. v1 supports:\n *   - string → path lookup via getByPath\n *   - Array<Value> → fallback chain: first non-undefined wins\n *   - { value: X } → literal\n *   - { key: 'path' } → path lookup\n *   - { map: {...} } → recursive object build\n *\n * Deferred to v2: condition, loop, fn, validate, set, consent, $code.\n */\nfunction evalValue(\n  value: Mapping.Value | Mapping.Values,\n  root: LookupRoot,\n): unknown {\n  if (Array.isArray(value)) {\n    for (const v of value) {\n      const resolved = evalValue(v, root);\n      if (resolved !== undefined && resolved !== null) return resolved;\n    }\n    return undefined;\n  }\n  if (typeof value === 'string') {\n    return getByPath(root, value);\n  }\n  if (typeof value === 'object' && value !== null) {\n    if ('value' in value && value.value !== undefined) return value.value;\n    if ('key' in value && typeof value.key === 'string') {\n      return getByPath(root, value.key);\n    }\n    if ('map' in value && value.map) {\n      const out: Record<string, unknown> = {};\n      for (const [k, v] of Object.entries(value.map)) {\n        const resolved = evalValue(v, root);\n        if (resolved !== undefined) out[k] = resolved;\n      }\n      return out;\n    }\n  }\n  return undefined;\n}\n","import type { GA4Mapping } from './types';\n\n/**\n * Default GA4 event-name → walkerOS mapping rules.\n * Users may override or extend these via settings.mapping at config time.\n * The `'*'` key is the fallback for unknown event names.\n *\n * Field naming for `data.map`:\n * - Monetary: `currency` from `ep.currency`, `value`/`total` from `epn.value`,\n *   `tax` from `epn.tax`, `shipping` from `epn.shipping`, `coupon` from\n *   `ep.coupon`.\n * - Promotions read from `firstItem` (synthetic `items[0]` reference exposed by\n *   the mapper), since GA4 encodes promotion info inside item tilde strings.\n */\nexport const defaultMapping: GA4Mapping = {\n  // --- page ---\n  page_view: {\n    name: 'page view',\n    data: {\n      map: {\n        id: 'hit.dl',\n        title: 'hit.dt',\n        referrer: 'hit.dr',\n      },\n    },\n  },\n\n  // --- ecommerce ---\n  purchase: {\n    name: 'order complete',\n    data: {\n      map: {\n        id: 'params.ep.transaction_id',\n        currency: 'params.ep.currency',\n        total: 'params.epn.value',\n        tax: 'params.epn.tax',\n        shipping: 'params.epn.shipping',\n        coupon: 'params.ep.coupon',\n      },\n    },\n  },\n  view_item: {\n    name: 'product view',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n      },\n    },\n  },\n  add_to_cart: {\n    name: 'product add',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n      },\n    },\n  },\n  remove_from_cart: {\n    name: 'product remove',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n      },\n    },\n  },\n  view_cart: {\n    name: 'cart view',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n      },\n    },\n  },\n  begin_checkout: {\n    name: 'order start',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n        coupon: 'params.ep.coupon',\n      },\n    },\n  },\n  add_shipping_info: {\n    name: 'order shipping',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n        tier: 'params.ep.shipping_tier',\n      },\n    },\n  },\n  add_payment_info: {\n    name: 'order payment',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n        type: 'params.ep.payment_type',\n      },\n    },\n  },\n  refund: {\n    name: 'order refund',\n    data: {\n      map: {\n        id: 'params.ep.transaction_id',\n        currency: 'params.ep.currency',\n        total: 'params.epn.value',\n      },\n    },\n  },\n  add_to_wishlist: {\n    name: 'wishlist add',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n      },\n    },\n  },\n\n  // --- list / promotion ---\n  view_item_list: {\n    name: 'list view',\n    data: {\n      map: {\n        id: 'params.ep.item_list_id',\n        name: 'params.ep.item_list_name',\n      },\n    },\n  },\n  select_item: {\n    name: 'product click',\n    data: {\n      map: {\n        list_id: 'params.ep.item_list_id',\n        list_name: 'params.ep.item_list_name',\n      },\n    },\n  },\n  view_promotion: {\n    name: 'promotion view',\n    data: {\n      map: {\n        id: 'firstItem.promotionId',\n        name: 'firstItem.promotionName',\n        creative: 'firstItem.creativeName',\n        slot: 'firstItem.creativeSlot',\n      },\n    },\n  },\n  select_promotion: {\n    name: 'promotion click',\n    data: {\n      map: {\n        id: 'firstItem.promotionId',\n        name: 'firstItem.promotionName',\n        creative: 'firstItem.creativeName',\n        slot: 'firstItem.creativeSlot',\n      },\n    },\n  },\n  select_content: {\n    name: 'content select',\n    data: {\n      map: {\n        type: 'params.ep.content_type',\n        id: 'params.ep.content_id',\n      },\n    },\n  },\n\n  // --- engagement ---\n  scroll: {\n    name: 'page scroll',\n    data: {\n      map: {\n        percent: 'params.epn.percent_scrolled',\n      },\n    },\n  },\n  click: {\n    name: 'link click',\n    data: {\n      map: {\n        url: 'params.ep.link_url',\n        domain: 'params.ep.link_domain',\n        outbound: 'params.ep.outbound',\n      },\n    },\n  },\n  file_download: {\n    name: 'file download',\n    data: {\n      map: {\n        name: 'params.ep.file_name',\n        extension: 'params.ep.file_extension',\n        url: 'params.ep.link_url',\n      },\n    },\n  },\n  video_start: {\n    name: 'video start',\n    data: {\n      map: {\n        title: 'params.ep.video_title',\n        duration: 'params.epn.video_duration',\n        current: 'params.epn.video_current_time',\n        percent: 'params.epn.video_percent',\n      },\n    },\n  },\n  video_progress: {\n    name: 'video progress',\n    data: {\n      map: {\n        title: 'params.ep.video_title',\n        duration: 'params.epn.video_duration',\n        current: 'params.epn.video_current_time',\n        percent: 'params.epn.video_percent',\n      },\n    },\n  },\n  video_complete: {\n    name: 'video complete',\n    data: {\n      map: {\n        title: 'params.ep.video_title',\n        duration: 'params.epn.video_duration',\n        current: 'params.epn.video_current_time',\n        percent: 'params.epn.video_percent',\n      },\n    },\n  },\n  form_start: {\n    name: 'form start',\n    data: {\n      map: {\n        id: 'params.ep.form_id',\n        name: 'params.ep.form_name',\n        destination: 'params.ep.form_destination',\n      },\n    },\n  },\n  form_submit: {\n    name: 'form submit',\n    data: {\n      map: {\n        id: 'params.ep.form_id',\n        name: 'params.ep.form_name',\n        destination: 'params.ep.form_destination',\n      },\n    },\n  },\n  search: {\n    name: 'search submit',\n    data: {\n      map: {\n        term: 'params.ep.search_term',\n      },\n    },\n  },\n  login: {\n    name: 'session login',\n    data: {\n      map: {\n        method: 'params.ep.method',\n      },\n    },\n  },\n  sign_up: {\n    name: 'session signup',\n    data: {\n      map: {\n        method: 'params.ep.method',\n      },\n    },\n  },\n  generate_lead: {\n    name: 'lead generate',\n    data: {\n      map: {\n        currency: 'params.ep.currency',\n        value: 'params.epn.value',\n      },\n    },\n  },\n  share: {\n    name: 'content share',\n    data: {\n      map: {\n        method: 'params.ep.method',\n        type: 'params.ep.content_type',\n        id: 'params.ep.item_id',\n      },\n    },\n  },\n\n  // --- auto-fired noise: ignore by default (users can override) ---\n  user_engagement: { ignore: true },\n  session_start: { ignore: true },\n  first_visit: { ignore: true },\n\n  // --- fallback for unknown event names ---\n  '*': {\n    name: 'ga4 track',\n    data: {\n      map: {\n        event_name: 'en',\n      },\n    },\n  },\n};\n","import { mergeMappingRule } from '@walkeros/core';\nimport type { GA4Mapping } from './types';\n\n/**\n * Merge user mapping overrides onto the shipped defaults, per GA4 event key.\n * A user entry with `extend`/`remove` patches the default; otherwise it\n * replaces it. `GA4Mapping` values are single rules (no Rule[]), matching\n * the evaluator. `extend` only changes anything for keys that ship a default.\n */\nexport function mergeGa4Mapping(\n  defaults: GA4Mapping,\n  user: GA4Mapping,\n): GA4Mapping {\n  const merged: GA4Mapping = { ...defaults };\n  for (const key of Object.keys(user)) {\n    const userRule = user[key];\n    if (!userRule) continue;\n    const baseRule = defaults[key];\n    merged[key] = baseRule\n      ? mergeMappingRule(baseRule, userRule)\n      : mergeMappingRule({}, userRule);\n  }\n  return merged;\n}\n","import type { Ingest, Transformer } from '@walkeros/core';\nimport { parseRequest } from './parse';\nimport { mapHitToEvents } from './map';\nimport { defaultMapping } from './defaults';\nimport { mergeGa4Mapping } from './merge';\nimport type { GA4Request, GA4Settings } from './types';\n\n/**\n * Read the raw GA4 HTTP request from `ctx.ingest`.\n *\n * Source wiring (e.g. an express source) is expected to populate\n * `ingest.url` (full request URL, query string included) and optionally\n * `ingest.body` (raw POST body as a string). `Ingest` is an open\n * `Record<string, unknown>` per `@walkeros/core`, so each field is\n * narrowed with a `typeof` guard instead of a cast.\n *\n * Returns `null` if `url` is missing or not a string — the caller drops\n * the event in that case.\n */\nfunction readGA4Request(ingest: Ingest): GA4Request | null {\n  const url = ingest.url;\n  if (typeof url !== 'string') return null;\n  const body = ingest.body;\n  return {\n    url,\n    body: typeof body === 'string' ? body : undefined,\n  };\n}\n\nexport const transformerGa4: Transformer.Init<\n  Transformer.Types<GA4Settings>\n> = (context) => {\n  const { config } = context;\n  const settings = config.settings ?? {};\n  const tidPattern = new RegExp(settings.tidPattern ?? '^G-');\n  const mapping = mergeGa4Mapping(defaultMapping, settings.mapping ?? {});\n\n  return {\n    type: 'ga4',\n    config,\n    async push(_event, ctx) {\n      const { logger } = ctx;\n\n      const raw = readGA4Request(ctx.ingest);\n      if (!raw) {\n        logger.debug('transformer-ga4: no request in ingest; skipping');\n        return false;\n      }\n\n      try {\n        const hit = parseRequest(raw);\n\n        if (hit.hit.tid && !tidPattern.test(hit.hit.tid)) {\n          logger.debug(\n            `transformer-ga4: tid ${hit.hit.tid} dropped by tidPattern`,\n          );\n          return false;\n        }\n\n        const events = mapHitToEvents(hit, mapping);\n        if (events.length === 0) {\n          logger.debug(\n            `transformer-ga4: no events mapped (tid=${hit.hit.tid ?? 'unknown'})`,\n          );\n          return false;\n        }\n\n        logger.debug(\n          `transformer-ga4: decoded ${events.length} events from ${hit.hit.tid ?? 'unknown'}`,\n        );\n\n        if (events.length === 1) return { event: events[0] };\n        return events.map((event) => ({ event }));\n      } catch (err) {\n        const message = err instanceof Error ? err.message : String(err);\n        logger.error(`transformer-ga4: parse error: ${message}`);\n        return false;\n      }\n    },\n  };\n};\n"],"mappings":"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","names":["val"]}