@walkeros/web-destination-optimizely 4.0.0-next-1777463920154 → 4.0.0
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.browser.js +1 -1
- package/dist/index.es5.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +7 -7
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t,e=Object.create,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,a=(t,e,i,a)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let
|
|
1
|
+
"use strict";var t,e=Object.create,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,a=(t,e,i,a)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let l of r(e))c.call(t,l)||l===i||n(t,l,{get:()=>e[l],enumerable:!(a=o(e,l))||a.enumerable});return t},l={};((t,e)=>{for(var o in e)n(t,o,{get:e[o],enumerable:!0})})(l,{DestinationOptimizely:()=>k,default:()=>z,destinationOptimizely:()=>I}),module.exports=(t=l,a(n({},"__esModule",{value:!0}),t));var s=Object.defineProperty;((t,e)=>{for(var n in e)s(t,n,{get:e[n],enumerable:!0})})({},{Level:()=>f});var u,f=((u=f||{})[u.ERROR=0]="ERROR",u[u.WARN=1]="WARN",u[u.INFO=2]="INFO",u[u.DEBUG=3]="DEBUG",u);function v(t){return Array.isArray(t)}function d(t){return void 0!==t}function y(t){return"number"==typeof t&&!Number.isNaN(t)}function p(t){return"object"==typeof t&&null!==t&&!v(t)&&"[object Object]"===Object.prototype.toString.call(t)}function g(t){return"string"==typeof t}function b(t,e="",n){const o=e.split(".");let r=t;for(let t=0;t<o.length;t++){const e=o[t];if("*"===e&&v(r)){const e=o.slice(t+1).join("."),i=[];for(const t of r){const o=b(t,e,n);i.push(o)}return i}if(r=r instanceof Object?r[e]:void 0,void 0===r)break}return d(r)?r:n}function m(t){return function(t){return"boolean"==typeof t}(t)||g(t)||y(t)||!d(t)||v(t)&&t.every(m)||p(t)&&Object.values(t).every(m)}function O(t){return m(t)?t:void 0}function w(t,e,n){return async function(...o){try{return await t(...o)}catch(t){if(!e)return;return await e(t)}finally{await(null==n?void 0:n())}}}async function j(t,e={},n={}){var o,r;if(!d(t))return;const i=p(t)&&t.consent||n.consent||(null==(o=n.collector)?void 0:o.consent),c=null!=(r=n.event)?r:p(t)?t:{};if(!n.collector)throw new Error("getMappingValue: context.collector is required");const a={event:c,mapping:e,collector:n.collector,logger:n.collector.logger,consent:i},l=v(e)?e:[e];for(const e of l){const n=await w(h)(t,e,{...a,mapping:e});if(d(n))return n}}async function h(t,e,n){return(v(e)?e:[e]).reduce(async(e,o)=>{const r=await e;if(r)return r;const i=g(o)?{key:o}:o;if(!Object.keys(i).length)return;const{condition:c,consent:a,fn:l,key:s,loop:u,map:f,set:y,validate:p,value:m}=i,P={...n,mapping:o};if(c&&!await w(c)(t,P))return;if(a&&!function(t,e={},n={}){const o={...e,...n},r={};let i=!t||0===Object.keys(t).length;return Object.keys(o).forEach(e=>{o[e]&&(r[e]=!0,t&&t[e]&&(i=!0))}),!!i&&r}(a,P.consent))return m;let k=d(m)?m:t;if(l&&(k=await w(l)(t,P)),s&&(k=b(t,s,m)),u){const[e,n]=u,o="this"===e?[t]:await j(t,e,P);v(o)&&(k=(await Promise.all(o.map(t=>j(t,n,P)))).filter(d))}else f?k=await Object.entries(f).reduce(async(e,[n,o])=>{const r=await e,i=await j(t,o,P);return d(i)&&(r[n]=i),r},Promise.resolve({})):y&&(k=await Promise.all(y.map(e=>h(t,e,P))));p&&!await w(p)(k,P)&&(k=void 0);const I=O(k);return d(I)?I:O(m)},Promise.resolve(void 0))}var P=((t,o,r)=>(r=null!=t?e(i(t)):{},a(!o&&t&&t.__esModule?r:n(r,"default",{value:t,enumerable:!0}),t)))(require("@optimizely/optimizely-sdk")),k={};var I={type:"optimizely",config:{},async init({config:t,env:e}){var n,o,r,i;const c=t.settings;if(!(null==c?void 0:c.sdkKey))return!1;const a=function(t){return(null==t?void 0:t.optimizely)?t.optimizely:P}(e),l={projectConfigManager:a.createPollingProjectConfigManager({sdkKey:c.sdkKey,autoUpdate:null==(n=c.autoUpdate)||n,updateInterval:null!=(o=c.updateInterval)?o:6e4}),eventProcessor:a.createBatchEventProcessor({batchSize:null!=(r=c.batchSize)?r:10,flushInterval:null!=(i=c.flushInterval)?i:1e3})},s=a.createInstance(l);await s.onReady();const u={client:s};return{...t,settings:{...c,_state:u}}},async push(t,{config:e,rule:n,env:o,collector:r}){const i=e.settings||{},c=i._state||{},a=(null==n?void 0:n.settings)||{};if(!c.client)return;const l=i.userId;let s,u;if(void 0!==l){const e=await j(t,l,{collector:r});g(e)&&(s=e)}if(!s)return;if(void 0!==i.attributes){const e=await j(t,i.attributes,{collector:r});p(e)&&(u=e)}if(s!==c.lastUserId||!c.userContext){const t=c.client.createUserContext(s,u);if(!t)return;c.userContext=t,c.lastUserId=s}const f=c.userContext;if(f){if(void 0!==a.attributes){const e=await j(t,a.attributes,{collector:r});if(p(e))for(const[t,n]of Object.entries(e))f.setAttribute(t,n)}if(!0!==(null==n?void 0:n.silent)){const e=g(null==n?void 0:n.name)?n.name:t.name,o={};if(void 0!==a.eventTags){const e=await j(t,a.eventTags,{collector:r});p(e)&&Object.assign(o,e)}if(void 0!==a.revenue){const e=await j(t,a.revenue,{collector:r});y(e)&&(o.revenue=e)}if(void 0!==a.value){const e=await j(t,a.value,{collector:r});y(e)&&(o.value=e)}f.trackEvent(e,o)}i._state=c}},on(t,e){var n,o,r;if("consent"!==t||!e.data)return;const i=null==(n=e.config)?void 0:n.consent;if(!i||0===Object.keys(i).length)return;const c=e.data,a=Object.keys(i).every(t=>!0===c[t]),l=null==(r=null==(o=e.config)?void 0:o.settings)?void 0:r._state;!a&&(null==l?void 0:l.client)&&(l.client.close(),l.client=void 0,l.userContext=void 0)},destroy({config:t}){const e=((null==t?void 0:t.settings)||{})._state;(null==e?void 0:e.client)&&(e.client.close(),e.client=void 0,e.userContext=void 0)}},z=I;//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isNumber, isObject, isString } from '@walkeros/core';\nimport * as optimizelySDK from '@optimizely/optimizely-sdk';\nimport type {\n Destination,\n Env,\n OptimizelySDK as OptimizelySDKType,\n RuntimeState,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationOptimizely from './types';\n\n/**\n * Resolve the Optimizely SDK: use the caller-provided mock when available\n * (tests), otherwise fall back to the real @optimizely/optimizely-sdk.\n */\nfunction getOptimizely(env: Env | undefined): OptimizelySDKType {\n if (env?.optimizely) return env.optimizely;\n return optimizelySDK as unknown as OptimizelySDKType;\n}\n\nexport const destinationOptimizely: Destination = {\n type: 'optimizely',\n\n config: {},\n\n async init({ config, env }) {\n const settings = config.settings;\n if (!settings?.sdkKey) return false;\n\n const sdk = getOptimizely(env as Env | undefined);\n\n const configManager = sdk.createPollingProjectConfigManager({\n sdkKey: settings.sdkKey,\n autoUpdate: settings.autoUpdate ?? true,\n updateInterval: settings.updateInterval ?? 60000,\n });\n\n const eventProcessor = sdk.createBatchEventProcessor({\n batchSize: settings.batchSize ?? 10,\n flushInterval: settings.flushInterval ?? 1000,\n });\n\n const instanceConfig: Record<string, unknown> = {\n projectConfigManager: configManager,\n eventProcessor: eventProcessor,\n };\n\n const client = sdk.createInstance(instanceConfig);\n await client.onReady();\n\n const _state: RuntimeState = { client };\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, collector }) {\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n\n if (!state.client) return;\n\n // 1. Resolve userId\n const userIdMapping = settings.userId;\n let userId: string | undefined;\n if (userIdMapping !== undefined) {\n const resolved = await getMappingValue(event, userIdMapping, {\n collector,\n });\n if (isString(resolved)) userId = resolved;\n }\n\n // Fallback: no userId means we cannot create a user context\n if (!userId) return;\n\n // 2. Resolve destination-level attributes\n let baseAttributes: Record<string, unknown> | undefined;\n if (settings.attributes !== undefined) {\n const resolved = await getMappingValue(event, settings.attributes, {\n collector,\n });\n if (isObject(resolved)) {\n baseAttributes = resolved as Record<string, unknown>;\n }\n }\n\n // 3. Create or reuse user context\n if (userId !== state.lastUserId || !state.userContext) {\n const userContext = state.client.createUserContext(\n userId,\n baseAttributes,\n );\n if (!userContext) return;\n state.userContext = userContext;\n state.lastUserId = userId;\n }\n\n const userContext = state.userContext;\n if (!userContext) return;\n\n // 4. Per-event attributes via setAttribute\n if (mappingSettings.attributes !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.attributes,\n { collector },\n );\n if (isObject(resolved)) {\n for (const [key, value] of Object.entries(\n resolved as Record<string, unknown>,\n )) {\n userContext.setAttribute(key, value);\n }\n }\n }\n\n // 5. Track event (unless silent: true)\n if (rule?.silent !== true) {\n const eventKey = isString(rule?.name) ? rule.name : event.name;\n\n // Build eventTags\n const eventTags: Record<string, unknown> = {};\n\n // Resolve eventTags mapping first (so revenue/value can override)\n if (mappingSettings.eventTags !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.eventTags,\n { collector },\n );\n if (isObject(resolved)) {\n Object.assign(eventTags, resolved);\n }\n }\n\n // Revenue (integer, cents)\n if (mappingSettings.revenue !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.revenue, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.revenue = resolved;\n }\n }\n\n // Value (float)\n if (mappingSettings.value !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.value, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.value = resolved;\n }\n }\n\n userContext.trackEvent(eventKey, eventTags);\n }\n\n // Persist state mutations\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const consent = context.data as WalkerOS.Consent;\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n const state = (context.config?.settings as Settings)?._state;\n if (!allGranted && state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n\n destroy({ config }) {\n const settings = (config?.settings || {}) as Settings;\n const state = settings._state;\n if (state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n};\n\nexport default destinationOptimizely;\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 * Destination-level settings.\n */\nexport interface Settings {\n /** Optimizely Feature Experimentation SDK key. Required. */\n sdkKey: string;\n /** walkerOS mapping value to resolve userId for experiment bucketing. */\n userId?: WalkerOSMapping.Value;\n /** User attributes for audience targeting, applied to every event. */\n attributes?: WalkerOSMapping.Value;\n /** Polling interval for datafile updates in ms. Default: 60000. */\n updateInterval?: number;\n /** Auto-update datafile via polling. Default: true. */\n autoUpdate?: boolean;\n /** Batch event processor: events per batch. Default: 10. */\n batchSize?: number;\n /** Batch event processor: flush interval in ms. Default: 1000. */\n flushInterval?: number;\n /** Skip ODP manager initialization. Default: true. */\n skipOdp?: boolean;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** The Optimizely client instance (typed as OptimizelyClient). */\n client?: OptimizelyClient;\n /** Cached user context. Recreated when userId changes. */\n userContext?: OptimizelyUserContext;\n /** Last resolved userId to detect identity changes. */\n lastUserId?: string;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings.\n */\nexport interface Mapping {\n /** Override event key sent to Optimizely. If omitted, event.name is used. */\n eventKey?: string;\n /** Revenue mapping. Resolves to integer (cents). Passed as eventTags.revenue. */\n revenue?: WalkerOSMapping.Value;\n /** Numeric value mapping. Resolves to float. Passed as eventTags.value. */\n value?: WalkerOSMapping.Value;\n /** Additional event tags. Resolves to Record<string, unknown>. */\n eventTags?: WalkerOSMapping.Value;\n /** Per-event user attributes override. Merged onto user context for this event. */\n attributes?: WalkerOSMapping.Value;\n}\n\n/**\n * OptimizelyClient -- the subset of the Optimizely SDK client the destination\n * actually uses. Tests provide a mock via env.optimizely.\n */\nexport interface OptimizelyClient {\n onReady: () => Promise<{ success: boolean }>;\n createUserContext: (\n userId: string,\n attributes?: Record<string, unknown>,\n ) => OptimizelyUserContext | null;\n close: () => void;\n}\n\n/**\n * OptimizelyUserContext -- user context methods the destination calls.\n */\nexport interface OptimizelyUserContext {\n trackEvent: (eventKey: string, eventTags?: Record<string, unknown>) => void;\n setAttribute: (key: string, value: unknown) => void;\n}\n\n/**\n * OptimizelySDK -- factory functions the destination imports from the SDK.\n * Tests provide this via env.optimizely to avoid importing the real SDK.\n */\nexport interface OptimizelySDK {\n createInstance: (config: Record<string, unknown>) => OptimizelyClient;\n createPollingProjectConfigManager: (\n config: Record<string, unknown>,\n ) => unknown;\n createBatchEventProcessor: (config: Record<string, unknown>) => unknown;\n}\n\n/**\n * Env -- optional SDK override. Production leaves env.optimizely undefined\n * and the destination falls back to the real @optimizely/optimizely-sdk\n * import. Tests provide a mock via env.optimizely.\n */\nexport interface Env extends DestinationWeb.Env {\n optimizely?: OptimizelySDK;\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":["userContext"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isNumber, isObject, isString } from '@walkeros/core';\nimport * as optimizelySDK from '@optimizely/optimizely-sdk';\nimport type {\n Destination,\n Env,\n OptimizelySDK as OptimizelySDKType,\n RuntimeState,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationOptimizely from './types';\n\n/**\n * Resolve the Optimizely SDK: use the caller-provided mock when available\n * (tests), otherwise fall back to the real @optimizely/optimizely-sdk.\n */\nfunction getOptimizely(env: Env | undefined): OptimizelySDKType {\n if (env?.optimizely) return env.optimizely;\n return optimizelySDK as unknown as OptimizelySDKType;\n}\n\nexport const destinationOptimizely: Destination = {\n type: 'optimizely',\n\n config: {},\n\n async init({ config, env }) {\n const settings = config.settings;\n if (!settings?.sdkKey) return false;\n\n const sdk = getOptimizely(env as Env | undefined);\n\n const configManager = sdk.createPollingProjectConfigManager({\n sdkKey: settings.sdkKey,\n autoUpdate: settings.autoUpdate ?? true,\n updateInterval: settings.updateInterval ?? 60000,\n });\n\n const eventProcessor = sdk.createBatchEventProcessor({\n batchSize: settings.batchSize ?? 10,\n flushInterval: settings.flushInterval ?? 1000,\n });\n\n const instanceConfig: Record<string, unknown> = {\n projectConfigManager: configManager,\n eventProcessor: eventProcessor,\n };\n\n const client = sdk.createInstance(instanceConfig);\n await client.onReady();\n\n const _state: RuntimeState = { client };\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, collector }) {\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n\n if (!state.client) return;\n\n // 1. Resolve userId\n const userIdMapping = settings.userId;\n let userId: string | undefined;\n if (userIdMapping !== undefined) {\n const resolved = await getMappingValue(event, userIdMapping, {\n collector,\n });\n if (isString(resolved)) userId = resolved;\n }\n\n // Fallback: no userId means we cannot create a user context\n if (!userId) return;\n\n // 2. Resolve destination-level attributes\n let baseAttributes: Record<string, unknown> | undefined;\n if (settings.attributes !== undefined) {\n const resolved = await getMappingValue(event, settings.attributes, {\n collector,\n });\n if (isObject(resolved)) {\n baseAttributes = resolved as Record<string, unknown>;\n }\n }\n\n // 3. Create or reuse user context\n if (userId !== state.lastUserId || !state.userContext) {\n const userContext = state.client.createUserContext(\n userId,\n baseAttributes,\n );\n if (!userContext) return;\n state.userContext = userContext;\n state.lastUserId = userId;\n }\n\n const userContext = state.userContext;\n if (!userContext) return;\n\n // 4. Per-event attributes via setAttribute\n if (mappingSettings.attributes !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.attributes,\n { collector },\n );\n if (isObject(resolved)) {\n for (const [key, value] of Object.entries(\n resolved as Record<string, unknown>,\n )) {\n userContext.setAttribute(key, value);\n }\n }\n }\n\n // 5. Track event (unless silent: true)\n if (rule?.silent !== true) {\n const eventKey = isString(rule?.name) ? rule.name : event.name;\n\n // Build eventTags\n const eventTags: Record<string, unknown> = {};\n\n // Resolve eventTags mapping first (so revenue/value can override)\n if (mappingSettings.eventTags !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.eventTags,\n { collector },\n );\n if (isObject(resolved)) {\n Object.assign(eventTags, resolved);\n }\n }\n\n // Revenue (integer, cents)\n if (mappingSettings.revenue !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.revenue, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.revenue = resolved;\n }\n }\n\n // Value (float)\n if (mappingSettings.value !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.value, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.value = resolved;\n }\n }\n\n userContext.trackEvent(eventKey, eventTags);\n }\n\n // Persist state mutations\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const consent = context.data as WalkerOS.Consent;\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n const state = (context.config?.settings as Settings)?._state;\n if (!allGranted && state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n\n destroy({ config }) {\n const settings = (config?.settings || {}) as Settings;\n const state = settings._state;\n if (state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n};\n\nexport default destinationOptimizely;\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 * Destination-level settings.\n */\nexport interface Settings {\n /** Optimizely Feature Experimentation SDK key. Required. */\n sdkKey: string;\n /** walkerOS mapping value to resolve userId for experiment bucketing. */\n userId?: WalkerOSMapping.Value;\n /** User attributes for audience targeting, applied to every event. */\n attributes?: WalkerOSMapping.Value;\n /** Polling interval for datafile updates in ms. Default: 60000. */\n updateInterval?: number;\n /** Auto-update datafile via polling. Default: true. */\n autoUpdate?: boolean;\n /** Batch event processor: events per batch. Default: 10. */\n batchSize?: number;\n /** Batch event processor: flush interval in ms. Default: 1000. */\n flushInterval?: number;\n /** Skip ODP manager initialization. Default: true. */\n skipOdp?: boolean;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** The Optimizely client instance (typed as OptimizelyClient). */\n client?: OptimizelyClient;\n /** Cached user context. Recreated when userId changes. */\n userContext?: OptimizelyUserContext;\n /** Last resolved userId to detect identity changes. */\n lastUserId?: string;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings.\n */\nexport interface Mapping {\n /** Override event key sent to Optimizely. If omitted, event.name is used. */\n eventKey?: string;\n /** Revenue mapping. Resolves to integer (cents). Passed as eventTags.revenue. */\n revenue?: WalkerOSMapping.Value;\n /** Numeric value mapping. Resolves to float. Passed as eventTags.value. */\n value?: WalkerOSMapping.Value;\n /** Additional event tags. Resolves to Record<string, unknown>. */\n eventTags?: WalkerOSMapping.Value;\n /** Per-event user attributes override. Merged onto user context for this event. */\n attributes?: WalkerOSMapping.Value;\n}\n\n/**\n * OptimizelyClient -- the subset of the Optimizely SDK client the destination\n * actually uses. Tests provide a mock via env.optimizely.\n */\nexport interface OptimizelyClient {\n onReady: () => Promise<{ success: boolean }>;\n createUserContext: (\n userId: string,\n attributes?: Record<string, unknown>,\n ) => OptimizelyUserContext | null;\n close: () => void;\n}\n\n/**\n * OptimizelyUserContext -- user context methods the destination calls.\n */\nexport interface OptimizelyUserContext {\n trackEvent: (eventKey: string, eventTags?: Record<string, unknown>) => void;\n setAttribute: (key: string, value: unknown) => void;\n}\n\n/**\n * OptimizelySDK -- factory functions the destination imports from the SDK.\n * Tests provide this via env.optimizely to avoid importing the real SDK.\n */\nexport interface OptimizelySDK {\n createInstance: (config: Record<string, unknown>) => OptimizelyClient;\n createPollingProjectConfigManager: (\n config: Record<string, unknown>,\n ) => unknown;\n createBatchEventProcessor: (config: Record<string, unknown>) => unknown;\n}\n\n/**\n * Env -- optional SDK override. Production leaves env.optimizely undefined\n * and the destination falls back to the real @optimizely/optimizely-sdk\n * import. Tests provide a mock via env.optimizely.\n */\nexport interface Env extends DestinationWeb.Env {\n optimizely?: OptimizelySDK;\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":["userContext"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=Object.defineProperty;((e,n)=>{for(var o in n)t(e,o,{get:n[o],enumerable:!0})})({},{Level:()=>n});var e,n=((e=n||{})[e.ERROR=0]="ERROR",e[e.WARN=1]="WARN",e[e.INFO=2]="INFO",e[e.DEBUG=3]="DEBUG",e);function o(t){return Array.isArray(t)}function i(t){return void 0!==t}function r(t){return"number"==typeof t&&!Number.isNaN(t)}function c(t){return"object"==typeof t&&null!==t&&!o(t)&&"[object Object]"===Object.prototype.toString.call(t)}function a(t){return"string"==typeof t}function s(t,e="",n){const r=e.split(".");let c=t;for(let t=0;t<r.length;t++){const e=r[t];if("*"===e&&o(c)){const e=r.slice(t+1).join("."),o=[];for(const t of c){const i=s(t,e,n);o.push(i)}return o}if(c=c instanceof Object?c[e]:void 0,void 0===c)break}return i(c)?c:n}function l(t){return function(t){return"boolean"==typeof t}(t)||a(t)||r(t)||!i(t)||o(t)&&t.every(l)||c(t)&&Object.values(t).every(l)}function u(t){return l(t)?t:void 0}function f(t,e,n){return async function(...o){try{return await t(...o)}catch(t){if(!e)return;return await e(t)}finally{await(null==n?void 0:n())}}}async function v(t,e={},n={}){var r;if(!i(t))return;const
|
|
1
|
+
var t=Object.defineProperty;((e,n)=>{for(var o in n)t(e,o,{get:n[o],enumerable:!0})})({},{Level:()=>n});var e,n=((e=n||{})[e.ERROR=0]="ERROR",e[e.WARN=1]="WARN",e[e.INFO=2]="INFO",e[e.DEBUG=3]="DEBUG",e);function o(t){return Array.isArray(t)}function i(t){return void 0!==t}function r(t){return"number"==typeof t&&!Number.isNaN(t)}function c(t){return"object"==typeof t&&null!==t&&!o(t)&&"[object Object]"===Object.prototype.toString.call(t)}function a(t){return"string"==typeof t}function s(t,e="",n){const r=e.split(".");let c=t;for(let t=0;t<r.length;t++){const e=r[t];if("*"===e&&o(c)){const e=r.slice(t+1).join("."),o=[];for(const t of c){const i=s(t,e,n);o.push(i)}return o}if(c=c instanceof Object?c[e]:void 0,void 0===c)break}return i(c)?c:n}function l(t){return function(t){return"boolean"==typeof t}(t)||a(t)||r(t)||!i(t)||o(t)&&t.every(l)||c(t)&&Object.values(t).every(l)}function u(t){return l(t)?t:void 0}function f(t,e,n){return async function(...o){try{return await t(...o)}catch(t){if(!e)return;return await e(t)}finally{await(null==n?void 0:n())}}}async function v(t,e={},n={}){var r,a;if(!i(t))return;const s=c(t)&&t.consent||n.consent||(null==(r=n.collector)?void 0:r.consent),l=null!=(a=n.event)?a:c(t)?t:{};if(!n.collector)throw new Error("getMappingValue: context.collector is required");const u={event:l,mapping:e,collector:n.collector,logger:n.collector.logger,consent:s},v=o(e)?e:[e];for(const e of v){const n=await f(d)(t,e,{...u,mapping:e});if(i(n))return n}}async function d(t,e,n){return(o(e)?e:[e]).reduce(async(e,r)=>{const c=await e;if(c)return c;const l=a(r)?{key:r}:r;if(!Object.keys(l).length)return;const{condition:y,consent:g,fn:p,key:b,loop:m,map:w,set:j,validate:O,value:h}=l,k={...n,mapping:r};if(y&&!await f(y)(t,k))return;if(g&&!function(t,e={},n={}){const o={...e,...n},i={};let r=!t||0===Object.keys(t).length;return Object.keys(o).forEach(e=>{o[e]&&(i[e]=!0,t&&t[e]&&(r=!0))}),!!r&&i}(g,k.consent))return h;let I=i(h)?h:t;if(p&&(I=await f(p)(t,k)),b&&(I=s(t,b,h)),m){const[e,n]=m,r="this"===e?[t]:await v(t,e,k);o(r)&&(I=(await Promise.all(r.map(t=>v(t,n,k)))).filter(i))}else w?I=await Object.entries(w).reduce(async(e,[n,o])=>{const r=await e,c=await v(t,o,k);return i(c)&&(r[n]=c),r},Promise.resolve({})):j&&(I=await Promise.all(j.map(e=>d(t,e,k))));O&&!await f(O)(I,k)&&(I=void 0);const P=u(I);return i(P)?P:u(h)},Promise.resolve(void 0))}import*as y from"@optimizely/optimizely-sdk";var g={};var p={type:"optimizely",config:{},async init({config:t,env:e}){var n,o,i,r;const c=t.settings;if(!(null==c?void 0:c.sdkKey))return!1;const a=function(t){return(null==t?void 0:t.optimizely)?t.optimizely:y}(e),s={projectConfigManager:a.createPollingProjectConfigManager({sdkKey:c.sdkKey,autoUpdate:null==(n=c.autoUpdate)||n,updateInterval:null!=(o=c.updateInterval)?o:6e4}),eventProcessor:a.createBatchEventProcessor({batchSize:null!=(i=c.batchSize)?i:10,flushInterval:null!=(r=c.flushInterval)?r:1e3})},l=a.createInstance(s);await l.onReady();const u={client:l};return{...t,settings:{...c,_state:u}}},async push(t,{config:e,rule:n,env:o,collector:i}){const s=e.settings||{},l=s._state||{},u=(null==n?void 0:n.settings)||{};if(!l.client)return;const f=s.userId;let d,y;if(void 0!==f){const e=await v(t,f,{collector:i});a(e)&&(d=e)}if(!d)return;if(void 0!==s.attributes){const e=await v(t,s.attributes,{collector:i});c(e)&&(y=e)}if(d!==l.lastUserId||!l.userContext){const t=l.client.createUserContext(d,y);if(!t)return;l.userContext=t,l.lastUserId=d}const g=l.userContext;if(g){if(void 0!==u.attributes){const e=await v(t,u.attributes,{collector:i});if(c(e))for(const[t,n]of Object.entries(e))g.setAttribute(t,n)}if(!0!==(null==n?void 0:n.silent)){const e=a(null==n?void 0:n.name)?n.name:t.name,o={};if(void 0!==u.eventTags){const e=await v(t,u.eventTags,{collector:i});c(e)&&Object.assign(o,e)}if(void 0!==u.revenue){const e=await v(t,u.revenue,{collector:i});r(e)&&(o.revenue=e)}if(void 0!==u.value){const e=await v(t,u.value,{collector:i});r(e)&&(o.value=e)}g.trackEvent(e,o)}s._state=l}},on(t,e){var n,o,i;if("consent"!==t||!e.data)return;const r=null==(n=e.config)?void 0:n.consent;if(!r||0===Object.keys(r).length)return;const c=e.data,a=Object.keys(r).every(t=>!0===c[t]),s=null==(i=null==(o=e.config)?void 0:o.settings)?void 0:i._state;!a&&(null==s?void 0:s.client)&&(s.client.close(),s.client=void 0,s.userContext=void 0)},destroy({config:t}){const e=((null==t?void 0:t.settings)||{})._state;(null==e?void 0:e.client)&&(e.client.close(),e.client=void 0,e.userContext=void 0)}},b=p;export{g as DestinationOptimizely,b as default,p as destinationOptimizely};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isNumber, isObject, isString } from '@walkeros/core';\nimport * as optimizelySDK from '@optimizely/optimizely-sdk';\nimport type {\n Destination,\n Env,\n OptimizelySDK as OptimizelySDKType,\n RuntimeState,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationOptimizely from './types';\n\n/**\n * Resolve the Optimizely SDK: use the caller-provided mock when available\n * (tests), otherwise fall back to the real @optimizely/optimizely-sdk.\n */\nfunction getOptimizely(env: Env | undefined): OptimizelySDKType {\n if (env?.optimizely) return env.optimizely;\n return optimizelySDK as unknown as OptimizelySDKType;\n}\n\nexport const destinationOptimizely: Destination = {\n type: 'optimizely',\n\n config: {},\n\n async init({ config, env }) {\n const settings = config.settings;\n if (!settings?.sdkKey) return false;\n\n const sdk = getOptimizely(env as Env | undefined);\n\n const configManager = sdk.createPollingProjectConfigManager({\n sdkKey: settings.sdkKey,\n autoUpdate: settings.autoUpdate ?? true,\n updateInterval: settings.updateInterval ?? 60000,\n });\n\n const eventProcessor = sdk.createBatchEventProcessor({\n batchSize: settings.batchSize ?? 10,\n flushInterval: settings.flushInterval ?? 1000,\n });\n\n const instanceConfig: Record<string, unknown> = {\n projectConfigManager: configManager,\n eventProcessor: eventProcessor,\n };\n\n const client = sdk.createInstance(instanceConfig);\n await client.onReady();\n\n const _state: RuntimeState = { client };\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, collector }) {\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n\n if (!state.client) return;\n\n // 1. Resolve userId\n const userIdMapping = settings.userId;\n let userId: string | undefined;\n if (userIdMapping !== undefined) {\n const resolved = await getMappingValue(event, userIdMapping, {\n collector,\n });\n if (isString(resolved)) userId = resolved;\n }\n\n // Fallback: no userId means we cannot create a user context\n if (!userId) return;\n\n // 2. Resolve destination-level attributes\n let baseAttributes: Record<string, unknown> | undefined;\n if (settings.attributes !== undefined) {\n const resolved = await getMappingValue(event, settings.attributes, {\n collector,\n });\n if (isObject(resolved)) {\n baseAttributes = resolved as Record<string, unknown>;\n }\n }\n\n // 3. Create or reuse user context\n if (userId !== state.lastUserId || !state.userContext) {\n const userContext = state.client.createUserContext(\n userId,\n baseAttributes,\n );\n if (!userContext) return;\n state.userContext = userContext;\n state.lastUserId = userId;\n }\n\n const userContext = state.userContext;\n if (!userContext) return;\n\n // 4. Per-event attributes via setAttribute\n if (mappingSettings.attributes !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.attributes,\n { collector },\n );\n if (isObject(resolved)) {\n for (const [key, value] of Object.entries(\n resolved as Record<string, unknown>,\n )) {\n userContext.setAttribute(key, value);\n }\n }\n }\n\n // 5. Track event (unless silent: true)\n if (rule?.silent !== true) {\n const eventKey = isString(rule?.name) ? rule.name : event.name;\n\n // Build eventTags\n const eventTags: Record<string, unknown> = {};\n\n // Resolve eventTags mapping first (so revenue/value can override)\n if (mappingSettings.eventTags !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.eventTags,\n { collector },\n );\n if (isObject(resolved)) {\n Object.assign(eventTags, resolved);\n }\n }\n\n // Revenue (integer, cents)\n if (mappingSettings.revenue !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.revenue, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.revenue = resolved;\n }\n }\n\n // Value (float)\n if (mappingSettings.value !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.value, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.value = resolved;\n }\n }\n\n userContext.trackEvent(eventKey, eventTags);\n }\n\n // Persist state mutations\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const consent = context.data as WalkerOS.Consent;\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n const state = (context.config?.settings as Settings)?._state;\n if (!allGranted && state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n\n destroy({ config }) {\n const settings = (config?.settings || {}) as Settings;\n const state = settings._state;\n if (state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n};\n\nexport default destinationOptimizely;\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 * Destination-level settings.\n */\nexport interface Settings {\n /** Optimizely Feature Experimentation SDK key. Required. */\n sdkKey: string;\n /** walkerOS mapping value to resolve userId for experiment bucketing. */\n userId?: WalkerOSMapping.Value;\n /** User attributes for audience targeting, applied to every event. */\n attributes?: WalkerOSMapping.Value;\n /** Polling interval for datafile updates in ms. Default: 60000. */\n updateInterval?: number;\n /** Auto-update datafile via polling. Default: true. */\n autoUpdate?: boolean;\n /** Batch event processor: events per batch. Default: 10. */\n batchSize?: number;\n /** Batch event processor: flush interval in ms. Default: 1000. */\n flushInterval?: number;\n /** Skip ODP manager initialization. Default: true. */\n skipOdp?: boolean;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** The Optimizely client instance (typed as OptimizelyClient). */\n client?: OptimizelyClient;\n /** Cached user context. Recreated when userId changes. */\n userContext?: OptimizelyUserContext;\n /** Last resolved userId to detect identity changes. */\n lastUserId?: string;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings.\n */\nexport interface Mapping {\n /** Override event key sent to Optimizely. If omitted, event.name is used. */\n eventKey?: string;\n /** Revenue mapping. Resolves to integer (cents). Passed as eventTags.revenue. */\n revenue?: WalkerOSMapping.Value;\n /** Numeric value mapping. Resolves to float. Passed as eventTags.value. */\n value?: WalkerOSMapping.Value;\n /** Additional event tags. Resolves to Record<string, unknown>. */\n eventTags?: WalkerOSMapping.Value;\n /** Per-event user attributes override. Merged onto user context for this event. */\n attributes?: WalkerOSMapping.Value;\n}\n\n/**\n * OptimizelyClient -- the subset of the Optimizely SDK client the destination\n * actually uses. Tests provide a mock via env.optimizely.\n */\nexport interface OptimizelyClient {\n onReady: () => Promise<{ success: boolean }>;\n createUserContext: (\n userId: string,\n attributes?: Record<string, unknown>,\n ) => OptimizelyUserContext | null;\n close: () => void;\n}\n\n/**\n * OptimizelyUserContext -- user context methods the destination calls.\n */\nexport interface OptimizelyUserContext {\n trackEvent: (eventKey: string, eventTags?: Record<string, unknown>) => void;\n setAttribute: (key: string, value: unknown) => void;\n}\n\n/**\n * OptimizelySDK -- factory functions the destination imports from the SDK.\n * Tests provide this via env.optimizely to avoid importing the real SDK.\n */\nexport interface OptimizelySDK {\n createInstance: (config: Record<string, unknown>) => OptimizelyClient;\n createPollingProjectConfigManager: (\n config: Record<string, unknown>,\n ) => unknown;\n createBatchEventProcessor: (config: Record<string, unknown>) => unknown;\n}\n\n/**\n * Env -- optional SDK override. Production leaves env.optimizely undefined\n * and the destination falls back to the real @optimizely/optimizely-sdk\n * import. Tests provide a mock via env.optimizely.\n */\nexport interface Env extends DestinationWeb.Env {\n optimizely?: OptimizelySDK;\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":["userContext"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isNumber, isObject, isString } from '@walkeros/core';\nimport * as optimizelySDK from '@optimizely/optimizely-sdk';\nimport type {\n Destination,\n Env,\n OptimizelySDK as OptimizelySDKType,\n RuntimeState,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationOptimizely from './types';\n\n/**\n * Resolve the Optimizely SDK: use the caller-provided mock when available\n * (tests), otherwise fall back to the real @optimizely/optimizely-sdk.\n */\nfunction getOptimizely(env: Env | undefined): OptimizelySDKType {\n if (env?.optimizely) return env.optimizely;\n return optimizelySDK as unknown as OptimizelySDKType;\n}\n\nexport const destinationOptimizely: Destination = {\n type: 'optimizely',\n\n config: {},\n\n async init({ config, env }) {\n const settings = config.settings;\n if (!settings?.sdkKey) return false;\n\n const sdk = getOptimizely(env as Env | undefined);\n\n const configManager = sdk.createPollingProjectConfigManager({\n sdkKey: settings.sdkKey,\n autoUpdate: settings.autoUpdate ?? true,\n updateInterval: settings.updateInterval ?? 60000,\n });\n\n const eventProcessor = sdk.createBatchEventProcessor({\n batchSize: settings.batchSize ?? 10,\n flushInterval: settings.flushInterval ?? 1000,\n });\n\n const instanceConfig: Record<string, unknown> = {\n projectConfigManager: configManager,\n eventProcessor: eventProcessor,\n };\n\n const client = sdk.createInstance(instanceConfig);\n await client.onReady();\n\n const _state: RuntimeState = { client };\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, collector }) {\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n\n if (!state.client) return;\n\n // 1. Resolve userId\n const userIdMapping = settings.userId;\n let userId: string | undefined;\n if (userIdMapping !== undefined) {\n const resolved = await getMappingValue(event, userIdMapping, {\n collector,\n });\n if (isString(resolved)) userId = resolved;\n }\n\n // Fallback: no userId means we cannot create a user context\n if (!userId) return;\n\n // 2. Resolve destination-level attributes\n let baseAttributes: Record<string, unknown> | undefined;\n if (settings.attributes !== undefined) {\n const resolved = await getMappingValue(event, settings.attributes, {\n collector,\n });\n if (isObject(resolved)) {\n baseAttributes = resolved as Record<string, unknown>;\n }\n }\n\n // 3. Create or reuse user context\n if (userId !== state.lastUserId || !state.userContext) {\n const userContext = state.client.createUserContext(\n userId,\n baseAttributes,\n );\n if (!userContext) return;\n state.userContext = userContext;\n state.lastUserId = userId;\n }\n\n const userContext = state.userContext;\n if (!userContext) return;\n\n // 4. Per-event attributes via setAttribute\n if (mappingSettings.attributes !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.attributes,\n { collector },\n );\n if (isObject(resolved)) {\n for (const [key, value] of Object.entries(\n resolved as Record<string, unknown>,\n )) {\n userContext.setAttribute(key, value);\n }\n }\n }\n\n // 5. Track event (unless silent: true)\n if (rule?.silent !== true) {\n const eventKey = isString(rule?.name) ? rule.name : event.name;\n\n // Build eventTags\n const eventTags: Record<string, unknown> = {};\n\n // Resolve eventTags mapping first (so revenue/value can override)\n if (mappingSettings.eventTags !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.eventTags,\n { collector },\n );\n if (isObject(resolved)) {\n Object.assign(eventTags, resolved);\n }\n }\n\n // Revenue (integer, cents)\n if (mappingSettings.revenue !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.revenue, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.revenue = resolved;\n }\n }\n\n // Value (float)\n if (mappingSettings.value !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.value, {\n collector,\n });\n if (isNumber(resolved)) {\n eventTags.value = resolved;\n }\n }\n\n userContext.trackEvent(eventKey, eventTags);\n }\n\n // Persist state mutations\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const consent = context.data as WalkerOS.Consent;\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n const state = (context.config?.settings as Settings)?._state;\n if (!allGranted && state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n\n destroy({ config }) {\n const settings = (config?.settings || {}) as Settings;\n const state = settings._state;\n if (state?.client) {\n state.client.close();\n state.client = undefined;\n state.userContext = undefined;\n }\n },\n};\n\nexport default destinationOptimizely;\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 * Destination-level settings.\n */\nexport interface Settings {\n /** Optimizely Feature Experimentation SDK key. Required. */\n sdkKey: string;\n /** walkerOS mapping value to resolve userId for experiment bucketing. */\n userId?: WalkerOSMapping.Value;\n /** User attributes for audience targeting, applied to every event. */\n attributes?: WalkerOSMapping.Value;\n /** Polling interval for datafile updates in ms. Default: 60000. */\n updateInterval?: number;\n /** Auto-update datafile via polling. Default: true. */\n autoUpdate?: boolean;\n /** Batch event processor: events per batch. Default: 10. */\n batchSize?: number;\n /** Batch event processor: flush interval in ms. Default: 1000. */\n flushInterval?: number;\n /** Skip ODP manager initialization. Default: true. */\n skipOdp?: boolean;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** The Optimizely client instance (typed as OptimizelyClient). */\n client?: OptimizelyClient;\n /** Cached user context. Recreated when userId changes. */\n userContext?: OptimizelyUserContext;\n /** Last resolved userId to detect identity changes. */\n lastUserId?: string;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings.\n */\nexport interface Mapping {\n /** Override event key sent to Optimizely. If omitted, event.name is used. */\n eventKey?: string;\n /** Revenue mapping. Resolves to integer (cents). Passed as eventTags.revenue. */\n revenue?: WalkerOSMapping.Value;\n /** Numeric value mapping. Resolves to float. Passed as eventTags.value. */\n value?: WalkerOSMapping.Value;\n /** Additional event tags. Resolves to Record<string, unknown>. */\n eventTags?: WalkerOSMapping.Value;\n /** Per-event user attributes override. Merged onto user context for this event. */\n attributes?: WalkerOSMapping.Value;\n}\n\n/**\n * OptimizelyClient -- the subset of the Optimizely SDK client the destination\n * actually uses. Tests provide a mock via env.optimizely.\n */\nexport interface OptimizelyClient {\n onReady: () => Promise<{ success: boolean }>;\n createUserContext: (\n userId: string,\n attributes?: Record<string, unknown>,\n ) => OptimizelyUserContext | null;\n close: () => void;\n}\n\n/**\n * OptimizelyUserContext -- user context methods the destination calls.\n */\nexport interface OptimizelyUserContext {\n trackEvent: (eventKey: string, eventTags?: Record<string, unknown>) => void;\n setAttribute: (key: string, value: unknown) => void;\n}\n\n/**\n * OptimizelySDK -- factory functions the destination imports from the SDK.\n * Tests provide this via env.optimizely to avoid importing the real SDK.\n */\nexport interface OptimizelySDK {\n createInstance: (config: Record<string, unknown>) => OptimizelyClient;\n createPollingProjectConfigManager: (\n config: Record<string, unknown>,\n ) => unknown;\n createBatchEventProcessor: (config: Record<string, unknown>) => unknown;\n}\n\n/**\n * Env -- optional SDK override. Production leaves env.optimizely undefined\n * and the destination falls back to the real @optimizely/optimizely-sdk\n * import. Tests provide a mock via env.optimizely.\n */\nexport interface Env extends DestinationWeb.Env {\n optimizely?: OptimizelySDK;\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":["userContext"]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/web-destination-optimizely",
|
|
4
|
-
"version": "4.0.0
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"type": "destination",
|
|
6
6
|
"platform": [
|
|
7
7
|
"web"
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"consent": {
|
|
157
157
|
"functional": true
|
|
158
158
|
},
|
|
159
|
-
"id": "
|
|
159
|
+
"id": "9d0741daa61eaba5",
|
|
160
160
|
"trigger": "test",
|
|
161
161
|
"entity": "profile",
|
|
162
162
|
"action": "update",
|
|
@@ -255,7 +255,7 @@
|
|
|
255
255
|
"consent": {
|
|
256
256
|
"functional": true
|
|
257
257
|
},
|
|
258
|
-
"id": "
|
|
258
|
+
"id": "f26089490386b68f",
|
|
259
259
|
"trigger": "load",
|
|
260
260
|
"entity": "page",
|
|
261
261
|
"action": "view",
|
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
"consent": {
|
|
308
308
|
"functional": true
|
|
309
309
|
},
|
|
310
|
-
"id": "
|
|
310
|
+
"id": "ffdc8feeed845cee",
|
|
311
311
|
"trigger": "load",
|
|
312
312
|
"entity": "product",
|
|
313
313
|
"action": "view",
|
|
@@ -408,7 +408,7 @@
|
|
|
408
408
|
"consent": {
|
|
409
409
|
"functional": true
|
|
410
410
|
},
|
|
411
|
-
"id": "
|
|
411
|
+
"id": "85d189184f4b1b3f",
|
|
412
412
|
"trigger": "load",
|
|
413
413
|
"entity": "order",
|
|
414
414
|
"action": "complete",
|
|
@@ -482,7 +482,7 @@
|
|
|
482
482
|
"consent": {
|
|
483
483
|
"functional": true
|
|
484
484
|
},
|
|
485
|
-
"id": "
|
|
485
|
+
"id": "12a092502a09802c",
|
|
486
486
|
"trigger": "test",
|
|
487
487
|
"entity": "user",
|
|
488
488
|
"action": "signup",
|
|
@@ -564,7 +564,7 @@
|
|
|
564
564
|
"consent": {
|
|
565
565
|
"functional": true
|
|
566
566
|
},
|
|
567
|
-
"id": "
|
|
567
|
+
"id": "8cb52f6c2ba90ef0",
|
|
568
568
|
"trigger": "test",
|
|
569
569
|
"entity": "debug",
|
|
570
570
|
"action": "noise",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/web-destination-optimizely",
|
|
3
3
|
"description": "Optimizely Feature Experimentation web destination for walkerOS (conversion tracking, revenue metrics, user targeting)",
|
|
4
|
-
"version": "4.0.0
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@optimizely/optimizely-sdk": "^6.0.0",
|
|
41
|
-
"@walkeros/web-core": "4.0.0
|
|
41
|
+
"@walkeros/web-core": "4.0.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@walkeros/collector": "4.0.0
|
|
44
|
+
"@walkeros/collector": "4.0.0"
|
|
45
45
|
},
|
|
46
46
|
"repository": {
|
|
47
47
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|