@walkeros/web-source-cmp-cookiepro 3.3.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.d.mts +39 -18
- package/dist/dev.d.ts +39 -18
- 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.js +44 -20
- package/dist/examples/index.mjs +44 -20
- 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 +79 -26
- package/package.json +3 -3
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/trigger.ts"],"sourcesContent":["import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, OneTrustAPI } from './types';\n\n// Export types for external usage\nexport * as SourceCookiePro from './types';\n\n// Export examples\nexport * from './examples';\n\n/**\n * Default category mapping from CookiePro/OneTrust to walkerOS consent groups.\n *\n * Keys use OneTrust's standard uppercase IDs (as shown in CookiePro dashboard).\n * Lookups are case-insensitive (normalized during init).\n *\n * Maps OneTrust's standard category IDs to walkerOS convention:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\nexport const DEFAULT_CATEGORY_MAP: Record<string, string> = {\n C0001: 'functional',\n C0002: 'analytics',\n C0003: 'functional',\n C0004: 'marketing',\n C0005: 'marketing',\n};\n\n/**\n * CookiePro/OneTrust consent management source for walkerOS.\n *\n * This source listens to CookiePro/OneTrust CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * Three detection paths:\n * 1. Already loaded: window.OneTrust + window.OptanonActiveGroups\n * 2. Init: Wraps OptanonWrapper (preserves existing)\n * 3. Change: OneTrustGroupsUpdated window event\n *\n * @example\n * ```typescript\n * import { sourceCookiePro } from '@walkeros/web-source-cmp-cookiepro';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceCookiePro,\n * config: {\n * settings: {\n * categoryMap: {\n * C0002: 'statistics', // Custom mapping\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceCookiePro: 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 (user overrides win)\n const mergedCategoryMap = {\n ...DEFAULT_CATEGORY_MAP,\n ...(config?.settings?.categoryMap ?? {}),\n };\n\n // Build normalized (lowercase) lookup map for case-insensitive matching\n const normalizedMap: Record<string, string> = {};\n Object.entries(mergedCategoryMap).forEach(([key, value]) => {\n normalizedMap[key.toLowerCase()] = value;\n });\n\n const settings: Settings = {\n categoryMap: mergedCategoryMap, // Preserves original casing for config\n explicitOnly: config?.settings?.explicitOnly ?? true,\n globalName: config?.settings?.globalName ?? 'OneTrust',\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track references for cleanup\n let eventListener: (() => void) | undefined;\n let originalOptanonWrapper: (() => void) | undefined;\n let wrappedOptanonWrapper = false;\n\n if (actualWindow) {\n const globalName = settings.globalName ?? 'OneTrust';\n\n /**\n * Collect all unique walkerOS group names from the normalizedMap.\n * Used to set explicit false for absent groups.\n */\n const allMappedGroups = new Set(Object.values(normalizedMap));\n\n /**\n * Parse OptanonActiveGroups string into walkerOS consent state.\n *\n * OptanonActiveGroups format: \",C0001,C0003,\" (comma-separated, leading/trailing commas)\n * Only active groups are listed. Absence means denied.\n * Uses case-insensitive comparison for category IDs via normalizedMap.\n * Only mapped categories produce consent entries (unmapped IDs are ignored).\n * Sets explicit false for all mapped groups not in the active list.\n */\n const parseActiveGroups = (activeGroups: string): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n // Initialize all mapped groups to false\n allMappedGroups.forEach((group) => {\n state[group] = false;\n });\n\n // Set active groups to true (case-insensitive via normalizedMap)\n activeGroups\n .split(',')\n .filter((id) => id.length > 0)\n .forEach((id) => {\n const mapped = normalizedMap[id.toLowerCase()];\n if (mapped) {\n state[mapped] = true;\n }\n });\n\n return state;\n };\n\n /**\n * Handle consent by reading current OptanonActiveGroups from window.\n * Checks explicitOnly against IsAlertBoxClosed when available.\n */\n const handleConsent = () => {\n const activeGroups = actualWindow.OptanonActiveGroups;\n if (activeGroups === undefined || activeGroups === null) return;\n\n // Check explicit consent if required\n if (settings.explicitOnly) {\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp?.IsAlertBoxClosed && !cmp.IsAlertBoxClosed()) return;\n }\n\n const state = parseActiveGroups(activeGroups);\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 // --- Detection path 1: Already loaded ---\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp && actualWindow.OptanonActiveGroups !== undefined) {\n handleConsent();\n }\n\n // --- Detection path 2: OptanonWrapper ---\n // Only wrap if SDK is not yet loaded (no already-loaded path).\n // Self-unwraps after first call -- the event listener handles all\n // subsequent changes, avoiding double-firing.\n if (!cmp) {\n originalOptanonWrapper = actualWindow.OptanonWrapper;\n wrappedOptanonWrapper = true;\n\n actualWindow.OptanonWrapper = () => {\n // Call original wrapper if it existed\n if (originalOptanonWrapper) originalOptanonWrapper();\n handleConsent();\n // Self-unwrap: restore original after first call (SDK init).\n // The OneTrustGroupsUpdated listener handles all future changes.\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n wrappedOptanonWrapper = false;\n };\n }\n\n // --- Detection path 3: OneTrustGroupsUpdated event ---\n eventListener = () => {\n handleConsent();\n };\n actualWindow.addEventListener('OneTrustGroupsUpdated', eventListener);\n }\n\n return {\n type: 'cookiepro',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n // Remove event listener\n if (actualWindow && eventListener) {\n actualWindow.removeEventListener(\n 'OneTrustGroupsUpdated',\n eventListener,\n );\n }\n // Restore original OptanonWrapper\n if (actualWindow && wrappedOptanonWrapper) {\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n }\n },\n };\n};\n\nexport default sourceCookiePro;\n","import type { Source, Elb } from '@walkeros/core';\n\n/**\n * OneTrust global API interface.\n *\n * Represents the subset of the OneTrust SDK we interact with.\n * The full SDK is much larger, but we only need consent-related methods.\n */\nexport interface OneTrustAPI {\n /** Returns true if user has made an explicit consent choice */\n IsAlertBoxClosed: () => boolean;\n /** Register a callback for consent changes (callback receives event with detail: string[]) */\n OnConsentChanged?: (fn: (event: { detail: string[] }) => void) => void;\n}\n\ndeclare global {\n interface Window {\n /** OneTrust SDK global object */\n OneTrust?: OneTrustAPI;\n /** Comma-separated string of active consent category IDs (e.g. \",C0001,C0003,\") */\n OptanonActiveGroups?: string;\n /** OneTrust callback function, called on SDK load and consent changes */\n OptanonWrapper?: () => void;\n /** CookiePro legacy alias for OneTrust */\n Optanon?: unknown;\n [key: string]: OneTrustAPI | unknown;\n }\n\n interface WindowEventMap {\n /** event.detail is an array of active group ID strings (e.g. [\"C0001\", \"C0002\"]) */\n OneTrustGroupsUpdated: CustomEvent<string[]>;\n }\n}\n\n/**\n * Settings for CookiePro/OneTrust source\n */\nexport interface Settings {\n /**\n * Map CookiePro category IDs to walkerOS consent groups.\n * Keys: CookiePro category IDs (e.g. 'C0001', 'C0002')\n * Values: walkerOS consent group names\n *\n * Comparison is case-insensitive (keys are normalized to lowercase during init).\n *\n * Default provides sensible mapping for standard OneTrust categories:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Checks OneTrust.IsAlertBoxClosed() -- only processes\n * consent if user has actively interacted with the banner.\n * When false: Processes any consent state including defaults.\n *\n * Default: true\n */\n explicitOnly?: boolean;\n\n /**\n * Custom name for window.OneTrust object.\n * Some implementations use a different global name.\n *\n * Default: 'OneTrust'\n */\n globalName?: string;\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 CookiePro source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for CookiePro 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","/**\n * Example CookiePro OptanonActiveGroups strings.\n *\n * These represent real consent states from CookiePro/OneTrust CMP.\n * Format: comma-separated active category IDs with leading/trailing commas.\n * Only active groups are listed. Absence means denied.\n */\n\n/**\n * Full consent - user accepted all categories\n */\nexport const fullConsent = ',C0001,C0002,C0003,C0004,C0005,';\n\n/**\n * Partial consent - necessary + functional only\n */\nexport const partialConsent = ',C0001,C0003,';\n\n/**\n * Minimal consent - only strictly necessary (always active)\n */\nexport const minimalConsent = ',C0001,';\n\n/**\n * Analytics only - necessary + performance\n */\nexport const analyticsOnlyConsent = ',C0001,C0002,';\n\n/**\n * Marketing only - necessary + targeting\n */\nexport const marketingOnlyConsent = ',C0001,C0004,';\n\n/**\n * Empty string - no consent yet or cleared\n */\nexport const emptyConsent = '';\n\n/**\n * Custom category IDs - some installations use custom IDs\n */\nexport const customCategoryConsent = ',C0001,CUSTOM01,CUSTOM02,';\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing OptanonActiveGroups\n * and mapping through the default categoryMap.\n *\n * Default map:\n * - C0001 -> functional\n * - C0002 -> analytics\n * - C0003 -> functional\n * - C0004 -> marketing\n * - C0005 -> marketing\n *\n * All mapped walkerOS groups get explicit true/false values.\n * Active groups -> true, absent groups -> false.\n */\n\n/**\n * Full consent mapped to walkerOS groups\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: true,\n};\n\n/**\n * Partial consent - necessary + functional mapped\n * C0001 -> functional (true), C0003 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Minimal consent - only strictly necessary\n * C0001 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Analytics only - necessary + performance\n * C0001 -> functional (true), C0002 -> analytics (true)\n * marketing absent -> false\n */\nexport const analyticsOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: false,\n};\n\n/**\n * Marketing only - necessary + targeting\n * C0001 -> functional (true), C0004 -> marketing (true)\n * analytics absent -> false\n */\nexport const marketingOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: true,\n};\n","import type { Source, Elb, Logger } from '@walkeros/core';\nimport type { OneTrustAPI } from '../types';\n\n/**\n * Example environment configurations for CookiePro 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\n/**\n * Create a mock OneTrust API object\n */\nexport const createMockOneTrustAPI = (\n isAlertBoxClosed = false,\n): OneTrustAPI => ({\n IsAlertBoxClosed: () => isAlertBoxClosed,\n});\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,C0002,C0003,C0004,C0005,',\n out: {\n functional: true,\n analytics: true,\n marketing: true,\n },\n};\n\nexport const minimalConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,',\n out: {\n functional: true,\n analytics: false,\n marketing: false,\n },\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description: 'Custom categoryMap remaps C0002 from analytics to statistics',\n trigger: { type: 'consent' },\n in: ',C0001,C0002,',\n mapping: { categoryMap: { C0002: 'statistics' } },\n out: {\n functional: true,\n statistics: true,\n marketing: false,\n },\n};\n\nexport const sdkLoadedDetection: Flow.StepExample = {\n description:\n 'Immediate detection when OneTrust SDK is already loaded with IsAlertBoxClosed() = true',\n trigger: { type: 'consent' },\n in: ',C0001,C0003,C0004,',\n out: {\n functional: true,\n analytics: false,\n marketing: true,\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\nconst createTrigger: Trigger.CreateFn<string, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<string, void> = () => async (content: string) => {\n // Pre-init: set OneTrust globals (source reads these during init)\n const win = window as unknown as Record<string, unknown>;\n win.OptanonActiveGroups = content;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n\n // Lazy startFlow — source checks globals immediately 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\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Sets OptanonActiveGroups and OneTrust globals before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n const win = env.window as Window & Record<string, unknown>;\n if (typeof input !== 'string') return;\n win.OptanonActiveGroups = input;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["fullConsent","minimalConsent","trigger","cmp"]}
|
|
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, OneTrustAPI } from './types';\n\n// Export types for external usage\nexport * as SourceCookiePro from './types';\n\n// Export examples\nexport * from './examples';\n\n/**\n * Default category mapping from CookiePro/OneTrust to walkerOS consent groups.\n *\n * Keys use OneTrust's standard uppercase IDs (as shown in CookiePro dashboard).\n * Lookups are case-insensitive (normalized during init).\n *\n * Maps OneTrust's standard category IDs to walkerOS convention:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\nexport const DEFAULT_CATEGORY_MAP: Record<string, string> = {\n C0001: 'functional',\n C0002: 'analytics',\n C0003: 'functional',\n C0004: 'marketing',\n C0005: 'marketing',\n};\n\n/**\n * CookiePro/OneTrust consent management source for walkerOS.\n *\n * This source listens to CookiePro/OneTrust CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * Three detection paths:\n * 1. Already loaded: window.OneTrust + window.OptanonActiveGroups\n * 2. Init: Wraps OptanonWrapper (preserves existing)\n * 3. Change: OneTrustGroupsUpdated window event\n *\n * @example\n * ```typescript\n * import { sourceCookiePro } from '@walkeros/web-source-cmp-cookiepro';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceCookiePro,\n * config: {\n * settings: {\n * categoryMap: {\n * C0002: 'statistics', // Custom mapping\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceCookiePro: 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 (user overrides win)\n const mergedCategoryMap = {\n ...DEFAULT_CATEGORY_MAP,\n ...(config?.settings?.categoryMap ?? {}),\n };\n\n // Build normalized (lowercase) lookup map for case-insensitive matching\n const normalizedMap: Record<string, string> = {};\n Object.entries(mergedCategoryMap).forEach(([key, value]) => {\n normalizedMap[key.toLowerCase()] = value;\n });\n\n const settings: Settings = {\n categoryMap: mergedCategoryMap, // Preserves original casing for config\n explicitOnly: config?.settings?.explicitOnly ?? true,\n globalName: config?.settings?.globalName ?? 'OneTrust',\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track references for cleanup\n let eventListener: (() => void) | undefined;\n let originalOptanonWrapper: (() => void) | undefined;\n let wrappedOptanonWrapper = false;\n\n if (actualWindow) {\n const globalName = settings.globalName ?? 'OneTrust';\n\n /**\n * Collect all unique walkerOS group names from the normalizedMap.\n * Used to set explicit false for absent groups.\n */\n const allMappedGroups = new Set(Object.values(normalizedMap));\n\n /**\n * Parse OptanonActiveGroups string into walkerOS consent state.\n *\n * OptanonActiveGroups format: \",C0001,C0003,\" (comma-separated, leading/trailing commas)\n * Only active groups are listed. Absence means denied.\n * Uses case-insensitive comparison for category IDs via normalizedMap.\n * Only mapped categories produce consent entries (unmapped IDs are ignored).\n * Sets explicit false for all mapped groups not in the active list.\n */\n const parseActiveGroups = (activeGroups: string): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n // Initialize all mapped groups to false\n allMappedGroups.forEach((group) => {\n state[group] = false;\n });\n\n // Set active groups to true (case-insensitive via normalizedMap)\n activeGroups\n .split(',')\n .filter((id) => id.length > 0)\n .forEach((id) => {\n const mapped = normalizedMap[id.toLowerCase()];\n if (mapped) {\n state[mapped] = true;\n }\n });\n\n return state;\n };\n\n /**\n * Handle consent by reading current OptanonActiveGroups from window.\n * Checks explicitOnly against IsAlertBoxClosed when available.\n */\n const handleConsent = () => {\n const activeGroups = actualWindow.OptanonActiveGroups;\n if (activeGroups === undefined || activeGroups === null) return;\n\n // Check explicit consent if required\n if (settings.explicitOnly) {\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp?.IsAlertBoxClosed && !cmp.IsAlertBoxClosed()) return;\n }\n\n const state = parseActiveGroups(activeGroups);\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 // --- Detection path 1: Already loaded ---\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp && actualWindow.OptanonActiveGroups !== undefined) {\n handleConsent();\n }\n\n // --- Detection path 2: OptanonWrapper ---\n // Only wrap if SDK is not yet loaded (no already-loaded path).\n // Self-unwraps after first call -- the event listener handles all\n // subsequent changes, avoiding double-firing.\n if (!cmp) {\n originalOptanonWrapper = actualWindow.OptanonWrapper;\n wrappedOptanonWrapper = true;\n\n actualWindow.OptanonWrapper = () => {\n // Call original wrapper if it existed\n if (originalOptanonWrapper) originalOptanonWrapper();\n handleConsent();\n // Self-unwrap: restore original after first call (SDK init).\n // The OneTrustGroupsUpdated listener handles all future changes.\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n wrappedOptanonWrapper = false;\n };\n }\n\n // --- Detection path 3: OneTrustGroupsUpdated event ---\n eventListener = () => {\n handleConsent();\n };\n actualWindow.addEventListener('OneTrustGroupsUpdated', eventListener);\n }\n\n return {\n type: 'cookiepro',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n // Remove event listener\n if (actualWindow && eventListener) {\n actualWindow.removeEventListener(\n 'OneTrustGroupsUpdated',\n eventListener,\n );\n }\n // Restore original OptanonWrapper\n if (actualWindow && wrappedOptanonWrapper) {\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n }\n },\n };\n};\n\nexport default sourceCookiePro;\n","import type { Source, Elb } from '@walkeros/core';\n\n/**\n * OneTrust global API interface.\n *\n * Represents the subset of the OneTrust SDK we interact with.\n * The full SDK is much larger, but we only need consent-related methods.\n */\nexport interface OneTrustAPI {\n /** Returns true if user has made an explicit consent choice */\n IsAlertBoxClosed: () => boolean;\n /** Register a callback for consent changes (callback receives event with detail: string[]) */\n OnConsentChanged?: (fn: (event: { detail: string[] }) => void) => void;\n}\n\ndeclare global {\n interface Window {\n /** OneTrust SDK global object */\n OneTrust?: OneTrustAPI;\n /** Comma-separated string of active consent category IDs (e.g. \",C0001,C0003,\") */\n OptanonActiveGroups?: string;\n /** OneTrust callback function, called on SDK load and consent changes */\n OptanonWrapper?: () => void;\n /** CookiePro legacy alias for OneTrust */\n Optanon?: unknown;\n [key: string]: OneTrustAPI | unknown;\n }\n\n interface WindowEventMap {\n /** event.detail is an array of active group ID strings (e.g. [\"C0001\", \"C0002\"]) */\n OneTrustGroupsUpdated: CustomEvent<string[]>;\n }\n}\n\n/**\n * Settings for CookiePro/OneTrust source\n */\nexport interface Settings {\n /**\n * Map CookiePro category IDs to walkerOS consent groups.\n * Keys: CookiePro category IDs (e.g. 'C0001', 'C0002')\n * Values: walkerOS consent group names\n *\n * Comparison is case-insensitive (keys are normalized to lowercase during init).\n *\n * Default provides sensible mapping for standard OneTrust categories:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Checks OneTrust.IsAlertBoxClosed() -- only processes\n * consent if user has actively interacted with the banner.\n * When false: Processes any consent state including defaults.\n *\n * Default: true\n */\n explicitOnly?: boolean;\n\n /**\n * Custom name for window.OneTrust object.\n * Some implementations use a different global name.\n *\n * Default: 'OneTrust'\n */\n globalName?: string;\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 CookiePro source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for CookiePro 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","/**\n * Example CookiePro OptanonActiveGroups strings.\n *\n * These represent real consent states from CookiePro/OneTrust CMP.\n * Format: comma-separated active category IDs with leading/trailing commas.\n * Only active groups are listed. Absence means denied.\n */\n\n/**\n * Full consent - user accepted all categories\n */\nexport const fullConsent = ',C0001,C0002,C0003,C0004,C0005,';\n\n/**\n * Partial consent - necessary + functional only\n */\nexport const partialConsent = ',C0001,C0003,';\n\n/**\n * Minimal consent - only strictly necessary (always active)\n */\nexport const minimalConsent = ',C0001,';\n\n/**\n * Analytics only - necessary + performance\n */\nexport const analyticsOnlyConsent = ',C0001,C0002,';\n\n/**\n * Marketing only - necessary + targeting\n */\nexport const marketingOnlyConsent = ',C0001,C0004,';\n\n/**\n * Empty string - no consent yet or cleared\n */\nexport const emptyConsent = '';\n\n/**\n * Custom category IDs - some installations use custom IDs\n */\nexport const customCategoryConsent = ',C0001,CUSTOM01,CUSTOM02,';\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing OptanonActiveGroups\n * and mapping through the default categoryMap.\n *\n * Default map:\n * - C0001 -> functional\n * - C0002 -> analytics\n * - C0003 -> functional\n * - C0004 -> marketing\n * - C0005 -> marketing\n *\n * All mapped walkerOS groups get explicit true/false values.\n * Active groups -> true, absent groups -> false.\n */\n\n/**\n * Full consent mapped to walkerOS groups\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: true,\n};\n\n/**\n * Partial consent - necessary + functional mapped\n * C0001 -> functional (true), C0003 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Minimal consent - only strictly necessary\n * C0001 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Analytics only - necessary + performance\n * C0001 -> functional (true), C0002 -> analytics (true)\n * marketing absent -> false\n */\nexport const analyticsOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: false,\n};\n\n/**\n * Marketing only - necessary + targeting\n * C0001 -> functional (true), C0004 -> marketing (true)\n * analytics absent -> false\n */\nexport const marketingOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: true,\n};\n","import type { Source, Elb, Logger } from '@walkeros/core';\nimport type { OneTrustAPI } from '../types';\n\n/**\n * Example environment configurations for CookiePro 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\n/**\n * Create a mock OneTrust API object\n */\nexport const createMockOneTrustAPI = (\n isAlertBoxClosed = false,\n): OneTrustAPI => ({\n IsAlertBoxClosed: () => isAlertBoxClosed,\n});\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,C0002,C0003,C0004,C0005,',\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n analytics: true,\n marketing: true,\n },\n ],\n ],\n};\n\nexport const minimalConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,',\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n analytics: false,\n marketing: false,\n },\n ],\n ],\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description: 'Custom categoryMap remaps C0002 from analytics to statistics',\n trigger: { type: 'consent' },\n in: ',C0001,C0002,',\n mapping: { categoryMap: { C0002: 'statistics' } },\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n statistics: true,\n marketing: false,\n },\n ],\n ],\n};\n\nexport const sdkLoadedDetection: Flow.StepExample = {\n description:\n 'Immediate detection when OneTrust SDK is already loaded with IsAlertBoxClosed() = true',\n trigger: { type: 'consent' },\n in: ',C0001,C0003,C0004,',\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n analytics: false,\n marketing: true,\n },\n ],\n ],\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\nconst createTrigger: Trigger.CreateFn<string, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<string, void> = () => async (content: string) => {\n // Pre-init: set OneTrust globals (source reads these during init)\n const win = window as unknown as Record<string, unknown>;\n win.OptanonActiveGroups = content;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n\n // Lazy startFlow — source checks globals immediately 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\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Sets OptanonActiveGroups and OneTrust globals before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n const win = env.window as Window & Record<string, unknown>;\n if (typeof input !== 'string') return;\n win.OptanonActiveGroups = input;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n};\n\nexport { createTrigger, trigger };\n"],"mappings":"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","names":["fullConsent","minimalConsent","trigger","cmp"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=Object.defineProperty,n={},e=",C0001,C0002,C0003,C0004,C0005,",o=",C0001,C0003,",r=",C0001,",
|
|
1
|
+
var t=Object.defineProperty,n={},e=",C0001,C0002,C0003,C0004,C0005,",o=",C0001,C0003,",r=",C0001,",a=",C0001,C0002,",i=",C0001,C0004,",l="",s=",C0001,CUSTOM01,CUSTOM02,",c={functional:!0,analytics:!0,marketing:!0},u={functional:!0,analytics:!1,marketing:!1},p={functional:!0,analytics:!1,marketing:!1},g={functional:!0,analytics:!0,marketing:!1},C={functional:!0,analytics:!1,marketing:!0},d=()=>{},y=()=>()=>Promise.resolve({ok:!0}),f={error:d,warn:d,info:d,debug:d,throw:t=>{throw"string"==typeof t?new Error(t):t},json:d,scope:()=>f},m=(t=!1)=>({IsAlertBoxClosed:()=>t}),v={};((n,e)=>{for(var o in e)t(n,o,{get:e[o],enumerable:!0})})(v,{categoryMapOverride:()=>k,fullConsent:()=>w,minimalConsent:()=>O,sdkLoadedDetection:()=>b});var w={trigger:{type:"consent"},in:",C0001,C0002,C0003,C0004,C0005,",out:[["elb","walker consent",{functional:!0,analytics:!0,marketing:!0}]]},O={trigger:{type:"consent"},in:",C0001,",out:[["elb","walker consent",{functional:!0,analytics:!1,marketing:!1}]]},k={description:"Custom categoryMap remaps C0002 from analytics to statistics",trigger:{type:"consent"},in:",C0001,C0002,",mapping:{categoryMap:{C0002:"statistics"}},out:[["elb","walker consent",{functional:!0,statistics:!0,marketing:!1}]]},b={description:"Immediate detection when OneTrust SDK is already loaded with IsAlertBoxClosed() = true",trigger:{type:"consent"},in:",C0001,C0003,C0004,",out:[["elb","walker consent",{functional:!0,analytics:!1,marketing:!0}]]};import{startFlow as h}from"@walkeros/collector";var T=async t=>{let n;return{get flow(){return n},trigger:()=>async e=>{var o;const r=window;if(r.OptanonActiveGroups=e,r.OneTrust={IsAlertBoxClosed:()=>!0},!n){const e=await h({...t,run:null==(o=t.run)||o});n={collector:e.collector,elb:e.elb}}}}},x=(t,n)=>{const e=n.window;"string"==typeof t&&(e.OptanonActiveGroups=t,e.OneTrust={IsAlertBoxClosed:()=>!0})},A={C0001:"functional",C0002:"analytics",C0003:"functional",C0004:"marketing",C0005:"marketing"},I=async t=>{var n,e,o,r,a,i,l,s;const{config:c,env:u}=t,{elb:p}=u,g=null!=(n=u.window)?n:void 0!==globalThis.window?globalThis.window:void 0,C={...A,...null!=(o=null==(e=null==c?void 0:c.settings)?void 0:e.categoryMap)?o:{}},d={};Object.entries(C).forEach(([t,n])=>{d[t.toLowerCase()]=n});const y={categoryMap:C,explicitOnly:null==(a=null==(r=null==c?void 0:c.settings)?void 0:r.explicitOnly)||a,globalName:null!=(l=null==(i=null==c?void 0:c.settings)?void 0:i.globalName)?l:"OneTrust"},f={settings:y};let m,v,w=!1;if(g){const t=null!=(s=y.globalName)?s:"OneTrust",n=new Set(Object.values(d)),e=t=>{const e={};return n.forEach(t=>{e[t]=!1}),t.split(",").filter(t=>t.length>0).forEach(t=>{const n=d[t.toLowerCase()];n&&(e[n]=!0)}),e},o=()=>{const n=g.OptanonActiveGroups;if(null==n)return;if(y.explicitOnly){const n=g[t];if((null==n?void 0:n.IsAlertBoxClosed)&&!n.IsAlertBoxClosed())return}const o=e(n);Object.keys(o).length>0&&p("walker consent",o)},r=g[t];r&&void 0!==g.OptanonActiveGroups&&o(),r||(v=g.OptanonWrapper,w=!0,g.OptanonWrapper=()=>{v&&v(),o(),g.OptanonWrapper=v,w=!1}),m=()=>{o()},g.addEventListener("OneTrustGroupsUpdated",m)}return{type:"cookiepro",config:f,push:p,destroy:async t=>{g&&m&&g.removeEventListener("OneTrustGroupsUpdated",m),g&&w&&(g.OptanonWrapper=v)}}},M=I;export{A as DEFAULT_CATEGORY_MAP,n as SourceCookiePro,a as analyticsOnlyConsent,g as analyticsOnlyMapped,y as createMockElbFn,m as createMockOneTrustAPI,T as createTrigger,s as customCategoryConsent,M as default,l as emptyConsent,e as fullConsent,c as fullConsentMapped,i as marketingOnlyConsent,C as marketingOnlyMapped,r as minimalConsent,p as minimalConsentMapped,f as noopLogger,o as partialConsent,u as partialConsentMapped,I as sourceCookiePro,v as step,x 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/trigger.ts","../src/index.ts"],"sourcesContent":["import type { Source, Elb } from '@walkeros/core';\n\n/**\n * OneTrust global API interface.\n *\n * Represents the subset of the OneTrust SDK we interact with.\n * The full SDK is much larger, but we only need consent-related methods.\n */\nexport interface OneTrustAPI {\n /** Returns true if user has made an explicit consent choice */\n IsAlertBoxClosed: () => boolean;\n /** Register a callback for consent changes (callback receives event with detail: string[]) */\n OnConsentChanged?: (fn: (event: { detail: string[] }) => void) => void;\n}\n\ndeclare global {\n interface Window {\n /** OneTrust SDK global object */\n OneTrust?: OneTrustAPI;\n /** Comma-separated string of active consent category IDs (e.g. \",C0001,C0003,\") */\n OptanonActiveGroups?: string;\n /** OneTrust callback function, called on SDK load and consent changes */\n OptanonWrapper?: () => void;\n /** CookiePro legacy alias for OneTrust */\n Optanon?: unknown;\n [key: string]: OneTrustAPI | unknown;\n }\n\n interface WindowEventMap {\n /** event.detail is an array of active group ID strings (e.g. [\"C0001\", \"C0002\"]) */\n OneTrustGroupsUpdated: CustomEvent<string[]>;\n }\n}\n\n/**\n * Settings for CookiePro/OneTrust source\n */\nexport interface Settings {\n /**\n * Map CookiePro category IDs to walkerOS consent groups.\n * Keys: CookiePro category IDs (e.g. 'C0001', 'C0002')\n * Values: walkerOS consent group names\n *\n * Comparison is case-insensitive (keys are normalized to lowercase during init).\n *\n * Default provides sensible mapping for standard OneTrust categories:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Checks OneTrust.IsAlertBoxClosed() -- only processes\n * consent if user has actively interacted with the banner.\n * When false: Processes any consent state including defaults.\n *\n * Default: true\n */\n explicitOnly?: boolean;\n\n /**\n * Custom name for window.OneTrust object.\n * Some implementations use a different global name.\n *\n * Default: 'OneTrust'\n */\n globalName?: string;\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 CookiePro source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for CookiePro 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","/**\n * Example CookiePro OptanonActiveGroups strings.\n *\n * These represent real consent states from CookiePro/OneTrust CMP.\n * Format: comma-separated active category IDs with leading/trailing commas.\n * Only active groups are listed. Absence means denied.\n */\n\n/**\n * Full consent - user accepted all categories\n */\nexport const fullConsent = ',C0001,C0002,C0003,C0004,C0005,';\n\n/**\n * Partial consent - necessary + functional only\n */\nexport const partialConsent = ',C0001,C0003,';\n\n/**\n * Minimal consent - only strictly necessary (always active)\n */\nexport const minimalConsent = ',C0001,';\n\n/**\n * Analytics only - necessary + performance\n */\nexport const analyticsOnlyConsent = ',C0001,C0002,';\n\n/**\n * Marketing only - necessary + targeting\n */\nexport const marketingOnlyConsent = ',C0001,C0004,';\n\n/**\n * Empty string - no consent yet or cleared\n */\nexport const emptyConsent = '';\n\n/**\n * Custom category IDs - some installations use custom IDs\n */\nexport const customCategoryConsent = ',C0001,CUSTOM01,CUSTOM02,';\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing OptanonActiveGroups\n * and mapping through the default categoryMap.\n *\n * Default map:\n * - C0001 -> functional\n * - C0002 -> analytics\n * - C0003 -> functional\n * - C0004 -> marketing\n * - C0005 -> marketing\n *\n * All mapped walkerOS groups get explicit true/false values.\n * Active groups -> true, absent groups -> false.\n */\n\n/**\n * Full consent mapped to walkerOS groups\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: true,\n};\n\n/**\n * Partial consent - necessary + functional mapped\n * C0001 -> functional (true), C0003 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Minimal consent - only strictly necessary\n * C0001 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Analytics only - necessary + performance\n * C0001 -> functional (true), C0002 -> analytics (true)\n * marketing absent -> false\n */\nexport const analyticsOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: false,\n};\n\n/**\n * Marketing only - necessary + targeting\n * C0001 -> functional (true), C0004 -> marketing (true)\n * analytics absent -> false\n */\nexport const marketingOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: true,\n};\n","import type { Source, Elb, Logger } from '@walkeros/core';\nimport type { OneTrustAPI } from '../types';\n\n/**\n * Example environment configurations for CookiePro 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\n/**\n * Create a mock OneTrust API object\n */\nexport const createMockOneTrustAPI = (\n isAlertBoxClosed = false,\n): OneTrustAPI => ({\n IsAlertBoxClosed: () => isAlertBoxClosed,\n});\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,C0002,C0003,C0004,C0005,',\n out: {\n functional: true,\n analytics: true,\n marketing: true,\n },\n};\n\nexport const minimalConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,',\n out: {\n functional: true,\n analytics: false,\n marketing: false,\n },\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description: 'Custom categoryMap remaps C0002 from analytics to statistics',\n trigger: { type: 'consent' },\n in: ',C0001,C0002,',\n mapping: { categoryMap: { C0002: 'statistics' } },\n out: {\n functional: true,\n statistics: true,\n marketing: false,\n },\n};\n\nexport const sdkLoadedDetection: Flow.StepExample = {\n description:\n 'Immediate detection when OneTrust SDK is already loaded with IsAlertBoxClosed() = true',\n trigger: { type: 'consent' },\n in: ',C0001,C0003,C0004,',\n out: {\n functional: true,\n analytics: false,\n marketing: true,\n },\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\nconst createTrigger: Trigger.CreateFn<string, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<string, void> = () => async (content: string) => {\n // Pre-init: set OneTrust globals (source reads these during init)\n const win = window as unknown as Record<string, unknown>;\n win.OptanonActiveGroups = content;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n\n // Lazy startFlow — source checks globals immediately 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\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Sets OptanonActiveGroups and OneTrust globals before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n const win = env.window as Window & Record<string, unknown>;\n if (typeof input !== 'string') return;\n win.OptanonActiveGroups = input;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n};\n\nexport { createTrigger, trigger };\n","import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, OneTrustAPI } from './types';\n\n// Export types for external usage\nexport * as SourceCookiePro from './types';\n\n// Export examples\nexport * from './examples';\n\n/**\n * Default category mapping from CookiePro/OneTrust to walkerOS consent groups.\n *\n * Keys use OneTrust's standard uppercase IDs (as shown in CookiePro dashboard).\n * Lookups are case-insensitive (normalized during init).\n *\n * Maps OneTrust's standard category IDs to walkerOS convention:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\nexport const DEFAULT_CATEGORY_MAP: Record<string, string> = {\n C0001: 'functional',\n C0002: 'analytics',\n C0003: 'functional',\n C0004: 'marketing',\n C0005: 'marketing',\n};\n\n/**\n * CookiePro/OneTrust consent management source for walkerOS.\n *\n * This source listens to CookiePro/OneTrust CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * Three detection paths:\n * 1. Already loaded: window.OneTrust + window.OptanonActiveGroups\n * 2. Init: Wraps OptanonWrapper (preserves existing)\n * 3. Change: OneTrustGroupsUpdated window event\n *\n * @example\n * ```typescript\n * import { sourceCookiePro } from '@walkeros/web-source-cmp-cookiepro';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceCookiePro,\n * config: {\n * settings: {\n * categoryMap: {\n * C0002: 'statistics', // Custom mapping\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceCookiePro: 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 (user overrides win)\n const mergedCategoryMap = {\n ...DEFAULT_CATEGORY_MAP,\n ...(config?.settings?.categoryMap ?? {}),\n };\n\n // Build normalized (lowercase) lookup map for case-insensitive matching\n const normalizedMap: Record<string, string> = {};\n Object.entries(mergedCategoryMap).forEach(([key, value]) => {\n normalizedMap[key.toLowerCase()] = value;\n });\n\n const settings: Settings = {\n categoryMap: mergedCategoryMap, // Preserves original casing for config\n explicitOnly: config?.settings?.explicitOnly ?? true,\n globalName: config?.settings?.globalName ?? 'OneTrust',\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track references for cleanup\n let eventListener: (() => void) | undefined;\n let originalOptanonWrapper: (() => void) | undefined;\n let wrappedOptanonWrapper = false;\n\n if (actualWindow) {\n const globalName = settings.globalName ?? 'OneTrust';\n\n /**\n * Collect all unique walkerOS group names from the normalizedMap.\n * Used to set explicit false for absent groups.\n */\n const allMappedGroups = new Set(Object.values(normalizedMap));\n\n /**\n * Parse OptanonActiveGroups string into walkerOS consent state.\n *\n * OptanonActiveGroups format: \",C0001,C0003,\" (comma-separated, leading/trailing commas)\n * Only active groups are listed. Absence means denied.\n * Uses case-insensitive comparison for category IDs via normalizedMap.\n * Only mapped categories produce consent entries (unmapped IDs are ignored).\n * Sets explicit false for all mapped groups not in the active list.\n */\n const parseActiveGroups = (activeGroups: string): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n // Initialize all mapped groups to false\n allMappedGroups.forEach((group) => {\n state[group] = false;\n });\n\n // Set active groups to true (case-insensitive via normalizedMap)\n activeGroups\n .split(',')\n .filter((id) => id.length > 0)\n .forEach((id) => {\n const mapped = normalizedMap[id.toLowerCase()];\n if (mapped) {\n state[mapped] = true;\n }\n });\n\n return state;\n };\n\n /**\n * Handle consent by reading current OptanonActiveGroups from window.\n * Checks explicitOnly against IsAlertBoxClosed when available.\n */\n const handleConsent = () => {\n const activeGroups = actualWindow.OptanonActiveGroups;\n if (activeGroups === undefined || activeGroups === null) return;\n\n // Check explicit consent if required\n if (settings.explicitOnly) {\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp?.IsAlertBoxClosed && !cmp.IsAlertBoxClosed()) return;\n }\n\n const state = parseActiveGroups(activeGroups);\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 // --- Detection path 1: Already loaded ---\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp && actualWindow.OptanonActiveGroups !== undefined) {\n handleConsent();\n }\n\n // --- Detection path 2: OptanonWrapper ---\n // Only wrap if SDK is not yet loaded (no already-loaded path).\n // Self-unwraps after first call -- the event listener handles all\n // subsequent changes, avoiding double-firing.\n if (!cmp) {\n originalOptanonWrapper = actualWindow.OptanonWrapper;\n wrappedOptanonWrapper = true;\n\n actualWindow.OptanonWrapper = () => {\n // Call original wrapper if it existed\n if (originalOptanonWrapper) originalOptanonWrapper();\n handleConsent();\n // Self-unwrap: restore original after first call (SDK init).\n // The OneTrustGroupsUpdated listener handles all future changes.\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n wrappedOptanonWrapper = false;\n };\n }\n\n // --- Detection path 3: OneTrustGroupsUpdated event ---\n eventListener = () => {\n handleConsent();\n };\n actualWindow.addEventListener('OneTrustGroupsUpdated', eventListener);\n }\n\n return {\n type: 'cookiepro',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n // Remove event listener\n if (actualWindow && eventListener) {\n actualWindow.removeEventListener(\n 'OneTrustGroupsUpdated',\n eventListener,\n );\n }\n // Restore original OptanonWrapper\n if (actualWindow && wrappedOptanonWrapper) {\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n }\n },\n };\n};\n\nexport default sourceCookiePro;\n"],"mappings":"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","names":["fullConsent","minimalConsent","trigger","cmp"]}
|
|
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 * OneTrust global API interface.\n *\n * Represents the subset of the OneTrust SDK we interact with.\n * The full SDK is much larger, but we only need consent-related methods.\n */\nexport interface OneTrustAPI {\n /** Returns true if user has made an explicit consent choice */\n IsAlertBoxClosed: () => boolean;\n /** Register a callback for consent changes (callback receives event with detail: string[]) */\n OnConsentChanged?: (fn: (event: { detail: string[] }) => void) => void;\n}\n\ndeclare global {\n interface Window {\n /** OneTrust SDK global object */\n OneTrust?: OneTrustAPI;\n /** Comma-separated string of active consent category IDs (e.g. \",C0001,C0003,\") */\n OptanonActiveGroups?: string;\n /** OneTrust callback function, called on SDK load and consent changes */\n OptanonWrapper?: () => void;\n /** CookiePro legacy alias for OneTrust */\n Optanon?: unknown;\n [key: string]: OneTrustAPI | unknown;\n }\n\n interface WindowEventMap {\n /** event.detail is an array of active group ID strings (e.g. [\"C0001\", \"C0002\"]) */\n OneTrustGroupsUpdated: CustomEvent<string[]>;\n }\n}\n\n/**\n * Settings for CookiePro/OneTrust source\n */\nexport interface Settings {\n /**\n * Map CookiePro category IDs to walkerOS consent groups.\n * Keys: CookiePro category IDs (e.g. 'C0001', 'C0002')\n * Values: walkerOS consent group names\n *\n * Comparison is case-insensitive (keys are normalized to lowercase during init).\n *\n * Default provides sensible mapping for standard OneTrust categories:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Checks OneTrust.IsAlertBoxClosed() -- only processes\n * consent if user has actively interacted with the banner.\n * When false: Processes any consent state including defaults.\n *\n * Default: true\n */\n explicitOnly?: boolean;\n\n /**\n * Custom name for window.OneTrust object.\n * Some implementations use a different global name.\n *\n * Default: 'OneTrust'\n */\n globalName?: string;\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 CookiePro source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for CookiePro 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","/**\n * Example CookiePro OptanonActiveGroups strings.\n *\n * These represent real consent states from CookiePro/OneTrust CMP.\n * Format: comma-separated active category IDs with leading/trailing commas.\n * Only active groups are listed. Absence means denied.\n */\n\n/**\n * Full consent - user accepted all categories\n */\nexport const fullConsent = ',C0001,C0002,C0003,C0004,C0005,';\n\n/**\n * Partial consent - necessary + functional only\n */\nexport const partialConsent = ',C0001,C0003,';\n\n/**\n * Minimal consent - only strictly necessary (always active)\n */\nexport const minimalConsent = ',C0001,';\n\n/**\n * Analytics only - necessary + performance\n */\nexport const analyticsOnlyConsent = ',C0001,C0002,';\n\n/**\n * Marketing only - necessary + targeting\n */\nexport const marketingOnlyConsent = ',C0001,C0004,';\n\n/**\n * Empty string - no consent yet or cleared\n */\nexport const emptyConsent = '';\n\n/**\n * Custom category IDs - some installations use custom IDs\n */\nexport const customCategoryConsent = ',C0001,CUSTOM01,CUSTOM02,';\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after parsing OptanonActiveGroups\n * and mapping through the default categoryMap.\n *\n * Default map:\n * - C0001 -> functional\n * - C0002 -> analytics\n * - C0003 -> functional\n * - C0004 -> marketing\n * - C0005 -> marketing\n *\n * All mapped walkerOS groups get explicit true/false values.\n * Active groups -> true, absent groups -> false.\n */\n\n/**\n * Full consent mapped to walkerOS groups\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: true,\n};\n\n/**\n * Partial consent - necessary + functional mapped\n * C0001 -> functional (true), C0003 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Minimal consent - only strictly necessary\n * C0001 -> functional (true)\n * analytics and marketing absent -> false\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Analytics only - necessary + performance\n * C0001 -> functional (true), C0002 -> analytics (true)\n * marketing absent -> false\n */\nexport const analyticsOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: false,\n};\n\n/**\n * Marketing only - necessary + targeting\n * C0001 -> functional (true), C0004 -> marketing (true)\n * analytics absent -> false\n */\nexport const marketingOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: true,\n};\n","import type { Source, Elb, Logger } from '@walkeros/core';\nimport type { OneTrustAPI } from '../types';\n\n/**\n * Example environment configurations for CookiePro 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\n/**\n * Create a mock OneTrust API object\n */\nexport const createMockOneTrustAPI = (\n isAlertBoxClosed = false,\n): OneTrustAPI => ({\n IsAlertBoxClosed: () => isAlertBoxClosed,\n});\n","import type { Flow } from '@walkeros/core';\n\nexport const fullConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,C0002,C0003,C0004,C0005,',\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n analytics: true,\n marketing: true,\n },\n ],\n ],\n};\n\nexport const minimalConsent: Flow.StepExample = {\n trigger: { type: 'consent' },\n in: ',C0001,',\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n analytics: false,\n marketing: false,\n },\n ],\n ],\n};\n\nexport const categoryMapOverride: Flow.StepExample = {\n description: 'Custom categoryMap remaps C0002 from analytics to statistics',\n trigger: { type: 'consent' },\n in: ',C0001,C0002,',\n mapping: { categoryMap: { C0002: 'statistics' } },\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n statistics: true,\n marketing: false,\n },\n ],\n ],\n};\n\nexport const sdkLoadedDetection: Flow.StepExample = {\n description:\n 'Immediate detection when OneTrust SDK is already loaded with IsAlertBoxClosed() = true',\n trigger: { type: 'consent' },\n in: ',C0001,C0003,C0004,',\n out: [\n [\n 'elb',\n 'walker consent',\n {\n functional: true,\n analytics: false,\n marketing: true,\n },\n ],\n ],\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\n\nconst createTrigger: Trigger.CreateFn<string, void> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<string, void> = () => async (content: string) => {\n // Pre-init: set OneTrust globals (source reads these during init)\n const win = window as unknown as Record<string, unknown>;\n win.OptanonActiveGroups = content;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n\n // Lazy startFlow — source checks globals immediately 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\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\n/** Sets OptanonActiveGroups and OneTrust globals before source init. */\nconst trigger = (input: unknown, env: Record<string, unknown>): void => {\n const win = env.window as Window & Record<string, unknown>;\n if (typeof input !== 'string') return;\n win.OptanonActiveGroups = input;\n win.OneTrust = { IsAlertBoxClosed: () => true };\n};\n\nexport { createTrigger, trigger };\n","import type { Source, WalkerOS } from '@walkeros/core';\nimport type { Types, Settings, OneTrustAPI } from './types';\n\n// Export types for external usage\nexport * as SourceCookiePro from './types';\n\n// Export examples\nexport * from './examples';\n\n/**\n * Default category mapping from CookiePro/OneTrust to walkerOS consent groups.\n *\n * Keys use OneTrust's standard uppercase IDs (as shown in CookiePro dashboard).\n * Lookups are case-insensitive (normalized during init).\n *\n * Maps OneTrust's standard category IDs to walkerOS convention:\n * - C0001 (Strictly Necessary) -> functional\n * - C0002 (Performance) -> analytics\n * - C0003 (Functional) -> functional\n * - C0004 (Targeting) -> marketing\n * - C0005 (Social Media) -> marketing\n */\nexport const DEFAULT_CATEGORY_MAP: Record<string, string> = {\n C0001: 'functional',\n C0002: 'analytics',\n C0003: 'functional',\n C0004: 'marketing',\n C0005: 'marketing',\n};\n\n/**\n * CookiePro/OneTrust consent management source for walkerOS.\n *\n * This source listens to CookiePro/OneTrust CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * Three detection paths:\n * 1. Already loaded: window.OneTrust + window.OptanonActiveGroups\n * 2. Init: Wraps OptanonWrapper (preserves existing)\n * 3. Change: OneTrustGroupsUpdated window event\n *\n * @example\n * ```typescript\n * import { sourceCookiePro } from '@walkeros/web-source-cmp-cookiepro';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceCookiePro,\n * config: {\n * settings: {\n * categoryMap: {\n * C0002: 'statistics', // Custom mapping\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceCookiePro: 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 (user overrides win)\n const mergedCategoryMap = {\n ...DEFAULT_CATEGORY_MAP,\n ...(config?.settings?.categoryMap ?? {}),\n };\n\n // Build normalized (lowercase) lookup map for case-insensitive matching\n const normalizedMap: Record<string, string> = {};\n Object.entries(mergedCategoryMap).forEach(([key, value]) => {\n normalizedMap[key.toLowerCase()] = value;\n });\n\n const settings: Settings = {\n categoryMap: mergedCategoryMap, // Preserves original casing for config\n explicitOnly: config?.settings?.explicitOnly ?? true,\n globalName: config?.settings?.globalName ?? 'OneTrust',\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track references for cleanup\n let eventListener: (() => void) | undefined;\n let originalOptanonWrapper: (() => void) | undefined;\n let wrappedOptanonWrapper = false;\n\n if (actualWindow) {\n const globalName = settings.globalName ?? 'OneTrust';\n\n /**\n * Collect all unique walkerOS group names from the normalizedMap.\n * Used to set explicit false for absent groups.\n */\n const allMappedGroups = new Set(Object.values(normalizedMap));\n\n /**\n * Parse OptanonActiveGroups string into walkerOS consent state.\n *\n * OptanonActiveGroups format: \",C0001,C0003,\" (comma-separated, leading/trailing commas)\n * Only active groups are listed. Absence means denied.\n * Uses case-insensitive comparison for category IDs via normalizedMap.\n * Only mapped categories produce consent entries (unmapped IDs are ignored).\n * Sets explicit false for all mapped groups not in the active list.\n */\n const parseActiveGroups = (activeGroups: string): WalkerOS.Consent => {\n const state: WalkerOS.Consent = {};\n\n // Initialize all mapped groups to false\n allMappedGroups.forEach((group) => {\n state[group] = false;\n });\n\n // Set active groups to true (case-insensitive via normalizedMap)\n activeGroups\n .split(',')\n .filter((id) => id.length > 0)\n .forEach((id) => {\n const mapped = normalizedMap[id.toLowerCase()];\n if (mapped) {\n state[mapped] = true;\n }\n });\n\n return state;\n };\n\n /**\n * Handle consent by reading current OptanonActiveGroups from window.\n * Checks explicitOnly against IsAlertBoxClosed when available.\n */\n const handleConsent = () => {\n const activeGroups = actualWindow.OptanonActiveGroups;\n if (activeGroups === undefined || activeGroups === null) return;\n\n // Check explicit consent if required\n if (settings.explicitOnly) {\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp?.IsAlertBoxClosed && !cmp.IsAlertBoxClosed()) return;\n }\n\n const state = parseActiveGroups(activeGroups);\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 // --- Detection path 1: Already loaded ---\n const cmp = actualWindow[globalName] as OneTrustAPI | undefined;\n if (cmp && actualWindow.OptanonActiveGroups !== undefined) {\n handleConsent();\n }\n\n // --- Detection path 2: OptanonWrapper ---\n // Only wrap if SDK is not yet loaded (no already-loaded path).\n // Self-unwraps after first call -- the event listener handles all\n // subsequent changes, avoiding double-firing.\n if (!cmp) {\n originalOptanonWrapper = actualWindow.OptanonWrapper;\n wrappedOptanonWrapper = true;\n\n actualWindow.OptanonWrapper = () => {\n // Call original wrapper if it existed\n if (originalOptanonWrapper) originalOptanonWrapper();\n handleConsent();\n // Self-unwrap: restore original after first call (SDK init).\n // The OneTrustGroupsUpdated listener handles all future changes.\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n wrappedOptanonWrapper = false;\n };\n }\n\n // --- Detection path 3: OneTrustGroupsUpdated event ---\n eventListener = () => {\n handleConsent();\n };\n actualWindow.addEventListener('OneTrustGroupsUpdated', eventListener);\n }\n\n return {\n type: 'cookiepro',\n config: fullConfig,\n push: elb,\n destroy: async (_context) => {\n // Remove event listener\n if (actualWindow && eventListener) {\n actualWindow.removeEventListener(\n 'OneTrustGroupsUpdated',\n eventListener,\n );\n }\n // Restore original OptanonWrapper\n if (actualWindow && wrappedOptanonWrapper) {\n actualWindow.OptanonWrapper = originalOptanonWrapper;\n }\n },\n };\n};\n\nexport default sourceCookiePro;\n"],"mappings":"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","names":["fullConsent","minimalConsent","trigger","cmp"]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/web-source-cmp-cookiepro",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.0",
|
|
5
5
|
"type": "source",
|
|
6
6
|
"platform": [
|
|
7
7
|
"web"
|
|
@@ -10,7 +10,36 @@
|
|
|
10
10
|
"docs": "https://www.walkeros.io/docs/sources/web/cmps/cookiepro",
|
|
11
11
|
"source": "https://github.com/elbwalker/walkerOS/tree/main/packages/web/sources/cmps/cookiepro/src"
|
|
12
12
|
},
|
|
13
|
-
"schemas": {
|
|
13
|
+
"schemas": {
|
|
14
|
+
"settings": {
|
|
15
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"categoryMap": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"propertyNames": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"additionalProperties": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"description": "Map the CMP's consent categories (keys) to walkerOS consent groups (values)."
|
|
27
|
+
},
|
|
28
|
+
"explicitOnly": {
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"description": "Only process consent after the user closed the OneTrust banner (IsAlertBoxClosed). Default: true."
|
|
31
|
+
},
|
|
32
|
+
"globalName": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Custom name for the OneTrust global on window. Default: 'OneTrust'."
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"id": "CookieProSettings",
|
|
39
|
+
"title": "Settings",
|
|
40
|
+
"description": "Settings for the CookiePro / OneTrust CMP source."
|
|
41
|
+
}
|
|
42
|
+
},
|
|
14
43
|
"examples": {
|
|
15
44
|
"analyticsOnlyConsent": ",C0001,C0002,",
|
|
16
45
|
"analyticsOnlyMapped": {
|
|
@@ -22,10 +51,10 @@
|
|
|
22
51
|
"$code": "()=>()=>Promise.resolve({ok:!0})"
|
|
23
52
|
},
|
|
24
53
|
"createMockOneTrustAPI": {
|
|
25
|
-
"$code": "(
|
|
54
|
+
"$code": "(e=!1)=>({IsAlertBoxClosed:()=>e})"
|
|
26
55
|
},
|
|
27
56
|
"createTrigger": {
|
|
28
|
-
"$code": "async
|
|
57
|
+
"$code": "async e=>{let t;return{get flow(){return t},trigger:()=>async n=>{var o;const r=window;if(r.OptanonActiveGroups=n,r.OneTrust={IsAlertBoxClosed:()=>!0},!t){const n=await h({...e,run:null==(o=e.run)||o});t={collector:n.collector,elb:n.elb}}}}}"
|
|
29
58
|
},
|
|
30
59
|
"customCategoryConsent": ",C0001,CUSTOM01,CUSTOM02,",
|
|
31
60
|
"emptyConsent": "",
|
|
@@ -61,7 +90,7 @@
|
|
|
61
90
|
"$code": "()=>{}"
|
|
62
91
|
},
|
|
63
92
|
"throw": {
|
|
64
|
-
"$code": "
|
|
93
|
+
"$code": "e=>{throw\"string\"==typeof e?new Error(e):e}"
|
|
65
94
|
},
|
|
66
95
|
"json": {
|
|
67
96
|
"$code": "()=>{}"
|
|
@@ -88,33 +117,51 @@
|
|
|
88
117
|
"C0002": "statistics"
|
|
89
118
|
}
|
|
90
119
|
},
|
|
91
|
-
"out":
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
120
|
+
"out": [
|
|
121
|
+
[
|
|
122
|
+
"elb",
|
|
123
|
+
"walker consent",
|
|
124
|
+
{
|
|
125
|
+
"functional": true,
|
|
126
|
+
"statistics": true,
|
|
127
|
+
"marketing": false
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
]
|
|
96
131
|
},
|
|
97
132
|
"fullConsent": {
|
|
98
133
|
"trigger": {
|
|
99
134
|
"type": "consent"
|
|
100
135
|
},
|
|
101
136
|
"in": ",C0001,C0002,C0003,C0004,C0005,",
|
|
102
|
-
"out":
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
137
|
+
"out": [
|
|
138
|
+
[
|
|
139
|
+
"elb",
|
|
140
|
+
"walker consent",
|
|
141
|
+
{
|
|
142
|
+
"functional": true,
|
|
143
|
+
"analytics": true,
|
|
144
|
+
"marketing": true
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
]
|
|
107
148
|
},
|
|
108
149
|
"minimalConsent": {
|
|
109
150
|
"trigger": {
|
|
110
151
|
"type": "consent"
|
|
111
152
|
},
|
|
112
153
|
"in": ",C0001,",
|
|
113
|
-
"out":
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
154
|
+
"out": [
|
|
155
|
+
[
|
|
156
|
+
"elb",
|
|
157
|
+
"walker consent",
|
|
158
|
+
{
|
|
159
|
+
"functional": true,
|
|
160
|
+
"analytics": false,
|
|
161
|
+
"marketing": false
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
]
|
|
118
165
|
},
|
|
119
166
|
"sdkLoadedDetection": {
|
|
120
167
|
"description": "Immediate detection when OneTrust SDK is already loaded with IsAlertBoxClosed() = true",
|
|
@@ -122,15 +169,21 @@
|
|
|
122
169
|
"type": "consent"
|
|
123
170
|
},
|
|
124
171
|
"in": ",C0001,C0003,C0004,",
|
|
125
|
-
"out":
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
172
|
+
"out": [
|
|
173
|
+
[
|
|
174
|
+
"elb",
|
|
175
|
+
"walker consent",
|
|
176
|
+
{
|
|
177
|
+
"functional": true,
|
|
178
|
+
"analytics": false,
|
|
179
|
+
"marketing": true
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
]
|
|
130
183
|
}
|
|
131
184
|
},
|
|
132
185
|
"trigger": {
|
|
133
|
-
"$code": "(t
|
|
186
|
+
"$code": "(e,t)=>{const n=t.window;\"string\"==typeof e&&(n.OptanonActiveGroups=e,n.OneTrust={IsAlertBoxClosed:()=>!0})}"
|
|
134
187
|
}
|
|
135
188
|
}
|
|
136
189
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/web-source-cmp-cookiepro",
|
|
3
3
|
"description": "CookiePro/OneTrust consent management source for walkerOS",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"walkerOS": {
|
|
7
7
|
"type": "source",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"update": "npx npm-check-updates -u && npm update"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@walkeros/core": "3.
|
|
49
|
-
"@walkeros/collector": "3.
|
|
48
|
+
"@walkeros/core": "3.4.0",
|
|
49
|
+
"@walkeros/collector": "3.4.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {},
|
|
52
52
|
"repository": {
|