From 0af28d9319a8cd42959efaad0ab6e7a3c0023e22 Mon Sep 17 00:00:00 2001 From: alexander Date: Mon, 10 Mar 2025 16:08:13 +0100 Subject: [PATCH] consentState source --- packages/types/src/mapping.ts | 1 + packages/utils/src/__tests__/mapping.test.ts | 75 +++++++++++++++----- packages/utils/src/core/mapping.ts | 18 +++-- website/docs/utils/mapping.mdx | 2 +- 4 files changed, 75 insertions(+), 21 deletions(-) diff --git a/packages/types/src/mapping.ts b/packages/types/src/mapping.ts index a200cfde..68ddec7a 100644 --- a/packages/types/src/mapping.ts +++ b/packages/types/src/mapping.ts @@ -60,6 +60,7 @@ export type Loop = [Value, Value]; export type Map = { [key: string]: Value }; export interface Options { + consent?: WalkerOS.Consent; instance?: WalkerOS.Instance; props?: unknown; } diff --git a/packages/utils/src/__tests__/mapping.test.ts b/packages/utils/src/__tests__/mapping.test.ts index 7634d855..ccef649a 100644 --- a/packages/utils/src/__tests__/mapping.test.ts +++ b/packages/utils/src/__tests__/mapping.test.ts @@ -328,41 +328,84 @@ describe('getMappingValue', () => { }); test('consent', () => { - const event = createEvent({ consent: { functional: true } }); const instance = { - consent: { functional: true }, + consent: { instanceLevel: true }, } as unknown as WalkerOS.Instance; - // Granted + expect(instance.consent.instanceLevel).toBeTruthy(); + + // Denied + expect( + getMappingValue( + { foo: 'bar' }, + { + key: 'foo', + consent: { notGranted: true }, + }, + ), + ).toBeUndefined(); + + // eventsLevel expect( getMappingValue( - event, + { foo: 'bar', consent: { eventLevel: true } }, { - key: 'data.string', - consent: { functional: true }, + key: 'foo', + consent: { eventLevel: true }, }, { instance }, ), - ).toBe(event.data.string); + ).toBe('bar'); - // Denied + // optionsLevel + expect( + getMappingValue( + { foo: 'bar' }, + { key: 'foo', consent: { optionsLevel: true } }, + { consent: { optionsLevel: true } }, + ), + ).toBe('bar'); + + // instanceLevel + expect( + getMappingValue( + { foo: 'bar' }, + { + key: 'foo', + consent: { instanceLevel: true }, + }, + { instance }, + ), + ).toBe('bar'); + + // eventsLevel override optionsLevel + expect( + getMappingValue( + { foo: 'bar', consent: { eventLevel: false } }, + { key: 'foo', consent: { eventLevel: true } }, + { instance }, + ), + ).toBeUndefined(); + + // eventLevel overrides instanceLevel expect( getMappingValue( - event, + { foo: 'bar', consent: { instanceLevel: false } }, { - key: 'data.string', - consent: { marketing: true }, + key: 'foo', + consent: { instanceLevel: true }, }, { instance }, ), ).toBeUndefined(); - // Denied automatically if no instance is provided + // optionsLevel overrides instanceLevel expect( - getMappingValue(event, { - key: 'data.string', - consent: { functional: true }, - }), + getMappingValue( + { foo: 'bar' }, + { key: 'foo', consent: { instanceLevel: true } }, + { instance, consent: { optionsLevel: false } }, + ), ).toBeUndefined(); }); diff --git a/packages/utils/src/core/mapping.ts b/packages/utils/src/core/mapping.ts index 1b24ad40..660473b4 100644 --- a/packages/utils/src/core/mapping.ts +++ b/packages/utils/src/core/mapping.ts @@ -1,7 +1,7 @@ import type { Mapping, WalkerOS } from '@elbwalker/types'; import { getGrantedConsent } from './consent'; import { getByPath } from './byPath'; -import { isArray, isDefined, isString } from './is'; +import { isArray, isDefined, isString, isObject } from './is'; import { castToProperty } from './property'; import { tryCatch } from './tryCatch'; @@ -58,10 +58,20 @@ export function getMappingValue( ): WalkerOS.Property | undefined { if (!isDefined(value)) return; + // Get consent state in priority order: value.consent > options.consent > instance?.consent + const consentState = + ((isObject(value) && value.consent) as WalkerOS.Consent) || + options.consent || + options.instance?.consent; + const mappings = isArray(data) ? data : [data]; for (const mapping of mappings) { - const result = tryCatch(processMappingValue)(value, mapping, options); + const result = tryCatch(processMappingValue)(value, mapping, { + ...options, + consent: consentState, + }); + if (isDefined(result)) return result; } } @@ -71,7 +81,7 @@ function processMappingValue( mapping: Mapping.Value, options: Mapping.Options = {}, ): WalkerOS.Property | undefined { - const { instance } = options; + const { instance, consent: consentState } = options; // Ensure mapping is an array for uniform processing const mappings = isArray(mapping) ? mapping : [mapping]; @@ -100,7 +110,7 @@ function processMappingValue( if (condition && !tryCatch(condition)(value, mappingItem, instance)) return; // Check if consent is required and granted - if (consent && !getGrantedConsent(consent, instance?.consent)) + if (consent && !getGrantedConsent(consent, consentState)) return staticValue; let mappingValue: unknown = staticValue || value; diff --git a/website/docs/utils/mapping.mdx b/website/docs/utils/mapping.mdx index b8ed77ad..f026cbfa 100644 --- a/website/docs/utils/mapping.mdx +++ b/website/docs/utils/mapping.mdx @@ -216,7 +216,7 @@ to standard fields of the destination. name: 'foo', consent: { functional: true, - // marketing: true + // marketing: true // uncomment me }, }, {