@walkeros/web-source-cmp-usercentrics 3.0.2 → 4.0.0-next-1773967844643
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.d.mts +14 -5
- package/dist/dev.d.ts +14 -5
- 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 +12 -4
- package/dist/examples/index.d.ts +12 -4
- package/dist/examples/index.js +34 -7
- package/dist/examples/index.mjs +31 -5
- package/dist/index.browser.js +1 -1
- package/dist/index.d.mts +12 -4
- package/dist/index.d.ts +12 -4
- 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 +25 -5
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,a=(e,n)=>{for(var o in n)t(e,o,{get:n[o],enumerable:!0})},
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,a=(e,n)=>{for(var o in n)t(e,o,{get:n[o],enumerable:!0})},l={};a(l,{SourceUsercentrics:()=>s,createMockElbFn:()=>E,createTrigger:()=>M,default:()=>U,fullConsent:()=>r,fullConsentCustomMapped:()=>C,fullConsentMapped:()=>f,fullConsentUpperCase:()=>p,implicitConsent:()=>g,minimalConsent:()=>u,minimalConsentMapped:()=>d,nonConsentEvent:()=>y,noopLogger:()=>b,partialConsent:()=>c,partialConsentMapped:()=>m,serviceLevelConsent:()=>v,serviceLevelMapped:()=>k,sourceUsercentrics:()=>G,step:()=>_,trigger:()=>N}),module.exports=(e=l,((e,a,l,s)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let r of o(a))i.call(e,r)||r===l||t(e,r,{get:()=>a[r],enumerable:!(s=n(a,r))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={},r={event:"consent_status",type:"explicit",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0},"Google Analytics":!0,"Google Ads Remarketing":!0},c={event:"consent_status",type:"explicit",action:"onUpdateServices",ucCategory:{essential:!0,functional:!0,marketing:!1},"Google Analytics":!0,"Google Ads Remarketing":!1},u={event:"consent_status",type:"explicit",action:"onDenyAllServices",ucCategory:{essential:!0,functional:!1,marketing:!1},"Google Analytics":!1,"Google Ads Remarketing":!1},g={event:"consent_status",type:"implicit",ucCategory:{essential:!0,functional:!1,marketing:!1},"Google Analytics":!1,"Google Ads Remarketing":!1},p={event:"consent_status",type:"EXPLICIT",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0}},v={event:"consent_status",type:"explicit",action:"onUpdateServices",ucCategory:{essential:!0,functional:"partial",marketing:"partial"},"Google Analytics":!0,"Google Ads Remarketing":!1,Hotjar:!0},y={event:"other_event",type:"explicit"},f={essential:!0,functional:!0,marketing:!0},m={essential:!0,functional:!0,marketing:!1},d={essential:!0,functional:!1,marketing:!1},C={functional:!0,marketing:!0},k={essential:!0,google_analytics:!0,google_ads_remarketing:!1,hotjar:!0},w=()=>{},E=()=>()=>Promise.resolve({ok:!0}),b={error:w,warn:w,info:w,debug:w,throw:e=>{throw"string"==typeof e?new Error(e):e},json:w,scope:()=>b},_={};a(_,{categoryMapOverride:()=>h,customEventName:()=>j,fullConsent:()=>A,minimalConsent:()=>O});var A={trigger:{type:"consent"},in:{event:"consent_status",type:"explicit",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0}},out:{essential:!0,functional:!0,marketing:!0}},O={trigger:{type:"consent"},in:{event:"consent_status",type:"explicit",action:"onDenyAllServices",ucCategory:{essential:!0,functional:!1,marketing:!1}},out:{essential:!0,functional:!1,marketing:!1}},h={description:"Custom categoryMap remaps essential to functional and functional to analytics",trigger:{type:"consent"},in:{event:"consent_status",type:"explicit",ucCategory:{essential:!0,functional:!0,marketing:!1}},mapping:{categoryMap:{essential:"functional",functional:"analytics"}},out:{functional:!0,analytics:!0,marketing:!1}},j={description:"Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2",trigger:{type:"consent",options:{eventName:"UC_SDK_EVENT"}},in:{event:"consent_status",type:"explicit",ucCategory:{essential:!0,functional:!0,marketing:!0}},mapping:{eventName:"UC_SDK_EVENT"},out:{essential:!0,functional:!0,marketing:!0}},x=require("@walkeros/collector"),M=async e=>{let t;return{get flow(){return t},trigger:(n,o)=>async n=>{var i;if(!t){const n=await(0,x.startFlow)({...e,run:null==(i=e.run)||i});t={collector:n.collector,elb:n.elb}}const a=(null==o?void 0:o.eventName)||"ucEvent";window.dispatchEvent(new CustomEvent(a,{detail:n}))}}},N=(e,t)=>{if(e&&"object"==typeof e)return()=>{t.window.dispatchEvent(new CustomEvent("ucEvent",{detail:e}))}},S=["action","event","type","ucCategory"],G=async e=>{var t,n,o,i,a,l,s,r;const{config:c,env:u}=e,{elb:g}=u,p=null!=(t=u.window)?t:void 0!==globalThis.window?globalThis.window:void 0,v={eventName:null!=(o=null==(n=null==c?void 0:c.settings)?void 0:n.eventName)?o:"ucEvent",categoryMap:null!=(a=null==(i=null==c?void 0:c.settings)?void 0:i.categoryMap)?a:{},explicitOnly:null==(s=null==(l=null==c?void 0:c.settings)?void 0:l.explicitOnly)||s},y={settings:v};let f;if(p){const e=e=>Object.values(e).every(e=>"boolean"==typeof e),t=t=>{const n={};return t.ucCategory&&e(t.ucCategory)?Object.entries(t.ucCategory).forEach(([e,t])=>{var o,i;if("boolean"!=typeof t)return;const a=null!=(i=null==(o=v.categoryMap)?void 0:o[e])?i:e;n[a]=n[a]||t}):(t.ucCategory&&Object.entries(t.ucCategory).forEach(([e,t])=>{var o,i;if("boolean"==typeof t){const a=null!=(i=null==(o=v.categoryMap)?void 0:o[e])?i:e;n[a]=n[a]||t}}),Object.entries(t).forEach(([e,t])=>{if(S.includes(e))return;if("boolean"!=typeof t)return;const o=e.toLowerCase().replace(/ /g,"_");n[o]=t})),n},n=e=>{var n;if("consent_status"!==e.event)return;if(v.explicitOnly&&"explicit"!==(null==(n=e.type)?void 0:n.toLowerCase()))return;const o=t(e);Object.keys(o).length>0&&g("walker consent",o)},o=null!=(r=v.eventName)?r:"ucEvent";f=e=>{const t=e;t.detail&&n(t.detail)},p.addEventListener(o,f)}return{type:"usercentrics",config:y,push:g,destroy:async e=>{var t;if(p&&f){const e=null!=(t=v.eventName)?t:"ucEvent";p.removeEventListener(e,f)}}}},U=G;//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/examples/inputs.ts","../src/examples/outputs.ts","../src/examples/env.ts","../src/examples/step.ts","../src/examples/setup.ts"],"sourcesContent":["import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, UsercentricsEventDetail } from './types';\n\n// Export types for external usage\nexport * as SourceUsercentrics from './types';\n\n// Export examples\nexport * from './examples';\n\n/** Reserved keys in event.detail that are not service names */\nconst RESERVED_KEYS = ['action', 'event', 'type', 'ucCategory'];\n\n/**\n * Usercentrics consent management source for walkerOS.\n *\n * This source listens to Usercentrics CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * @example\n * ```typescript\n * import { sourceUsercentrics } from '@walkeros/web-source-cmp-usercentrics';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceUsercentrics,\n * config: {\n * settings: {\n * eventName: 'ucEvent',\n * categoryMap: {\n * essential: 'functional',\n * functional: 'functional',\n * marketing: 'marketing',\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceUsercentrics: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb } = env;\n\n // Resolve window with fallback to globalThis\n const actualWindow =\n env.window ??\n (typeof globalThis.window !== 'undefined' ? globalThis.window : undefined);\n\n // Merge user settings with defaults\n const settings: Settings = {\n eventName: config?.settings?.eventName ?? 'ucEvent',\n categoryMap: config?.settings?.categoryMap ?? {},\n explicitOnly: config?.settings?.explicitOnly ?? true,\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track listener reference for cleanup\n let consentListener: ((e: Event) => void) | undefined;\n\n // Only setup if in browser environment\n if (actualWindow) {\n /**\n * Determine if ucCategory represents group-level consent.\n * Group-level: all values are booleans.\n * Service-level: some values are non-boolean (e.g., 'partial').\n */\n const isGroupLevel = (\n ucCategory: Record<string, boolean | unknown>,\n ): boolean => {\n return Object.values(ucCategory).every((val) => typeof val === 'boolean');\n };\n\n /**\n * Parse consent from Usercentrics event detail.\n *\n * Two modes:\n * 1. Group-level: ucCategory has all booleans -> use ucCategory as consent\n * 2. Service-level: ucCategory has non-booleans -> extract individual\n * service keys from event.detail + boolean entries from ucCategory\n *\n * categoryMap is applied in both modes for ucCategory boolean entries.\n */\n const parseConsent = (\n detail: UsercentricsEventDetail,\n ): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n if (detail.ucCategory && isGroupLevel(detail.ucCategory)) {\n // Group-level consent: use ucCategory values\n Object.entries(detail.ucCategory).forEach(([category, value]) => {\n if (typeof value !== 'boolean') return;\n const mapped = settings.categoryMap?.[category] ?? category;\n // OR logic: if ANY source category is true, target group is true\n state[mapped] = state[mapped] || value;\n });\n } else {\n // Service-level consent: extract individual services\n // Include boolean entries from ucCategory (with categoryMap applied)\n if (detail.ucCategory) {\n Object.entries(detail.ucCategory).forEach(([key, value]) => {\n if (typeof value === 'boolean') {\n const mapped = settings.categoryMap?.[key] ?? key;\n state[mapped] = state[mapped] || value;\n }\n });\n }\n\n // Extract service keys (not reserved keys)\n Object.entries(detail).forEach(([key, value]) => {\n if (RESERVED_KEYS.includes(key)) return;\n if (typeof value !== 'boolean') return;\n // Normalize: lowercase, spaces to underscores\n const normalized = key.toLowerCase().replace(/ /g, '_');\n state[normalized] = value;\n });\n }\n\n return state;\n };\n\n /**\n * Handle a Usercentrics consent event.\n */\n const handleConsent = (detail: UsercentricsEventDetail) => {\n // Only process consent_status events\n if (detail.event !== 'consent_status') return;\n\n // Skip implicit consent if explicitOnly is true\n // Use case-insensitive comparison (Usercentrics docs show both 'explicit' and 'EXPLICIT')\n if (settings.explicitOnly && detail.type?.toLowerCase() !== 'explicit')\n return;\n\n const state = parseConsent(detail);\n\n // Only call if we have consent state to report\n if (Object.keys(state).length > 0) {\n elb('walker consent', state);\n }\n };\n\n // Listen for Usercentrics consent events\n const eventName = settings.eventName ?? 'ucEvent';\n consentListener = (e: Event) => {\n const customEvent = e as CustomEvent<UsercentricsEventDetail>;\n if (customEvent.detail) {\n handleConsent(customEvent.detail);\n }\n };\n actualWindow.addEventListener(eventName, consentListener);\n }\n\n return {\n type: 'usercentrics',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n if (actualWindow && consentListener) {\n const eventName = settings.eventName ?? 'ucEvent';\n actualWindow.removeEventListener(eventName, consentListener);\n }\n },\n };\n};\n\nexport default sourceUsercentrics;\n","import type { Source, Elb } from '@walkeros/core';\n\n/**\n * Usercentrics consent event detail structure.\n *\n * Fired as event.detail on the configured window event (e.g. 'ucEvent').\n * Contains both category-level (ucCategory) and service-level consent.\n */\nexport interface UsercentricsEventDetail {\n /** Always 'consent_status' for consent events */\n event: string;\n /** 'explicit' when user actively chose, 'implicit' for page-load defaults (casing may vary) */\n type: string;\n /** Action taken: 'onAcceptAllServices', 'onDenyAllServices', 'onUpdateServices' */\n action?: string;\n /** Category-level consent booleans (e.g. { marketing: true, functional: false }) */\n ucCategory?: Record<string, boolean | unknown>;\n /** Service-level consent as top-level keys (e.g. 'Google Analytics': true) */\n [service: string]: unknown;\n}\n\ndeclare global {\n interface WindowEventMap {\n ucEvent: CustomEvent<UsercentricsEventDetail>;\n }\n}\n\n/**\n * Settings for Usercentrics source\n */\nexport interface Settings {\n /**\n * Window event name to listen for.\n * Configured in Usercentrics admin under Implementation > Data Layer & Events.\n * Can also be set to 'UC_SDK_EVENT' for the built-in Browser SDK event.\n *\n * Default: 'ucEvent'\n */\n eventName?: string;\n\n /**\n * Map Usercentrics categories to walkerOS consent groups.\n * Keys: Usercentrics category names (from ucCategory)\n * Values: walkerOS consent group names\n *\n * Applied in both group-level and service-level consent modes.\n * When multiple source categories map to the same group, OR logic applies:\n * if ANY source category is true, the target group is true.\n *\n * Default: {} (pass through category names as-is)\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Ignores events where type !== 'explicit'\n * When false: Processes any consent_status event including implicit/defaults\n *\n * Default: true\n */\n explicitOnly?: boolean;\n}\n\n/**\n * User input settings (all optional)\n */\nexport type InitSettings = Partial<Settings>;\n\n/**\n * No mapping configuration for this source\n */\nexport interface Mapping {}\n\n/**\n * Push function type - uses elb for consent commands\n */\nexport type Push = Elb.Fn;\n\n/**\n * Environment interface for Usercentrics source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for Usercentrics source\n */\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\n/**\n * Config type alias\n */\nexport type Config = Source.Config<Types>;\n","import type { UsercentricsEventDetail } from '../types';\n\n/**\n * Example Usercentrics consent event detail inputs.\n *\n * These represent real event.detail payloads from Usercentrics CMP.\n */\n\n/**\n * Full consent - user accepted all categories (explicit)\n */\nexport const fullConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': true,\n};\n\n/**\n * Partial consent - user accepted only essential and functional (explicit)\n */\nexport const partialConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Minimal consent - user denied everything except essential (explicit)\n */\nexport const minimalConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Implicit consent - page load with default consent state\n * (not an explicit user choice)\n */\nexport const implicitConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'implicit',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Explicit consent with uppercase type field (Usercentrics docs are\n * inconsistent about casing - some show 'EXPLICIT', others 'explicit')\n */\nexport const fullConsentUpperCase: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'EXPLICIT',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\n/**\n * Service-level consent - ucCategory has mixed types (non-boolean values\n * indicate individual service-level choice rather than group-level)\n */\nexport const serviceLevelConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: 'partial', // Non-boolean indicates mixed service choices\n marketing: 'partial',\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n Hotjar: true,\n};\n\n/**\n * Non-consent event (should be ignored)\n */\nexport const nonConsentEvent: UsercentricsEventDetail = {\n event: 'other_event',\n type: 'explicit',\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing Usercentrics event details\n * with no category mapping configured (pass-through).\n */\n\n/**\n * Full consent - all categories true (group-level)\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: true,\n};\n\n/**\n * Partial consent - essential and functional true, marketing false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: false,\n};\n\n/**\n * Minimal consent - only essential true\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: false,\n marketing: false,\n};\n\n/**\n * Full consent with custom category mapping applied\n * (essential->functional, functional->functional, marketing->marketing)\n */\nexport const fullConsentCustomMapped: WalkerOS.Consent = {\n functional: true,\n marketing: true,\n};\n\n/**\n * Service-level consent - individual service booleans + boolean ucCategory entries\n * (services normalized: lowercase, spaces to underscores)\n * (ucCategory boolean entries mapped through categoryMap)\n */\nexport const serviceLevelMapped: WalkerOS.Consent = {\n essential: true,\n google_analytics: true,\n google_ads_remarketing: false,\n hotjar: true,\n};\n","import type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment configurations for Usercentrics source testing.\n */\n\nconst noop = () => {};\n\n/**\n * Create a properly typed elb/push function mock\n */\nexport const createMockElbFn = (): Elb.Fn => {\n const fn = (() =>\n Promise.resolve({\n ok: true,\n })) as Elb.Fn;\n return fn;\n};\n\n/**\n * Simple no-op logger for demo purposes\n */\nexport const noopLogger: Logger.Instance = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noop,\n scope: () => noopLogger,\n};\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\nexport const minimalConsent: Flow.StepExample = {\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n },\n out: {\n essential: true,\n functional: false,\n marketing: false,\n },\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description:\n 'Custom categoryMap remaps essential to functional and functional to analytics',\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n },\n mapping: {\n categoryMap: { essential: 'functional', functional: 'analytics' },\n },\n out: {\n functional: true,\n analytics: true,\n marketing: false,\n },\n};\n\nexport const customEventName: Flow.StepExample = {\n description: 'Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2',\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n mapping: { eventName: 'UC_SDK_EVENT' },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n","import type { Source } from '@walkeros/core';\n\n/** Dispatches ucEvent CustomEvent after source init (trigger pattern). */\nexport const setup: Source.SetupFn = (input, env) => {\n if (!input || typeof input !== 'object') return;\n return () => {\n env.window.dispatchEvent(new CustomEvent('ucEvent', { detail: input }));\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;;;ACWO,IAAM,cAAuC;AAAA,EAClD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,oBAAoB;AAAA,EACpB,0BAA0B;AAC5B;AAKO,IAAM,iBAA0C;AAAA,EACrD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,oBAAoB;AAAA,EACpB,0BAA0B;AAC5B;AAKO,IAAM,iBAA0C;AAAA,EACrD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,oBAAoB;AAAA,EACpB,0BAA0B;AAC5B;AAMO,IAAM,kBAA2C;AAAA,EACtD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,oBAAoB;AAAA,EACpB,0BAA0B;AAC5B;AAMO,IAAM,uBAAgD;AAAA,EAC3D,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAMO,IAAM,sBAA+C;AAAA,EAC1D,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,oBAAoB;AAAA,EACpB,0BAA0B;AAAA,EAC1B,QAAQ;AACV;AAKO,IAAM,kBAA2C;AAAA,EACtD,OAAO;AAAA,EACP,MAAM;AACR;;;ACnGO,IAAM,oBAAsC;AAAA,EACjD,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AACb;AAKO,IAAM,uBAAyC;AAAA,EACpD,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AACb;AAKO,IAAM,uBAAyC;AAAA,EACpD,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AACb;AAMO,IAAM,0BAA4C;AAAA,EACvD,YAAY;AAAA,EACZ,WAAW;AACb;AAOO,IAAM,qBAAuC;AAAA,EAClD,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,QAAQ;AACV;;;ACjDA,IAAM,OAAO,MAAM;AAAC;AAKb,IAAM,kBAAkB,MAAc;AAC3C,QAAM,MAAM,MACV,QAAQ,QAAQ;AAAA,IACd,IAAI;AAAA,EACN,CAAC;AACH,SAAO;AACT;AAKO,IAAM,aAA8B;AAAA,EACzC,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO,CAAC,YAA4B;AAClC,UAAM,OAAO,YAAY,WAAW,IAAI,MAAM,OAAO,IAAI;AAAA,EAC3D;AAAA,EACA,MAAM;AAAA,EACN,OAAO,MAAM;AACf;;;AChCA;AAAA;AAAA;AAAA;AAAA,qBAAAA;AAAA,EAAA,sBAAAC;AAAA;AAEO,IAAMD,eAAgC;AAAA,EAC3C,IAAI;AAAA,IACF,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,MACV,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAEO,IAAMC,kBAAmC;AAAA,EAC9C,IAAI;AAAA,IACF,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,MACV,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAEO,IAAM,sBAAwC;AAAA,EACnD,aACE;AAAA,EACF,IAAI;AAAA,IACF,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,MACV,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,aAAa,EAAE,WAAW,cAAc,YAAY,YAAY;AAAA,EAClE;AAAA,EACA,KAAK;AAAA,IACH,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AACF;AAEO,IAAM,kBAAoC;AAAA,EAC/C,aAAa;AAAA,EACb,IAAI;AAAA,IACF,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,MACV,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,SAAS,EAAE,WAAW,eAAe;AAAA,EACrC,KAAK;AAAA,IACH,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;;;AC1EO,IAAM,QAAwB,CAAC,OAAO,QAAQ;AACnD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,SAAO,MAAM;AACX,QAAI,OAAO,cAAc,IAAI,YAAY,WAAW,EAAE,QAAQ,MAAM,CAAC,CAAC;AAAA,EACxE;AACF;;;ANEA,IAAM,gBAAgB,CAAC,UAAU,SAAS,QAAQ,YAAY;AA+BvD,IAAM,qBAAyC,OAAO,YAAY;AAzCzE;AA0CE,QAAM,EAAE,QAAQ,IAAI,IAAI;AACxB,QAAM,EAAE,IAAI,IAAI;AAGhB,QAAM,gBACJ,SAAI,WAAJ,YACC,OAAO,WAAW,WAAW,cAAc,WAAW,SAAS;AAGlE,QAAM,WAAqB;AAAA,IACzB,YAAW,4CAAQ,aAAR,mBAAkB,cAAlB,YAA+B;AAAA,IAC1C,cAAa,4CAAQ,aAAR,mBAAkB,gBAAlB,YAAiC,CAAC;AAAA,IAC/C,eAAc,4CAAQ,aAAR,mBAAkB,iBAAlB,YAAkC;AAAA,EAClD;AAEA,QAAM,aAAmC,EAAE,SAAS;AAGpD,MAAI;AAGJ,MAAI,cAAc;AAMhB,UAAM,eAAe,CACnB,eACY;AACZ,aAAO,OAAO,OAAO,UAAU,EAAE,MAAM,CAAC,QAAQ,OAAO,QAAQ,SAAS;AAAA,IAC1E;AAYA,UAAM,eAAe,CACnB,WACqB;AACrB,YAAM,QAA0B,CAAC;AAEjC,UAAI,OAAO,cAAc,aAAa,OAAO,UAAU,GAAG;AAExD,eAAO,QAAQ,OAAO,UAAU,EAAE,QAAQ,CAAC,CAAC,UAAU,KAAK,MAAM;AA5FzE,cAAAC,KAAAC;AA6FU,cAAI,OAAO,UAAU,UAAW;AAChC,gBAAM,UAASA,OAAAD,MAAA,SAAS,gBAAT,gBAAAA,IAAuB,cAAvB,OAAAC,MAAoC;AAEnD,gBAAM,MAAM,IAAI,MAAM,MAAM,KAAK;AAAA,QACnC,CAAC;AAAA,MACH,OAAO;AAGL,YAAI,OAAO,YAAY;AACrB,iBAAO,QAAQ,OAAO,UAAU,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAtGtE,gBAAAD,KAAAC;AAuGY,gBAAI,OAAO,UAAU,WAAW;AAC9B,oBAAM,UAASA,OAAAD,MAAA,SAAS,gBAAT,gBAAAA,IAAuB,SAAvB,OAAAC,MAA+B;AAC9C,oBAAM,MAAM,IAAI,MAAM,MAAM,KAAK;AAAA,YACnC;AAAA,UACF,CAAC;AAAA,QACH;AAGA,eAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,cAAI,cAAc,SAAS,GAAG,EAAG;AACjC,cAAI,OAAO,UAAU,UAAW;AAEhC,gBAAM,aAAa,IAAI,YAAY,EAAE,QAAQ,MAAM,GAAG;AACtD,gBAAM,UAAU,IAAI;AAAA,QACtB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AAKA,UAAM,gBAAgB,CAAC,WAAoC;AA9H/D,UAAAD;AAgIM,UAAI,OAAO,UAAU,iBAAkB;AAIvC,UAAI,SAAS,kBAAgBA,MAAA,OAAO,SAAP,gBAAAA,IAAa,mBAAkB;AAC1D;AAEF,YAAM,QAAQ,aAAa,MAAM;AAGjC,UAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,YAAI,kBAAkB,KAAK;AAAA,MAC7B;AAAA,IACF;AAGA,UAAM,aAAY,cAAS,cAAT,YAAsB;AACxC,sBAAkB,CAAC,MAAa;AAC9B,YAAM,cAAc;AACpB,UAAI,YAAY,QAAQ;AACtB,sBAAc,YAAY,MAAM;AAAA,MAClC;AAAA,IACF;AACA,iBAAa,iBAAiB,WAAW,eAAe;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,OAAO,aAAa;AA9JjC,UAAAA;AA+JM,UAAI,gBAAgB,iBAAiB;AACnC,cAAM,aAAYA,MAAA,SAAS,cAAT,OAAAA,MAAsB;AACxC,qBAAa,oBAAoB,WAAW,eAAe;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":["fullConsent","minimalConsent","_a","_b"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/examples/inputs.ts","../src/examples/outputs.ts","../src/examples/env.ts","../src/examples/step.ts","../src/examples/trigger.ts"],"sourcesContent":["import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, UsercentricsEventDetail } from './types';\n\n// Export types for external usage\nexport * as SourceUsercentrics from './types';\n\n// Export examples\nexport * from './examples';\n\n/** Reserved keys in event.detail that are not service names */\nconst RESERVED_KEYS = ['action', 'event', 'type', 'ucCategory'];\n\n/**\n * Usercentrics consent management source for walkerOS.\n *\n * This source listens to Usercentrics CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * @example\n * ```typescript\n * import { sourceUsercentrics } from '@walkeros/web-source-cmp-usercentrics';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceUsercentrics,\n * config: {\n * settings: {\n * eventName: 'ucEvent',\n * categoryMap: {\n * essential: 'functional',\n * functional: 'functional',\n * marketing: 'marketing',\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceUsercentrics: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb } = env;\n\n // Resolve window with fallback to globalThis\n const actualWindow =\n env.window ??\n (typeof globalThis.window !== 'undefined' ? globalThis.window : undefined);\n\n // Merge user settings with defaults\n const settings: Settings = {\n eventName: config?.settings?.eventName ?? 'ucEvent',\n categoryMap: config?.settings?.categoryMap ?? {},\n explicitOnly: config?.settings?.explicitOnly ?? true,\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track listener reference for cleanup\n let consentListener: ((e: Event) => void) | undefined;\n\n // Only setup if in browser environment\n if (actualWindow) {\n /**\n * Determine if ucCategory represents group-level consent.\n * Group-level: all values are booleans.\n * Service-level: some values are non-boolean (e.g., 'partial').\n */\n const isGroupLevel = (\n ucCategory: Record<string, boolean | unknown>,\n ): boolean => {\n return Object.values(ucCategory).every((val) => typeof val === 'boolean');\n };\n\n /**\n * Parse consent from Usercentrics event detail.\n *\n * Two modes:\n * 1. Group-level: ucCategory has all booleans -> use ucCategory as consent\n * 2. Service-level: ucCategory has non-booleans -> extract individual\n * service keys from event.detail + boolean entries from ucCategory\n *\n * categoryMap is applied in both modes for ucCategory boolean entries.\n */\n const parseConsent = (\n detail: UsercentricsEventDetail,\n ): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n if (detail.ucCategory && isGroupLevel(detail.ucCategory)) {\n // Group-level consent: use ucCategory values\n Object.entries(detail.ucCategory).forEach(([category, value]) => {\n if (typeof value !== 'boolean') return;\n const mapped = settings.categoryMap?.[category] ?? category;\n // OR logic: if ANY source category is true, target group is true\n state[mapped] = state[mapped] || value;\n });\n } else {\n // Service-level consent: extract individual services\n // Include boolean entries from ucCategory (with categoryMap applied)\n if (detail.ucCategory) {\n Object.entries(detail.ucCategory).forEach(([key, value]) => {\n if (typeof value === 'boolean') {\n const mapped = settings.categoryMap?.[key] ?? key;\n state[mapped] = state[mapped] || value;\n }\n });\n }\n\n // Extract service keys (not reserved keys)\n Object.entries(detail).forEach(([key, value]) => {\n if (RESERVED_KEYS.includes(key)) return;\n if (typeof value !== 'boolean') return;\n // Normalize: lowercase, spaces to underscores\n const normalized = key.toLowerCase().replace(/ /g, '_');\n state[normalized] = value;\n });\n }\n\n return state;\n };\n\n /**\n * Handle a Usercentrics consent event.\n */\n const handleConsent = (detail: UsercentricsEventDetail) => {\n // Only process consent_status events\n if (detail.event !== 'consent_status') return;\n\n // Skip implicit consent if explicitOnly is true\n // Use case-insensitive comparison (Usercentrics docs show both 'explicit' and 'EXPLICIT')\n if (settings.explicitOnly && detail.type?.toLowerCase() !== 'explicit')\n return;\n\n const state = parseConsent(detail);\n\n // Only call if we have consent state to report\n if (Object.keys(state).length > 0) {\n elb('walker consent', state);\n }\n };\n\n // Listen for Usercentrics consent events\n const eventName = settings.eventName ?? 'ucEvent';\n consentListener = (e: Event) => {\n const customEvent = e as CustomEvent<UsercentricsEventDetail>;\n if (customEvent.detail) {\n handleConsent(customEvent.detail);\n }\n };\n actualWindow.addEventListener(eventName, consentListener);\n }\n\n return {\n type: 'usercentrics',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n if (actualWindow && consentListener) {\n const eventName = settings.eventName ?? 'ucEvent';\n actualWindow.removeEventListener(eventName, consentListener);\n }\n },\n };\n};\n\nexport default sourceUsercentrics;\n","import type { Source, Elb } from '@walkeros/core';\n\n/**\n * Usercentrics consent event detail structure.\n *\n * Fired as event.detail on the configured window event (e.g. 'ucEvent').\n * Contains both category-level (ucCategory) and service-level consent.\n */\nexport interface UsercentricsEventDetail {\n /** Always 'consent_status' for consent events */\n event: string;\n /** 'explicit' when user actively chose, 'implicit' for page-load defaults (casing may vary) */\n type: string;\n /** Action taken: 'onAcceptAllServices', 'onDenyAllServices', 'onUpdateServices' */\n action?: string;\n /** Category-level consent booleans (e.g. { marketing: true, functional: false }) */\n ucCategory?: Record<string, boolean | unknown>;\n /** Service-level consent as top-level keys (e.g. 'Google Analytics': true) */\n [service: string]: unknown;\n}\n\ndeclare global {\n interface WindowEventMap {\n ucEvent: CustomEvent<UsercentricsEventDetail>;\n }\n}\n\n/**\n * Settings for Usercentrics source\n */\nexport interface Settings {\n /**\n * Window event name to listen for.\n * Configured in Usercentrics admin under Implementation > Data Layer & Events.\n * Can also be set to 'UC_SDK_EVENT' for the built-in Browser SDK event.\n *\n * Default: 'ucEvent'\n */\n eventName?: string;\n\n /**\n * Map Usercentrics categories to walkerOS consent groups.\n * Keys: Usercentrics category names (from ucCategory)\n * Values: walkerOS consent group names\n *\n * Applied in both group-level and service-level consent modes.\n * When multiple source categories map to the same group, OR logic applies:\n * if ANY source category is true, the target group is true.\n *\n * Default: {} (pass through category names as-is)\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Ignores events where type !== 'explicit'\n * When false: Processes any consent_status event including implicit/defaults\n *\n * Default: true\n */\n explicitOnly?: boolean;\n}\n\n/**\n * User input settings (all optional)\n */\nexport type InitSettings = Partial<Settings>;\n\n/**\n * No mapping configuration for this source\n */\nexport interface Mapping {}\n\n/**\n * Push function type - uses elb for consent commands\n */\nexport type Push = Elb.Fn;\n\n/**\n * Environment interface for Usercentrics source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for Usercentrics source\n */\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\n/**\n * Config type alias\n */\nexport type Config = Source.Config<Types>;\n","import type { UsercentricsEventDetail } from '../types';\n\n/**\n * Example Usercentrics consent event detail inputs.\n *\n * These represent real event.detail payloads from Usercentrics CMP.\n */\n\n/**\n * Full consent - user accepted all categories (explicit)\n */\nexport const fullConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': true,\n};\n\n/**\n * Partial consent - user accepted only essential and functional (explicit)\n */\nexport const partialConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Minimal consent - user denied everything except essential (explicit)\n */\nexport const minimalConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Implicit consent - page load with default consent state\n * (not an explicit user choice)\n */\nexport const implicitConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'implicit',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Explicit consent with uppercase type field (Usercentrics docs are\n * inconsistent about casing - some show 'EXPLICIT', others 'explicit')\n */\nexport const fullConsentUpperCase: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'EXPLICIT',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\n/**\n * Service-level consent - ucCategory has mixed types (non-boolean values\n * indicate individual service-level choice rather than group-level)\n */\nexport const serviceLevelConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: 'partial', // Non-boolean indicates mixed service choices\n marketing: 'partial',\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n Hotjar: true,\n};\n\n/**\n * Non-consent event (should be ignored)\n */\nexport const nonConsentEvent: UsercentricsEventDetail = {\n event: 'other_event',\n type: 'explicit',\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing Usercentrics event details\n * with no category mapping configured (pass-through).\n */\n\n/**\n * Full consent - all categories true (group-level)\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: true,\n};\n\n/**\n * Partial consent - essential and functional true, marketing false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: false,\n};\n\n/**\n * Minimal consent - only essential true\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: false,\n marketing: false,\n};\n\n/**\n * Full consent with custom category mapping applied\n * (essential->functional, functional->functional, marketing->marketing)\n */\nexport const fullConsentCustomMapped: WalkerOS.Consent = {\n functional: true,\n marketing: true,\n};\n\n/**\n * Service-level consent - individual service booleans + boolean ucCategory entries\n * (services normalized: lowercase, spaces to underscores)\n * (ucCategory boolean entries mapped through categoryMap)\n */\nexport const serviceLevelMapped: WalkerOS.Consent = {\n essential: true,\n google_analytics: true,\n google_ads_remarketing: false,\n hotjar: true,\n};\n","import type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment configurations for Usercentrics source testing.\n */\n\nconst noop = () => {};\n\n/**\n * Create a properly typed elb/push function mock\n */\nexport const createMockElbFn = (): Elb.Fn => {\n const fn = (() =>\n Promise.resolve({\n ok: true,\n })) as Elb.Fn;\n return fn;\n};\n\n/**\n * Simple no-op logger for demo purposes\n */\nexport const noopLogger: Logger.Instance = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noop,\n scope: () => noopLogger,\n};\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\nexport const minimalConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n },\n out: {\n essential: true,\n functional: false,\n marketing: false,\n },\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description:\n 'Custom categoryMap remaps essential to functional and functional to analytics',\n trigger: { type: 'consent' },\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n },\n mapping: {\n categoryMap: { essential: 'functional', functional: 'analytics' },\n },\n out: {\n functional: true,\n analytics: true,\n marketing: false,\n },\n};\n\nexport const customEventName: Flow.StepExample = {\n description: 'Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2',\n trigger: { type: 'consent', options: { eventName: 'UC_SDK_EVENT' } },\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n mapping: { eventName: 'UC_SDK_EVENT' },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\ninterface UsercentricsContent {\n event: string;\n type: string;\n action?: string;\n ucCategory?: Record<string, boolean | unknown>;\n [service: string]: unknown;\n}\n\nconst createTrigger: Trigger.CreateFn<UsercentricsContent, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<UsercentricsContent, void> =\n (type?: string, opts?: unknown) => async (content: UsercentricsContent) => {\n // Lazy startFlow — source registers ucEvent listener during init\n if (!flow) {\n const result = await startFlow({ ...config, run: config.run ?? true });\n flow = { collector: result.collector, elb: result.elb };\n }\n\n // Dispatch the CMP event — source's listener catches it\n const eventName =\n (opts as { eventName?: string })?.eventName || 'ucEvent';\n window.dispatchEvent(new CustomEvent(eventName, { detail: content }));\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Dispatches ucEvent CustomEvent after source init (post-init trigger). */\nconst trigger = (\n input: unknown,\n env: Record<string, unknown>,\n): void | (() => void) => {\n if (!input || typeof input !== 'object') return;\n return () => {\n (env.window as Window).dispatchEvent(\n new CustomEvent('ucEvent', { detail: input }),\n );\n };\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["fullConsent","minimalConsent","trigger","_a","_b"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,t={},n={event:"consent_status",type:"explicit",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0},"Google Analytics":!0,"Google Ads Remarketing":!0},
|
|
1
|
+
var e=Object.defineProperty,t={},n={event:"consent_status",type:"explicit",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0},"Google Analytics":!0,"Google Ads Remarketing":!0},o={event:"consent_status",type:"explicit",action:"onUpdateServices",ucCategory:{essential:!0,functional:!0,marketing:!1},"Google Analytics":!0,"Google Ads Remarketing":!1},i={event:"consent_status",type:"explicit",action:"onDenyAllServices",ucCategory:{essential:!0,functional:!1,marketing:!1},"Google Analytics":!1,"Google Ads Remarketing":!1},a={event:"consent_status",type:"implicit",ucCategory:{essential:!0,functional:!1,marketing:!1},"Google Analytics":!1,"Google Ads Remarketing":!1},l={event:"consent_status",type:"EXPLICIT",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0}},s={event:"consent_status",type:"explicit",action:"onUpdateServices",ucCategory:{essential:!0,functional:"partial",marketing:"partial"},"Google Analytics":!0,"Google Ads Remarketing":!1,Hotjar:!0},c={event:"other_event",type:"explicit"},r={essential:!0,functional:!0,marketing:!0},u={essential:!0,functional:!0,marketing:!1},g={essential:!0,functional:!1,marketing:!1},v={functional:!0,marketing:!0},p={essential:!0,google_analytics:!0,google_ads_remarketing:!1,hotjar:!0},y=()=>{},f=()=>()=>Promise.resolve({ok:!0}),m={error:y,warn:y,info:y,debug:y,throw:e=>{throw"string"==typeof e?new Error(e):e},json:y,scope:()=>m},d={};((t,n)=>{for(var o in n)e(t,o,{get:n[o],enumerable:!0})})(d,{categoryMapOverride:()=>E,customEventName:()=>w,fullConsent:()=>k,minimalConsent:()=>C});var k={trigger:{type:"consent"},in:{event:"consent_status",type:"explicit",action:"onAcceptAllServices",ucCategory:{essential:!0,functional:!0,marketing:!0}},out:{essential:!0,functional:!0,marketing:!0}},C={trigger:{type:"consent"},in:{event:"consent_status",type:"explicit",action:"onDenyAllServices",ucCategory:{essential:!0,functional:!1,marketing:!1}},out:{essential:!0,functional:!1,marketing:!1}},E={description:"Custom categoryMap remaps essential to functional and functional to analytics",trigger:{type:"consent"},in:{event:"consent_status",type:"explicit",ucCategory:{essential:!0,functional:!0,marketing:!1}},mapping:{categoryMap:{essential:"functional",functional:"analytics"}},out:{functional:!0,analytics:!0,marketing:!1}},w={description:"Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2",trigger:{type:"consent",options:{eventName:"UC_SDK_EVENT"}},in:{event:"consent_status",type:"explicit",ucCategory:{essential:!0,functional:!0,marketing:!0}},mapping:{eventName:"UC_SDK_EVENT"},out:{essential:!0,functional:!0,marketing:!0}};import{startFlow as _}from"@walkeros/collector";var b=async e=>{let t;return{get flow(){return t},trigger:(n,o)=>async n=>{var i;if(!t){const n=await _({...e,run:null==(i=e.run)||i});t={collector:n.collector,elb:n.elb}}const a=(null==o?void 0:o.eventName)||"ucEvent";window.dispatchEvent(new CustomEvent(a,{detail:n}))}}},A=(e,t)=>{if(e&&"object"==typeof e)return()=>{t.window.dispatchEvent(new CustomEvent("ucEvent",{detail:e}))}},x=["action","event","type","ucCategory"],h=async e=>{var t,n,o,i,a,l,s,c;const{config:r,env:u}=e,{elb:g}=u,v=null!=(t=u.window)?t:void 0!==globalThis.window?globalThis.window:void 0,p={eventName:null!=(o=null==(n=null==r?void 0:r.settings)?void 0:n.eventName)?o:"ucEvent",categoryMap:null!=(a=null==(i=null==r?void 0:r.settings)?void 0:i.categoryMap)?a:{},explicitOnly:null==(s=null==(l=null==r?void 0:r.settings)?void 0:l.explicitOnly)||s},y={settings:p};let f;if(v){const e=e=>Object.values(e).every(e=>"boolean"==typeof e),t=t=>{const n={};return t.ucCategory&&e(t.ucCategory)?Object.entries(t.ucCategory).forEach(([e,t])=>{var o,i;if("boolean"!=typeof t)return;const a=null!=(i=null==(o=p.categoryMap)?void 0:o[e])?i:e;n[a]=n[a]||t}):(t.ucCategory&&Object.entries(t.ucCategory).forEach(([e,t])=>{var o,i;if("boolean"==typeof t){const a=null!=(i=null==(o=p.categoryMap)?void 0:o[e])?i:e;n[a]=n[a]||t}}),Object.entries(t).forEach(([e,t])=>{if(x.includes(e))return;if("boolean"!=typeof t)return;const o=e.toLowerCase().replace(/ /g,"_");n[o]=t})),n},n=e=>{var n;if("consent_status"!==e.event)return;if(p.explicitOnly&&"explicit"!==(null==(n=e.type)?void 0:n.toLowerCase()))return;const o=t(e);Object.keys(o).length>0&&g("walker consent",o)},o=null!=(c=p.eventName)?c:"ucEvent";f=e=>{const t=e;t.detail&&n(t.detail)},v.addEventListener(o,f)}return{type:"usercentrics",config:y,push:g,destroy:async e=>{var t;if(v&&f){const e=null!=(t=p.eventName)?t:"ucEvent";v.removeEventListener(e,f)}}}},S=h;export{t as SourceUsercentrics,f as createMockElbFn,b as createTrigger,S as default,n as fullConsent,v as fullConsentCustomMapped,r as fullConsentMapped,l as fullConsentUpperCase,a as implicitConsent,i as minimalConsent,g as minimalConsentMapped,c as nonConsentEvent,m as noopLogger,o as partialConsent,u as partialConsentMapped,s as serviceLevelConsent,p as serviceLevelMapped,h as sourceUsercentrics,d as step,A as trigger};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/index.ts","../src/examples/inputs.ts","../src/examples/outputs.ts","../src/examples/env.ts","../src/examples/step.ts","../src/examples/setup.ts","../src/index.ts"],"sourcesContent":["import type { Source, Elb } from '@walkeros/core';\n\n/**\n * Usercentrics consent event detail structure.\n *\n * Fired as event.detail on the configured window event (e.g. 'ucEvent').\n * Contains both category-level (ucCategory) and service-level consent.\n */\nexport interface UsercentricsEventDetail {\n /** Always 'consent_status' for consent events */\n event: string;\n /** 'explicit' when user actively chose, 'implicit' for page-load defaults (casing may vary) */\n type: string;\n /** Action taken: 'onAcceptAllServices', 'onDenyAllServices', 'onUpdateServices' */\n action?: string;\n /** Category-level consent booleans (e.g. { marketing: true, functional: false }) */\n ucCategory?: Record<string, boolean | unknown>;\n /** Service-level consent as top-level keys (e.g. 'Google Analytics': true) */\n [service: string]: unknown;\n}\n\ndeclare global {\n interface WindowEventMap {\n ucEvent: CustomEvent<UsercentricsEventDetail>;\n }\n}\n\n/**\n * Settings for Usercentrics source\n */\nexport interface Settings {\n /**\n * Window event name to listen for.\n * Configured in Usercentrics admin under Implementation > Data Layer & Events.\n * Can also be set to 'UC_SDK_EVENT' for the built-in Browser SDK event.\n *\n * Default: 'ucEvent'\n */\n eventName?: string;\n\n /**\n * Map Usercentrics categories to walkerOS consent groups.\n * Keys: Usercentrics category names (from ucCategory)\n * Values: walkerOS consent group names\n *\n * Applied in both group-level and service-level consent modes.\n * When multiple source categories map to the same group, OR logic applies:\n * if ANY source category is true, the target group is true.\n *\n * Default: {} (pass through category names as-is)\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Ignores events where type !== 'explicit'\n * When false: Processes any consent_status event including implicit/defaults\n *\n * Default: true\n */\n explicitOnly?: boolean;\n}\n\n/**\n * User input settings (all optional)\n */\nexport type InitSettings = Partial<Settings>;\n\n/**\n * No mapping configuration for this source\n */\nexport interface Mapping {}\n\n/**\n * Push function type - uses elb for consent commands\n */\nexport type Push = Elb.Fn;\n\n/**\n * Environment interface for Usercentrics source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for Usercentrics source\n */\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\n/**\n * Config type alias\n */\nexport type Config = Source.Config<Types>;\n","import type { UsercentricsEventDetail } from '../types';\n\n/**\n * Example Usercentrics consent event detail inputs.\n *\n * These represent real event.detail payloads from Usercentrics CMP.\n */\n\n/**\n * Full consent - user accepted all categories (explicit)\n */\nexport const fullConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': true,\n};\n\n/**\n * Partial consent - user accepted only essential and functional (explicit)\n */\nexport const partialConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Minimal consent - user denied everything except essential (explicit)\n */\nexport const minimalConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Implicit consent - page load with default consent state\n * (not an explicit user choice)\n */\nexport const implicitConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'implicit',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Explicit consent with uppercase type field (Usercentrics docs are\n * inconsistent about casing - some show 'EXPLICIT', others 'explicit')\n */\nexport const fullConsentUpperCase: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'EXPLICIT',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\n/**\n * Service-level consent - ucCategory has mixed types (non-boolean values\n * indicate individual service-level choice rather than group-level)\n */\nexport const serviceLevelConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: 'partial', // Non-boolean indicates mixed service choices\n marketing: 'partial',\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n Hotjar: true,\n};\n\n/**\n * Non-consent event (should be ignored)\n */\nexport const nonConsentEvent: UsercentricsEventDetail = {\n event: 'other_event',\n type: 'explicit',\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing Usercentrics event details\n * with no category mapping configured (pass-through).\n */\n\n/**\n * Full consent - all categories true (group-level)\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: true,\n};\n\n/**\n * Partial consent - essential and functional true, marketing false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: false,\n};\n\n/**\n * Minimal consent - only essential true\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: false,\n marketing: false,\n};\n\n/**\n * Full consent with custom category mapping applied\n * (essential->functional, functional->functional, marketing->marketing)\n */\nexport const fullConsentCustomMapped: WalkerOS.Consent = {\n functional: true,\n marketing: true,\n};\n\n/**\n * Service-level consent - individual service booleans + boolean ucCategory entries\n * (services normalized: lowercase, spaces to underscores)\n * (ucCategory boolean entries mapped through categoryMap)\n */\nexport const serviceLevelMapped: WalkerOS.Consent = {\n essential: true,\n google_analytics: true,\n google_ads_remarketing: false,\n hotjar: true,\n};\n","import type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment configurations for Usercentrics source testing.\n */\n\nconst noop = () => {};\n\n/**\n * Create a properly typed elb/push function mock\n */\nexport const createMockElbFn = (): Elb.Fn => {\n const fn = (() =>\n Promise.resolve({\n ok: true,\n })) as Elb.Fn;\n return fn;\n};\n\n/**\n * Simple no-op logger for demo purposes\n */\nexport const noopLogger: Logger.Instance = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noop,\n scope: () => noopLogger,\n};\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\nexport const minimalConsent: Flow.StepExample = {\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n },\n out: {\n essential: true,\n functional: false,\n marketing: false,\n },\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description:\n 'Custom categoryMap remaps essential to functional and functional to analytics',\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n },\n mapping: {\n categoryMap: { essential: 'functional', functional: 'analytics' },\n },\n out: {\n functional: true,\n analytics: true,\n marketing: false,\n },\n};\n\nexport const customEventName: Flow.StepExample = {\n description: 'Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2',\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n mapping: { eventName: 'UC_SDK_EVENT' },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n","import type { Source } from '@walkeros/core';\n\n/** Dispatches ucEvent CustomEvent after source init (trigger pattern). */\nexport const setup: Source.SetupFn = (input, env) => {\n if (!input || typeof input !== 'object') return;\n return () => {\n env.window.dispatchEvent(new CustomEvent('ucEvent', { detail: input }));\n };\n};\n","import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, UsercentricsEventDetail } from './types';\n\n// Export types for external usage\nexport * as SourceUsercentrics from './types';\n\n// Export examples\nexport * from './examples';\n\n/** Reserved keys in event.detail that are not service names */\nconst RESERVED_KEYS = ['action', 'event', 'type', 'ucCategory'];\n\n/**\n * Usercentrics consent management source for walkerOS.\n *\n * This source listens to Usercentrics CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * @example\n * ```typescript\n * import { sourceUsercentrics } from '@walkeros/web-source-cmp-usercentrics';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceUsercentrics,\n * config: {\n * settings: {\n * eventName: 'ucEvent',\n * categoryMap: {\n * essential: 'functional',\n * functional: 'functional',\n * marketing: 'marketing',\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceUsercentrics: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb } = env;\n\n // Resolve window with fallback to globalThis\n const actualWindow =\n env.window ??\n (typeof globalThis.window !== 'undefined' ? globalThis.window : undefined);\n\n // Merge user settings with defaults\n const settings: Settings = {\n eventName: config?.settings?.eventName ?? 'ucEvent',\n categoryMap: config?.settings?.categoryMap ?? {},\n explicitOnly: config?.settings?.explicitOnly ?? true,\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track listener reference for cleanup\n let consentListener: ((e: Event) => void) | undefined;\n\n // Only setup if in browser environment\n if (actualWindow) {\n /**\n * Determine if ucCategory represents group-level consent.\n * Group-level: all values are booleans.\n * Service-level: some values are non-boolean (e.g., 'partial').\n */\n const isGroupLevel = (\n ucCategory: Record<string, boolean | unknown>,\n ): boolean => {\n return Object.values(ucCategory).every((val) => typeof val === 'boolean');\n };\n\n /**\n * Parse consent from Usercentrics event detail.\n *\n * Two modes:\n * 1. Group-level: ucCategory has all booleans -> use ucCategory as consent\n * 2. Service-level: ucCategory has non-booleans -> extract individual\n * service keys from event.detail + boolean entries from ucCategory\n *\n * categoryMap is applied in both modes for ucCategory boolean entries.\n */\n const parseConsent = (\n detail: UsercentricsEventDetail,\n ): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n if (detail.ucCategory && isGroupLevel(detail.ucCategory)) {\n // Group-level consent: use ucCategory values\n Object.entries(detail.ucCategory).forEach(([category, value]) => {\n if (typeof value !== 'boolean') return;\n const mapped = settings.categoryMap?.[category] ?? category;\n // OR logic: if ANY source category is true, target group is true\n state[mapped] = state[mapped] || value;\n });\n } else {\n // Service-level consent: extract individual services\n // Include boolean entries from ucCategory (with categoryMap applied)\n if (detail.ucCategory) {\n Object.entries(detail.ucCategory).forEach(([key, value]) => {\n if (typeof value === 'boolean') {\n const mapped = settings.categoryMap?.[key] ?? key;\n state[mapped] = state[mapped] || value;\n }\n });\n }\n\n // Extract service keys (not reserved keys)\n Object.entries(detail).forEach(([key, value]) => {\n if (RESERVED_KEYS.includes(key)) return;\n if (typeof value !== 'boolean') return;\n // Normalize: lowercase, spaces to underscores\n const normalized = key.toLowerCase().replace(/ /g, '_');\n state[normalized] = value;\n });\n }\n\n return state;\n };\n\n /**\n * Handle a Usercentrics consent event.\n */\n const handleConsent = (detail: UsercentricsEventDetail) => {\n // Only process consent_status events\n if (detail.event !== 'consent_status') return;\n\n // Skip implicit consent if explicitOnly is true\n // Use case-insensitive comparison (Usercentrics docs show both 'explicit' and 'EXPLICIT')\n if (settings.explicitOnly && detail.type?.toLowerCase() !== 'explicit')\n return;\n\n const state = parseConsent(detail);\n\n // Only call if we have consent state to report\n if (Object.keys(state).length > 0) {\n elb('walker consent', state);\n }\n };\n\n // Listen for Usercentrics consent events\n const eventName = settings.eventName ?? 'ucEvent';\n consentListener = (e: Event) => {\n const customEvent = e as CustomEvent<UsercentricsEventDetail>;\n if (customEvent.detail) {\n handleConsent(customEvent.detail);\n }\n };\n actualWindow.addEventListener(eventName, consentListener);\n }\n\n return {\n type: 'usercentrics',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n if (actualWindow && consentListener) {\n const eventName = settings.eventName ?? 'ucEvent';\n actualWindow.removeEventListener(eventName, consentListener);\n }\n },\n };\n};\n\nexport default sourceUsercentrics;\n"],"mappings":"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","names":["fullConsent","minimalConsent","_a","_b"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/index.ts","../src/examples/inputs.ts","../src/examples/outputs.ts","../src/examples/env.ts","../src/examples/step.ts","../src/examples/trigger.ts","../src/index.ts"],"sourcesContent":["import type { Source, Elb } from '@walkeros/core';\n\n/**\n * Usercentrics consent event detail structure.\n *\n * Fired as event.detail on the configured window event (e.g. 'ucEvent').\n * Contains both category-level (ucCategory) and service-level consent.\n */\nexport interface UsercentricsEventDetail {\n /** Always 'consent_status' for consent events */\n event: string;\n /** 'explicit' when user actively chose, 'implicit' for page-load defaults (casing may vary) */\n type: string;\n /** Action taken: 'onAcceptAllServices', 'onDenyAllServices', 'onUpdateServices' */\n action?: string;\n /** Category-level consent booleans (e.g. { marketing: true, functional: false }) */\n ucCategory?: Record<string, boolean | unknown>;\n /** Service-level consent as top-level keys (e.g. 'Google Analytics': true) */\n [service: string]: unknown;\n}\n\ndeclare global {\n interface WindowEventMap {\n ucEvent: CustomEvent<UsercentricsEventDetail>;\n }\n}\n\n/**\n * Settings for Usercentrics source\n */\nexport interface Settings {\n /**\n * Window event name to listen for.\n * Configured in Usercentrics admin under Implementation > Data Layer & Events.\n * Can also be set to 'UC_SDK_EVENT' for the built-in Browser SDK event.\n *\n * Default: 'ucEvent'\n */\n eventName?: string;\n\n /**\n * Map Usercentrics categories to walkerOS consent groups.\n * Keys: Usercentrics category names (from ucCategory)\n * Values: walkerOS consent group names\n *\n * Applied in both group-level and service-level consent modes.\n * When multiple source categories map to the same group, OR logic applies:\n * if ANY source category is true, the target group is true.\n *\n * Default: {} (pass through category names as-is)\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Ignores events where type !== 'explicit'\n * When false: Processes any consent_status event including implicit/defaults\n *\n * Default: true\n */\n explicitOnly?: boolean;\n}\n\n/**\n * User input settings (all optional)\n */\nexport type InitSettings = Partial<Settings>;\n\n/**\n * No mapping configuration for this source\n */\nexport interface Mapping {}\n\n/**\n * Push function type - uses elb for consent commands\n */\nexport type Push = Elb.Fn;\n\n/**\n * Environment interface for Usercentrics source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for Usercentrics source\n */\nexport type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;\n\n/**\n * Config type alias\n */\nexport type Config = Source.Config<Types>;\n","import type { UsercentricsEventDetail } from '../types';\n\n/**\n * Example Usercentrics consent event detail inputs.\n *\n * These represent real event.detail payloads from Usercentrics CMP.\n */\n\n/**\n * Full consent - user accepted all categories (explicit)\n */\nexport const fullConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': true,\n};\n\n/**\n * Partial consent - user accepted only essential and functional (explicit)\n */\nexport const partialConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Minimal consent - user denied everything except essential (explicit)\n */\nexport const minimalConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Implicit consent - page load with default consent state\n * (not an explicit user choice)\n */\nexport const implicitConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'implicit',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n 'Google Analytics': false,\n 'Google Ads Remarketing': false,\n};\n\n/**\n * Explicit consent with uppercase type field (Usercentrics docs are\n * inconsistent about casing - some show 'EXPLICIT', others 'explicit')\n */\nexport const fullConsentUpperCase: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'EXPLICIT',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\n/**\n * Service-level consent - ucCategory has mixed types (non-boolean values\n * indicate individual service-level choice rather than group-level)\n */\nexport const serviceLevelConsent: UsercentricsEventDetail = {\n event: 'consent_status',\n type: 'explicit',\n action: 'onUpdateServices',\n ucCategory: {\n essential: true,\n functional: 'partial', // Non-boolean indicates mixed service choices\n marketing: 'partial',\n },\n 'Google Analytics': true,\n 'Google Ads Remarketing': false,\n Hotjar: true,\n};\n\n/**\n * Non-consent event (should be ignored)\n */\nexport const nonConsentEvent: UsercentricsEventDetail = {\n event: 'other_event',\n type: 'explicit',\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing Usercentrics event details\n * with no category mapping configured (pass-through).\n */\n\n/**\n * Full consent - all categories true (group-level)\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: true,\n};\n\n/**\n * Partial consent - essential and functional true, marketing false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: true,\n marketing: false,\n};\n\n/**\n * Minimal consent - only essential true\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n essential: true,\n functional: false,\n marketing: false,\n};\n\n/**\n * Full consent with custom category mapping applied\n * (essential->functional, functional->functional, marketing->marketing)\n */\nexport const fullConsentCustomMapped: WalkerOS.Consent = {\n functional: true,\n marketing: true,\n};\n\n/**\n * Service-level consent - individual service booleans + boolean ucCategory entries\n * (services normalized: lowercase, spaces to underscores)\n * (ucCategory boolean entries mapped through categoryMap)\n */\nexport const serviceLevelMapped: WalkerOS.Consent = {\n essential: true,\n google_analytics: true,\n google_ads_remarketing: false,\n hotjar: true,\n};\n","import type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment configurations for Usercentrics source testing.\n */\n\nconst noop = () => {};\n\n/**\n * Create a properly typed elb/push function mock\n */\nexport const createMockElbFn = (): Elb.Fn => {\n const fn = (() =>\n Promise.resolve({\n ok: true,\n })) as Elb.Fn;\n return fn;\n};\n\n/**\n * Simple no-op logger for demo purposes\n */\nexport const noopLogger: Logger.Instance = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noop,\n scope: () => noopLogger,\n};\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onAcceptAllServices',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n\nexport const minimalConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: {\n event: 'consent_status',\n type: 'explicit',\n action: 'onDenyAllServices',\n ucCategory: {\n essential: true,\n functional: false,\n marketing: false,\n },\n },\n out: {\n essential: true,\n functional: false,\n marketing: false,\n },\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description:\n 'Custom categoryMap remaps essential to functional and functional to analytics',\n trigger: { type: 'consent' },\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: false,\n },\n },\n mapping: {\n categoryMap: { essential: 'functional', functional: 'analytics' },\n },\n out: {\n functional: true,\n analytics: true,\n marketing: false,\n },\n};\n\nexport const customEventName: Flow.StepExample = {\n description: 'Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2',\n trigger: { type: 'consent', options: { eventName: 'UC_SDK_EVENT' } },\n in: {\n event: 'consent_status',\n type: 'explicit',\n ucCategory: {\n essential: true,\n functional: true,\n marketing: true,\n },\n },\n mapping: { eventName: 'UC_SDK_EVENT' },\n out: {\n essential: true,\n functional: true,\n marketing: true,\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\ninterface UsercentricsContent {\n event: string;\n type: string;\n action?: string;\n ucCategory?: Record<string, boolean | unknown>;\n [service: string]: unknown;\n}\n\nconst createTrigger: Trigger.CreateFn<UsercentricsContent, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<UsercentricsContent, void> =\n (type?: string, opts?: unknown) => async (content: UsercentricsContent) => {\n // Lazy startFlow — source registers ucEvent listener during init\n if (!flow) {\n const result = await startFlow({ ...config, run: config.run ?? true });\n flow = { collector: result.collector, elb: result.elb };\n }\n\n // Dispatch the CMP event — source's listener catches it\n const eventName =\n (opts as { eventName?: string })?.eventName || 'ucEvent';\n window.dispatchEvent(new CustomEvent(eventName, { detail: content }));\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Dispatches ucEvent CustomEvent after source init (post-init trigger). */\nconst trigger = (\n input: unknown,\n env: Record<string, unknown>,\n): void | (() => void) => {\n if (!input || typeof input !== 'object') return;\n return () => {\n (env.window as Window).dispatchEvent(\n new CustomEvent('ucEvent', { detail: input }),\n );\n };\n};\n\nexport { createTrigger, trigger };\n","import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, UsercentricsEventDetail } from './types';\n\n// Export types for external usage\nexport * as SourceUsercentrics from './types';\n\n// Export examples\nexport * from './examples';\n\n/** Reserved keys in event.detail that are not service names */\nconst RESERVED_KEYS = ['action', 'event', 'type', 'ucCategory'];\n\n/**\n * Usercentrics consent management source for walkerOS.\n *\n * This source listens to Usercentrics CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * @example\n * ```typescript\n * import { sourceUsercentrics } from '@walkeros/web-source-cmp-usercentrics';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceUsercentrics,\n * config: {\n * settings: {\n * eventName: 'ucEvent',\n * categoryMap: {\n * essential: 'functional',\n * functional: 'functional',\n * marketing: 'marketing',\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceUsercentrics: Source.Init<Types> = async (context) => {\n const { config, env } = context;\n const { elb } = env;\n\n // Resolve window with fallback to globalThis\n const actualWindow =\n env.window ??\n (typeof globalThis.window !== 'undefined' ? globalThis.window : undefined);\n\n // Merge user settings with defaults\n const settings: Settings = {\n eventName: config?.settings?.eventName ?? 'ucEvent',\n categoryMap: config?.settings?.categoryMap ?? {},\n explicitOnly: config?.settings?.explicitOnly ?? true,\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track listener reference for cleanup\n let consentListener: ((e: Event) => void) | undefined;\n\n // Only setup if in browser environment\n if (actualWindow) {\n /**\n * Determine if ucCategory represents group-level consent.\n * Group-level: all values are booleans.\n * Service-level: some values are non-boolean (e.g., 'partial').\n */\n const isGroupLevel = (\n ucCategory: Record<string, boolean | unknown>,\n ): boolean => {\n return Object.values(ucCategory).every((val) => typeof val === 'boolean');\n };\n\n /**\n * Parse consent from Usercentrics event detail.\n *\n * Two modes:\n * 1. Group-level: ucCategory has all booleans -> use ucCategory as consent\n * 2. Service-level: ucCategory has non-booleans -> extract individual\n * service keys from event.detail + boolean entries from ucCategory\n *\n * categoryMap is applied in both modes for ucCategory boolean entries.\n */\n const parseConsent = (\n detail: UsercentricsEventDetail,\n ): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n if (detail.ucCategory && isGroupLevel(detail.ucCategory)) {\n // Group-level consent: use ucCategory values\n Object.entries(detail.ucCategory).forEach(([category, value]) => {\n if (typeof value !== 'boolean') return;\n const mapped = settings.categoryMap?.[category] ?? category;\n // OR logic: if ANY source category is true, target group is true\n state[mapped] = state[mapped] || value;\n });\n } else {\n // Service-level consent: extract individual services\n // Include boolean entries from ucCategory (with categoryMap applied)\n if (detail.ucCategory) {\n Object.entries(detail.ucCategory).forEach(([key, value]) => {\n if (typeof value === 'boolean') {\n const mapped = settings.categoryMap?.[key] ?? key;\n state[mapped] = state[mapped] || value;\n }\n });\n }\n\n // Extract service keys (not reserved keys)\n Object.entries(detail).forEach(([key, value]) => {\n if (RESERVED_KEYS.includes(key)) return;\n if (typeof value !== 'boolean') return;\n // Normalize: lowercase, spaces to underscores\n const normalized = key.toLowerCase().replace(/ /g, '_');\n state[normalized] = value;\n });\n }\n\n return state;\n };\n\n /**\n * Handle a Usercentrics consent event.\n */\n const handleConsent = (detail: UsercentricsEventDetail) => {\n // Only process consent_status events\n if (detail.event !== 'consent_status') return;\n\n // Skip implicit consent if explicitOnly is true\n // Use case-insensitive comparison (Usercentrics docs show both 'explicit' and 'EXPLICIT')\n if (settings.explicitOnly && detail.type?.toLowerCase() !== 'explicit')\n return;\n\n const state = parseConsent(detail);\n\n // Only call if we have consent state to report\n if (Object.keys(state).length > 0) {\n elb('walker consent', state);\n }\n };\n\n // Listen for Usercentrics consent events\n const eventName = settings.eventName ?? 'ucEvent';\n consentListener = (e: Event) => {\n const customEvent = e as CustomEvent<UsercentricsEventDetail>;\n if (customEvent.detail) {\n handleConsent(customEvent.detail);\n }\n };\n actualWindow.addEventListener(eventName, consentListener);\n }\n\n return {\n type: 'usercentrics',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n if (actualWindow && consentListener) {\n const eventName = settings.eventName ?? 'ucEvent';\n actualWindow.removeEventListener(eventName, consentListener);\n }\n },\n };\n};\n\nexport default sourceUsercentrics;\n"],"mappings":"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","names":["fullConsent","minimalConsent","trigger","_a","_b"]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/web-source-cmp-usercentrics",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.2",
|
|
5
5
|
"type": "source",
|
|
6
|
-
"platform":
|
|
6
|
+
"platform": [
|
|
7
|
+
"web"
|
|
8
|
+
],
|
|
7
9
|
"renderer": "codebox",
|
|
8
10
|
"docs": "https://www.walkeros.io/docs/sources/web/cmps/usercentrics",
|
|
9
11
|
"source": "https://github.com/elbwalker/walkerOS/tree/main/packages/web/sources/cmps/usercentrics/src"
|
|
@@ -13,6 +15,9 @@
|
|
|
13
15
|
"createMockElbFn": {
|
|
14
16
|
"$code": "()=>()=>Promise.resolve({ok:!0})"
|
|
15
17
|
},
|
|
18
|
+
"createTrigger": {
|
|
19
|
+
"$code": "async e=>{let t;return{get flow(){return t},trigger:(n,a)=>async n=>{var i;if(!t){const n=await w({...e,run:null==(i=e.run)||i});t={collector:n.collector,elb:n.elb}}const o=(null==a?void 0:a.eventName)||\"ucEvent\";window.dispatchEvent(new CustomEvent(o,{detail:n}))}}}"
|
|
20
|
+
},
|
|
16
21
|
"fullConsent": {
|
|
17
22
|
"event": "consent_status",
|
|
18
23
|
"type": "explicit",
|
|
@@ -135,12 +140,12 @@
|
|
|
135
140
|
"google_ads_remarketing": false,
|
|
136
141
|
"hotjar": true
|
|
137
142
|
},
|
|
138
|
-
"setup": {
|
|
139
|
-
"$code": "(e,t)=>{if(e&&\"object\"==typeof e)return()=>{t.window.dispatchEvent(new CustomEvent(\"ucEvent\",{detail:e}))}}"
|
|
140
|
-
},
|
|
141
143
|
"step": {
|
|
142
144
|
"categoryMapOverride": {
|
|
143
145
|
"description": "Custom categoryMap remaps essential to functional and functional to analytics",
|
|
146
|
+
"trigger": {
|
|
147
|
+
"type": "consent"
|
|
148
|
+
},
|
|
144
149
|
"in": {
|
|
145
150
|
"event": "consent_status",
|
|
146
151
|
"type": "explicit",
|
|
@@ -164,6 +169,12 @@
|
|
|
164
169
|
},
|
|
165
170
|
"customEventName": {
|
|
166
171
|
"description": "Using UC_SDK_EVENT instead of ucEvent for Usercentrics SDK v2",
|
|
172
|
+
"trigger": {
|
|
173
|
+
"type": "consent",
|
|
174
|
+
"options": {
|
|
175
|
+
"eventName": "UC_SDK_EVENT"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
167
178
|
"in": {
|
|
168
179
|
"event": "consent_status",
|
|
169
180
|
"type": "explicit",
|
|
@@ -183,6 +194,9 @@
|
|
|
183
194
|
}
|
|
184
195
|
},
|
|
185
196
|
"fullConsent": {
|
|
197
|
+
"trigger": {
|
|
198
|
+
"type": "consent"
|
|
199
|
+
},
|
|
186
200
|
"in": {
|
|
187
201
|
"event": "consent_status",
|
|
188
202
|
"type": "explicit",
|
|
@@ -200,6 +214,9 @@
|
|
|
200
214
|
}
|
|
201
215
|
},
|
|
202
216
|
"minimalConsent": {
|
|
217
|
+
"trigger": {
|
|
218
|
+
"type": "consent"
|
|
219
|
+
},
|
|
203
220
|
"in": {
|
|
204
221
|
"event": "consent_status",
|
|
205
222
|
"type": "explicit",
|
|
@@ -216,6 +233,9 @@
|
|
|
216
233
|
"marketing": false
|
|
217
234
|
}
|
|
218
235
|
}
|
|
236
|
+
},
|
|
237
|
+
"trigger": {
|
|
238
|
+
"$code": "(e,t)=>{if(e&&\"object\"==typeof e)return()=>{t.window.dispatchEvent(new CustomEvent(\"ucEvent\",{detail:e}))}}"
|
|
219
239
|
}
|
|
220
240
|
}
|
|
221
241
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/web-source-cmp-usercentrics",
|
|
3
3
|
"description": "Usercentrics consent management source for walkerOS",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0-next-1773967844643",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"walkerOS": {
|
|
7
7
|
"type": "source",
|
|
8
|
-
"platform":
|
|
8
|
+
"platform": [
|
|
9
|
+
"web"
|
|
10
|
+
],
|
|
9
11
|
"renderer": "codebox",
|
|
10
12
|
"docs": "https://www.walkeros.io/docs/sources/web/cmps/usercentrics"
|
|
11
13
|
},
|
|
@@ -41,8 +43,8 @@
|
|
|
41
43
|
"update": "npx npm-check-updates -u && npm update"
|
|
42
44
|
},
|
|
43
45
|
"dependencies": {
|
|
44
|
-
"@walkeros/core": "
|
|
45
|
-
"@walkeros/collector": "
|
|
46
|
+
"@walkeros/core": "4.0.0-next-1773967844643",
|
|
47
|
+
"@walkeros/collector": "4.0.0-next-1773967844643"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {},
|
|
48
50
|
"repository": {
|