{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { DestinationWeb } from '@walkeros/web-core';\nimport { getMappingValue, isObject, isString } from '@walkeros/core';\nimport { getEnv } from '@walkeros/web-core';\nimport type {\n  Destination,\n  Env,\n  HeapConfig,\n  HeapPropertyValue,\n  HeapSDK,\n  Mapping,\n  Settings,\n} from './types';\n\n// Types export\nexport * as DestinationHeap from './types';\n\n/**\n * Resolve the Heap SDK: prefer the caller-provided mock (tests) via\n * env.window.heap, otherwise fall back to the global window.heap the\n * init function established (real snippet command queue).\n */\nfunction getHeap(env: Env | undefined): HeapSDK | undefined {\n  if (env?.window?.heap) return env.window.heap;\n  const { window } = getEnv(env as DestinationWeb.Env | undefined);\n  return (window as Window).heap;\n}\n\n/**\n * Coerce a resolved object into a flat { key: primitive } map suitable\n * for Heap's property APIs. Drops non-primitive values.\n */\nfunction toHeapProperties(value: unknown): Record<string, HeapPropertyValue> {\n  const out: Record<string, HeapPropertyValue> = {};\n  if (!isObject(value)) return out;\n  for (const [key, val] of Object.entries(value)) {\n    if (\n      typeof val === 'string' ||\n      typeof val === 'number' ||\n      typeof val === 'boolean'\n    ) {\n      out[key] = val;\n    }\n  }\n  return out;\n}\n\nexport const destinationHeap: Destination = {\n  type: 'heap',\n\n  config: {},\n\n  init({ config, env }) {\n    const settings = config.settings;\n    if (!settings?.appId) return false;\n\n    // In tests a mock is provided via env.window.heap and there's nothing\n    // for us to bootstrap. In production we install the Heap snippet's\n    // command queue and call heap.load().\n    if (env?.window?.heap) return config;\n\n    const { window, document } = getEnv(env as DestinationWeb.Env | undefined);\n    const w = window as Window;\n    const doc = document as Document;\n\n    const heapConfig: HeapConfig = {\n      disableTextCapture: settings.disableTextCapture ?? true,\n      disablePageviewAutocapture: settings.disablePageviewAutocapture ?? true,\n      ...(settings.disableSessionReplay !== undefined && {\n        disableSessionReplay: settings.disableSessionReplay,\n      }),\n      ...(settings.secureCookie !== undefined && {\n        secureCookie: settings.secureCookie,\n      }),\n      ...(settings.ingestServer !== undefined && {\n        ingestServer: settings.ingestServer,\n      }),\n      ...settings.heapConfig,\n    };\n\n    // Install the Heap snippet's command queue if not already present.\n    if (!w.heap) {\n      const heap: HeapSDK = {\n        load: (appId: string, cfg?: HeapConfig) => {\n          heap.appid = appId;\n          heap.config = cfg ?? {};\n        },\n        track: (() => undefined) as HeapSDK['track'],\n        identify: (() => undefined) as HeapSDK['identify'],\n        resetIdentity: () => undefined,\n        addUserProperties: (() => undefined) as HeapSDK['addUserProperties'],\n        addEventProperties: (() => undefined) as HeapSDK['addEventProperties'],\n        clearEventProperties: () => undefined,\n        startTracking: () => undefined,\n        stopTracking: () => undefined,\n        q: [],\n      };\n\n      // Queue all calls until the real snippet boots and replaces these.\n      const methods: Array<keyof HeapSDK> = [\n        'addEventProperties',\n        'addUserProperties',\n        'clearEventProperties',\n        'identify',\n        'resetIdentity',\n        'track',\n        'startTracking',\n        'stopTracking',\n      ];\n      for (const method of methods) {\n        const queue = (...args: unknown[]) => {\n          heap.q = heap.q || [];\n          heap.q.push([method, ...args]);\n        };\n        (heap as unknown as Record<string, (...args: unknown[]) => void>)[\n          method as string\n        ] = queue;\n      }\n\n      w.heap = heap;\n    }\n\n    // Load real snippet script unless disabled.\n    if (config.loadScript) addScript(settings.appId, doc);\n\n    const heap = w.heap as HeapSDK;\n    if (!heap.appid) heap.load(settings.appId, heapConfig);\n\n    return config;\n  },\n\n  async push(event, { config, data, env, rule, collector }) {\n    const heap = getHeap(env as Env | undefined);\n    if (!heap) return;\n\n    const settings = (config.settings || {}) as Partial<Settings>;\n    const mappingSettings = (rule?.settings || {}) as Mapping;\n\n    // 1. Reset identity first - subsequent identify/userProperties\n    //    operate on the fresh anonymous user.\n    if (mappingSettings.reset !== undefined) {\n      const resolved =\n        typeof mappingSettings.reset === 'boolean'\n          ? mappingSettings.reset\n          : await getMappingValue(event, mappingSettings.reset, { collector });\n      if (resolved) heap.resetIdentity();\n    }\n\n    // 2. Identify - rule-level wins over destination-level.\n    const identifyMapping = mappingSettings.identify ?? settings.identify;\n    if (identifyMapping !== undefined) {\n      const resolved = await getMappingValue(event, identifyMapping, {\n        collector,\n      });\n      if (isString(resolved) && resolved.length > 0) {\n        heap.identify(resolved);\n      }\n    }\n\n    // 3. User properties - rule-level wins over destination-level.\n    const userPropsMapping =\n      mappingSettings.userProperties ?? settings.userProperties;\n    if (userPropsMapping !== undefined) {\n      const resolved = await getMappingValue(event, userPropsMapping, {\n        collector,\n      });\n      if (isObject(resolved)) {\n        heap.addUserProperties(toHeapProperties(resolved));\n      }\n    }\n\n    // 4. Persistent event properties.\n    if (mappingSettings.eventProperties !== undefined) {\n      const resolved = await getMappingValue(\n        event,\n        mappingSettings.eventProperties,\n        { collector },\n      );\n      if (isObject(resolved)) {\n        heap.addEventProperties(toHeapProperties(resolved));\n      }\n    }\n\n    // 5. Clear persistent event properties.\n    if (mappingSettings.clearEventProperties !== undefined) {\n      const resolved =\n        typeof mappingSettings.clearEventProperties === 'boolean'\n          ? mappingSettings.clearEventProperties\n          : await getMappingValue(event, mappingSettings.clearEventProperties, {\n              collector,\n            });\n      if (resolved) heap.clearEventProperties();\n    }\n\n    // 6. Default track - unless rule.silent is set.\n    if (rule?.silent !== true) {\n      const eventName = isString(rule?.name) ? rule.name : event.name;\n      const properties = toHeapProperties(data);\n      heap.track(eventName, properties);\n    }\n  },\n\n  on(type, context) {\n    if (type !== 'consent' || !context.data) return;\n\n    const heap = getHeap(context.env as Env | undefined);\n    if (!heap) return;\n\n    const required = context.config?.consent;\n    if (!required || Object.keys(required).length === 0) return;\n\n    const consent = context.data as Record<string, boolean>;\n    const allGranted = Object.keys(required).every(\n      (key) => consent[key] === true,\n    );\n\n    if (allGranted) heap.startTracking();\n    else heap.stopTracking();\n  },\n};\n\nfunction addScript(appId: string, doc: Document) {\n  const script = doc.createElement('script');\n  script.type = 'text/javascript';\n  script.async = true;\n  script.src = `https://cdn.heapanalytics.com/js/heap-${appId}.js`;\n  const firstScript = doc.getElementsByTagName('script')[0];\n  if (firstScript && firstScript.parentNode) {\n    firstScript.parentNode.insertBefore(script, firstScript);\n  } else {\n    doc.head.appendChild(script);\n  }\n}\n\nexport default destinationHeap;\n","import type {\n  Mapping as WalkerOSMapping,\n  Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationWeb } from '@walkeros/web-core';\n\n/** Property value types accepted by Heap SDK methods. */\nexport type HeapPropertyValue = string | number | boolean;\n\n/** Options accepted by heap.load() as the second argument. */\nexport interface HeapConfig {\n  disableTextCapture?: boolean;\n  disablePageviewAutocapture?: boolean;\n  disableSessionReplay?: boolean;\n  secureCookie?: boolean;\n  compressCookies?: boolean;\n  clearEventPropertiesOnNewUser?: boolean;\n  ingestServer?: string;\n  trackingServer?: string;\n  eventPropertiesStorageMedium?: string;\n  metadataStorageMedium?: string;\n  [key: string]: unknown;\n}\n\n/**\n * Heap SDK surface — the subset of window.heap methods this destination uses.\n * Mirrors the snippet-provided command queue so tests can mock each method.\n */\nexport interface HeapSDK {\n  load: (appId: string, config?: HeapConfig) => void;\n  track: (\n    event: string,\n    properties?: Record<string, HeapPropertyValue>,\n  ) => void;\n  identify: (identity: string) => void;\n  resetIdentity: () => void;\n  addUserProperties: (properties: Record<string, HeapPropertyValue>) => void;\n  addEventProperties: (properties: Record<string, HeapPropertyValue>) => void;\n  clearEventProperties: () => void;\n  startTracking: () => void;\n  stopTracking: () => void;\n  appid?: string;\n  config?: HeapConfig;\n  q?: unknown[][];\n}\n\n/**\n * Settings (destination-level).\n *\n * appId is required (Heap Project Settings → App ID).\n * identify/userProperties resolve every push to keep identity sticky.\n */\nexport interface Settings {\n  /** Heap App ID (required). Find it in Project > Settings > App ID. */\n  appId: string;\n  /** Disable Heap auto text capture. Default: true. */\n  disableTextCapture?: boolean;\n  /** Disable Heap automatic pageview tracking. Default: true (walkerOS handles pageviews). */\n  disablePageviewAutocapture?: boolean;\n  /** Disable Heap session replay. */\n  disableSessionReplay?: boolean;\n  /** SSL-only cookies. */\n  secureCookie?: boolean;\n  /** Custom server endpoint (first-party proxy). */\n  ingestServer?: string;\n  /** Destination-level identity mapping. Resolves to a string for heap.identify(). */\n  identify?: WalkerOSMapping.Value;\n  /** Destination-level user properties mapping. Resolves to object for heap.addUserProperties(). */\n  userProperties?: WalkerOSMapping.Value;\n  /** Additional heap.load() config passthrough. */\n  heapConfig?: HeapConfig;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Mapping (rule.settings) — per-event overrides.\n *\n * identify             — resolves to string for heap.identify()\n * reset                — truthy triggers heap.resetIdentity()\n * userProperties       — resolves to object for heap.addUserProperties()\n * eventProperties      — resolves to object for heap.addEventProperties() (persistent)\n * clearEventProperties — truthy triggers heap.clearEventProperties()\n */\nexport interface Mapping {\n  identify?: WalkerOSMapping.Value;\n  reset?: boolean | WalkerOSMapping.Value;\n  userProperties?: WalkerOSMapping.Value;\n  eventProperties?: WalkerOSMapping.Value;\n  clearEventProperties?: boolean | WalkerOSMapping.Value;\n}\n\n/**\n * Env — optional override for the Heap SDK. Production leaves this\n * undefined and the destination creates the snippet's command queue on\n * window.heap. Tests provide a mock via env.window.heap = { ... }.\n */\nexport interface Env extends DestinationWeb.Env {\n  window: {\n    heap: HeapSDK;\n  };\n}\n\ndeclare global {\n  interface Window {\n    heap?: HeapSDK;\n  }\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport type Destination = DestinationWeb.Destination<Types>;\nexport type Config = DestinationWeb.Config<Types>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":"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","names":["heap"]}