@walkeros/server-destination-posthog 3.3.0-next-1776098542393

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationPostHog:()=>types_exports,default:()=>index_default,destinationPostHog:()=>destinationPostHog}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var import_posthog_node=require("posthog-node");var import_core=require("@walkeros/core"),types_exports={},destinationPostHog={type:"posthog",config:{},async init({config:partialConfig,env:env,logger:logger}){const config=function(partialConfig={},env,logger){const settings=partialConfig.settings||{},{apiKey:apiKey}=settings;apiKey||logger.throw("Config settings apiKey missing");const options={};settings.host&&(options.host=settings.host),void 0!==settings.flushAt&&(options.flushAt=settings.flushAt),void 0!==settings.flushInterval&&(options.flushInterval=settings.flushInterval),settings.personalApiKey&&(options.personalApiKey=settings.personalApiKey),void 0!==settings.featureFlagsPollingInterval&&(options.featureFlagsPollingInterval=settings.featureFlagsPollingInterval),void 0!==settings.disableGeoip&&(options.disableGeoip=settings.disableGeoip),void 0!==settings.disableCompression&&(options.disableCompression=settings.disableCompression),void 0!==settings.requestTimeout&&(options.requestTimeout=settings.requestTimeout),void 0!==settings.fetchRetryCount&&(options.fetchRetryCount=settings.fetchRetryCount),void 0!==settings.fetchRetryDelay&&(options.fetchRetryDelay=settings.fetchRetryDelay),void 0!==settings.debug&&(options.debug=settings.debug),void 0!==settings.disabled&&(options.disabled=settings.disabled);const client=new((null==env?void 0:env.PostHog)||import_posthog_node.PostHog)(apiKey,options),settingsConfig={...settings,apiKey:apiKey,client:client};return{...partialConfig,settings:settingsConfig}}(partialConfig,env,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,collector:collector}){var _a,_b,_c,_d,_e;const settings=config.settings,client=settings.client;if(!client)return;const mappingSettings=(null==rule?void 0:rule.settings)||{},identifyMapping=null!=(_a=mappingSettings.identify)?_a:settings.identify;let distinctId,identifyResolved;if(void 0!==identifyMapping){const resolved=await(0,import_core.getMappingValue)(event,identifyMapping,{collector:collector});(0,import_core.isObject)(resolved)&&(identifyResolved=resolved,(0,import_core.isString)(identifyResolved.distinctId)&&(distinctId=identifyResolved.distinctId))}if(distinctId||(distinctId=((0,import_core.isString)(null==(_b=event.user)?void 0:_b.id)?event.user.id:void 0)||((0,import_core.isString)(null==(_c=event.user)?void 0:_c.hash)?event.user.hash:void 0)||((0,import_core.isString)(null==(_d=event.user)?void 0:_d.session)?event.user.session:void 0)||"anonymous"),identifyResolved){const $set=(0,import_core.isObject)(identifyResolved.$set)?identifyResolved.$set:void 0,$setOnce=(0,import_core.isObject)(identifyResolved.$set_once)?identifyResolved.$set_once:void 0;if($set||$setOnce){const properties={};$set&&(properties.$set=$set),$setOnce&&(properties.$set_once=$setOnce),client.identify({distinctId:distinctId,properties:properties})}}const groupMapping=null!=(_e=mappingSettings.group)?_e:settings.group;let groups;if(void 0!==groupMapping){const resolved=await(0,import_core.getMappingValue)(event,groupMapping,{collector:collector});if((0,import_core.isObject)(resolved)){const groupResolved=resolved,type=groupResolved.type,key=groupResolved.key,properties=(0,import_core.isObject)(groupResolved.properties)?groupResolved.properties:void 0;(0,import_core.isString)(type)&&((0,import_core.isString)(key)||"number"==typeof key)&&(properties&&client.groupIdentify({groupType:type,groupKey:String(key),properties:properties}),groups={[type]:key})}}if(!0!==(null==rule?void 0:rule.skip)){const captureArgs={distinctId:distinctId,event:(0,import_core.isString)(null==rule?void 0:rule.name)?rule.name:event.name,properties:(0,import_core.isObject)(data)?data:{}};groups&&(captureArgs.groups=groups),client.capture(captureArgs)}}(event,context),async destroy({config:config}){var _a;const client=null==(_a=null==config?void 0:config.settings)?void 0:_a.client;client&&await client.shutdown()},on(type,context){var _a,_b;if("consent"!==type||!(null==context?void 0:context.data))return;const client=((null==(_a=context.config)?void 0:_a.settings)||{}).client;if(!client)return;const consent=context.data,required=null==(_b=context.config)?void 0:_b.consent;if(!required||0===Object.keys(required).length)return;Object.keys(required).every(key=>!0===consent[key])?client.enable():client.disable()}},index_default=destinationPostHog;//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport type { Destination, Env, Settings } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationPostHog from './types';\n\nexport const destinationPostHog: Destination = {\n type: 'posthog',\n\n config: {},\n\n async init({ config: partialConfig, env, logger }) {\n const config = getConfig(partialConfig, env as Env | undefined, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const client = (config?.settings as Settings | undefined)?.client;\n if (client) {\n await client.shutdown();\n }\n },\n\n on(type, context) {\n if (type !== 'consent' || !context?.data) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const client = settings.client;\n if (!client) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = (context.config as { consent?: WalkerOS.Consent })\n ?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n if (allGranted) {\n client.enable();\n } else {\n client.disable();\n }\n },\n};\n\nexport default destinationPostHog;\n","import type { Config, Env, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\nimport { PostHog } from 'posthog-node';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n env: Env | undefined,\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n // Extract PostHog SDK options from settings\n const options: Record<string, unknown> = {};\n if (settings.host) options.host = settings.host;\n if (settings.flushAt !== undefined) options.flushAt = settings.flushAt;\n if (settings.flushInterval !== undefined)\n options.flushInterval = settings.flushInterval;\n if (settings.personalApiKey) options.personalApiKey = settings.personalApiKey;\n if (settings.featureFlagsPollingInterval !== undefined)\n options.featureFlagsPollingInterval = settings.featureFlagsPollingInterval;\n if (settings.disableGeoip !== undefined)\n options.disableGeoip = settings.disableGeoip;\n if (settings.disableCompression !== undefined)\n options.disableCompression = settings.disableCompression;\n if (settings.requestTimeout !== undefined)\n options.requestTimeout = settings.requestTimeout;\n if (settings.fetchRetryCount !== undefined)\n options.fetchRetryCount = settings.fetchRetryCount;\n if (settings.fetchRetryDelay !== undefined)\n options.fetchRetryDelay = settings.fetchRetryDelay;\n if (settings.debug !== undefined) options.debug = settings.debug;\n if (settings.disabled !== undefined) options.disabled = settings.disabled;\n\n // Use PostHog from env if available, otherwise use real PostHog\n const PostHogClass = env?.PostHog || PostHog;\n const client = new PostHogClass(apiKey, options);\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { PushFn } from './types';\nimport { getMappingValue, isObject, isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector },\n) {\n const settings = config.settings!;\n const client = settings.client;\n if (!client) return;\n\n const mappingSettings = (rule?.settings || {}) as Record<string, unknown>;\n\n // Resolve distinctId: rule-level identify wins over destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let identifyResolved: Record<string, unknown> | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n identifyResolved = resolved as Record<string, unknown>;\n if (isString(identifyResolved.distinctId)) {\n distinctId = identifyResolved.distinctId as string;\n }\n }\n }\n\n // Fallback distinctId from event.user\n if (!distinctId) {\n distinctId =\n (isString(event.user?.id) ? event.user.id : undefined) ||\n (isString(event.user?.hash) ? event.user.hash : undefined) ||\n (isString(event.user?.session) ? event.user.session : undefined) ||\n 'anonymous';\n }\n\n // 1. Identity — if $set or $set_once present, call client.identify()\n if (identifyResolved) {\n const $set = isObject(identifyResolved.$set)\n ? (identifyResolved.$set as Record<string, unknown>)\n : undefined;\n const $setOnce = isObject(identifyResolved.$set_once)\n ? (identifyResolved.$set_once as Record<string, unknown>)\n : undefined;\n\n if ($set || $setOnce) {\n const properties: Record<string, unknown> = {};\n if ($set) properties.$set = $set;\n if ($setOnce) properties.$set_once = $setOnce;\n client.identify({ distinctId, properties });\n }\n }\n\n // 2. Group — resolve group mapping (rule-level wins)\n const groupMapping = mappingSettings.group ?? settings.group;\n let groups: Record<string, string | number> | undefined;\n\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const groupResolved = resolved as Record<string, unknown>;\n const type = groupResolved.type;\n const key = groupResolved.key;\n const properties = isObject(groupResolved.properties)\n ? (groupResolved.properties as Record<string, unknown>)\n : undefined;\n\n if (isString(type) && (isString(key) || typeof key === 'number')) {\n // If properties present, call groupIdentify\n if (properties) {\n client.groupIdentify({\n groupType: type,\n groupKey: String(key),\n properties,\n });\n }\n // Build groups object for capture\n groups = { [type]: key as string | number };\n }\n }\n }\n\n // 3. Capture — unless rule opts out via skip\n if (rule?.skip !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data) ? (data as Record<string, unknown>) : {};\n\n const captureArgs: Record<string, unknown> = {\n distinctId,\n event: eventName,\n properties,\n };\n if (groups) captureArgs.groups = groups;\n\n client.capture(captureArgs as Parameters<typeof client.capture>[0]);\n }\n};\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\nimport type { PostHog } from 'posthog-node';\n\nexport interface Settings {\n /** PostHog project API key (phc_...) */\n apiKey: string;\n /** PostHog client instance, populated by init */\n client?: PostHog;\n /** Destination-level identity mapping */\n identify?: WalkerOSMapping.Value;\n /** Destination-level group mapping */\n group?: WalkerOSMapping.Value;\n /** Event sections to flatten into capture properties */\n include?: string[];\n // PostHog SDK passthrough options\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n personalApiKey?: string;\n featureFlagsPollingInterval?: number;\n disableGeoip?: boolean;\n disableCompression?: boolean;\n requestTimeout?: number;\n fetchRetryCount?: number;\n fetchRetryDelay?: number;\n debug?: boolean;\n disabled?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n PostHog?: typeof PostHog;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{PostHog}from"posthog-node";import{getMappingValue,isObject,isString}from"@walkeros/core";var types_exports={},destinationPostHog={type:"posthog",config:{},async init({config:partialConfig,env:env,logger:logger}){const config=function(partialConfig={},env,logger){const settings=partialConfig.settings||{},{apiKey:apiKey}=settings;apiKey||logger.throw("Config settings apiKey missing");const options={};settings.host&&(options.host=settings.host),void 0!==settings.flushAt&&(options.flushAt=settings.flushAt),void 0!==settings.flushInterval&&(options.flushInterval=settings.flushInterval),settings.personalApiKey&&(options.personalApiKey=settings.personalApiKey),void 0!==settings.featureFlagsPollingInterval&&(options.featureFlagsPollingInterval=settings.featureFlagsPollingInterval),void 0!==settings.disableGeoip&&(options.disableGeoip=settings.disableGeoip),void 0!==settings.disableCompression&&(options.disableCompression=settings.disableCompression),void 0!==settings.requestTimeout&&(options.requestTimeout=settings.requestTimeout),void 0!==settings.fetchRetryCount&&(options.fetchRetryCount=settings.fetchRetryCount),void 0!==settings.fetchRetryDelay&&(options.fetchRetryDelay=settings.fetchRetryDelay),void 0!==settings.debug&&(options.debug=settings.debug),void 0!==settings.disabled&&(options.disabled=settings.disabled);const client=new((null==env?void 0:env.PostHog)||PostHog)(apiKey,options),settingsConfig={...settings,apiKey:apiKey,client:client};return{...partialConfig,settings:settingsConfig}}(partialConfig,env,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,collector:collector}){var _a,_b,_c,_d,_e;const settings=config.settings,client=settings.client;if(!client)return;const mappingSettings=(null==rule?void 0:rule.settings)||{},identifyMapping=null!=(_a=mappingSettings.identify)?_a:settings.identify;let distinctId,identifyResolved;if(void 0!==identifyMapping){const resolved=await getMappingValue(event,identifyMapping,{collector:collector});isObject(resolved)&&(identifyResolved=resolved,isString(identifyResolved.distinctId)&&(distinctId=identifyResolved.distinctId))}if(distinctId||(distinctId=(isString(null==(_b=event.user)?void 0:_b.id)?event.user.id:void 0)||(isString(null==(_c=event.user)?void 0:_c.hash)?event.user.hash:void 0)||(isString(null==(_d=event.user)?void 0:_d.session)?event.user.session:void 0)||"anonymous"),identifyResolved){const $set=isObject(identifyResolved.$set)?identifyResolved.$set:void 0,$setOnce=isObject(identifyResolved.$set_once)?identifyResolved.$set_once:void 0;if($set||$setOnce){const properties={};$set&&(properties.$set=$set),$setOnce&&(properties.$set_once=$setOnce),client.identify({distinctId:distinctId,properties:properties})}}const groupMapping=null!=(_e=mappingSettings.group)?_e:settings.group;let groups;if(void 0!==groupMapping){const resolved=await getMappingValue(event,groupMapping,{collector:collector});if(isObject(resolved)){const groupResolved=resolved,type=groupResolved.type,key=groupResolved.key,properties=isObject(groupResolved.properties)?groupResolved.properties:void 0;isString(type)&&(isString(key)||"number"==typeof key)&&(properties&&client.groupIdentify({groupType:type,groupKey:String(key),properties:properties}),groups={[type]:key})}}if(!0!==(null==rule?void 0:rule.skip)){const captureArgs={distinctId:distinctId,event:isString(null==rule?void 0:rule.name)?rule.name:event.name,properties:isObject(data)?data:{}};groups&&(captureArgs.groups=groups),client.capture(captureArgs)}}(event,context),async destroy({config:config}){var _a;const client=null==(_a=null==config?void 0:config.settings)?void 0:_a.client;client&&await client.shutdown()},on(type,context){var _a,_b;if("consent"!==type||!(null==context?void 0:context.data))return;const client=((null==(_a=context.config)?void 0:_a.settings)||{}).client;if(!client)return;const consent=context.data,required=null==(_b=context.config)?void 0:_b.consent;if(!required||0===Object.keys(required).length)return;Object.keys(required).every(key=>!0===consent[key])?client.enable():client.disable()}},index_default=destinationPostHog;export{types_exports as DestinationPostHog,index_default as default,destinationPostHog};//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Env, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\nimport { PostHog } from 'posthog-node';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n env: Env | undefined,\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n // Extract PostHog SDK options from settings\n const options: Record<string, unknown> = {};\n if (settings.host) options.host = settings.host;\n if (settings.flushAt !== undefined) options.flushAt = settings.flushAt;\n if (settings.flushInterval !== undefined)\n options.flushInterval = settings.flushInterval;\n if (settings.personalApiKey) options.personalApiKey = settings.personalApiKey;\n if (settings.featureFlagsPollingInterval !== undefined)\n options.featureFlagsPollingInterval = settings.featureFlagsPollingInterval;\n if (settings.disableGeoip !== undefined)\n options.disableGeoip = settings.disableGeoip;\n if (settings.disableCompression !== undefined)\n options.disableCompression = settings.disableCompression;\n if (settings.requestTimeout !== undefined)\n options.requestTimeout = settings.requestTimeout;\n if (settings.fetchRetryCount !== undefined)\n options.fetchRetryCount = settings.fetchRetryCount;\n if (settings.fetchRetryDelay !== undefined)\n options.fetchRetryDelay = settings.fetchRetryDelay;\n if (settings.debug !== undefined) options.debug = settings.debug;\n if (settings.disabled !== undefined) options.disabled = settings.disabled;\n\n // Use PostHog from env if available, otherwise use real PostHog\n const PostHogClass = env?.PostHog || PostHog;\n const client = new PostHogClass(apiKey, options);\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { PushFn } from './types';\nimport { getMappingValue, isObject, isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector },\n) {\n const settings = config.settings!;\n const client = settings.client;\n if (!client) return;\n\n const mappingSettings = (rule?.settings || {}) as Record<string, unknown>;\n\n // Resolve distinctId: rule-level identify wins over destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let identifyResolved: Record<string, unknown> | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n identifyResolved = resolved as Record<string, unknown>;\n if (isString(identifyResolved.distinctId)) {\n distinctId = identifyResolved.distinctId as string;\n }\n }\n }\n\n // Fallback distinctId from event.user\n if (!distinctId) {\n distinctId =\n (isString(event.user?.id) ? event.user.id : undefined) ||\n (isString(event.user?.hash) ? event.user.hash : undefined) ||\n (isString(event.user?.session) ? event.user.session : undefined) ||\n 'anonymous';\n }\n\n // 1. Identity — if $set or $set_once present, call client.identify()\n if (identifyResolved) {\n const $set = isObject(identifyResolved.$set)\n ? (identifyResolved.$set as Record<string, unknown>)\n : undefined;\n const $setOnce = isObject(identifyResolved.$set_once)\n ? (identifyResolved.$set_once as Record<string, unknown>)\n : undefined;\n\n if ($set || $setOnce) {\n const properties: Record<string, unknown> = {};\n if ($set) properties.$set = $set;\n if ($setOnce) properties.$set_once = $setOnce;\n client.identify({ distinctId, properties });\n }\n }\n\n // 2. Group — resolve group mapping (rule-level wins)\n const groupMapping = mappingSettings.group ?? settings.group;\n let groups: Record<string, string | number> | undefined;\n\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const groupResolved = resolved as Record<string, unknown>;\n const type = groupResolved.type;\n const key = groupResolved.key;\n const properties = isObject(groupResolved.properties)\n ? (groupResolved.properties as Record<string, unknown>)\n : undefined;\n\n if (isString(type) && (isString(key) || typeof key === 'number')) {\n // If properties present, call groupIdentify\n if (properties) {\n client.groupIdentify({\n groupType: type,\n groupKey: String(key),\n properties,\n });\n }\n // Build groups object for capture\n groups = { [type]: key as string | number };\n }\n }\n }\n\n // 3. Capture — unless rule opts out via skip\n if (rule?.skip !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data) ? (data as Record<string, unknown>) : {};\n\n const captureArgs: Record<string, unknown> = {\n distinctId,\n event: eventName,\n properties,\n };\n if (groups) captureArgs.groups = groups;\n\n client.capture(captureArgs as Parameters<typeof client.capture>[0]);\n }\n};\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\nimport type { PostHog } from 'posthog-node';\n\nexport interface Settings {\n /** PostHog project API key (phc_...) */\n apiKey: string;\n /** PostHog client instance, populated by init */\n client?: PostHog;\n /** Destination-level identity mapping */\n identify?: WalkerOSMapping.Value;\n /** Destination-level group mapping */\n group?: WalkerOSMapping.Value;\n /** Event sections to flatten into capture properties */\n include?: string[];\n // PostHog SDK passthrough options\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n personalApiKey?: string;\n featureFlagsPollingInterval?: number;\n disableGeoip?: boolean;\n disableCompression?: boolean;\n requestTimeout?: number;\n fetchRetryCount?: number;\n fetchRetryDelay?: number;\n debug?: boolean;\n disabled?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n PostHog?: typeof PostHog;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n","import type { WalkerOS } from '@walkeros/core';\nimport type { Destination, Env, Settings } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationPostHog from './types';\n\nexport const destinationPostHog: Destination = {\n type: 'posthog',\n\n config: {},\n\n async init({ config: partialConfig, env, logger }) {\n const config = getConfig(partialConfig, env as Env | undefined, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const client = (config?.settings as Settings | undefined)?.client;\n if (client) {\n await client.shutdown();\n }\n },\n\n on(type, context) {\n if (type !== 'consent' || !context?.data) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const client = settings.client;\n if (!client) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = (context.config as { consent?: WalkerOS.Consent })\n ?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n if (allGranted) {\n client.enable();\n } else {\n client.disable();\n }\n },\n};\n\nexport default destinationPostHog;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,571 @@
1
+ {
2
+ "$meta": {
3
+ "package": "@walkeros/server-destination-posthog",
4
+ "version": "3.2.0",
5
+ "type": "destination",
6
+ "platform": [
7
+ "server"
8
+ ],
9
+ "docs": "https://www.walkeros.io/docs/destinations/server/posthog",
10
+ "source": "https://github.com/elbwalker/walkerOS/tree/main/packages/server/destinations/posthog/src"
11
+ },
12
+ "schemas": {
13
+ "mapping": {
14
+ "$schema": "http://json-schema.org/draft-07/schema#",
15
+ "type": "object",
16
+ "properties": {
17
+ "identify": {
18
+ "description": "Per-event identity mapping. Resolves to { distinctId, $set?, $set_once? }. Fires client.identify() when $set/$set_once present."
19
+ },
20
+ "group": {
21
+ "description": "Group assignment. Resolves to { type, key, properties? }. Fires client.groupIdentify() when properties present, adds groups to capture()."
22
+ }
23
+ },
24
+ "additionalProperties": false
25
+ },
26
+ "settings": {
27
+ "$schema": "http://json-schema.org/draft-07/schema#",
28
+ "type": "object",
29
+ "properties": {
30
+ "apiKey": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "description": "PostHog project API key (starts with \"phc_\"). Find it in PostHog project settings."
34
+ },
35
+ "host": {
36
+ "type": "string",
37
+ "description": "PostHog API host. Defaults to https://us.i.posthog.com. Use https://eu.i.posthog.com for EU or your self-hosted URL."
38
+ },
39
+ "flushAt": {
40
+ "type": "number",
41
+ "description": "Number of events queued before auto-flush. Default: 20."
42
+ },
43
+ "flushInterval": {
44
+ "type": "number",
45
+ "description": "Milliseconds between periodic flushes. Default: 10000."
46
+ },
47
+ "personalApiKey": {
48
+ "type": "string",
49
+ "description": "Personal API key (phx_...) for local feature flag evaluation."
50
+ },
51
+ "featureFlagsPollingInterval": {
52
+ "type": "number",
53
+ "description": "Milliseconds between feature flag definition polls. Default: 30000."
54
+ },
55
+ "disableGeoip": {
56
+ "type": "boolean",
57
+ "description": "Disable GeoIP lookups globally. Useful for GDPR compliance."
58
+ },
59
+ "debug": {
60
+ "type": "boolean",
61
+ "description": "Enable PostHog SDK debug logging. Default: false."
62
+ },
63
+ "identify": {
64
+ "description": "walkerOS mapping value resolving to an identity object. Keys: distinctId, $set, $set_once. Resolved on every push (server is stateless)."
65
+ },
66
+ "group": {
67
+ "description": "walkerOS mapping value resolving to a group object. Keys: type, key, properties. Resolved on every push."
68
+ },
69
+ "include": {
70
+ "type": "array",
71
+ "items": {
72
+ "type": "string"
73
+ },
74
+ "description": "Event sections to flatten into capture() properties (e.g. [\"data\", \"globals\"])."
75
+ }
76
+ },
77
+ "required": [
78
+ "apiKey"
79
+ ],
80
+ "additionalProperties": false
81
+ }
82
+ },
83
+ "examples": {
84
+ "env": {
85
+ "push": {
86
+ "PostHog": {
87
+ "$code": "class{constructor(e,t){this.apiKey=e,this.options=t||{},this.calls=[]}capture(e){this.calls.push({method:\"capture\",args:[e]})}identify(e){this.calls.push({method:\"identify\",args:[e]})}groupIdentify(e){this.calls.push({method:\"groupIdentify\",args:[e]})}flush(){return this.calls.push({method:\"flush\",args:[]}),Promise.resolve()}async shutdown(){this.calls.push({method:\"shutdown\",args:[]})}enable(){this.calls.push({method:\"enable\",args:[]})}disable(){this.calls.push({method:\"disable\",args:[]})}}"
88
+ }
89
+ },
90
+ "simulation": [
91
+ "call:client.capture",
92
+ "call:client.identify",
93
+ "call:client.groupIdentify",
94
+ "call:client.shutdown"
95
+ ]
96
+ },
97
+ "step": {
98
+ "captureWithGroupContext": {
99
+ "in": {
100
+ "name": "page view",
101
+ "data": {
102
+ "domain": "www.example.com",
103
+ "title": "walkerOS documentation",
104
+ "referrer": "https://www.walkeros.io/",
105
+ "search": "?foo=bar",
106
+ "hash": "#hash",
107
+ "id": "/docs/"
108
+ },
109
+ "context": {
110
+ "dev": [
111
+ "test",
112
+ 1
113
+ ]
114
+ },
115
+ "globals": {
116
+ "pagegroup": "docs",
117
+ "company_id": "company_123"
118
+ },
119
+ "custom": {
120
+ "completely": "random"
121
+ },
122
+ "user": {
123
+ "id": "us3r",
124
+ "device": "c00k13",
125
+ "session": "s3ss10n"
126
+ },
127
+ "nested": [
128
+ {
129
+ "entity": "child",
130
+ "data": {
131
+ "is": "subordinated"
132
+ },
133
+ "nested": [],
134
+ "context": {
135
+ "element": [
136
+ "child",
137
+ 0
138
+ ]
139
+ }
140
+ }
141
+ ],
142
+ "consent": {
143
+ "functional": true
144
+ },
145
+ "id": "1700000104-gr0up-1",
146
+ "trigger": "load",
147
+ "entity": "page",
148
+ "action": "view",
149
+ "timestamp": 1700000104,
150
+ "timing": 3.14,
151
+ "group": "gr0up",
152
+ "count": 1,
153
+ "version": {
154
+ "source": "3.2.0",
155
+ "tagging": 1
156
+ },
157
+ "source": {
158
+ "type": "web",
159
+ "id": "https://localhost:80",
160
+ "previous_id": "http://remotehost:9001"
161
+ }
162
+ },
163
+ "settings": {
164
+ "group": {
165
+ "map": {
166
+ "type": {
167
+ "value": "company"
168
+ },
169
+ "key": "globals.company_id"
170
+ }
171
+ }
172
+ },
173
+ "out": [
174
+ "client.capture",
175
+ {
176
+ "distinctId": "us3r",
177
+ "event": "page view",
178
+ "properties": {},
179
+ "groups": {
180
+ "company": "company_123"
181
+ }
182
+ }
183
+ ]
184
+ },
185
+ "captureWithInclude": {
186
+ "in": {
187
+ "name": "order complete",
188
+ "data": {
189
+ "id": "0rd3r1d",
190
+ "currency": "EUR",
191
+ "shipping": 5.22,
192
+ "taxes": 73.76,
193
+ "total": 555
194
+ },
195
+ "context": {
196
+ "shopping": [
197
+ "complete",
198
+ 0
199
+ ]
200
+ },
201
+ "globals": {
202
+ "pagegroup": "shop"
203
+ },
204
+ "custom": {
205
+ "completely": "random"
206
+ },
207
+ "user": {
208
+ "id": "us3r",
209
+ "device": "c00k13",
210
+ "session": "s3ss10n"
211
+ },
212
+ "nested": [
213
+ {
214
+ "entity": "product",
215
+ "data": {
216
+ "id": "ers",
217
+ "name": "Everyday Ruck Snack",
218
+ "color": "black",
219
+ "size": "l",
220
+ "price": 420
221
+ },
222
+ "context": {
223
+ "shopping": [
224
+ "complete",
225
+ 0
226
+ ]
227
+ },
228
+ "nested": []
229
+ },
230
+ {
231
+ "entity": "product",
232
+ "data": {
233
+ "id": "cc",
234
+ "name": "Cool Cap",
235
+ "size": "one size",
236
+ "price": 42
237
+ },
238
+ "context": {
239
+ "shopping": [
240
+ "complete",
241
+ 0
242
+ ]
243
+ },
244
+ "nested": []
245
+ },
246
+ {
247
+ "entity": "gift",
248
+ "data": {
249
+ "name": "Surprise"
250
+ },
251
+ "context": {
252
+ "shopping": [
253
+ "complete",
254
+ 0
255
+ ]
256
+ },
257
+ "nested": []
258
+ }
259
+ ],
260
+ "consent": {
261
+ "functional": true
262
+ },
263
+ "id": "1700000101-gr0up-1",
264
+ "trigger": "load",
265
+ "entity": "order",
266
+ "action": "complete",
267
+ "timestamp": 1700000101,
268
+ "timing": 3.14,
269
+ "group": "gr0up",
270
+ "count": 1,
271
+ "version": {
272
+ "source": "3.2.0",
273
+ "tagging": 1
274
+ },
275
+ "source": {
276
+ "type": "web",
277
+ "id": "https://localhost:80",
278
+ "previous_id": "http://remotehost:9001"
279
+ }
280
+ },
281
+ "configInclude": [
282
+ "data",
283
+ "globals"
284
+ ],
285
+ "out": [
286
+ "client.capture",
287
+ {
288
+ "distinctId": "us3r",
289
+ "event": "order complete",
290
+ "properties": {
291
+ "data_id": "0rd3r1d",
292
+ "data_currency": "EUR",
293
+ "data_shipping": 5.22,
294
+ "data_taxes": 73.76,
295
+ "data_total": 555,
296
+ "globals_pagegroup": "shop"
297
+ }
298
+ }
299
+ ]
300
+ },
301
+ "consentGrant": {
302
+ "command": "consent",
303
+ "in": {
304
+ "analytics": true
305
+ },
306
+ "settings": {},
307
+ "out": [
308
+ "client.enable"
309
+ ]
310
+ },
311
+ "consentRevoke": {
312
+ "command": "consent",
313
+ "in": {
314
+ "analytics": false
315
+ },
316
+ "settings": {},
317
+ "out": [
318
+ "client.disable"
319
+ ]
320
+ },
321
+ "defaultCapture": {
322
+ "in": {
323
+ "name": "product view",
324
+ "data": {
325
+ "id": "ers",
326
+ "name": "Everyday Ruck Snack",
327
+ "color": "black",
328
+ "size": "l",
329
+ "price": 420
330
+ },
331
+ "context": {
332
+ "shopping": [
333
+ "detail",
334
+ 0
335
+ ]
336
+ },
337
+ "globals": {
338
+ "pagegroup": "shop"
339
+ },
340
+ "custom": {
341
+ "completely": "random"
342
+ },
343
+ "user": {
344
+ "id": "us3r",
345
+ "device": "c00k13",
346
+ "session": "s3ss10n"
347
+ },
348
+ "nested": [],
349
+ "consent": {
350
+ "functional": true
351
+ },
352
+ "id": "1700000100-gr0up-1",
353
+ "trigger": "load",
354
+ "entity": "product",
355
+ "action": "view",
356
+ "timestamp": 1700000100,
357
+ "timing": 3.14,
358
+ "group": "gr0up",
359
+ "count": 1,
360
+ "version": {
361
+ "source": "3.2.0",
362
+ "tagging": 1
363
+ },
364
+ "source": {
365
+ "type": "web",
366
+ "id": "https://localhost:80",
367
+ "previous_id": "http://remotehost:9001"
368
+ }
369
+ },
370
+ "out": [
371
+ "client.capture",
372
+ {
373
+ "distinctId": "us3r",
374
+ "event": "product view",
375
+ "properties": {}
376
+ }
377
+ ]
378
+ },
379
+ "groupIdentifyWithProperties": {
380
+ "in": {
381
+ "name": "company update",
382
+ "data": {
383
+ "company_id": "company_123",
384
+ "company_name": "Acme",
385
+ "plan": "enterprise"
386
+ },
387
+ "context": {
388
+ "dev": [
389
+ "test",
390
+ 1
391
+ ]
392
+ },
393
+ "globals": {
394
+ "lang": "elb"
395
+ },
396
+ "custom": {
397
+ "completely": "random"
398
+ },
399
+ "user": {
400
+ "id": "us3r",
401
+ "device": "c00k13",
402
+ "session": "s3ss10n"
403
+ },
404
+ "nested": [
405
+ {
406
+ "entity": "child",
407
+ "data": {
408
+ "is": "subordinated"
409
+ },
410
+ "nested": [],
411
+ "context": {
412
+ "element": [
413
+ "child",
414
+ 0
415
+ ]
416
+ }
417
+ }
418
+ ],
419
+ "consent": {
420
+ "functional": true
421
+ },
422
+ "id": "1700000103-gr0up-1",
423
+ "trigger": "test",
424
+ "entity": "company",
425
+ "action": "update",
426
+ "timestamp": 1700000103,
427
+ "timing": 3.14,
428
+ "group": "gr0up",
429
+ "count": 1,
430
+ "version": {
431
+ "source": "3.2.0",
432
+ "tagging": 1
433
+ },
434
+ "source": {
435
+ "type": "web",
436
+ "id": "https://localhost:80",
437
+ "previous_id": "http://remotehost:9001"
438
+ }
439
+ },
440
+ "mapping": {
441
+ "skip": true,
442
+ "settings": {
443
+ "group": {
444
+ "map": {
445
+ "type": {
446
+ "value": "company"
447
+ },
448
+ "key": "data.company_id",
449
+ "properties": {
450
+ "map": {
451
+ "name": "data.company_name",
452
+ "plan": "data.plan"
453
+ }
454
+ }
455
+ }
456
+ }
457
+ }
458
+ },
459
+ "out": [
460
+ "client.groupIdentify",
461
+ {
462
+ "groupType": "company",
463
+ "groupKey": "company_123",
464
+ "properties": {
465
+ "name": "Acme",
466
+ "plan": "enterprise"
467
+ }
468
+ }
469
+ ]
470
+ },
471
+ "identifyWithSetAndSetOnce": {
472
+ "in": {
473
+ "name": "user login",
474
+ "data": {
475
+ "user_id": "new-user-123",
476
+ "email": "user@acme.com",
477
+ "plan": "premium"
478
+ },
479
+ "context": {
480
+ "dev": [
481
+ "test",
482
+ 1
483
+ ]
484
+ },
485
+ "globals": {
486
+ "lang": "elb"
487
+ },
488
+ "custom": {
489
+ "completely": "random"
490
+ },
491
+ "user": {
492
+ "id": "us3r",
493
+ "device": "c00k13",
494
+ "session": "s3ss10n"
495
+ },
496
+ "nested": [
497
+ {
498
+ "entity": "child",
499
+ "data": {
500
+ "is": "subordinated"
501
+ },
502
+ "nested": [],
503
+ "context": {
504
+ "element": [
505
+ "child",
506
+ 0
507
+ ]
508
+ }
509
+ }
510
+ ],
511
+ "consent": {
512
+ "functional": true
513
+ },
514
+ "id": "1700000102-gr0up-1",
515
+ "trigger": "test",
516
+ "entity": "user",
517
+ "action": "login",
518
+ "timestamp": 1700000102,
519
+ "timing": 3.14,
520
+ "group": "gr0up",
521
+ "count": 1,
522
+ "version": {
523
+ "source": "3.2.0",
524
+ "tagging": 1
525
+ },
526
+ "source": {
527
+ "type": "web",
528
+ "id": "https://localhost:80",
529
+ "previous_id": "http://remotehost:9001"
530
+ }
531
+ },
532
+ "mapping": {
533
+ "skip": true,
534
+ "settings": {
535
+ "identify": {
536
+ "map": {
537
+ "distinctId": "data.user_id",
538
+ "$set": {
539
+ "map": {
540
+ "email": "data.email",
541
+ "plan": "data.plan"
542
+ }
543
+ },
544
+ "$set_once": {
545
+ "map": {
546
+ "first_login": "timestamp"
547
+ }
548
+ }
549
+ }
550
+ }
551
+ }
552
+ },
553
+ "out": [
554
+ "client.identify",
555
+ {
556
+ "distinctId": "new-user-123",
557
+ "properties": {
558
+ "$set": {
559
+ "email": "user@acme.com",
560
+ "plan": "premium"
561
+ },
562
+ "$set_once": {
563
+ "first_login": 1700000102
564
+ }
565
+ }
566
+ }
567
+ ]
568
+ }
569
+ }
570
+ }
571
+ }