{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isObject, isString } from '@walkeros/core';\nimport { init as fsInit, FullStory } from '@fullstory/browser';\nimport type {\n  Destination,\n  Env,\n  FullStorySDK,\n  Mapping,\n  Settings,\n} from './types';\n\n// Types export\nexport * as DestinationFullStory from './types';\n\n/**\n * Resolve the FullStory SDK: use the caller-provided mock when available\n * (tests), otherwise fall back to the real @fullstory/browser functions.\n */\nfunction getFS(env: Env | undefined): FullStorySDK {\n  if (env?.fullstory) return env.fullstory;\n  return {\n    init: fsInit,\n    trackEvent: (opts) =>\n      FullStory('trackEvent', {\n        name: opts.name,\n        properties: opts.properties ?? {},\n      }),\n    setIdentity: (opts) => FullStory('setIdentity', opts),\n    setProperties: (opts) => FullStory('setProperties', opts),\n    shutdown: () => FullStory('shutdown'),\n    start: () => FullStory('start'),\n  };\n}\n\nexport const destinationFullStory: Destination = {\n  type: 'fullstory',\n\n  config: {},\n\n  init({ config, env }) {\n    const settings = config.settings;\n    if (!settings?.orgId) return false;\n\n    const fs = getFS(env as Env | undefined);\n    const initOpts: Parameters<FullStorySDK['init']>[0] = {\n      orgId: settings.orgId,\n    };\n    if (settings.host !== undefined) initOpts.host = settings.host;\n    if (settings.script !== undefined) initOpts.script = settings.script;\n    if (settings.cookieDomain !== undefined)\n      initOpts.cookieDomain = settings.cookieDomain;\n    if (settings.debug !== undefined) initOpts.debug = settings.debug;\n    if (settings.devMode !== undefined) initOpts.devMode = settings.devMode;\n    if (settings.startCaptureManually !== undefined)\n      initOpts.startCaptureManually = settings.startCaptureManually;\n    if (settings.namespace !== undefined)\n      initOpts.namespace = settings.namespace;\n    if (settings.recordCrossDomainIFrames !== undefined)\n      initOpts.recordCrossDomainIFrames = settings.recordCrossDomainIFrames;\n    fs.init(initOpts);\n\n    return config;\n  },\n\n  async push(event, { config, rule, env, data, collector }) {\n    const fs = getFS(env as Env | undefined);\n    const settings = (config.settings || {}) as Partial<Settings>;\n    const mappingSettings = (rule?.settings || {}) as Mapping;\n\n    // 1. Identify -- rule-level override 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 (isObject(resolved)) {\n        const { uid, properties } = resolved as {\n          uid?: unknown;\n          properties?: unknown;\n        };\n        if (isString(uid) && uid) {\n          const identityOpts: {\n            uid: string;\n            properties?: Record<string, unknown>;\n          } = { uid };\n          if (isObject(properties)) {\n            identityOpts.properties = properties as Record<string, unknown>;\n          }\n          fs.setIdentity(identityOpts);\n        }\n      }\n    }\n\n    // 2. setProperties -- user or page scope\n    if (mappingSettings.set !== undefined) {\n      const resolved = await getMappingValue(event, mappingSettings.set, {\n        collector,\n      });\n      if (isObject(resolved)) {\n        const propertyType = mappingSettings.setType || 'user';\n        fs.setProperties({\n          type: propertyType,\n          properties: resolved as Record<string, unknown>,\n        });\n      }\n    }\n\n    // 3. Default trackEvent -- unless rule.silent is set\n    if (rule?.silent !== true) {\n      const eventName = isString(rule?.name) ? rule.name : event.name;\n      const properties = isObject(data)\n        ? (data as Record<string, unknown>)\n        : {};\n      fs.trackEvent({ name: eventName, properties });\n    }\n  },\n\n  on(type, context) {\n    if (type !== 'consent' || !context.data) return;\n    const fs = getFS(context.env as Env | undefined);\n\n    const consent = context.data as WalkerOS.Consent;\n    const settings = (context.config?.settings || {}) as Partial<Settings>;\n    const consentMap = settings.consent;\n    if (!consentMap) return;\n\n    for (const [walkerKey, fsAction] of Object.entries(consentMap)) {\n      if (!(walkerKey in consent)) continue;\n      const granted = consent[walkerKey] === true;\n\n      if (fsAction === 'capture') {\n        if (granted) {\n          fs.start();\n        } else {\n          fs.shutdown();\n        }\n      } else if (fsAction === 'consent') {\n        fs.setIdentity({ consent: granted });\n      }\n    }\n  },\n};\n\nexport default destinationFullStory;\n","import type {\n  Mapping as WalkerOSMapping,\n  Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationWeb } from '@walkeros/web-core';\n\n/**\n * Settings (destination-level).\n *\n * orgId is the FullStory organization ID (e.g. \"o-XXXXXX-na1\").\n * All SnippetOptions from @fullstory/browser are available as passthrough.\n */\nexport interface Settings {\n  orgId: string;\n  host?: string;\n  script?: string;\n  cookieDomain?: string;\n  debug?: boolean;\n  devMode?: boolean;\n  startCaptureManually?: boolean;\n  namespace?: string;\n  recordCrossDomainIFrames?: boolean;\n  identify?: WalkerOSMapping.Value;\n  consent?: Record<string, 'capture' | 'consent'>;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Mapping (rule.settings) -- per-event overrides.\n *\n * identify -- mapping value resolving to { uid, properties? } for FullStory('setIdentity', ...)\n * set      -- mapping value resolving to properties for FullStory('setProperties', ...)\n * setType  -- property scope: 'user' (default) or 'page'\n */\nexport interface Mapping {\n  identify?: WalkerOSMapping.Value;\n  set?: WalkerOSMapping.Value;\n  setType?: 'user' | 'page';\n}\n\n/**\n * FullStory SDK surface -- the subset of @fullstory/browser methods this\n * destination actually calls. Tests can mock each method individually.\n *\n * Uses V2 API only: FullStory('operationName', options).\n */\nexport interface FullStorySDK {\n  init: (options: {\n    orgId: string;\n    host?: string;\n    script?: string;\n    cookieDomain?: string;\n    debug?: boolean;\n    devMode?: boolean;\n    startCaptureManually?: boolean;\n    namespace?: string;\n    recordCrossDomainIFrames?: boolean;\n  }) => void;\n  trackEvent: (options: {\n    name: string;\n    properties?: Record<string, unknown>;\n  }) => void;\n  setIdentity: (options: {\n    uid?: string | false;\n    anonymous?: boolean;\n    consent?: boolean;\n    properties?: Record<string, unknown>;\n  }) => void;\n  setProperties: (options: {\n    type: 'user' | 'page';\n    properties: Record<string, unknown>;\n  }) => void;\n  shutdown: () => void;\n  start: () => void;\n}\n\n/**\n * Env -- optional override for the vendor SDK. Production leaves this\n * undefined and the destination falls back to the real @fullstory/browser.\n * Tests provide a mock via env.fullstory = { ... }.\n */\nexport interface Env extends DestinationWeb.Env {\n  fullstory?: FullStorySDK;\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":[]}