@walkeros/web-destination-segment 3.4.2 → 4.0.0-next-1777463920154
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/README.md +23 -23
- package/dist/dev.d.mts +13 -13
- package/dist/dev.d.ts +13 -13
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/examples/index.d.mts +13 -13
- package/dist/examples/index.d.ts +13 -13
- package/dist/examples/index.js +37 -32
- package/dist/examples/index.mjs +37 -32
- 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 +52 -199
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t,n=Object.defineProperty,e=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,i={};((t,e)=>{for(var o in e)n(t,o,{get:e[o],enumerable:!0})})(i,{DestinationSegment:()=>w,default:()=>N,destinationSegment:()=>P}),module.exports=(t=i,((t,i,a,s)=>{if(i&&"object"==typeof i||"function"==typeof i)for(let c of o(i))r.call(t,c)||c===a||n(t,c,{get:()=>i[c],enumerable:!(s=e(i,c))||s.enumerable});return t})(n({},"__esModule",{value:!0}),t));var a=Object.defineProperty;((t,n)=>{for(var e in n)a(t,e,{get:n[e],enumerable:!0})})({},{Level:()=>c});var s,c=((s=c||{})[s.ERROR=0]="ERROR",s[s.WARN=1]="WARN",s[s.INFO=2]="INFO",s[s.DEBUG=3]="DEBUG",s);function l(t){return Array.isArray(t)}function u(t){return void 0!==t}function d(t){return"object"==typeof t&&null!==t&&!l(t)&&"[object Object]"===Object.prototype.toString.call(t)}function f(t){return"string"==typeof t}function y(t,n="",e){const o=n.split(".");let r=t;for(let t=0;t<o.length;t++){const n=o[t];if("*"===n&&l(r)){const n=o.slice(t+1).join("."),i=[];for(const t of r){const o=y(t,n,e);i.push(o)}return i}if(r=r instanceof Object?r[n]:void 0,void 0===r)break}return u(r)?r:e}function v(t){return function(t){return"boolean"==typeof t}(t)||f(t)||function(t){return"number"==typeof t&&!Number.isNaN(t)}(t)||!u(t)||l(t)&&t.every(v)||d(t)&&Object.values(t).every(v)}function p(t){return v(t)?t:void 0}function g(t,n,e){return async function(...o){try{return await t(...o)}catch(t){if(!n)return;return await n(t)}finally{await(null==e?void 0:e())}}}async function b(t,n={},e={}){var o;if(!u(t))return;const r=d(t)&&t.consent||e.consent||(null==(o=e.collector)?void 0:o.consent),i=l(n)?n:[n];for(const n of i){const o=await g(m)(t,n,{...e,consent:r});if(u(o))return o}}async function m(t,n,e={}){const{collector:o,consent:r}=e;return(l(n)?n:[n]).reduce(async(n,i)=>{const a=await n;if(a)return a;const s=f(i)?{key:i}:i;if(!Object.keys(s).length)return;const{condition:c,consent:d,fn:v,key:O,loop:w,map:j,set:I,validate:h,value:k}=s;if(c&&!await g(c)(t,i,o))return;if(d&&!function(t,n={},e={}){const o={...n,...e},r={};let i=!t||0===Object.keys(t).length;return Object.keys(o).forEach(n=>{o[n]&&(r[n]=!0,t&&t[n]&&(i=!0))}),!!i&&r}(d,r))return k;let P=u(k)?k:t;if(v&&(P=await g(v)(t,i,e)),O&&(P=y(t,O,k)),w){const[n,o]=w,r="this"===n?[t]:await b(t,n,e);l(r)&&(P=(await Promise.all(r.map(t=>b(t,o,e)))).filter(u))}else j?P=await Object.entries(j).reduce(async(n,[o,r])=>{const i=await n,a=await b(t,r,e);return u(a)&&(i[o]=a),i},Promise.resolve({})):I&&(P=await Promise.all(I.map(n=>m(t,n,e))));h&&!await g(h)(P)&&(P=void 0);const N=p(P);return u(N)?N:p(k)},Promise.resolve(void 0))}var O=require("@segment/analytics-next"),w={},j={load:(t,n)=>O.AnalyticsBrowser.load(t,n)};function I(t){var n;return null!=(n=null==t?void 0:t.analytics)?n:j}function h(t,n){const{apiKey:e,identify:o,group:r,consent:i,_state:a,...s}=n,c={initialPageview:!1,...s};return t.load({writeKey:e},c)}function k(t){if(!t)return"";try{return JSON.stringify(t)}catch(t){return""}}var P={type:"segment",config:{},init({config:t,env:n}){var e;if(!(null==(e=t.settings)?void 0:e.apiKey))return!1;const o=t.settings,r=I(n),i={lastIdentity:{},lastGroup:{},loaded:!1};return!!t.consent&&Object.keys(t.consent).length>0||(i.analytics=h(r,o),i.loaded=!0),{...t,settings:{...o,_state:i}}},async push(t,{config:n,rule:e,env:o,data:r,collector:i}){var a,s;const c=I(o),u=n.settings||{},y=u._state||{},v=function(t,n,e){return e.analytics?e.analytics:e.loaded?void 0:(e.analytics=h(t,n),e.loaded=!0,e.analytics)}(c,u,y);if(!v)return;const p=(null==e?void 0:e.settings)||{},g=function(t,n){const e=n.consent;if(!e||0===Object.keys(e).length)return;const o=t.consent;if(!d(o))return;const r={};for(const[t,n]of Object.entries(e))t in o&&(r[n]=!0===o[t]);return 0!==Object.keys(r).length?{context:{consent:{categoryPreferences:r}}}:void 0}(t,u);if(void 0!==p.reset){("boolean"==typeof p.reset?p.reset:await b(t,p.reset,{collector:i}))&&(v.reset(),y.lastIdentity={},y.lastGroup={})}const m=null!=(a=p.identify)?a:u.identify;if(void 0!==m){const n=await b(t,m,{collector:i});d(n)&&function(t,n,e,o){var r;const i=e.lastIdentity||{},a=f(n.userId)?n.userId:void 0,s=f(n.anonymousId)?n.anonymousId:void 0,c=d(n.traits)&&!l(n.traits)?n.traits:void 0;s&&s!==i.anonymousId&&t.setAnonymousId(s);const u=k(c),y=a!==i.userId,v=u!==(null!=(r=i.traitsHash)?r:"");(y||void 0!==c&&v||s)&&(o?t.identify(a,c||{},o):t.identify(a,c||{}),e.lastIdentity={userId:a,anonymousId:null!=s?s:i.anonymousId,traitsHash:u})}(v,n,y,g)}const O=null!=(s=p.group)?s:u.group;if(void 0!==O){const n=await b(t,O,{collector:i});d(n)&&function(t,n,e,o){var r;const i=f(n.groupId)?n.groupId:void 0;if(!i)return;const a=d(n.traits)&&!l(n.traits)?n.traits:void 0,s=e.lastGroup||{},c=k(a),u=i!==s.groupId,y=c!==(null!=(r=s.traitsHash)?r:"");(u||y)&&(o?t.group(i,a||{},o):t.group(i,a||{}),e.lastGroup={groupId:i,traitsHash:c})}(v,n,y,g)}if(void 0!==p.page&&await async function(t,n,e,o,r){if(!0===n)return void(r?t.page(void 0,void 0,void 0,r):t.page());const i=await b(e,n,{collector:o});if(!d(i))return;const a=i,s=f(a.category)?a.category:void 0,c=f(a.name)?a.name:void 0,u=d(a.properties)&&!l(a.properties)?a.properties:void 0;r?t.page(null!=s?s:null,null!=c?c:null,null!=u?u:{},r):void 0!==u?t.page(null!=s?s:null,null!=c?c:null,u):void 0!==c||void 0!==s?t.page(null!=s?s:null,null!=c?c:null):t.page()}(v,p.page,t,i,g),!0!==(null==e?void 0:e.
|
|
1
|
+
"use strict";var t,n=Object.defineProperty,e=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,i={};((t,e)=>{for(var o in e)n(t,o,{get:e[o],enumerable:!0})})(i,{DestinationSegment:()=>w,default:()=>N,destinationSegment:()=>P}),module.exports=(t=i,((t,i,a,s)=>{if(i&&"object"==typeof i||"function"==typeof i)for(let c of o(i))r.call(t,c)||c===a||n(t,c,{get:()=>i[c],enumerable:!(s=e(i,c))||s.enumerable});return t})(n({},"__esModule",{value:!0}),t));var a=Object.defineProperty;((t,n)=>{for(var e in n)a(t,e,{get:n[e],enumerable:!0})})({},{Level:()=>c});var s,c=((s=c||{})[s.ERROR=0]="ERROR",s[s.WARN=1]="WARN",s[s.INFO=2]="INFO",s[s.DEBUG=3]="DEBUG",s);function l(t){return Array.isArray(t)}function u(t){return void 0!==t}function d(t){return"object"==typeof t&&null!==t&&!l(t)&&"[object Object]"===Object.prototype.toString.call(t)}function f(t){return"string"==typeof t}function y(t,n="",e){const o=n.split(".");let r=t;for(let t=0;t<o.length;t++){const n=o[t];if("*"===n&&l(r)){const n=o.slice(t+1).join("."),i=[];for(const t of r){const o=y(t,n,e);i.push(o)}return i}if(r=r instanceof Object?r[n]:void 0,void 0===r)break}return u(r)?r:e}function v(t){return function(t){return"boolean"==typeof t}(t)||f(t)||function(t){return"number"==typeof t&&!Number.isNaN(t)}(t)||!u(t)||l(t)&&t.every(v)||d(t)&&Object.values(t).every(v)}function p(t){return v(t)?t:void 0}function g(t,n,e){return async function(...o){try{return await t(...o)}catch(t){if(!n)return;return await n(t)}finally{await(null==e?void 0:e())}}}async function b(t,n={},e={}){var o;if(!u(t))return;const r=d(t)&&t.consent||e.consent||(null==(o=e.collector)?void 0:o.consent),i=l(n)?n:[n];for(const n of i){const o=await g(m)(t,n,{...e,consent:r});if(u(o))return o}}async function m(t,n,e={}){const{collector:o,consent:r}=e;return(l(n)?n:[n]).reduce(async(n,i)=>{const a=await n;if(a)return a;const s=f(i)?{key:i}:i;if(!Object.keys(s).length)return;const{condition:c,consent:d,fn:v,key:O,loop:w,map:j,set:I,validate:h,value:k}=s;if(c&&!await g(c)(t,i,o))return;if(d&&!function(t,n={},e={}){const o={...n,...e},r={};let i=!t||0===Object.keys(t).length;return Object.keys(o).forEach(n=>{o[n]&&(r[n]=!0,t&&t[n]&&(i=!0))}),!!i&&r}(d,r))return k;let P=u(k)?k:t;if(v&&(P=await g(v)(t,i,e)),O&&(P=y(t,O,k)),w){const[n,o]=w,r="this"===n?[t]:await b(t,n,e);l(r)&&(P=(await Promise.all(r.map(t=>b(t,o,e)))).filter(u))}else j?P=await Object.entries(j).reduce(async(n,[o,r])=>{const i=await n,a=await b(t,r,e);return u(a)&&(i[o]=a),i},Promise.resolve({})):I&&(P=await Promise.all(I.map(n=>m(t,n,e))));h&&!await g(h)(P)&&(P=void 0);const N=p(P);return u(N)?N:p(k)},Promise.resolve(void 0))}var O=require("@segment/analytics-next"),w={},j={load:(t,n)=>O.AnalyticsBrowser.load(t,n)};function I(t){var n;return null!=(n=null==t?void 0:t.analytics)?n:j}function h(t,n){const{apiKey:e,identify:o,group:r,consent:i,_state:a,...s}=n,c={initialPageview:!1,...s};return t.load({writeKey:e},c)}function k(t){if(!t)return"";try{return JSON.stringify(t)}catch(t){return""}}var P={type:"segment",config:{},init({config:t,env:n}){var e;if(!(null==(e=t.settings)?void 0:e.apiKey))return!1;const o=t.settings,r=I(n),i={lastIdentity:{},lastGroup:{},loaded:!1};return!!t.consent&&Object.keys(t.consent).length>0||(i.analytics=h(r,o),i.loaded=!0),{...t,settings:{...o,_state:i}}},async push(t,{config:n,rule:e,env:o,data:r,collector:i}){var a,s;const c=I(o),u=n.settings||{},y=u._state||{},v=function(t,n,e){return e.analytics?e.analytics:e.loaded?void 0:(e.analytics=h(t,n),e.loaded=!0,e.analytics)}(c,u,y);if(!v)return;const p=(null==e?void 0:e.settings)||{},g=function(t,n){const e=n.consent;if(!e||0===Object.keys(e).length)return;const o=t.consent;if(!d(o))return;const r={};for(const[t,n]of Object.entries(e))t in o&&(r[n]=!0===o[t]);return 0!==Object.keys(r).length?{context:{consent:{categoryPreferences:r}}}:void 0}(t,u);if(void 0!==p.reset){("boolean"==typeof p.reset?p.reset:await b(t,p.reset,{collector:i}))&&(v.reset(),y.lastIdentity={},y.lastGroup={})}const m=null!=(a=p.identify)?a:u.identify;if(void 0!==m){const n=await b(t,m,{collector:i});d(n)&&function(t,n,e,o){var r;const i=e.lastIdentity||{},a=f(n.userId)?n.userId:void 0,s=f(n.anonymousId)?n.anonymousId:void 0,c=d(n.traits)&&!l(n.traits)?n.traits:void 0;s&&s!==i.anonymousId&&t.setAnonymousId(s);const u=k(c),y=a!==i.userId,v=u!==(null!=(r=i.traitsHash)?r:"");(y||void 0!==c&&v||s)&&(o?t.identify(a,c||{},o):t.identify(a,c||{}),e.lastIdentity={userId:a,anonymousId:null!=s?s:i.anonymousId,traitsHash:u})}(v,n,y,g)}const O=null!=(s=p.group)?s:u.group;if(void 0!==O){const n=await b(t,O,{collector:i});d(n)&&function(t,n,e,o){var r;const i=f(n.groupId)?n.groupId:void 0;if(!i)return;const a=d(n.traits)&&!l(n.traits)?n.traits:void 0,s=e.lastGroup||{},c=k(a),u=i!==s.groupId,y=c!==(null!=(r=s.traitsHash)?r:"");(u||y)&&(o?t.group(i,a||{},o):t.group(i,a||{}),e.lastGroup={groupId:i,traitsHash:c})}(v,n,y,g)}if(void 0!==p.page&&await async function(t,n,e,o,r){if(!0===n)return void(r?t.page(void 0,void 0,void 0,r):t.page());const i=await b(e,n,{collector:o});if(!d(i))return;const a=i,s=f(a.category)?a.category:void 0,c=f(a.name)?a.name:void 0,u=d(a.properties)&&!l(a.properties)?a.properties:void 0;r?t.page(null!=s?s:null,null!=c?c:null,null!=u?u:{},r):void 0!==u?t.page(null!=s?s:null,null!=c?c:null,u):void 0!==c||void 0!==s?t.page(null!=s?s:null,null!=c?c:null):t.page()}(v,p.page,t,i,g),!0!==(null==e?void 0:e.silent)){const n=f(null==e?void 0:e.name)?e.name:t.name,o=d(r)?r:{};g?v.track(n,o,g):v.track(n,o)}u._state=y},on(t,n){var e,o;if("consent"!==t||!n.data)return;const r=n.data,i=null==(e=n.config)?void 0:e.consent;if(!i||0===Object.keys(i).length)return;const a=(null==(o=n.config)?void 0:o.settings)||{},s=a._state||{},c=I(n.env);Object.keys(i).every(t=>!0===r[t])&&!s.loaded&&(s.analytics=h(c,a),s.loaded=!0,a._state=s)}},N=P;//# 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, isArray, isObject, isString } from '@walkeros/core';\nimport { AnalyticsBrowser } from '@segment/analytics-next';\nimport type {\n Destination,\n Env,\n RuntimeState,\n SegmentAnalytics,\n SegmentEventOptions,\n SegmentSDK,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationSegment from './types';\n\n/**\n * Real-SDK adapter — wraps AnalyticsBrowser's static load() in our\n * SegmentSDK shape so `env?.analytics ?? realSegment` works.\n *\n * Task 1 confirmed AnalyticsBrowser.load(settings, options) returns an\n * AnalyticsBrowser instance that exposes track/identify/group/page/...\n * The returned instance buffers method calls pre-load and replays them\n * once the internal load promise resolves.\n */\nconst realSegment: SegmentSDK = {\n load: (settings, options) =>\n AnalyticsBrowser.load(settings, options) as unknown as SegmentAnalytics,\n};\n\nfunction getSegment(env: Env | undefined): SegmentSDK {\n return env?.analytics ?? realSegment;\n}\n\n/**\n * Call sdk.load() with destructured Segment settings. Strips walkerOS-\n * specific keys from the options arg passed to the real SDK.\n */\nfunction loadAnalytics(sdk: SegmentSDK, settings: Settings): SegmentAnalytics {\n const {\n apiKey,\n identify: _identify,\n group: _group,\n consent: _consent,\n _state: _existingState,\n ...initOptions\n } = settings;\n\n // Apply walkerOS defaults that differ from Segment defaults.\n const options = {\n initialPageview: false,\n ...initOptions,\n };\n\n return sdk.load({ writeKey: apiKey }, options);\n}\n\n/**\n * Resolve the live analytics instance, loading on demand if deferred.\n * Returns undefined if load() was deferred and consent hasn't fired yet.\n */\nfunction resolveAnalytics(\n sdk: SegmentSDK,\n settings: Settings,\n state: RuntimeState,\n): SegmentAnalytics | undefined {\n if (state.analytics) return state.analytics;\n if (state.loaded) return undefined;\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n return state.analytics;\n}\n\n/**\n * Stable hash of a traits object for state-diffing. Uses a deterministic\n * JSON stringify — key order matters but is consistent within a session\n * because object literal keys come in insertion order.\n */\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\n/**\n * Build the Segment event options object with consent context from the\n * current walker consent state. Returns undefined unless the user has\n * explicitly opted in by configuring `settings.consent` — this keeps the\n * consent forwarding feature off-by-default so events stay clean.\n *\n * `settings.consent` maps walkerOS consent keys → Segment category names.\n * Only walker keys present in the mapping are forwarded.\n */\nfunction buildEventOptions(\n event: WalkerOS.Event,\n settings: Settings,\n): SegmentEventOptions | undefined {\n const map = settings.consent;\n if (!map || Object.keys(map).length === 0) return undefined;\n\n const consentState = event.consent;\n if (!isObject(consentState)) return undefined;\n\n const categoryPreferences: Record<string, boolean> = {};\n for (const [walkerKey, segmentKey] of Object.entries(map)) {\n if (walkerKey in consentState) {\n categoryPreferences[segmentKey] = consentState[walkerKey] === true;\n }\n }\n\n if (Object.keys(categoryPreferences).length === 0) return undefined;\n\n return {\n context: {\n consent: {\n categoryPreferences,\n },\n },\n };\n}\n\n/**\n * Resolve and apply identity mapping. Calls analytics.identify() only\n * when the resolved value differs from the last-fired identity.\n */\nfunction applyIdentify(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const last = state.lastIdentity || {};\n const userId = isString(resolved.userId) ? resolved.userId : undefined;\n const anonymousId = isString(resolved.anonymousId)\n ? resolved.anonymousId\n : undefined;\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n if (anonymousId && anonymousId !== last.anonymousId) {\n analytics.setAnonymousId(anonymousId);\n }\n\n const traitsHash = hashTraits(traits);\n const userIdChanged = userId !== last.userId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n const hasChange = userIdChanged || (traits !== undefined && traitsChanged);\n\n if (!hasChange && !anonymousId) return;\n\n if (options) {\n analytics.identify(userId, traits || {}, options);\n } else {\n analytics.identify(userId, traits || {});\n }\n\n state.lastIdentity = {\n userId,\n anonymousId: anonymousId ?? last.anonymousId,\n traitsHash,\n };\n}\n\nfunction applyGroup(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const groupId = isString(resolved.groupId) ? resolved.groupId : undefined;\n if (!groupId) return;\n\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n const last = state.lastGroup || {};\n const traitsHash = hashTraits(traits);\n const groupIdChanged = groupId !== last.groupId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n if (!groupIdChanged && !traitsChanged) return;\n\n if (options) {\n analytics.group(groupId, traits || {}, options);\n } else {\n analytics.group(groupId, traits || {});\n }\n\n state.lastGroup = { groupId, traitsHash };\n}\n\nasync function applyPage(\n analytics: SegmentAnalytics,\n pageMapping: unknown,\n event: WalkerOS.Event,\n collector: unknown,\n options?: SegmentEventOptions,\n): Promise<void> {\n // Boolean true → call page() with no args (SDK auto-collect).\n if (pageMapping === true) {\n if (options) {\n analytics.page(undefined, undefined, undefined, options);\n } else {\n analytics.page();\n }\n return;\n }\n\n const resolved = await getMappingValue(\n event,\n pageMapping as Parameters<typeof getMappingValue>[1],\n { collector } as Parameters<typeof getMappingValue>[2],\n );\n if (!isObject(resolved)) return;\n\n const r = resolved as {\n category?: unknown;\n name?: unknown;\n properties?: unknown;\n };\n const category = isString(r.category) ? r.category : undefined;\n const name = isString(r.name) ? r.name : undefined;\n const properties =\n isObject(r.properties) && !isArray(r.properties)\n ? (r.properties as Record<string, unknown>)\n : undefined;\n\n if (options) {\n analytics.page(category ?? null, name ?? null, properties ?? {}, options);\n } else if (properties !== undefined) {\n analytics.page(category ?? null, name ?? null, properties);\n } else if (name !== undefined || category !== undefined) {\n analytics.page(category ?? null, name ?? null);\n } else {\n analytics.page();\n }\n}\n\nexport const destinationSegment: Destination = {\n type: 'segment',\n\n config: {},\n\n init({ config, env }) {\n if (!config.settings?.apiKey) return false;\n const settings = config.settings as Settings;\n\n const sdk = getSegment(env as Env | undefined);\n const _state: RuntimeState = {\n lastIdentity: {},\n lastGroup: {},\n loaded: false,\n };\n\n // If config.consent is declared, defer load() until on('consent').\n // Otherwise load immediately.\n const requiresConsent =\n !!config.consent && Object.keys(config.consent).length > 0;\n\n if (!requiresConsent) {\n _state.analytics = loadAnalytics(sdk, settings);\n _state.loaded = true;\n }\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, data, collector }) {\n const sdk = getSegment(env as Env | undefined);\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const analytics = resolveAnalytics(sdk, settings, state);\n if (!analytics) return;\n\n const mappingSettings = rule?.settings || {};\n const options = buildEventOptions(event, settings);\n\n // 1. Reset fires first so subsequent identity calls start clean.\n if (mappingSettings.reset !== undefined) {\n const resolved =\n typeof mappingSettings.reset === 'boolean'\n ? mappingSettings.reset\n : await getMappingValue(event, mappingSettings.reset, { collector });\n if (resolved) {\n analytics.reset();\n state.lastIdentity = {};\n state.lastGroup = {};\n }\n }\n\n // 2. Identity — 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 applyIdentify(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 3. Group — rule-level override wins over destination-level.\n const groupMapping = mappingSettings.group ?? settings.group;\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n applyGroup(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 4. Page (explicit first-class Segment pattern)\n if (mappingSettings.page !== undefined) {\n await applyPage(\n analytics,\n mappingSettings.page,\n event,\n collector,\n options,\n );\n }\n\n // 5. Default track call 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)\n ? (data as Record<string, unknown>)\n : {};\n\n if (options) {\n analytics.track(eventName, properties, options);\n } else {\n analytics.track(eventName, properties);\n }\n }\n\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const sdk = getSegment(context.env as Env | undefined);\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n if (allGranted && !state.loaded) {\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n settings._state = state;\n }\n // If not all granted, walkerOS's config.consent gate blocks subsequent\n // push() calls — no SDK action needed (Segment has no opt-out method).\n },\n};\n\nexport default destinationSegment;\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationWeb } from '@walkeros/web-core';\nimport type {\n AnalyticsBrowserSettings,\n InitOptions,\n} from '@segment/analytics-next';\n\n/**\n * Destination-level settings.\n *\n * Extends Segment's `InitOptions` (minus the `group` key which clashes with\n * walkerOS's own `group` mapping) so every passthrough option (cookie,\n * storage, integrations, plan, etc.) keeps IntelliSense intact. walkerOS\n * adds:\n * - `apiKey` (required) — maps to `writeKey` in `AnalyticsBrowser.load()`\n * - `identify` — destination-level identity mapping (Segment `identify()`)\n * - `group` — destination-level group mapping (Segment `group()`)\n * - `include` — event sections flattened into track `properties`\n * - `consent` — walkerOS consent key → Segment category name mapping\n * - `_state` — runtime state (not user-facing, mutated by init/push)\n */\nexport interface Settings extends Omit<InitOptions, 'group'> {\n /** Segment write key. Maps to `writeKey` in the load() settings arg. */\n apiKey: string;\n /** walkerOS mapping value resolving to an identity object (userId, traits, anonymousId). */\n identify?: WalkerOSMapping.Value;\n /** walkerOS mapping value resolving to a group object (groupId, traits). */\n group?: WalkerOSMapping.Value;\n /**\n * Mapping from walkerOS consent keys → Segment `categoryPreferences` keys.\n * Example: { marketing: \"Advertising\", analytics: \"Analytics\" }\n * If omitted, walkerOS keys are forwarded 1:1.\n */\n consent?: Record<string, string>;\n /** Runtime state — populated by init() and mutated by push(). Not user-facing. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** Last-set identity values, used to skip redundant identify() calls. */\n lastIdentity?: {\n userId?: string;\n anonymousId?: string;\n traitsHash?: string;\n };\n /** Last-set group assignment, used to skip redundant group() calls. */\n lastGroup?: {\n groupId?: string;\n traitsHash?: string;\n };\n /** Holds the AnalyticsBrowser instance created in init(). */\n analytics?: SegmentAnalytics;\n /** True once load() has been called (may be deferred pending consent). */\n loaded?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Every feature here is a walkerOS mapping\n * value resolved via getMappingValue(). The resolved object's keys drive\n * which Segment SDK methods to call.\n */\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n page?: WalkerOSMapping.Value | boolean;\n reset?: WalkerOSMapping.Value | boolean;\n}\n\n/**\n * Segment SDK surface — the subset of @segment/analytics-next the\n * destination actually uses. Mirrors the AnalyticsBrowser instance shape\n * so tests can mock each method individually via env.analytics.\n */\nexport interface SegmentAnalytics {\n track: (\n event: string,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n identify: (\n userId?: string | Record<string, unknown>,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n group: (\n groupId: string,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n page: (\n category?: string | null,\n name?: string | null,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n alias: (\n to: string,\n from?: string,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n reset: () => Promise<unknown> | void;\n setAnonymousId: (id: string) => Promise<unknown> | void;\n}\n\n/**\n * Segment event options — the fourth argument to track/identify/group/page\n * that carries context and integration overrides. The destination uses\n * this to stamp consent context on every event.\n */\nexport interface SegmentEventOptions {\n context?: {\n consent?: {\n categoryPreferences?: Record<string, boolean>;\n };\n [key: string]: unknown;\n };\n integrations?: Record<string, boolean | Record<string, unknown>>;\n}\n\n/**\n * The module namespace used for `env?.analytics ?? realSegment`.\n * AnalyticsBrowser is the class; tests mock with a factory that returns\n * an object matching SegmentAnalytics.\n *\n * Task 1 verified: `AnalyticsBrowser.load(settings, options)` returns an\n * `AnalyticsBrowser` instance **synchronously**. The instance buffers\n * method calls until the internal load promise resolves.\n */\nexport interface SegmentSDK {\n load: (\n settings: AnalyticsBrowserSettings,\n options?: InitOptions,\n ) => SegmentAnalytics;\n}\n\n/**\n * Env — optional SDK override. Production leaves this undefined and the\n * destination falls back to the real @segment/analytics-next module.\n * Tests provide a mock via env.analytics = { ... }.\n */\nexport interface Env extends DestinationWeb.Env {\n analytics?: SegmentSDK;\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 interface SegmentDestination extends Destination {\n env?: Env;\n}\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,4BAAiC;;;ACFjC;;;ADyBA,IAAM,cAA0B;AAAA,EAC9B,MAAM,CAAC,UAAU,YACf,uCAAiB,KAAK,UAAU,OAAO;AAC3C;AAEA,SAAS,WAAW,KAAkC;AA9BtD;AA+BE,UAAO,gCAAK,cAAL,YAAkB;AAC3B;AAMA,SAAS,cAAc,KAAiB,UAAsC;AAC5E,QAAM;AAAA,IACJ;AAAA,IACA,UAAU;AAAA,IACV,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,GAAG;AAAA,EACL,IAAI;AAGJ,QAAM,UAAU;AAAA,IACd,iBAAiB;AAAA,IACjB,GAAG;AAAA,EACL;AAEA,SAAO,IAAI,KAAK,EAAE,UAAU,OAAO,GAAG,OAAO;AAC/C;AAMA,SAAS,iBACP,KACA,UACA,OAC8B;AAC9B,MAAI,MAAM,UAAW,QAAO,MAAM;AAClC,MAAI,MAAM,OAAQ,QAAO;AACzB,QAAM,YAAY,cAAc,KAAK,QAAQ;AAC7C,QAAM,SAAS;AACf,SAAO,MAAM;AACf;AAOA,SAAS,WAAW,QAAqD;AACvE,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AACF,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B,SAAQA,IAAA;AACN,WAAO;AAAA,EACT;AACF;AAWA,SAAS,kBACP,OACA,UACiC;AACjC,QAAM,MAAM,SAAS;AACrB,MAAI,CAAC,OAAO,OAAO,KAAK,GAAG,EAAE,WAAW,EAAG,QAAO;AAElD,QAAM,eAAe,MAAM;AAC3B,MAAI,CAAC,EAAS,YAAY,EAAG,QAAO;AAEpC,QAAM,sBAA+C,CAAC;AACtD,aAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,GAAG,GAAG;AACzD,QAAI,aAAa,cAAc;AAC7B,0BAAoB,UAAU,IAAI,aAAa,SAAS,MAAM;AAAA,IAChE;AAAA,EACF;AAEA,MAAI,OAAO,KAAK,mBAAmB,EAAE,WAAW,EAAG,QAAO;AAE1D,SAAO;AAAA,IACL,SAAS;AAAA,MACP,SAAS;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,cACP,WACA,UACA,OACA,SACM;AArIR;AAsIE,QAAM,OAAO,MAAM,gBAAgB,CAAC;AACpC,QAAM,SAAS,GAAS,SAAS,MAAM,IAAI,SAAS,SAAS;AAC7D,QAAM,cAAc,GAAS,SAAS,WAAW,IAC7C,SAAS,cACT;AACJ,QAAM,SACJ,EAAS,SAAS,MAAM,KAAK,CAAC,EAAQ,SAAS,MAAM,IAChD,SAAS,SACV;AAEN,MAAI,eAAe,gBAAgB,KAAK,aAAa;AACnD,cAAU,eAAe,WAAW;AAAA,EACtC;AAEA,QAAM,aAAa,WAAW,MAAM;AACpC,QAAM,gBAAgB,WAAW,KAAK;AACtC,QAAM,gBAAgB,iBAAgB,UAAK,eAAL,YAAmB;AACzD,QAAM,YAAY,iBAAkB,WAAW,UAAa;AAE5D,MAAI,CAAC,aAAa,CAAC,YAAa;AAEhC,MAAI,SAAS;AACX,cAAU,SAAS,QAAQ,UAAU,CAAC,GAAG,OAAO;AAAA,EAClD,OAAO;AACL,cAAU,SAAS,QAAQ,UAAU,CAAC,CAAC;AAAA,EACzC;AAEA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA,aAAa,oCAAe,KAAK;AAAA,IACjC;AAAA,EACF;AACF;AAEA,SAAS,WACP,WACA,UACA,OACA,SACM;AA7KR;AA8KE,QAAM,UAAU,GAAS,SAAS,OAAO,IAAI,SAAS,UAAU;AAChE,MAAI,CAAC,QAAS;AAEd,QAAM,SACJ,EAAS,SAAS,MAAM,KAAK,CAAC,EAAQ,SAAS,MAAM,IAChD,SAAS,SACV;AAEN,QAAM,OAAO,MAAM,aAAa,CAAC;AACjC,QAAM,aAAa,WAAW,MAAM;AACpC,QAAM,iBAAiB,YAAY,KAAK;AACxC,QAAM,gBAAgB,iBAAgB,UAAK,eAAL,YAAmB;AACzD,MAAI,CAAC,kBAAkB,CAAC,cAAe;AAEvC,MAAI,SAAS;AACX,cAAU,MAAM,SAAS,UAAU,CAAC,GAAG,OAAO;AAAA,EAChD,OAAO;AACL,cAAU,MAAM,SAAS,UAAU,CAAC,CAAC;AAAA,EACvC;AAEA,QAAM,YAAY,EAAE,SAAS,WAAW;AAC1C;AAEA,eAAe,UACb,WACA,aACA,OACA,WACA,SACe;AAEf,MAAI,gBAAgB,MAAM;AACxB,QAAI,SAAS;AACX,gBAAU,KAAK,QAAW,QAAW,QAAW,OAAO;AAAA,IACzD,OAAO;AACL,gBAAU,KAAK;AAAA,IACjB;AACA;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA,EAAE,UAAU;AAAA,EACd;AACA,MAAI,CAAC,EAAS,QAAQ,EAAG;AAEzB,QAAM,IAAI;AAKV,QAAM,WAAW,GAAS,EAAE,QAAQ,IAAI,EAAE,WAAW;AACrD,QAAM,OAAO,GAAS,EAAE,IAAI,IAAI,EAAE,OAAO;AACzC,QAAM,aACJ,EAAS,EAAE,UAAU,KAAK,CAAC,EAAQ,EAAE,UAAU,IAC1C,EAAE,aACH;AAEN,MAAI,SAAS;AACX,cAAU,KAAK,8BAAY,MAAM,sBAAQ,MAAM,kCAAc,CAAC,GAAG,OAAO;AAAA,EAC1E,WAAW,eAAe,QAAW;AACnC,cAAU,KAAK,8BAAY,MAAM,sBAAQ,MAAM,UAAU;AAAA,EAC3D,WAAW,SAAS,UAAa,aAAa,QAAW;AACvD,cAAU,KAAK,8BAAY,MAAM,sBAAQ,IAAI;AAAA,EAC/C,OAAO;AACL,cAAU,KAAK;AAAA,EACjB;AACF;AAEO,IAAM,qBAAkC;AAAA,EAC7C,MAAM;AAAA,EAEN,QAAQ,CAAC;AAAA,EAET,KAAK,EAAE,QAAQ,IAAI,GAAG;AAzPxB;AA0PI,QAAI,GAAC,YAAO,aAAP,mBAAiB,QAAQ,QAAO;AACrC,UAAM,WAAW,OAAO;AAExB,UAAM,MAAM,WAAW,GAAsB;AAC7C,UAAM,SAAuB;AAAA,MAC3B,cAAc,CAAC;AAAA,MACf,WAAW,CAAC;AAAA,MACZ,QAAQ;AAAA,IACV;AAIA,UAAM,kBACJ,CAAC,CAAC,OAAO,WAAW,OAAO,KAAK,OAAO,OAAO,EAAE,SAAS;AAE3D,QAAI,CAAC,iBAAiB;AACpB,aAAO,YAAY,cAAc,KAAK,QAAQ;AAC9C,aAAO,SAAS;AAAA,IAClB;AAEA,WAAO,EAAE,GAAG,QAAQ,UAAU,EAAE,GAAG,UAAU,OAAO,EAAE;AAAA,EACxD;AAAA,EAEA,MAAM,KAAK,OAAO,EAAE,QAAQ,MAAM,KAAK,MAAM,UAAU,GAAG;AAjR5D;AAkRI,UAAM,MAAM,WAAW,GAAsB;AAC7C,UAAM,WAAY,OAAO,YAAY,CAAC;AACtC,UAAM,QAAsB,SAAS,UAAU,CAAC;AAChD,UAAM,YAAY,iBAAiB,KAAK,UAAU,KAAK;AACvD,QAAI,CAAC,UAAW;AAEhB,UAAM,mBAAkB,6BAAM,aAAY,CAAC;AAC3C,UAAM,UAAU,kBAAkB,OAAO,QAAQ;AAGjD,QAAI,gBAAgB,UAAU,QAAW;AACvC,YAAM,WACJ,OAAO,gBAAgB,UAAU,YAC7B,gBAAgB,QAChB,MAAM,GAAgB,OAAO,gBAAgB,OAAO,EAAE,UAAU,CAAC;AACvE,UAAI,UAAU;AACZ,kBAAU,MAAM;AAChB,cAAM,eAAe,CAAC;AACtB,cAAM,YAAY,CAAC;AAAA,MACrB;AAAA,IACF;AAGA,UAAM,mBAAkB,qBAAgB,aAAhB,YAA4B,SAAS;AAC7D,QAAI,oBAAoB,QAAW;AACjC,YAAM,WAAW,MAAM,GAAgB,OAAO,iBAAiB;AAAA,QAC7D;AAAA,MACF,CAAC;AACD,UAAI,EAAS,QAAQ,GAAG;AACtB;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,gBAAe,qBAAgB,UAAhB,YAAyB,SAAS;AACvD,QAAI,iBAAiB,QAAW;AAC9B,YAAM,WAAW,MAAM,GAAgB,OAAO,cAAc;AAAA,QAC1D;AAAA,MACF,CAAC;AACD,UAAI,EAAS,QAAQ,GAAG;AACtB;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,gBAAgB,SAAS,QAAW;AACtC,YAAM;AAAA,QACJ;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,SAAI,6BAAM,UAAS,MAAM;AACvB,YAAM,YAAY,GAAS,6BAAM,IAAI,IAAI,KAAK,OAAO,MAAM;AAC3D,YAAM,aAAa,EAAS,IAAI,IAC3B,OACD,CAAC;AAEL,UAAI,SAAS;AACX,kBAAU,MAAM,WAAW,YAAY,OAAO;AAAA,MAChD,OAAO;AACL,kBAAU,MAAM,WAAW,UAAU;AAAA,MACvC;AAAA,IACF;AAEA,aAAS,SAAS;AAAA,EACpB;AAAA,EAEA,GAAG,MAAM,SAAS;AApWpB;AAqWI,QAAI,SAAS,aAAa,CAAC,QAAQ,KAAM;AAEzC,UAAM,UAAU,QAAQ;AACxB,UAAM,YAAW,aAAQ,WAAR,mBAAgB;AACjC,QAAI,CAAC,YAAY,OAAO,KAAK,QAAQ,EAAE,WAAW,EAAG;AAErD,UAAM,aAAY,aAAQ,WAAR,mBAAgB,aAAY,CAAC;AAC/C,UAAM,QAAsB,SAAS,UAAU,CAAC;AAChD,UAAM,MAAM,WAAW,QAAQ,GAAsB;AAErD,UAAM,aAAa,OAAO,KAAK,QAAQ,EAAE;AAAA,MACvC,CAAC,QAAQ,QAAQ,GAAG,MAAM;AAAA,IAC5B;AAEA,QAAI,cAAc,CAAC,MAAM,QAAQ;AAC/B,YAAM,YAAY,cAAc,KAAK,QAAQ;AAC7C,YAAM,SAAS;AACf,eAAS,SAAS;AAAA,IACpB;AAAA,EAGF;AACF;AAEA,IAAO,gBAAQ;","names":["e"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isArray, isObject, isString } from '@walkeros/core';\nimport { AnalyticsBrowser } from '@segment/analytics-next';\nimport type {\n Destination,\n Env,\n RuntimeState,\n SegmentAnalytics,\n SegmentEventOptions,\n SegmentSDK,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationSegment from './types';\n\n/**\n * Real-SDK adapter - wraps AnalyticsBrowser's static load() in our\n * SegmentSDK shape so `env?.analytics ?? realSegment` works.\n *\n * Task 1 confirmed AnalyticsBrowser.load(settings, options) returns an\n * AnalyticsBrowser instance that exposes track/identify/group/page/...\n * The returned instance buffers method calls pre-load and replays them\n * once the internal load promise resolves.\n */\nconst realSegment: SegmentSDK = {\n load: (settings, options) =>\n AnalyticsBrowser.load(settings, options) as unknown as SegmentAnalytics,\n};\n\nfunction getSegment(env: Env | undefined): SegmentSDK {\n return env?.analytics ?? realSegment;\n}\n\n/**\n * Call sdk.load() with destructured Segment settings. Strips walkerOS-\n * specific keys from the options arg passed to the real SDK.\n */\nfunction loadAnalytics(sdk: SegmentSDK, settings: Settings): SegmentAnalytics {\n const {\n apiKey,\n identify: _identify,\n group: _group,\n consent: _consent,\n _state: _existingState,\n ...initOptions\n } = settings;\n\n // Apply walkerOS defaults that differ from Segment defaults.\n const options = {\n initialPageview: false,\n ...initOptions,\n };\n\n return sdk.load({ writeKey: apiKey }, options);\n}\n\n/**\n * Resolve the live analytics instance, loading on demand if deferred.\n * Returns undefined if load() was deferred and consent hasn't fired yet.\n */\nfunction resolveAnalytics(\n sdk: SegmentSDK,\n settings: Settings,\n state: RuntimeState,\n): SegmentAnalytics | undefined {\n if (state.analytics) return state.analytics;\n if (state.loaded) return undefined;\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n return state.analytics;\n}\n\n/**\n * Stable hash of a traits object for state-diffing. Uses a deterministic\n * JSON stringify - key order matters but is consistent within a session\n * because object literal keys come in insertion order.\n */\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\n/**\n * Build the Segment event options object with consent context from the\n * current walker consent state. Returns undefined unless the user has\n * explicitly opted in by configuring `settings.consent` - this keeps the\n * consent forwarding feature off-by-default so events stay clean.\n *\n * `settings.consent` maps walkerOS consent keys → Segment category names.\n * Only walker keys present in the mapping are forwarded.\n */\nfunction buildEventOptions(\n event: WalkerOS.Event,\n settings: Settings,\n): SegmentEventOptions | undefined {\n const map = settings.consent;\n if (!map || Object.keys(map).length === 0) return undefined;\n\n const consentState = event.consent;\n if (!isObject(consentState)) return undefined;\n\n const categoryPreferences: Record<string, boolean> = {};\n for (const [walkerKey, segmentKey] of Object.entries(map)) {\n if (walkerKey in consentState) {\n categoryPreferences[segmentKey] = consentState[walkerKey] === true;\n }\n }\n\n if (Object.keys(categoryPreferences).length === 0) return undefined;\n\n return {\n context: {\n consent: {\n categoryPreferences,\n },\n },\n };\n}\n\n/**\n * Resolve and apply identity mapping. Calls analytics.identify() only\n * when the resolved value differs from the last-fired identity.\n */\nfunction applyIdentify(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const last = state.lastIdentity || {};\n const userId = isString(resolved.userId) ? resolved.userId : undefined;\n const anonymousId = isString(resolved.anonymousId)\n ? resolved.anonymousId\n : undefined;\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n if (anonymousId && anonymousId !== last.anonymousId) {\n analytics.setAnonymousId(anonymousId);\n }\n\n const traitsHash = hashTraits(traits);\n const userIdChanged = userId !== last.userId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n const hasChange = userIdChanged || (traits !== undefined && traitsChanged);\n\n if (!hasChange && !anonymousId) return;\n\n if (options) {\n analytics.identify(userId, traits || {}, options);\n } else {\n analytics.identify(userId, traits || {});\n }\n\n state.lastIdentity = {\n userId,\n anonymousId: anonymousId ?? last.anonymousId,\n traitsHash,\n };\n}\n\nfunction applyGroup(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const groupId = isString(resolved.groupId) ? resolved.groupId : undefined;\n if (!groupId) return;\n\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n const last = state.lastGroup || {};\n const traitsHash = hashTraits(traits);\n const groupIdChanged = groupId !== last.groupId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n if (!groupIdChanged && !traitsChanged) return;\n\n if (options) {\n analytics.group(groupId, traits || {}, options);\n } else {\n analytics.group(groupId, traits || {});\n }\n\n state.lastGroup = { groupId, traitsHash };\n}\n\nasync function applyPage(\n analytics: SegmentAnalytics,\n pageMapping: unknown,\n event: WalkerOS.Event,\n collector: unknown,\n options?: SegmentEventOptions,\n): Promise<void> {\n // Boolean true → call page() with no args (SDK auto-collect).\n if (pageMapping === true) {\n if (options) {\n analytics.page(undefined, undefined, undefined, options);\n } else {\n analytics.page();\n }\n return;\n }\n\n const resolved = await getMappingValue(\n event,\n pageMapping as Parameters<typeof getMappingValue>[1],\n { collector } as Parameters<typeof getMappingValue>[2],\n );\n if (!isObject(resolved)) return;\n\n const r = resolved as {\n category?: unknown;\n name?: unknown;\n properties?: unknown;\n };\n const category = isString(r.category) ? r.category : undefined;\n const name = isString(r.name) ? r.name : undefined;\n const properties =\n isObject(r.properties) && !isArray(r.properties)\n ? (r.properties as Record<string, unknown>)\n : undefined;\n\n if (options) {\n analytics.page(category ?? null, name ?? null, properties ?? {}, options);\n } else if (properties !== undefined) {\n analytics.page(category ?? null, name ?? null, properties);\n } else if (name !== undefined || category !== undefined) {\n analytics.page(category ?? null, name ?? null);\n } else {\n analytics.page();\n }\n}\n\nexport const destinationSegment: Destination = {\n type: 'segment',\n\n config: {},\n\n init({ config, env }) {\n if (!config.settings?.apiKey) return false;\n const settings = config.settings as Settings;\n\n const sdk = getSegment(env as Env | undefined);\n const _state: RuntimeState = {\n lastIdentity: {},\n lastGroup: {},\n loaded: false,\n };\n\n // If config.consent is declared, defer load() until on('consent').\n // Otherwise load immediately.\n const requiresConsent =\n !!config.consent && Object.keys(config.consent).length > 0;\n\n if (!requiresConsent) {\n _state.analytics = loadAnalytics(sdk, settings);\n _state.loaded = true;\n }\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, data, collector }) {\n const sdk = getSegment(env as Env | undefined);\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const analytics = resolveAnalytics(sdk, settings, state);\n if (!analytics) return;\n\n const mappingSettings = rule?.settings || {};\n const options = buildEventOptions(event, settings);\n\n // 1. Reset fires first so subsequent identity calls start clean.\n if (mappingSettings.reset !== undefined) {\n const resolved =\n typeof mappingSettings.reset === 'boolean'\n ? mappingSettings.reset\n : await getMappingValue(event, mappingSettings.reset, { collector });\n if (resolved) {\n analytics.reset();\n state.lastIdentity = {};\n state.lastGroup = {};\n }\n }\n\n // 2. Identity - 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 applyIdentify(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 3. Group - rule-level override wins over destination-level.\n const groupMapping = mappingSettings.group ?? settings.group;\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n applyGroup(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 4. Page (explicit first-class Segment pattern)\n if (mappingSettings.page !== undefined) {\n await applyPage(\n analytics,\n mappingSettings.page,\n event,\n collector,\n options,\n );\n }\n\n // 5. Default track call unless rule opts out via silent.\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\n if (options) {\n analytics.track(eventName, properties, options);\n } else {\n analytics.track(eventName, properties);\n }\n }\n\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const sdk = getSegment(context.env as Env | undefined);\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n if (allGranted && !state.loaded) {\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n settings._state = state;\n }\n // If not all granted, walkerOS's config.consent gate blocks subsequent\n // push() calls - no SDK action needed (Segment has no opt-out method).\n },\n};\n\nexport default destinationSegment;\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationWeb } from '@walkeros/web-core';\nimport type {\n AnalyticsBrowserSettings,\n InitOptions,\n} from '@segment/analytics-next';\n\n/**\n * Destination-level settings.\n *\n * Extends Segment's `InitOptions` (minus the `group` key which clashes with\n * walkerOS's own `group` mapping) so every passthrough option (cookie,\n * storage, integrations, plan, etc.) keeps IntelliSense intact. walkerOS\n * adds:\n * - `apiKey` (required) — maps to `writeKey` in `AnalyticsBrowser.load()`\n * - `identify` — destination-level identity mapping (Segment `identify()`)\n * - `group` — destination-level group mapping (Segment `group()`)\n * - `include` — event sections flattened into track `properties`\n * - `consent` — walkerOS consent key → Segment category name mapping\n * - `_state` — runtime state (not user-facing, mutated by init/push)\n */\nexport interface Settings extends Omit<InitOptions, 'group'> {\n /** Segment write key. Maps to `writeKey` in the load() settings arg. */\n apiKey: string;\n /** walkerOS mapping value resolving to an identity object (userId, traits, anonymousId). */\n identify?: WalkerOSMapping.Value;\n /** walkerOS mapping value resolving to a group object (groupId, traits). */\n group?: WalkerOSMapping.Value;\n /**\n * Mapping from walkerOS consent keys → Segment `categoryPreferences` keys.\n * Example: { marketing: \"Advertising\", analytics: \"Analytics\" }\n * If omitted, walkerOS keys are forwarded 1:1.\n */\n consent?: Record<string, string>;\n /** Runtime state — populated by init() and mutated by push(). Not user-facing. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** Last-set identity values, used to skip redundant identify() calls. */\n lastIdentity?: {\n userId?: string;\n anonymousId?: string;\n traitsHash?: string;\n };\n /** Last-set group assignment, used to skip redundant group() calls. */\n lastGroup?: {\n groupId?: string;\n traitsHash?: string;\n };\n /** Holds the AnalyticsBrowser instance created in init(). */\n analytics?: SegmentAnalytics;\n /** True once load() has been called (may be deferred pending consent). */\n loaded?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Every feature here is a walkerOS mapping\n * value resolved via getMappingValue(). The resolved object's keys drive\n * which Segment SDK methods to call.\n */\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n page?: WalkerOSMapping.Value | boolean;\n reset?: WalkerOSMapping.Value | boolean;\n}\n\n/**\n * Segment SDK surface — the subset of @segment/analytics-next the\n * destination actually uses. Mirrors the AnalyticsBrowser instance shape\n * so tests can mock each method individually via env.analytics.\n */\nexport interface SegmentAnalytics {\n track: (\n event: string,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n identify: (\n userId?: string | Record<string, unknown>,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n group: (\n groupId: string,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n page: (\n category?: string | null,\n name?: string | null,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n alias: (\n to: string,\n from?: string,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n reset: () => Promise<unknown> | void;\n setAnonymousId: (id: string) => Promise<unknown> | void;\n}\n\n/**\n * Segment event options — the fourth argument to track/identify/group/page\n * that carries context and integration overrides. The destination uses\n * this to stamp consent context on every event.\n */\nexport interface SegmentEventOptions {\n context?: {\n consent?: {\n categoryPreferences?: Record<string, boolean>;\n };\n [key: string]: unknown;\n };\n integrations?: Record<string, boolean | Record<string, unknown>>;\n}\n\n/**\n * The module namespace used for `env?.analytics ?? realSegment`.\n * AnalyticsBrowser is the class; tests mock with a factory that returns\n * an object matching SegmentAnalytics.\n *\n * Task 1 verified: `AnalyticsBrowser.load(settings, options)` returns an\n * `AnalyticsBrowser` instance **synchronously**. The instance buffers\n * method calls until the internal load promise resolves.\n */\nexport interface SegmentSDK {\n load: (\n settings: AnalyticsBrowserSettings,\n options?: InitOptions,\n ) => SegmentAnalytics;\n}\n\n/**\n * Env — optional SDK override. Production leaves this undefined and the\n * destination falls back to the real @segment/analytics-next module.\n * Tests provide a mock via env.analytics = { ... }.\n */\nexport interface Env extends DestinationWeb.Env {\n analytics?: SegmentSDK;\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 interface SegmentDestination extends Destination {\n env?: Env;\n}\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":"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","names":["e"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=Object.defineProperty;((n,e)=>{for(var o in e)t(n,o,{get:e[o],enumerable:!0})})({},{Level:()=>e});var n,e=((n=e||{})[n.ERROR=0]="ERROR",n[n.WARN=1]="WARN",n[n.INFO=2]="INFO",n[n.DEBUG=3]="DEBUG",n);function o(t){return Array.isArray(t)}function r(t){return void 0!==t}function i(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,n="",e){const i=n.split(".");let a=t;for(let t=0;t<i.length;t++){const n=i[t];if("*"===n&&o(a)){const n=i.slice(t+1).join("."),o=[];for(const t of a){const r=s(t,n,e);o.push(r)}return o}if(a=a instanceof Object?a[n]:void 0,void 0===a)break}return r(a)?a:e}function c(t){return function(t){return"boolean"==typeof t}(t)||a(t)||function(t){return"number"==typeof t&&!Number.isNaN(t)}(t)||!r(t)||o(t)&&t.every(c)||i(t)&&Object.values(t).every(c)}function l(t){return c(t)?t:void 0}function u(t,n,e){return async function(...o){try{return await t(...o)}catch(t){if(!n)return;return await n(t)}finally{await(null==e?void 0:e())}}}async function d(t,n={},e={}){var a;if(!r(t))return;const s=i(t)&&t.consent||e.consent||(null==(a=e.collector)?void 0:a.consent),c=o(n)?n:[n];for(const n of c){const o=await u(f)(t,n,{...e,consent:s});if(r(o))return o}}async function f(t,n,e={}){const{collector:i,consent:c}=e;return(o(n)?n:[n]).reduce(async(n,y)=>{const v=await n;if(v)return v;const p=a(y)?{key:y}:y;if(!Object.keys(p).length)return;const{condition:g,consent:m,fn:b,key:w,loop:I,map:O,set:j,validate:h,value:k}=p;if(g&&!await u(g)(t,y,i))return;if(m&&!function(t,n={},e={}){const o={...n,...e},r={};let i=!t||0===Object.keys(t).length;return Object.keys(o).forEach(n=>{o[n]&&(r[n]=!0,t&&t[n]&&(i=!0))}),!!i&&r}(m,c))return k;let N=r(k)?k:t;if(b&&(N=await u(b)(t,y,e)),w&&(N=s(t,w,k)),I){const[n,i]=I,a="this"===n?[t]:await d(t,n,e);o(a)&&(N=(await Promise.all(a.map(t=>d(t,i,e)))).filter(r))}else O?N=await Object.entries(O).reduce(async(n,[o,i])=>{const a=await n,s=await d(t,i,e);return r(s)&&(a[o]=s),a},Promise.resolve({})):j&&(N=await Promise.all(j.map(n=>f(t,n,e))));h&&!await u(h)(N)&&(N=void 0);const R=l(N);return r(R)?R:l(k)},Promise.resolve(void 0))}import{AnalyticsBrowser as y}from"@segment/analytics-next";var v={},p={load:(t,n)=>y.load(t,n)};function g(t){var n;return null!=(n=null==t?void 0:t.analytics)?n:p}function m(t,n){const{apiKey:e,identify:o,group:r,consent:i,_state:a,...s}=n,c={initialPageview:!1,...s};return t.load({writeKey:e},c)}function b(t){if(!t)return"";try{return JSON.stringify(t)}catch(t){return""}}var w={type:"segment",config:{},init({config:t,env:n}){var e;if(!(null==(e=t.settings)?void 0:e.apiKey))return!1;const o=t.settings,r=g(n),i={lastIdentity:{},lastGroup:{},loaded:!1};return!!t.consent&&Object.keys(t.consent).length>0||(i.analytics=m(r,o),i.loaded=!0),{...t,settings:{...o,_state:i}}},async push(t,{config:n,rule:e,env:r,data:s,collector:c}){var l,u;const f=g(r),y=n.settings||{},v=y._state||{},p=function(t,n,e){return e.analytics?e.analytics:e.loaded?void 0:(e.analytics=m(t,n),e.loaded=!0,e.analytics)}(f,y,v);if(!p)return;const w=(null==e?void 0:e.settings)||{},I=function(t,n){const e=n.consent;if(!e||0===Object.keys(e).length)return;const o=t.consent;if(!i(o))return;const r={};for(const[t,n]of Object.entries(e))t in o&&(r[n]=!0===o[t]);return 0!==Object.keys(r).length?{context:{consent:{categoryPreferences:r}}}:void 0}(t,y);if(void 0!==w.reset){("boolean"==typeof w.reset?w.reset:await d(t,w.reset,{collector:c}))&&(p.reset(),v.lastIdentity={},v.lastGroup={})}const O=null!=(l=w.identify)?l:y.identify;if(void 0!==O){const n=await d(t,O,{collector:c});i(n)&&function(t,n,e,r){var s;const c=e.lastIdentity||{},l=a(n.userId)?n.userId:void 0,u=a(n.anonymousId)?n.anonymousId:void 0,d=i(n.traits)&&!o(n.traits)?n.traits:void 0;u&&u!==c.anonymousId&&t.setAnonymousId(u);const f=b(d),y=l!==c.userId,v=f!==(null!=(s=c.traitsHash)?s:"");(y||void 0!==d&&v||u)&&(r?t.identify(l,d||{},r):t.identify(l,d||{}),e.lastIdentity={userId:l,anonymousId:null!=u?u:c.anonymousId,traitsHash:f})}(p,n,v,I)}const j=null!=(u=w.group)?u:y.group;if(void 0!==j){const n=await d(t,j,{collector:c});i(n)&&function(t,n,e,r){var s;const c=a(n.groupId)?n.groupId:void 0;if(!c)return;const l=i(n.traits)&&!o(n.traits)?n.traits:void 0,u=e.lastGroup||{},d=b(l),f=c!==u.groupId,y=d!==(null!=(s=u.traitsHash)?s:"");(f||y)&&(r?t.group(c,l||{},r):t.group(c,l||{}),e.lastGroup={groupId:c,traitsHash:d})}(p,n,v,I)}if(void 0!==w.page&&await async function(t,n,e,r,s){if(!0===n)return void(s?t.page(void 0,void 0,void 0,s):t.page());const c=await d(e,n,{collector:r});if(!i(c))return;const l=c,u=a(l.category)?l.category:void 0,f=a(l.name)?l.name:void 0,y=i(l.properties)&&!o(l.properties)?l.properties:void 0;s?t.page(null!=u?u:null,null!=f?f:null,null!=y?y:{},s):void 0!==y?t.page(null!=u?u:null,null!=f?f:null,y):void 0!==f||void 0!==u?t.page(null!=u?u:null,null!=f?f:null):t.page()}(p,w.page,t,c,I),!0!==(null==e?void 0:e.
|
|
1
|
+
var t=Object.defineProperty;((n,e)=>{for(var o in e)t(n,o,{get:e[o],enumerable:!0})})({},{Level:()=>e});var n,e=((n=e||{})[n.ERROR=0]="ERROR",n[n.WARN=1]="WARN",n[n.INFO=2]="INFO",n[n.DEBUG=3]="DEBUG",n);function o(t){return Array.isArray(t)}function r(t){return void 0!==t}function i(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,n="",e){const i=n.split(".");let a=t;for(let t=0;t<i.length;t++){const n=i[t];if("*"===n&&o(a)){const n=i.slice(t+1).join("."),o=[];for(const t of a){const r=s(t,n,e);o.push(r)}return o}if(a=a instanceof Object?a[n]:void 0,void 0===a)break}return r(a)?a:e}function c(t){return function(t){return"boolean"==typeof t}(t)||a(t)||function(t){return"number"==typeof t&&!Number.isNaN(t)}(t)||!r(t)||o(t)&&t.every(c)||i(t)&&Object.values(t).every(c)}function l(t){return c(t)?t:void 0}function u(t,n,e){return async function(...o){try{return await t(...o)}catch(t){if(!n)return;return await n(t)}finally{await(null==e?void 0:e())}}}async function d(t,n={},e={}){var a;if(!r(t))return;const s=i(t)&&t.consent||e.consent||(null==(a=e.collector)?void 0:a.consent),c=o(n)?n:[n];for(const n of c){const o=await u(f)(t,n,{...e,consent:s});if(r(o))return o}}async function f(t,n,e={}){const{collector:i,consent:c}=e;return(o(n)?n:[n]).reduce(async(n,y)=>{const v=await n;if(v)return v;const p=a(y)?{key:y}:y;if(!Object.keys(p).length)return;const{condition:g,consent:m,fn:b,key:w,loop:I,map:O,set:j,validate:h,value:k}=p;if(g&&!await u(g)(t,y,i))return;if(m&&!function(t,n={},e={}){const o={...n,...e},r={};let i=!t||0===Object.keys(t).length;return Object.keys(o).forEach(n=>{o[n]&&(r[n]=!0,t&&t[n]&&(i=!0))}),!!i&&r}(m,c))return k;let N=r(k)?k:t;if(b&&(N=await u(b)(t,y,e)),w&&(N=s(t,w,k)),I){const[n,i]=I,a="this"===n?[t]:await d(t,n,e);o(a)&&(N=(await Promise.all(a.map(t=>d(t,i,e)))).filter(r))}else O?N=await Object.entries(O).reduce(async(n,[o,i])=>{const a=await n,s=await d(t,i,e);return r(s)&&(a[o]=s),a},Promise.resolve({})):j&&(N=await Promise.all(j.map(n=>f(t,n,e))));h&&!await u(h)(N)&&(N=void 0);const R=l(N);return r(R)?R:l(k)},Promise.resolve(void 0))}import{AnalyticsBrowser as y}from"@segment/analytics-next";var v={},p={load:(t,n)=>y.load(t,n)};function g(t){var n;return null!=(n=null==t?void 0:t.analytics)?n:p}function m(t,n){const{apiKey:e,identify:o,group:r,consent:i,_state:a,...s}=n,c={initialPageview:!1,...s};return t.load({writeKey:e},c)}function b(t){if(!t)return"";try{return JSON.stringify(t)}catch(t){return""}}var w={type:"segment",config:{},init({config:t,env:n}){var e;if(!(null==(e=t.settings)?void 0:e.apiKey))return!1;const o=t.settings,r=g(n),i={lastIdentity:{},lastGroup:{},loaded:!1};return!!t.consent&&Object.keys(t.consent).length>0||(i.analytics=m(r,o),i.loaded=!0),{...t,settings:{...o,_state:i}}},async push(t,{config:n,rule:e,env:r,data:s,collector:c}){var l,u;const f=g(r),y=n.settings||{},v=y._state||{},p=function(t,n,e){return e.analytics?e.analytics:e.loaded?void 0:(e.analytics=m(t,n),e.loaded=!0,e.analytics)}(f,y,v);if(!p)return;const w=(null==e?void 0:e.settings)||{},I=function(t,n){const e=n.consent;if(!e||0===Object.keys(e).length)return;const o=t.consent;if(!i(o))return;const r={};for(const[t,n]of Object.entries(e))t in o&&(r[n]=!0===o[t]);return 0!==Object.keys(r).length?{context:{consent:{categoryPreferences:r}}}:void 0}(t,y);if(void 0!==w.reset){("boolean"==typeof w.reset?w.reset:await d(t,w.reset,{collector:c}))&&(p.reset(),v.lastIdentity={},v.lastGroup={})}const O=null!=(l=w.identify)?l:y.identify;if(void 0!==O){const n=await d(t,O,{collector:c});i(n)&&function(t,n,e,r){var s;const c=e.lastIdentity||{},l=a(n.userId)?n.userId:void 0,u=a(n.anonymousId)?n.anonymousId:void 0,d=i(n.traits)&&!o(n.traits)?n.traits:void 0;u&&u!==c.anonymousId&&t.setAnonymousId(u);const f=b(d),y=l!==c.userId,v=f!==(null!=(s=c.traitsHash)?s:"");(y||void 0!==d&&v||u)&&(r?t.identify(l,d||{},r):t.identify(l,d||{}),e.lastIdentity={userId:l,anonymousId:null!=u?u:c.anonymousId,traitsHash:f})}(p,n,v,I)}const j=null!=(u=w.group)?u:y.group;if(void 0!==j){const n=await d(t,j,{collector:c});i(n)&&function(t,n,e,r){var s;const c=a(n.groupId)?n.groupId:void 0;if(!c)return;const l=i(n.traits)&&!o(n.traits)?n.traits:void 0,u=e.lastGroup||{},d=b(l),f=c!==u.groupId,y=d!==(null!=(s=u.traitsHash)?s:"");(f||y)&&(r?t.group(c,l||{},r):t.group(c,l||{}),e.lastGroup={groupId:c,traitsHash:d})}(p,n,v,I)}if(void 0!==w.page&&await async function(t,n,e,r,s){if(!0===n)return void(s?t.page(void 0,void 0,void 0,s):t.page());const c=await d(e,n,{collector:r});if(!i(c))return;const l=c,u=a(l.category)?l.category:void 0,f=a(l.name)?l.name:void 0,y=i(l.properties)&&!o(l.properties)?l.properties:void 0;s?t.page(null!=u?u:null,null!=f?f:null,null!=y?y:{},s):void 0!==y?t.page(null!=u?u:null,null!=f?f:null,y):void 0!==f||void 0!==u?t.page(null!=u?u:null,null!=f?f:null):t.page()}(p,w.page,t,c,I),!0!==(null==e?void 0:e.silent)){const n=a(null==e?void 0:e.name)?e.name:t.name,o=i(s)?s:{};I?p.track(n,o,I):p.track(n,o)}y._state=v},on(t,n){var e,o;if("consent"!==t||!n.data)return;const r=n.data,i=null==(e=n.config)?void 0:e.consent;if(!i||0===Object.keys(i).length)return;const a=(null==(o=n.config)?void 0:o.settings)||{},s=a._state||{},c=g(n.env);Object.keys(i).every(t=>!0===r[t])&&!s.loaded&&(s.analytics=m(c,a),s.loaded=!0,a._state=s)}},I=w;export{v as DestinationSegment,I as default,w as destinationSegment};//# 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, isArray, isObject, isString } from '@walkeros/core';\nimport { AnalyticsBrowser } from '@segment/analytics-next';\nimport type {\n Destination,\n Env,\n RuntimeState,\n SegmentAnalytics,\n SegmentEventOptions,\n SegmentSDK,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationSegment from './types';\n\n/**\n * Real-SDK adapter — wraps AnalyticsBrowser's static load() in our\n * SegmentSDK shape so `env?.analytics ?? realSegment` works.\n *\n * Task 1 confirmed AnalyticsBrowser.load(settings, options) returns an\n * AnalyticsBrowser instance that exposes track/identify/group/page/...\n * The returned instance buffers method calls pre-load and replays them\n * once the internal load promise resolves.\n */\nconst realSegment: SegmentSDK = {\n load: (settings, options) =>\n AnalyticsBrowser.load(settings, options) as unknown as SegmentAnalytics,\n};\n\nfunction getSegment(env: Env | undefined): SegmentSDK {\n return env?.analytics ?? realSegment;\n}\n\n/**\n * Call sdk.load() with destructured Segment settings. Strips walkerOS-\n * specific keys from the options arg passed to the real SDK.\n */\nfunction loadAnalytics(sdk: SegmentSDK, settings: Settings): SegmentAnalytics {\n const {\n apiKey,\n identify: _identify,\n group: _group,\n consent: _consent,\n _state: _existingState,\n ...initOptions\n } = settings;\n\n // Apply walkerOS defaults that differ from Segment defaults.\n const options = {\n initialPageview: false,\n ...initOptions,\n };\n\n return sdk.load({ writeKey: apiKey }, options);\n}\n\n/**\n * Resolve the live analytics instance, loading on demand if deferred.\n * Returns undefined if load() was deferred and consent hasn't fired yet.\n */\nfunction resolveAnalytics(\n sdk: SegmentSDK,\n settings: Settings,\n state: RuntimeState,\n): SegmentAnalytics | undefined {\n if (state.analytics) return state.analytics;\n if (state.loaded) return undefined;\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n return state.analytics;\n}\n\n/**\n * Stable hash of a traits object for state-diffing. Uses a deterministic\n * JSON stringify — key order matters but is consistent within a session\n * because object literal keys come in insertion order.\n */\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\n/**\n * Build the Segment event options object with consent context from the\n * current walker consent state. Returns undefined unless the user has\n * explicitly opted in by configuring `settings.consent` — this keeps the\n * consent forwarding feature off-by-default so events stay clean.\n *\n * `settings.consent` maps walkerOS consent keys → Segment category names.\n * Only walker keys present in the mapping are forwarded.\n */\nfunction buildEventOptions(\n event: WalkerOS.Event,\n settings: Settings,\n): SegmentEventOptions | undefined {\n const map = settings.consent;\n if (!map || Object.keys(map).length === 0) return undefined;\n\n const consentState = event.consent;\n if (!isObject(consentState)) return undefined;\n\n const categoryPreferences: Record<string, boolean> = {};\n for (const [walkerKey, segmentKey] of Object.entries(map)) {\n if (walkerKey in consentState) {\n categoryPreferences[segmentKey] = consentState[walkerKey] === true;\n }\n }\n\n if (Object.keys(categoryPreferences).length === 0) return undefined;\n\n return {\n context: {\n consent: {\n categoryPreferences,\n },\n },\n };\n}\n\n/**\n * Resolve and apply identity mapping. Calls analytics.identify() only\n * when the resolved value differs from the last-fired identity.\n */\nfunction applyIdentify(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const last = state.lastIdentity || {};\n const userId = isString(resolved.userId) ? resolved.userId : undefined;\n const anonymousId = isString(resolved.anonymousId)\n ? resolved.anonymousId\n : undefined;\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n if (anonymousId && anonymousId !== last.anonymousId) {\n analytics.setAnonymousId(anonymousId);\n }\n\n const traitsHash = hashTraits(traits);\n const userIdChanged = userId !== last.userId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n const hasChange = userIdChanged || (traits !== undefined && traitsChanged);\n\n if (!hasChange && !anonymousId) return;\n\n if (options) {\n analytics.identify(userId, traits || {}, options);\n } else {\n analytics.identify(userId, traits || {});\n }\n\n state.lastIdentity = {\n userId,\n anonymousId: anonymousId ?? last.anonymousId,\n traitsHash,\n };\n}\n\nfunction applyGroup(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const groupId = isString(resolved.groupId) ? resolved.groupId : undefined;\n if (!groupId) return;\n\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n const last = state.lastGroup || {};\n const traitsHash = hashTraits(traits);\n const groupIdChanged = groupId !== last.groupId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n if (!groupIdChanged && !traitsChanged) return;\n\n if (options) {\n analytics.group(groupId, traits || {}, options);\n } else {\n analytics.group(groupId, traits || {});\n }\n\n state.lastGroup = { groupId, traitsHash };\n}\n\nasync function applyPage(\n analytics: SegmentAnalytics,\n pageMapping: unknown,\n event: WalkerOS.Event,\n collector: unknown,\n options?: SegmentEventOptions,\n): Promise<void> {\n // Boolean true → call page() with no args (SDK auto-collect).\n if (pageMapping === true) {\n if (options) {\n analytics.page(undefined, undefined, undefined, options);\n } else {\n analytics.page();\n }\n return;\n }\n\n const resolved = await getMappingValue(\n event,\n pageMapping as Parameters<typeof getMappingValue>[1],\n { collector } as Parameters<typeof getMappingValue>[2],\n );\n if (!isObject(resolved)) return;\n\n const r = resolved as {\n category?: unknown;\n name?: unknown;\n properties?: unknown;\n };\n const category = isString(r.category) ? r.category : undefined;\n const name = isString(r.name) ? r.name : undefined;\n const properties =\n isObject(r.properties) && !isArray(r.properties)\n ? (r.properties as Record<string, unknown>)\n : undefined;\n\n if (options) {\n analytics.page(category ?? null, name ?? null, properties ?? {}, options);\n } else if (properties !== undefined) {\n analytics.page(category ?? null, name ?? null, properties);\n } else if (name !== undefined || category !== undefined) {\n analytics.page(category ?? null, name ?? null);\n } else {\n analytics.page();\n }\n}\n\nexport const destinationSegment: Destination = {\n type: 'segment',\n\n config: {},\n\n init({ config, env }) {\n if (!config.settings?.apiKey) return false;\n const settings = config.settings as Settings;\n\n const sdk = getSegment(env as Env | undefined);\n const _state: RuntimeState = {\n lastIdentity: {},\n lastGroup: {},\n loaded: false,\n };\n\n // If config.consent is declared, defer load() until on('consent').\n // Otherwise load immediately.\n const requiresConsent =\n !!config.consent && Object.keys(config.consent).length > 0;\n\n if (!requiresConsent) {\n _state.analytics = loadAnalytics(sdk, settings);\n _state.loaded = true;\n }\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, data, collector }) {\n const sdk = getSegment(env as Env | undefined);\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const analytics = resolveAnalytics(sdk, settings, state);\n if (!analytics) return;\n\n const mappingSettings = rule?.settings || {};\n const options = buildEventOptions(event, settings);\n\n // 1. Reset fires first so subsequent identity calls start clean.\n if (mappingSettings.reset !== undefined) {\n const resolved =\n typeof mappingSettings.reset === 'boolean'\n ? mappingSettings.reset\n : await getMappingValue(event, mappingSettings.reset, { collector });\n if (resolved) {\n analytics.reset();\n state.lastIdentity = {};\n state.lastGroup = {};\n }\n }\n\n // 2. Identity — 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 applyIdentify(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 3. Group — rule-level override wins over destination-level.\n const groupMapping = mappingSettings.group ?? settings.group;\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n applyGroup(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 4. Page (explicit first-class Segment pattern)\n if (mappingSettings.page !== undefined) {\n await applyPage(\n analytics,\n mappingSettings.page,\n event,\n collector,\n options,\n );\n }\n\n // 5. Default track call 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)\n ? (data as Record<string, unknown>)\n : {};\n\n if (options) {\n analytics.track(eventName, properties, options);\n } else {\n analytics.track(eventName, properties);\n }\n }\n\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const sdk = getSegment(context.env as Env | undefined);\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n if (allGranted && !state.loaded) {\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n settings._state = state;\n }\n // If not all granted, walkerOS's config.consent gate blocks subsequent\n // push() calls — no SDK action needed (Segment has no opt-out method).\n },\n};\n\nexport default destinationSegment;\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationWeb } from '@walkeros/web-core';\nimport type {\n AnalyticsBrowserSettings,\n InitOptions,\n} from '@segment/analytics-next';\n\n/**\n * Destination-level settings.\n *\n * Extends Segment's `InitOptions` (minus the `group` key which clashes with\n * walkerOS's own `group` mapping) so every passthrough option (cookie,\n * storage, integrations, plan, etc.) keeps IntelliSense intact. walkerOS\n * adds:\n * - `apiKey` (required) — maps to `writeKey` in `AnalyticsBrowser.load()`\n * - `identify` — destination-level identity mapping (Segment `identify()`)\n * - `group` — destination-level group mapping (Segment `group()`)\n * - `include` — event sections flattened into track `properties`\n * - `consent` — walkerOS consent key → Segment category name mapping\n * - `_state` — runtime state (not user-facing, mutated by init/push)\n */\nexport interface Settings extends Omit<InitOptions, 'group'> {\n /** Segment write key. Maps to `writeKey` in the load() settings arg. */\n apiKey: string;\n /** walkerOS mapping value resolving to an identity object (userId, traits, anonymousId). */\n identify?: WalkerOSMapping.Value;\n /** walkerOS mapping value resolving to a group object (groupId, traits). */\n group?: WalkerOSMapping.Value;\n /**\n * Mapping from walkerOS consent keys → Segment `categoryPreferences` keys.\n * Example: { marketing: \"Advertising\", analytics: \"Analytics\" }\n * If omitted, walkerOS keys are forwarded 1:1.\n */\n consent?: Record<string, string>;\n /** Runtime state — populated by init() and mutated by push(). Not user-facing. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** Last-set identity values, used to skip redundant identify() calls. */\n lastIdentity?: {\n userId?: string;\n anonymousId?: string;\n traitsHash?: string;\n };\n /** Last-set group assignment, used to skip redundant group() calls. */\n lastGroup?: {\n groupId?: string;\n traitsHash?: string;\n };\n /** Holds the AnalyticsBrowser instance created in init(). */\n analytics?: SegmentAnalytics;\n /** True once load() has been called (may be deferred pending consent). */\n loaded?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Every feature here is a walkerOS mapping\n * value resolved via getMappingValue(). The resolved object's keys drive\n * which Segment SDK methods to call.\n */\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n page?: WalkerOSMapping.Value | boolean;\n reset?: WalkerOSMapping.Value | boolean;\n}\n\n/**\n * Segment SDK surface — the subset of @segment/analytics-next the\n * destination actually uses. Mirrors the AnalyticsBrowser instance shape\n * so tests can mock each method individually via env.analytics.\n */\nexport interface SegmentAnalytics {\n track: (\n event: string,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n identify: (\n userId?: string | Record<string, unknown>,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n group: (\n groupId: string,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n page: (\n category?: string | null,\n name?: string | null,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n alias: (\n to: string,\n from?: string,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n reset: () => Promise<unknown> | void;\n setAnonymousId: (id: string) => Promise<unknown> | void;\n}\n\n/**\n * Segment event options — the fourth argument to track/identify/group/page\n * that carries context and integration overrides. The destination uses\n * this to stamp consent context on every event.\n */\nexport interface SegmentEventOptions {\n context?: {\n consent?: {\n categoryPreferences?: Record<string, boolean>;\n };\n [key: string]: unknown;\n };\n integrations?: Record<string, boolean | Record<string, unknown>>;\n}\n\n/**\n * The module namespace used for `env?.analytics ?? realSegment`.\n * AnalyticsBrowser is the class; tests mock with a factory that returns\n * an object matching SegmentAnalytics.\n *\n * Task 1 verified: `AnalyticsBrowser.load(settings, options)` returns an\n * `AnalyticsBrowser` instance **synchronously**. The instance buffers\n * method calls until the internal load promise resolves.\n */\nexport interface SegmentSDK {\n load: (\n settings: AnalyticsBrowserSettings,\n options?: InitOptions,\n ) => SegmentAnalytics;\n}\n\n/**\n * Env — optional SDK override. Production leaves this undefined and the\n * destination falls back to the real @segment/analytics-next module.\n * Tests provide a mock via env.analytics = { ... }.\n */\nexport interface Env extends DestinationWeb.Env {\n analytics?: SegmentSDK;\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 interface SegmentDestination extends Destination {\n env?: Env;\n}\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":"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","names":["e"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport { getMappingValue, isArray, isObject, isString } from '@walkeros/core';\nimport { AnalyticsBrowser } from '@segment/analytics-next';\nimport type {\n Destination,\n Env,\n RuntimeState,\n SegmentAnalytics,\n SegmentEventOptions,\n SegmentSDK,\n Settings,\n} from './types';\n\n// Types export\nexport * as DestinationSegment from './types';\n\n/**\n * Real-SDK adapter - wraps AnalyticsBrowser's static load() in our\n * SegmentSDK shape so `env?.analytics ?? realSegment` works.\n *\n * Task 1 confirmed AnalyticsBrowser.load(settings, options) returns an\n * AnalyticsBrowser instance that exposes track/identify/group/page/...\n * The returned instance buffers method calls pre-load and replays them\n * once the internal load promise resolves.\n */\nconst realSegment: SegmentSDK = {\n load: (settings, options) =>\n AnalyticsBrowser.load(settings, options) as unknown as SegmentAnalytics,\n};\n\nfunction getSegment(env: Env | undefined): SegmentSDK {\n return env?.analytics ?? realSegment;\n}\n\n/**\n * Call sdk.load() with destructured Segment settings. Strips walkerOS-\n * specific keys from the options arg passed to the real SDK.\n */\nfunction loadAnalytics(sdk: SegmentSDK, settings: Settings): SegmentAnalytics {\n const {\n apiKey,\n identify: _identify,\n group: _group,\n consent: _consent,\n _state: _existingState,\n ...initOptions\n } = settings;\n\n // Apply walkerOS defaults that differ from Segment defaults.\n const options = {\n initialPageview: false,\n ...initOptions,\n };\n\n return sdk.load({ writeKey: apiKey }, options);\n}\n\n/**\n * Resolve the live analytics instance, loading on demand if deferred.\n * Returns undefined if load() was deferred and consent hasn't fired yet.\n */\nfunction resolveAnalytics(\n sdk: SegmentSDK,\n settings: Settings,\n state: RuntimeState,\n): SegmentAnalytics | undefined {\n if (state.analytics) return state.analytics;\n if (state.loaded) return undefined;\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n return state.analytics;\n}\n\n/**\n * Stable hash of a traits object for state-diffing. Uses a deterministic\n * JSON stringify - key order matters but is consistent within a session\n * because object literal keys come in insertion order.\n */\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\n/**\n * Build the Segment event options object with consent context from the\n * current walker consent state. Returns undefined unless the user has\n * explicitly opted in by configuring `settings.consent` - this keeps the\n * consent forwarding feature off-by-default so events stay clean.\n *\n * `settings.consent` maps walkerOS consent keys → Segment category names.\n * Only walker keys present in the mapping are forwarded.\n */\nfunction buildEventOptions(\n event: WalkerOS.Event,\n settings: Settings,\n): SegmentEventOptions | undefined {\n const map = settings.consent;\n if (!map || Object.keys(map).length === 0) return undefined;\n\n const consentState = event.consent;\n if (!isObject(consentState)) return undefined;\n\n const categoryPreferences: Record<string, boolean> = {};\n for (const [walkerKey, segmentKey] of Object.entries(map)) {\n if (walkerKey in consentState) {\n categoryPreferences[segmentKey] = consentState[walkerKey] === true;\n }\n }\n\n if (Object.keys(categoryPreferences).length === 0) return undefined;\n\n return {\n context: {\n consent: {\n categoryPreferences,\n },\n },\n };\n}\n\n/**\n * Resolve and apply identity mapping. Calls analytics.identify() only\n * when the resolved value differs from the last-fired identity.\n */\nfunction applyIdentify(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const last = state.lastIdentity || {};\n const userId = isString(resolved.userId) ? resolved.userId : undefined;\n const anonymousId = isString(resolved.anonymousId)\n ? resolved.anonymousId\n : undefined;\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n if (anonymousId && anonymousId !== last.anonymousId) {\n analytics.setAnonymousId(anonymousId);\n }\n\n const traitsHash = hashTraits(traits);\n const userIdChanged = userId !== last.userId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n const hasChange = userIdChanged || (traits !== undefined && traitsChanged);\n\n if (!hasChange && !anonymousId) return;\n\n if (options) {\n analytics.identify(userId, traits || {}, options);\n } else {\n analytics.identify(userId, traits || {});\n }\n\n state.lastIdentity = {\n userId,\n anonymousId: anonymousId ?? last.anonymousId,\n traitsHash,\n };\n}\n\nfunction applyGroup(\n analytics: SegmentAnalytics,\n resolved: Record<string, unknown>,\n state: RuntimeState,\n options?: SegmentEventOptions,\n): void {\n const groupId = isString(resolved.groupId) ? resolved.groupId : undefined;\n if (!groupId) return;\n\n const traits =\n isObject(resolved.traits) && !isArray(resolved.traits)\n ? (resolved.traits as Record<string, unknown>)\n : undefined;\n\n const last = state.lastGroup || {};\n const traitsHash = hashTraits(traits);\n const groupIdChanged = groupId !== last.groupId;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n if (!groupIdChanged && !traitsChanged) return;\n\n if (options) {\n analytics.group(groupId, traits || {}, options);\n } else {\n analytics.group(groupId, traits || {});\n }\n\n state.lastGroup = { groupId, traitsHash };\n}\n\nasync function applyPage(\n analytics: SegmentAnalytics,\n pageMapping: unknown,\n event: WalkerOS.Event,\n collector: unknown,\n options?: SegmentEventOptions,\n): Promise<void> {\n // Boolean true → call page() with no args (SDK auto-collect).\n if (pageMapping === true) {\n if (options) {\n analytics.page(undefined, undefined, undefined, options);\n } else {\n analytics.page();\n }\n return;\n }\n\n const resolved = await getMappingValue(\n event,\n pageMapping as Parameters<typeof getMappingValue>[1],\n { collector } as Parameters<typeof getMappingValue>[2],\n );\n if (!isObject(resolved)) return;\n\n const r = resolved as {\n category?: unknown;\n name?: unknown;\n properties?: unknown;\n };\n const category = isString(r.category) ? r.category : undefined;\n const name = isString(r.name) ? r.name : undefined;\n const properties =\n isObject(r.properties) && !isArray(r.properties)\n ? (r.properties as Record<string, unknown>)\n : undefined;\n\n if (options) {\n analytics.page(category ?? null, name ?? null, properties ?? {}, options);\n } else if (properties !== undefined) {\n analytics.page(category ?? null, name ?? null, properties);\n } else if (name !== undefined || category !== undefined) {\n analytics.page(category ?? null, name ?? null);\n } else {\n analytics.page();\n }\n}\n\nexport const destinationSegment: Destination = {\n type: 'segment',\n\n config: {},\n\n init({ config, env }) {\n if (!config.settings?.apiKey) return false;\n const settings = config.settings as Settings;\n\n const sdk = getSegment(env as Env | undefined);\n const _state: RuntimeState = {\n lastIdentity: {},\n lastGroup: {},\n loaded: false,\n };\n\n // If config.consent is declared, defer load() until on('consent').\n // Otherwise load immediately.\n const requiresConsent =\n !!config.consent && Object.keys(config.consent).length > 0;\n\n if (!requiresConsent) {\n _state.analytics = loadAnalytics(sdk, settings);\n _state.loaded = true;\n }\n\n return { ...config, settings: { ...settings, _state } };\n },\n\n async push(event, { config, rule, env, data, collector }) {\n const sdk = getSegment(env as Env | undefined);\n const settings = (config.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const analytics = resolveAnalytics(sdk, settings, state);\n if (!analytics) return;\n\n const mappingSettings = rule?.settings || {};\n const options = buildEventOptions(event, settings);\n\n // 1. Reset fires first so subsequent identity calls start clean.\n if (mappingSettings.reset !== undefined) {\n const resolved =\n typeof mappingSettings.reset === 'boolean'\n ? mappingSettings.reset\n : await getMappingValue(event, mappingSettings.reset, { collector });\n if (resolved) {\n analytics.reset();\n state.lastIdentity = {};\n state.lastGroup = {};\n }\n }\n\n // 2. Identity - 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 applyIdentify(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 3. Group - rule-level override wins over destination-level.\n const groupMapping = mappingSettings.group ?? settings.group;\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n applyGroup(\n analytics,\n resolved as Record<string, unknown>,\n state,\n options,\n );\n }\n }\n\n // 4. Page (explicit first-class Segment pattern)\n if (mappingSettings.page !== undefined) {\n await applyPage(\n analytics,\n mappingSettings.page,\n event,\n collector,\n options,\n );\n }\n\n // 5. Default track call unless rule opts out via silent.\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\n if (options) {\n analytics.track(eventName, properties, options);\n } else {\n analytics.track(eventName, properties);\n }\n }\n\n settings._state = state;\n },\n\n on(type, context) {\n if (type !== 'consent' || !context.data) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = context.config?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const state: RuntimeState = settings._state || {};\n const sdk = getSegment(context.env as Env | undefined);\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n\n if (allGranted && !state.loaded) {\n state.analytics = loadAnalytics(sdk, settings);\n state.loaded = true;\n settings._state = state;\n }\n // If not all granted, walkerOS's config.consent gate blocks subsequent\n // push() calls - no SDK action needed (Segment has no opt-out method).\n },\n};\n\nexport default destinationSegment;\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationWeb } from '@walkeros/web-core';\nimport type {\n AnalyticsBrowserSettings,\n InitOptions,\n} from '@segment/analytics-next';\n\n/**\n * Destination-level settings.\n *\n * Extends Segment's `InitOptions` (minus the `group` key which clashes with\n * walkerOS's own `group` mapping) so every passthrough option (cookie,\n * storage, integrations, plan, etc.) keeps IntelliSense intact. walkerOS\n * adds:\n * - `apiKey` (required) — maps to `writeKey` in `AnalyticsBrowser.load()`\n * - `identify` — destination-level identity mapping (Segment `identify()`)\n * - `group` — destination-level group mapping (Segment `group()`)\n * - `include` — event sections flattened into track `properties`\n * - `consent` — walkerOS consent key → Segment category name mapping\n * - `_state` — runtime state (not user-facing, mutated by init/push)\n */\nexport interface Settings extends Omit<InitOptions, 'group'> {\n /** Segment write key. Maps to `writeKey` in the load() settings arg. */\n apiKey: string;\n /** walkerOS mapping value resolving to an identity object (userId, traits, anonymousId). */\n identify?: WalkerOSMapping.Value;\n /** walkerOS mapping value resolving to a group object (groupId, traits). */\n group?: WalkerOSMapping.Value;\n /**\n * Mapping from walkerOS consent keys → Segment `categoryPreferences` keys.\n * Example: { marketing: \"Advertising\", analytics: \"Analytics\" }\n * If omitted, walkerOS keys are forwarded 1:1.\n */\n consent?: Record<string, string>;\n /** Runtime state — populated by init() and mutated by push(). Not user-facing. */\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n /** Last-set identity values, used to skip redundant identify() calls. */\n lastIdentity?: {\n userId?: string;\n anonymousId?: string;\n traitsHash?: string;\n };\n /** Last-set group assignment, used to skip redundant group() calls. */\n lastGroup?: {\n groupId?: string;\n traitsHash?: string;\n };\n /** Holds the AnalyticsBrowser instance created in init(). */\n analytics?: SegmentAnalytics;\n /** True once load() has been called (may be deferred pending consent). */\n loaded?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Every feature here is a walkerOS mapping\n * value resolved via getMappingValue(). The resolved object's keys drive\n * which Segment SDK methods to call.\n */\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n page?: WalkerOSMapping.Value | boolean;\n reset?: WalkerOSMapping.Value | boolean;\n}\n\n/**\n * Segment SDK surface — the subset of @segment/analytics-next the\n * destination actually uses. Mirrors the AnalyticsBrowser instance shape\n * so tests can mock each method individually via env.analytics.\n */\nexport interface SegmentAnalytics {\n track: (\n event: string,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n identify: (\n userId?: string | Record<string, unknown>,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n group: (\n groupId: string,\n traits?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n page: (\n category?: string | null,\n name?: string | null,\n properties?: Record<string, unknown>,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n alias: (\n to: string,\n from?: string,\n options?: SegmentEventOptions,\n ) => Promise<unknown> | void;\n reset: () => Promise<unknown> | void;\n setAnonymousId: (id: string) => Promise<unknown> | void;\n}\n\n/**\n * Segment event options — the fourth argument to track/identify/group/page\n * that carries context and integration overrides. The destination uses\n * this to stamp consent context on every event.\n */\nexport interface SegmentEventOptions {\n context?: {\n consent?: {\n categoryPreferences?: Record<string, boolean>;\n };\n [key: string]: unknown;\n };\n integrations?: Record<string, boolean | Record<string, unknown>>;\n}\n\n/**\n * The module namespace used for `env?.analytics ?? realSegment`.\n * AnalyticsBrowser is the class; tests mock with a factory that returns\n * an object matching SegmentAnalytics.\n *\n * Task 1 verified: `AnalyticsBrowser.load(settings, options)` returns an\n * `AnalyticsBrowser` instance **synchronously**. The instance buffers\n * method calls until the internal load promise resolves.\n */\nexport interface SegmentSDK {\n load: (\n settings: AnalyticsBrowserSettings,\n options?: InitOptions,\n ) => SegmentAnalytics;\n}\n\n/**\n * Env — optional SDK override. Production leaves this undefined and the\n * destination falls back to the real @segment/analytics-next module.\n * Tests provide a mock via env.analytics = { ... }.\n */\nexport interface Env extends DestinationWeb.Env {\n analytics?: SegmentSDK;\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 interface SegmentDestination extends Destination {\n env?: Env;\n}\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":"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","names":["e"]}
|