@walkeros/web-source-cmp-cookiefirst 1.1.0-next-1771252576264
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -0
- package/dist/dev.d.mts +149 -0
- package/dist/dev.d.ts +149 -0
- package/dist/dev.js +1 -0
- package/dist/dev.js.map +1 -0
- package/dist/dev.mjs +1 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/examples/index.d.mts +125 -0
- package/dist/examples/index.d.ts +125 -0
- package/dist/examples/index.js +161 -0
- package/dist/examples/index.mjs +119 -0
- package/dist/index.browser.js +1 -0
- package/dist/index.d.mts +234 -0
- package/dist/index.d.ts +234 -0
- package/dist/index.es5.js +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { Source, Elb, WalkerOS, Logger } from '@walkeros/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CookieFirst consent object structure
|
|
5
|
+
*/
|
|
6
|
+
interface CookieFirstConsent {
|
|
7
|
+
necessary?: boolean;
|
|
8
|
+
functional?: boolean;
|
|
9
|
+
performance?: boolean;
|
|
10
|
+
advertising?: boolean;
|
|
11
|
+
[category: string]: boolean | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* CookieFirst global API interface
|
|
15
|
+
*/
|
|
16
|
+
interface CookieFirstAPI {
|
|
17
|
+
consent: CookieFirstConsent | null;
|
|
18
|
+
}
|
|
19
|
+
declare global {
|
|
20
|
+
interface Window {
|
|
21
|
+
CookieFirst?: CookieFirstAPI;
|
|
22
|
+
[key: string]: CookieFirstAPI | unknown;
|
|
23
|
+
}
|
|
24
|
+
interface WindowEventMap {
|
|
25
|
+
cf_init: Event;
|
|
26
|
+
cf_consent: CustomEvent<CookieFirstConsent>;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Settings for CookieFirst source
|
|
31
|
+
*/
|
|
32
|
+
interface Settings {
|
|
33
|
+
/**
|
|
34
|
+
* Map CookieFirst categories to walkerOS consent groups.
|
|
35
|
+
* Keys: CookieFirst category names
|
|
36
|
+
* Values: walkerOS consent group names
|
|
37
|
+
*
|
|
38
|
+
* Default maps to standard walkerOS groups:
|
|
39
|
+
* - necessary → functional
|
|
40
|
+
* - functional → functional
|
|
41
|
+
* - performance → analytics
|
|
42
|
+
* - advertising → marketing
|
|
43
|
+
*/
|
|
44
|
+
categoryMap?: Record<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* Only process explicit consent (user made a choice).
|
|
47
|
+
* When true: Ignores consent if CookieFirst.consent is null
|
|
48
|
+
* When false: Processes any consent state including defaults
|
|
49
|
+
*
|
|
50
|
+
* Default: true
|
|
51
|
+
*/
|
|
52
|
+
explicitOnly?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Custom name for window.CookieFirst object.
|
|
55
|
+
* Some implementations use a different global name.
|
|
56
|
+
*
|
|
57
|
+
* Default: 'CookieFirst'
|
|
58
|
+
*/
|
|
59
|
+
globalName?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* User input settings (all optional)
|
|
63
|
+
*/
|
|
64
|
+
type InitSettings = Partial<Settings>;
|
|
65
|
+
/**
|
|
66
|
+
* No mapping configuration for this source
|
|
67
|
+
*/
|
|
68
|
+
interface Mapping {
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Push function type - uses elb for consent commands
|
|
72
|
+
*/
|
|
73
|
+
type Push = Elb.Fn;
|
|
74
|
+
/**
|
|
75
|
+
* Environment interface for CookieFirst source
|
|
76
|
+
*/
|
|
77
|
+
interface Env extends Source.BaseEnv {
|
|
78
|
+
window?: Window & typeof globalThis;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Types bundle for CookieFirst source
|
|
82
|
+
*/
|
|
83
|
+
type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;
|
|
84
|
+
/**
|
|
85
|
+
* Config type alias
|
|
86
|
+
*/
|
|
87
|
+
type Config = Source.Config<Types>;
|
|
88
|
+
|
|
89
|
+
type index_Config = Config;
|
|
90
|
+
type index_CookieFirstAPI = CookieFirstAPI;
|
|
91
|
+
type index_CookieFirstConsent = CookieFirstConsent;
|
|
92
|
+
type index_Env = Env;
|
|
93
|
+
type index_InitSettings = InitSettings;
|
|
94
|
+
type index_Mapping = Mapping;
|
|
95
|
+
type index_Push = Push;
|
|
96
|
+
type index_Settings = Settings;
|
|
97
|
+
type index_Types = Types;
|
|
98
|
+
declare namespace index {
|
|
99
|
+
export type { index_Config as Config, index_CookieFirstAPI as CookieFirstAPI, index_CookieFirstConsent as CookieFirstConsent, index_Env as Env, index_InitSettings as InitSettings, index_Mapping as Mapping, index_Push as Push, index_Settings as Settings, index_Types as Types };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Example CookieFirst consent inputs.
|
|
104
|
+
*
|
|
105
|
+
* These represent real consent states from CookieFirst CMP.
|
|
106
|
+
*/
|
|
107
|
+
/**
|
|
108
|
+
* Full consent - user accepted all categories
|
|
109
|
+
*/
|
|
110
|
+
declare const fullConsent: CookieFirstConsent;
|
|
111
|
+
/**
|
|
112
|
+
* Partial consent - user accepted only necessary and functional
|
|
113
|
+
*/
|
|
114
|
+
declare const partialConsent: CookieFirstConsent;
|
|
115
|
+
/**
|
|
116
|
+
* Minimal consent - user accepted only necessary (required)
|
|
117
|
+
*/
|
|
118
|
+
declare const minimalConsent: CookieFirstConsent;
|
|
119
|
+
/**
|
|
120
|
+
* No consent - user hasn't made a choice yet
|
|
121
|
+
* CookieFirst returns null when no explicit choice has been made
|
|
122
|
+
*/
|
|
123
|
+
declare const noConsent: CookieFirstConsent | null;
|
|
124
|
+
/**
|
|
125
|
+
* Analytics only - user accepted performance tracking
|
|
126
|
+
*/
|
|
127
|
+
declare const analyticsOnlyConsent: CookieFirstConsent;
|
|
128
|
+
/**
|
|
129
|
+
* Marketing only - user accepted advertising
|
|
130
|
+
*/
|
|
131
|
+
declare const marketingOnlyConsent: CookieFirstConsent;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Expected walkerOS consent outputs.
|
|
135
|
+
*
|
|
136
|
+
* These represent the consent state after mapping CookieFirst categories
|
|
137
|
+
* to walkerOS consent groups using the default category map.
|
|
138
|
+
*/
|
|
139
|
+
/**
|
|
140
|
+
* Full consent mapped to walkerOS groups
|
|
141
|
+
* (necessary + functional → functional, performance → analytics, advertising → marketing)
|
|
142
|
+
*/
|
|
143
|
+
declare const fullConsentMapped: WalkerOS.Consent;
|
|
144
|
+
/**
|
|
145
|
+
* Partial consent mapped to walkerOS groups
|
|
146
|
+
*/
|
|
147
|
+
declare const partialConsentMapped: WalkerOS.Consent;
|
|
148
|
+
/**
|
|
149
|
+
* Minimal consent mapped to walkerOS groups
|
|
150
|
+
*/
|
|
151
|
+
declare const minimalConsentMapped: WalkerOS.Consent;
|
|
152
|
+
/**
|
|
153
|
+
* Analytics only consent mapped to walkerOS groups
|
|
154
|
+
* Note: functional is true because necessary=true maps to functional
|
|
155
|
+
* (OR logic: if ANY source category is true, target group is true)
|
|
156
|
+
*/
|
|
157
|
+
declare const analyticsOnlyMapped: WalkerOS.Consent;
|
|
158
|
+
/**
|
|
159
|
+
* Marketing only consent mapped to walkerOS groups
|
|
160
|
+
* Note: functional is true because necessary=true maps to functional
|
|
161
|
+
* (OR logic: if ANY source category is true, target group is true)
|
|
162
|
+
*/
|
|
163
|
+
declare const marketingOnlyMapped: WalkerOS.Consent;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create a properly typed elb/push function mock that returns a promise with PushResult
|
|
167
|
+
*/
|
|
168
|
+
declare const createMockElbFn: () => Elb.Fn;
|
|
169
|
+
/**
|
|
170
|
+
* Simple no-op logger for demo purposes
|
|
171
|
+
*/
|
|
172
|
+
declare const noopLogger: Logger.Instance;
|
|
173
|
+
/**
|
|
174
|
+
* Environment interface for CookieFirst source
|
|
175
|
+
*/
|
|
176
|
+
interface CookieFirstEnv extends Source.BaseEnv {
|
|
177
|
+
window?: typeof window;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Create a mock CookieFirst API object
|
|
181
|
+
*/
|
|
182
|
+
declare const createMockCookieFirstAPI: (consent?: CookieFirstConsent | null) => CookieFirstAPI;
|
|
183
|
+
/**
|
|
184
|
+
* Create a mock window object with CookieFirst
|
|
185
|
+
*/
|
|
186
|
+
declare const createMockWindow: (consent?: CookieFirstConsent | null) => Partial<Window> & {
|
|
187
|
+
CookieFirst: CookieFirstAPI;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Standard mock environment for testing CookieFirst source
|
|
191
|
+
*
|
|
192
|
+
* Use this for testing consent handling without requiring
|
|
193
|
+
* a real browser environment.
|
|
194
|
+
*/
|
|
195
|
+
declare const mockEnv: CookieFirstEnv;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Default category mapping from CookieFirst to walkerOS consent groups.
|
|
199
|
+
*
|
|
200
|
+
* Maps CookieFirst's standard categories to walkerOS convention:
|
|
201
|
+
* - necessary/functional → functional (essential)
|
|
202
|
+
* - performance → analytics (measurement)
|
|
203
|
+
* - advertising → marketing (ads)
|
|
204
|
+
*/
|
|
205
|
+
declare const DEFAULT_CATEGORY_MAP: Record<string, string>;
|
|
206
|
+
/**
|
|
207
|
+
* CookieFirst consent management source for walkerOS.
|
|
208
|
+
*
|
|
209
|
+
* This source listens to CookieFirst CMP events and translates
|
|
210
|
+
* consent states to walkerOS consent commands.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```typescript
|
|
214
|
+
* import { sourceCookieFirst } from '@walkeros/web-source-cmp-cookiefirst';
|
|
215
|
+
*
|
|
216
|
+
* await startFlow({
|
|
217
|
+
* sources: {
|
|
218
|
+
* consent: {
|
|
219
|
+
* code: sourceCookieFirst,
|
|
220
|
+
* config: {
|
|
221
|
+
* settings: {
|
|
222
|
+
* categoryMap: {
|
|
223
|
+
* performance: 'statistics', // Custom mapping
|
|
224
|
+
* },
|
|
225
|
+
* },
|
|
226
|
+
* },
|
|
227
|
+
* },
|
|
228
|
+
* },
|
|
229
|
+
* });
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
declare const sourceCookieFirst: Source.Init<Types>;
|
|
233
|
+
|
|
234
|
+
export { DEFAULT_CATEGORY_MAP, index as SourceCookieFirst, analyticsOnlyConsent, analyticsOnlyMapped, createMockCookieFirstAPI, createMockElbFn, createMockWindow, sourceCookieFirst as default, fullConsent, fullConsentMapped, marketingOnlyConsent, marketingOnlyMapped, minimalConsent, minimalConsentMapped, mockEnv, noConsent, noopLogger, partialConsent, partialConsentMapped, sourceCookieFirst };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function _array_like_to_array(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t<e;t++)r[t]=n[t];return r}function _array_with_holes(n){if(Array.isArray(n))return n}function asyncGeneratorStep(n,e,t,r,o,i,a){try{var u=n[i](a),l=u.value}catch(n){return void t(n)}u.done?e(l):Promise.resolve(l).then(r,o)}function _async_to_generator(n){return function(){var e=this,t=arguments;return new Promise(function(r,o){var i=n.apply(e,t);function a(n){asyncGeneratorStep(i,r,o,a,u,"next",n)}function u(n){asyncGeneratorStep(i,r,o,a,u,"throw",n)}a(void 0)})}}function _define_property(n,e,t){return e in n?Object.defineProperty(n,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):n[e]=t,n}function _iterable_to_array_limit(n,e){var t=null==n?null:"undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(null!=t){var r,o,i=[],a=!0,u=!1;try{for(t=t.call(n);!(a=(r=t.next()).done)&&(i.push(r.value),!e||i.length!==e);a=!0);}catch(n){u=!0,o=n}finally{try{a||null==t.return||t.return()}finally{if(u)throw o}}return i}}function _non_iterable_rest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _object_spread(n){for(var e=1;e<arguments.length;e++){var t=null!=arguments[e]?arguments[e]:{},r=Object.keys(t);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(t).filter(function(n){return Object.getOwnPropertyDescriptor(t,n).enumerable}))),r.forEach(function(e){_define_property(n,e,t[e])})}return n}function _sliced_to_array(n,e){return _array_with_holes(n)||_iterable_to_array_limit(n,e)||_unsupported_iterable_to_array(n,e)||_non_iterable_rest()}function _type_of(n){return n&&"undefined"!=typeof Symbol&&n.constructor===Symbol?"symbol":typeof n}function _unsupported_iterable_to_array(n,e){if(n){if("string"==typeof n)return _array_like_to_array(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);return"Object"===t&&n.constructor&&(t=n.constructor.name),"Map"===t||"Set"===t?Array.from(t):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_array_like_to_array(n,e):void 0}}function _ts_generator(n,e){var t,r,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:l(0)}),u(a,"throw",{value:l(1)}),u(a,"return",{value:l(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function l(u){return function(l){return function(u){if(t)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(t=1,r&&(o=2&u[0]?r.return:u[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,u[1])).done)return o;switch(r=0,o&&(u=[2&u[0],o.value]),u[0]){case 0:case 1:o=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,r=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!o||u[1]>o[0]&&u[1]<o[3])){i.label=u[1];break}if(6===u[0]&&i.label<o[1]){i.label=o[1],o=u;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(u);break}o[2]&&i.ops.pop(),i.trys.pop();continue}u=e.call(n,i)}catch(n){u=[6,n],r=0}finally{t=o=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}var SourceCookieFirst=function(){var n=Object.defineProperty,e=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,o={};!function(e,t){for(var r in t)n(e,r,{get:t[r],enumerable:!0})}(o,{DEFAULT_CATEGORY_MAP:function(){return j},SourceCookieFirst:function(){return a},analyticsOnlyConsent:function(){return s},analyticsOnlyMapped:function(){return _},createMockCookieFirstAPI:function(){return w},createMockElbFn:function(){return m},createMockWindow:function(){return k},default:function(){return S},fullConsent:function(){return u},fullConsentMapped:function(){return p},marketingOnlyConsent:function(){return y},marketingOnlyMapped:function(){return b},minimalConsent:function(){return c},minimalConsentMapped:function(){return v},mockEnv:function(){return O},noConsent:function(){return f},noopLogger:function(){return h},partialConsent:function(){return l},partialConsentMapped:function(){return d},sourceCookieFirst:function(){return C}});var i,a={},u={necessary:!0,functional:!0,performance:!0,advertising:!0},l={necessary:!0,functional:!0,performance:!1,advertising:!1},c={necessary:!0,functional:!1,performance:!1,advertising:!1},f=null,s={necessary:!0,functional:!1,performance:!0,advertising:!1},y={necessary:!0,functional:!1,performance:!1,advertising:!0},p={functional:!0,analytics:!0,marketing:!0},d={functional:!0,analytics:!1,marketing:!1},v={functional:!0,analytics:!1,marketing:!1},_={functional:!0,analytics:!0,marketing:!1},b={functional:!0,analytics:!1,marketing:!0},g=function(){},m=function(){return function(){return Promise.resolve({ok:!0})}},h={error:g,info:g,debug:g,throw:function(n){throw"string"==typeof n?new Error(n):n},scope:function(){return h}},w=function(){return{consent:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}},k=function(){return{CookieFirst:w(arguments.length>0&&void 0!==arguments[0]?arguments[0]:null),addEventListener:g,removeEventListener:g}},O={get push(){return m()},get command(){return m()},get elb(){return m()},get window(){return k()},logger:h},j={necessary:"functional",functional:"functional",performance:"analytics",advertising:"marketing"},C=function(n){return _async_to_generator(function(){var e,t,r,o,i,a,u,l,c,f,s,y,p,d,v,_,b,g;return _ts_generator(this,function(m){return u=n.config,l=n.env,c=l.elb,f=null!==(e=l.window)&&void 0!==e?e:void 0!==globalThis.window?globalThis.window:void 0,s={categoryMap:_object_spread({},j,null==u||null===(o=u.settings)||void 0===o?void 0:o.categoryMap),explicitOnly:null===(t=null==u||null===(i=u.settings)||void 0===i?void 0:i.explicitOnly)||void 0===t||t,globalName:null!==(r=null==u||null===(a=u.settings)||void 0===a?void 0:a.globalName)&&void 0!==r?r:"CookieFirst"},y={settings:s},f&&(_=function(n){if((!s.explicitOnly||n)&&n){var e={};Object.entries(n).forEach(function(n){var t,r,o=_sliced_to_array(n,2),i=o[0],a=o[1];if("boolean"==typeof a){var u=null!==(t=null===(r=s.categoryMap)||void 0===r?void 0:r[i])&&void 0!==t?t:i;e[u]=e[u]||a}}),Object.keys(e).length>0&&c("walker consent",e)}},b=null!==(v=s.globalName)&&void 0!==v?v:"CookieFirst",(null==(g=f[b])?void 0:g.consent)&&_(g.consent),p=function(){var n,e=f[b];_(null!==(n=null==e?void 0:e.consent)&&void 0!==n?n:null)},f.addEventListener("cf_init",p),d=function(n){_(n.detail)},f.addEventListener("cf_consent",d)),[2,{type:"cookiefirst",config:y,push:c,destroy:function(){return _async_to_generator(function(){return _ts_generator(this,function(n){return f&&p&&f.removeEventListener("cf_init",p),f&&d&&f.removeEventListener("cf_consent",d),[2]})})()}}]})})()},S=C;return i=o,function(o,i,a,u){if(i&&"object"===(void 0===i?"undefined":_type_of(i))||"function"==typeof i){var l=!0,c=!1,f=void 0;try{for(var s,y=function(){var t=s.value;r.call(o,t)||t===a||n(o,t,{get:function(){return i[t]},enumerable:!(u=e(i,t))||u.enumerable})},p=t(i)[Symbol.iterator]();!(l=(s=p.next()).done);l=!0)y()}catch(n){c=!0,f=n}finally{try{l||null==p.return||p.return()}finally{if(c)throw f}}}return o}(n({},"__esModule",{value:!0}),i)}();
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e,n=Object.defineProperty,t=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var o in t)n(e,o,{get:t[o],enumerable:!0})})(i,{DEFAULT_CATEGORY_MAP:()=>E,SourceCookieFirst:()=>a,analyticsOnlyConsent:()=>f,analyticsOnlyMapped:()=>v,createMockCookieFirstAPI:()=>w,createMockElbFn:()=>b,createMockWindow:()=>C,default:()=>F,fullConsent:()=>l,fullConsentMapped:()=>d,marketingOnlyConsent:()=>g,marketingOnlyMapped:()=>m,minimalConsent:()=>c,minimalConsentMapped:()=>y,mockEnv:()=>M,noConsent:()=>u,noopLogger:()=>O,partialConsent:()=>s,partialConsentMapped:()=>p,sourceCookieFirst:()=>h}),module.exports=(e=i,((e,i,a,l)=>{if(i&&"object"==typeof i||"function"==typeof i)for(let s of o(i))r.call(e,s)||s===a||n(e,s,{get:()=>i[s],enumerable:!(l=t(i,s))||l.enumerable});return e})(n({},"__esModule",{value:!0}),e));var a={},l={necessary:!0,functional:!0,performance:!0,advertising:!0},s={necessary:!0,functional:!0,performance:!1,advertising:!1},c={necessary:!0,functional:!1,performance:!1,advertising:!1},u=null,f={necessary:!0,functional:!1,performance:!0,advertising:!1},g={necessary:!0,functional:!1,performance:!1,advertising:!0},d={functional:!0,analytics:!0,marketing:!0},p={functional:!0,analytics:!1,marketing:!1},y={functional:!0,analytics:!1,marketing:!1},v={functional:!0,analytics:!0,marketing:!1},m={functional:!0,analytics:!1,marketing:!0},k=()=>{},b=()=>()=>Promise.resolve({ok:!0}),O={error:k,info:k,debug:k,throw:e=>{throw"string"==typeof e?new Error(e):e},scope:()=>O},w=(e=null)=>({consent:e}),C=(e=null)=>({CookieFirst:w(e),addEventListener:k,removeEventListener:k}),M={get push(){return b()},get command(){return b()},get elb(){return b()},get window(){return C()},logger:O},E={necessary:"functional",functional:"functional",performance:"analytics",advertising:"marketing"},h=async e=>{var n,t,o,r,i,a,l;const{config:s,env:c}=e,{elb:u}=c,f=null!=(n=c.window)?n:void 0!==globalThis.window?globalThis.window:void 0,g={categoryMap:{...E,...null==(t=null==s?void 0:s.settings)?void 0:t.categoryMap},explicitOnly:null==(r=null==(o=null==s?void 0:s.settings)?void 0:o.explicitOnly)||r,globalName:null!=(a=null==(i=null==s?void 0:s.settings)?void 0:i.globalName)?a:"CookieFirst"},d={settings:g};let p,y;if(f){const e=e=>{if(g.explicitOnly&&!e)return;if(!e)return;const n={};Object.entries(e).forEach(([e,t])=>{var o,r;if("boolean"!=typeof t)return;const i=null!=(r=null==(o=g.categoryMap)?void 0:o[e])?r:e;n[i]=n[i]||t}),Object.keys(n).length>0&&u("walker consent",n)},n=null!=(l=g.globalName)?l:"CookieFirst",t=f[n];(null==t?void 0:t.consent)&&e(t.consent),p=()=>{var t;const o=f[n];e(null!=(t=null==o?void 0:o.consent)?t:null)},f.addEventListener("cf_init",p),y=n=>{e(n.detail)},f.addEventListener("cf_consent",y)}return{type:"cookiefirst",config:d,push:u,destroy:async()=>{f&&p&&f.removeEventListener("cf_init",p),f&&y&&f.removeEventListener("cf_consent",y)}}},F=h;//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/examples/inputs.ts","../src/examples/outputs.ts","../src/examples/env.ts"],"sourcesContent":["import type { Source, WalkerOS } from '@walkeros/core';\nimport type {\n Types,\n Settings,\n CookieFirstConsent,\n CookieFirstAPI,\n} from './types';\n\n// Export types for external usage\nexport * as SourceCookieFirst from './types';\n\n// Export examples\nexport * from './examples';\n\n/**\n * Default category mapping from CookieFirst to walkerOS consent groups.\n *\n * Maps CookieFirst's standard categories to walkerOS convention:\n * - necessary/functional → functional (essential)\n * - performance → analytics (measurement)\n * - advertising → marketing (ads)\n */\nexport const DEFAULT_CATEGORY_MAP: Record<string, string> = {\n necessary: 'functional',\n functional: 'functional',\n performance: 'analytics',\n advertising: 'marketing',\n};\n\n/**\n * CookieFirst consent management source for walkerOS.\n *\n * This source listens to CookieFirst CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * @example\n * ```typescript\n * import { sourceCookieFirst } from '@walkeros/web-source-cmp-cookiefirst';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceCookieFirst,\n * config: {\n * settings: {\n * categoryMap: {\n * performance: 'statistics', // Custom mapping\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceCookieFirst: 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 categoryMap: { ...DEFAULT_CATEGORY_MAP, ...config?.settings?.categoryMap },\n explicitOnly: config?.settings?.explicitOnly ?? true,\n globalName: config?.settings?.globalName ?? 'CookieFirst',\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track listener references for cleanup\n let initListener: (() => void) | undefined;\n let consentListener: ((e: Event) => void) | undefined;\n\n // Only setup if in browser environment\n if (actualWindow) {\n /**\n * Handle consent state from CookieFirst.\n * Maps CookieFirst categories to walkerOS consent groups and calls elb.\n *\n * When multiple CookieFirst categories map to the same walkerOS group,\n * uses OR logic: if ANY category is true, the group is true.\n */\n const handleConsent = (consent: CookieFirstConsent | null) => {\n // Skip if explicitOnly and no explicit consent given\n if (settings.explicitOnly && !consent) return;\n if (!consent) return;\n\n // Map CookieFirst categories to walkerOS consent groups\n // Use OR logic: if ANY source category is true, the target group is true\n const state: WalkerOS.Consent = {};\n Object.entries(consent).forEach(([category, value]) => {\n if (typeof value !== 'boolean') return;\n const mapped = settings.categoryMap?.[category] ?? category;\n // OR logic: once true, stays true\n state[mapped] = state[mapped] || value;\n });\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 const globalName = settings.globalName ?? 'CookieFirst';\n const cmp = actualWindow[globalName] as CookieFirstAPI | undefined;\n\n // Process existing consent if CMP already loaded\n if (cmp?.consent) {\n handleConsent(cmp.consent);\n }\n\n // Listen for CMP initialization\n initListener = () => {\n const cmp = actualWindow[globalName] as CookieFirstAPI | undefined;\n handleConsent(cmp?.consent ?? null);\n };\n actualWindow.addEventListener('cf_init', initListener);\n\n // Listen for consent changes\n consentListener = (e: Event) => {\n const customEvent = e as CustomEvent<CookieFirstConsent>;\n handleConsent(customEvent.detail);\n };\n actualWindow.addEventListener('cf_consent', consentListener);\n }\n\n return {\n type: 'cookiefirst',\n config: fullConfig,\n push: elb,\n destroy: async () => {\n // Remove event listeners on cleanup\n if (actualWindow && initListener) {\n actualWindow.removeEventListener('cf_init', initListener);\n }\n if (actualWindow && consentListener) {\n actualWindow.removeEventListener('cf_consent', consentListener);\n }\n },\n };\n};\n\nexport default sourceCookieFirst;\n","import type { Source, Elb } from '@walkeros/core';\n\n/**\n * CookieFirst consent object structure\n */\nexport interface CookieFirstConsent {\n necessary?: boolean;\n functional?: boolean;\n performance?: boolean;\n advertising?: boolean;\n [category: string]: boolean | undefined;\n}\n\n/**\n * CookieFirst global API interface\n */\nexport interface CookieFirstAPI {\n consent: CookieFirstConsent | null;\n}\n\ndeclare global {\n interface Window {\n CookieFirst?: CookieFirstAPI;\n [key: string]: CookieFirstAPI | unknown;\n }\n\n interface WindowEventMap {\n cf_init: Event;\n cf_consent: CustomEvent<CookieFirstConsent>;\n }\n}\n\n/**\n * Settings for CookieFirst source\n */\nexport interface Settings {\n /**\n * Map CookieFirst categories to walkerOS consent groups.\n * Keys: CookieFirst category names\n * Values: walkerOS consent group names\n *\n * Default maps to standard walkerOS groups:\n * - necessary → functional\n * - functional → functional\n * - performance → analytics\n * - advertising → marketing\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Ignores consent if CookieFirst.consent is null\n * When false: Processes any consent state including defaults\n *\n * Default: true\n */\n explicitOnly?: boolean;\n\n /**\n * Custom name for window.CookieFirst object.\n * Some implementations use a different global name.\n *\n * Default: 'CookieFirst'\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 CookieFirst source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for CookieFirst 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 { CookieFirstConsent } from '../types';\n\n/**\n * Example CookieFirst consent inputs.\n *\n * These represent real consent states from CookieFirst CMP.\n */\n\n/**\n * Full consent - user accepted all categories\n */\nexport const fullConsent: CookieFirstConsent = {\n necessary: true,\n functional: true,\n performance: true,\n advertising: true,\n};\n\n/**\n * Partial consent - user accepted only necessary and functional\n */\nexport const partialConsent: CookieFirstConsent = {\n necessary: true,\n functional: true,\n performance: false,\n advertising: false,\n};\n\n/**\n * Minimal consent - user accepted only necessary (required)\n */\nexport const minimalConsent: CookieFirstConsent = {\n necessary: true,\n functional: false,\n performance: false,\n advertising: false,\n};\n\n/**\n * No consent - user hasn't made a choice yet\n * CookieFirst returns null when no explicit choice has been made\n */\nexport const noConsent: CookieFirstConsent | null = null;\n\n/**\n * Analytics only - user accepted performance tracking\n */\nexport const analyticsOnlyConsent: CookieFirstConsent = {\n necessary: true,\n functional: false,\n performance: true,\n advertising: false,\n};\n\n/**\n * Marketing only - user accepted advertising\n */\nexport const marketingOnlyConsent: CookieFirstConsent = {\n necessary: true,\n functional: false,\n performance: false,\n advertising: true,\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after mapping CookieFirst categories\n * to walkerOS consent groups using the default category map.\n */\n\n/**\n * Full consent mapped to walkerOS groups\n * (necessary + functional → functional, performance → analytics, advertising → marketing)\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: true,\n};\n\n/**\n * Partial consent mapped to walkerOS groups\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Minimal consent mapped to walkerOS groups\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Analytics only consent mapped to walkerOS groups\n * Note: functional is true because necessary=true maps to functional\n * (OR logic: if ANY source category is true, target group is true)\n */\nexport const analyticsOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: false,\n};\n\n/**\n * Marketing only consent mapped to walkerOS groups\n * Note: functional is true because necessary=true maps to functional\n * (OR logic: if ANY source category is true, target group is true)\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 { CookieFirstAPI, CookieFirstConsent } from '../types';\n\n/**\n * Example environment configurations for CookieFirst source testing.\n *\n * These provide mock structures for testing consent handling\n * without requiring a real browser environment.\n */\n\n// Simple no-op function for mocking\nconst noop = () => {};\n\n/**\n * Create a properly typed elb/push function mock that returns a promise with PushResult\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 info: noop,\n debug: noop,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n scope: () => noopLogger,\n};\n\n/**\n * Environment interface for CookieFirst source\n */\ninterface CookieFirstEnv extends Source.BaseEnv {\n window?: typeof window;\n}\n\n/**\n * Create a mock CookieFirst API object\n */\nexport const createMockCookieFirstAPI = (\n consent: CookieFirstConsent | null = null,\n): CookieFirstAPI => ({\n consent,\n});\n\n/**\n * Create a mock window object with CookieFirst\n */\nexport const createMockWindow = (\n consent: CookieFirstConsent | null = null,\n): Partial<Window> & { CookieFirst: CookieFirstAPI } => ({\n CookieFirst: createMockCookieFirstAPI(consent),\n addEventListener: noop,\n removeEventListener: noop,\n});\n\n/**\n * Standard mock environment for testing CookieFirst source\n *\n * Use this for testing consent handling without requiring\n * a real browser environment.\n */\nexport const mockEnv: CookieFirstEnv = {\n get push() {\n return createMockElbFn();\n },\n get command() {\n return createMockElbFn();\n },\n get elb() {\n return createMockElbFn();\n },\n get window() {\n return createMockWindow() as unknown as typeof window;\n },\n logger: noopLogger,\n};\n"],"mappings":"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","names":["_a","_b","cmp"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n={},e={necessary:!0,functional:!0,performance:!0,advertising:!0},t={necessary:!0,functional:!0,performance:!1,advertising:!1},i={necessary:!0,functional:!1,performance:!1,advertising:!1},o=null,r={necessary:!0,functional:!1,performance:!0,advertising:!1},l={necessary:!0,functional:!1,performance:!1,advertising:!0},a={functional:!0,analytics:!0,marketing:!0},s={functional:!0,analytics:!1,marketing:!1},c={functional:!0,analytics:!1,marketing:!1},u={functional:!0,analytics:!0,marketing:!1},f={functional:!0,analytics:!1,marketing:!0},g=()=>{},d=()=>()=>Promise.resolve({ok:!0}),v={error:g,info:g,debug:g,throw:n=>{throw"string"==typeof n?new Error(n):n},scope:()=>v},y=(n=null)=>({consent:n}),m=(n=null)=>({CookieFirst:y(n),addEventListener:g,removeEventListener:g}),p={get push(){return d()},get command(){return d()},get elb(){return d()},get window(){return m()},logger:v},k={necessary:"functional",functional:"functional",performance:"analytics",advertising:"marketing"},w=async n=>{var e,t,i,o,r,l,a;const{config:s,env:c}=n,{elb:u}=c,f=null!=(e=c.window)?e:void 0!==globalThis.window?globalThis.window:void 0,g={categoryMap:{...k,...null==(t=null==s?void 0:s.settings)?void 0:t.categoryMap},explicitOnly:null==(o=null==(i=null==s?void 0:s.settings)?void 0:i.explicitOnly)||o,globalName:null!=(l=null==(r=null==s?void 0:s.settings)?void 0:r.globalName)?l:"CookieFirst"},d={settings:g};let v,y;if(f){const n=n=>{if(g.explicitOnly&&!n)return;if(!n)return;const e={};Object.entries(n).forEach(([n,t])=>{var i,o;if("boolean"!=typeof t)return;const r=null!=(o=null==(i=g.categoryMap)?void 0:i[n])?o:n;e[r]=e[r]||t}),Object.keys(e).length>0&&u("walker consent",e)},e=null!=(a=g.globalName)?a:"CookieFirst",t=f[e];(null==t?void 0:t.consent)&&n(t.consent),v=()=>{var t;const i=f[e];n(null!=(t=null==i?void 0:i.consent)?t:null)},f.addEventListener("cf_init",v),y=e=>{n(e.detail)},f.addEventListener("cf_consent",y)}return{type:"cookiefirst",config:d,push:u,destroy:async()=>{f&&v&&f.removeEventListener("cf_init",v),f&&y&&f.removeEventListener("cf_consent",y)}}},b=w;export{k as DEFAULT_CATEGORY_MAP,n as SourceCookieFirst,r as analyticsOnlyConsent,u as analyticsOnlyMapped,y as createMockCookieFirstAPI,d as createMockElbFn,m as createMockWindow,b as default,e as fullConsent,a as fullConsentMapped,l as marketingOnlyConsent,f as marketingOnlyMapped,i as minimalConsent,c as minimalConsentMapped,p as mockEnv,o as noConsent,v as noopLogger,t as partialConsent,s as partialConsentMapped,w as sourceCookieFirst};//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/index.ts","../src/examples/inputs.ts","../src/examples/outputs.ts","../src/examples/env.ts","../src/index.ts"],"sourcesContent":["import type { Source, Elb } from '@walkeros/core';\n\n/**\n * CookieFirst consent object structure\n */\nexport interface CookieFirstConsent {\n necessary?: boolean;\n functional?: boolean;\n performance?: boolean;\n advertising?: boolean;\n [category: string]: boolean | undefined;\n}\n\n/**\n * CookieFirst global API interface\n */\nexport interface CookieFirstAPI {\n consent: CookieFirstConsent | null;\n}\n\ndeclare global {\n interface Window {\n CookieFirst?: CookieFirstAPI;\n [key: string]: CookieFirstAPI | unknown;\n }\n\n interface WindowEventMap {\n cf_init: Event;\n cf_consent: CustomEvent<CookieFirstConsent>;\n }\n}\n\n/**\n * Settings for CookieFirst source\n */\nexport interface Settings {\n /**\n * Map CookieFirst categories to walkerOS consent groups.\n * Keys: CookieFirst category names\n * Values: walkerOS consent group names\n *\n * Default maps to standard walkerOS groups:\n * - necessary → functional\n * - functional → functional\n * - performance → analytics\n * - advertising → marketing\n */\n categoryMap?: Record<string, string>;\n\n /**\n * Only process explicit consent (user made a choice).\n * When true: Ignores consent if CookieFirst.consent is null\n * When false: Processes any consent state including defaults\n *\n * Default: true\n */\n explicitOnly?: boolean;\n\n /**\n * Custom name for window.CookieFirst object.\n * Some implementations use a different global name.\n *\n * Default: 'CookieFirst'\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 CookieFirst source\n */\nexport interface Env extends Source.BaseEnv {\n window?: Window & typeof globalThis;\n}\n\n/**\n * Types bundle for CookieFirst 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 { CookieFirstConsent } from '../types';\n\n/**\n * Example CookieFirst consent inputs.\n *\n * These represent real consent states from CookieFirst CMP.\n */\n\n/**\n * Full consent - user accepted all categories\n */\nexport const fullConsent: CookieFirstConsent = {\n necessary: true,\n functional: true,\n performance: true,\n advertising: true,\n};\n\n/**\n * Partial consent - user accepted only necessary and functional\n */\nexport const partialConsent: CookieFirstConsent = {\n necessary: true,\n functional: true,\n performance: false,\n advertising: false,\n};\n\n/**\n * Minimal consent - user accepted only necessary (required)\n */\nexport const minimalConsent: CookieFirstConsent = {\n necessary: true,\n functional: false,\n performance: false,\n advertising: false,\n};\n\n/**\n * No consent - user hasn't made a choice yet\n * CookieFirst returns null when no explicit choice has been made\n */\nexport const noConsent: CookieFirstConsent | null = null;\n\n/**\n * Analytics only - user accepted performance tracking\n */\nexport const analyticsOnlyConsent: CookieFirstConsent = {\n necessary: true,\n functional: false,\n performance: true,\n advertising: false,\n};\n\n/**\n * Marketing only - user accepted advertising\n */\nexport const marketingOnlyConsent: CookieFirstConsent = {\n necessary: true,\n functional: false,\n performance: false,\n advertising: true,\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/**\n * Expected walkerOS consent outputs.\n *\n * These represent the consent state after mapping CookieFirst categories\n * to walkerOS consent groups using the default category map.\n */\n\n/**\n * Full consent mapped to walkerOS groups\n * (necessary + functional → functional, performance → analytics, advertising → marketing)\n */\nexport const fullConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: true,\n};\n\n/**\n * Partial consent mapped to walkerOS groups\n */\nexport const partialConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Minimal consent mapped to walkerOS groups\n */\nexport const minimalConsentMapped: WalkerOS.Consent = {\n functional: true,\n analytics: false,\n marketing: false,\n};\n\n/**\n * Analytics only consent mapped to walkerOS groups\n * Note: functional is true because necessary=true maps to functional\n * (OR logic: if ANY source category is true, target group is true)\n */\nexport const analyticsOnlyMapped: WalkerOS.Consent = {\n functional: true,\n analytics: true,\n marketing: false,\n};\n\n/**\n * Marketing only consent mapped to walkerOS groups\n * Note: functional is true because necessary=true maps to functional\n * (OR logic: if ANY source category is true, target group is true)\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 { CookieFirstAPI, CookieFirstConsent } from '../types';\n\n/**\n * Example environment configurations for CookieFirst source testing.\n *\n * These provide mock structures for testing consent handling\n * without requiring a real browser environment.\n */\n\n// Simple no-op function for mocking\nconst noop = () => {};\n\n/**\n * Create a properly typed elb/push function mock that returns a promise with PushResult\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 info: noop,\n debug: noop,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n scope: () => noopLogger,\n};\n\n/**\n * Environment interface for CookieFirst source\n */\ninterface CookieFirstEnv extends Source.BaseEnv {\n window?: typeof window;\n}\n\n/**\n * Create a mock CookieFirst API object\n */\nexport const createMockCookieFirstAPI = (\n consent: CookieFirstConsent | null = null,\n): CookieFirstAPI => ({\n consent,\n});\n\n/**\n * Create a mock window object with CookieFirst\n */\nexport const createMockWindow = (\n consent: CookieFirstConsent | null = null,\n): Partial<Window> & { CookieFirst: CookieFirstAPI } => ({\n CookieFirst: createMockCookieFirstAPI(consent),\n addEventListener: noop,\n removeEventListener: noop,\n});\n\n/**\n * Standard mock environment for testing CookieFirst source\n *\n * Use this for testing consent handling without requiring\n * a real browser environment.\n */\nexport const mockEnv: CookieFirstEnv = {\n get push() {\n return createMockElbFn();\n },\n get command() {\n return createMockElbFn();\n },\n get elb() {\n return createMockElbFn();\n },\n get window() {\n return createMockWindow() as unknown as typeof window;\n },\n logger: noopLogger,\n};\n","import type { Source, WalkerOS } from '@walkeros/core';\nimport type {\n Types,\n Settings,\n CookieFirstConsent,\n CookieFirstAPI,\n} from './types';\n\n// Export types for external usage\nexport * as SourceCookieFirst from './types';\n\n// Export examples\nexport * from './examples';\n\n/**\n * Default category mapping from CookieFirst to walkerOS consent groups.\n *\n * Maps CookieFirst's standard categories to walkerOS convention:\n * - necessary/functional → functional (essential)\n * - performance → analytics (measurement)\n * - advertising → marketing (ads)\n */\nexport const DEFAULT_CATEGORY_MAP: Record<string, string> = {\n necessary: 'functional',\n functional: 'functional',\n performance: 'analytics',\n advertising: 'marketing',\n};\n\n/**\n * CookieFirst consent management source for walkerOS.\n *\n * This source listens to CookieFirst CMP events and translates\n * consent states to walkerOS consent commands.\n *\n * @example\n * ```typescript\n * import { sourceCookieFirst } from '@walkeros/web-source-cmp-cookiefirst';\n *\n * await startFlow({\n * sources: {\n * consent: {\n * code: sourceCookieFirst,\n * config: {\n * settings: {\n * categoryMap: {\n * performance: 'statistics', // Custom mapping\n * },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\nexport const sourceCookieFirst: 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 categoryMap: { ...DEFAULT_CATEGORY_MAP, ...config?.settings?.categoryMap },\n explicitOnly: config?.settings?.explicitOnly ?? true,\n globalName: config?.settings?.globalName ?? 'CookieFirst',\n };\n\n const fullConfig: Source.Config<Types> = { settings };\n\n // Track listener references for cleanup\n let initListener: (() => void) | undefined;\n let consentListener: ((e: Event) => void) | undefined;\n\n // Only setup if in browser environment\n if (actualWindow) {\n /**\n * Handle consent state from CookieFirst.\n * Maps CookieFirst categories to walkerOS consent groups and calls elb.\n *\n * When multiple CookieFirst categories map to the same walkerOS group,\n * uses OR logic: if ANY category is true, the group is true.\n */\n const handleConsent = (consent: CookieFirstConsent | null) => {\n // Skip if explicitOnly and no explicit consent given\n if (settings.explicitOnly && !consent) return;\n if (!consent) return;\n\n // Map CookieFirst categories to walkerOS consent groups\n // Use OR logic: if ANY source category is true, the target group is true\n const state: WalkerOS.Consent = {};\n Object.entries(consent).forEach(([category, value]) => {\n if (typeof value !== 'boolean') return;\n const mapped = settings.categoryMap?.[category] ?? category;\n // OR logic: once true, stays true\n state[mapped] = state[mapped] || value;\n });\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 const globalName = settings.globalName ?? 'CookieFirst';\n const cmp = actualWindow[globalName] as CookieFirstAPI | undefined;\n\n // Process existing consent if CMP already loaded\n if (cmp?.consent) {\n handleConsent(cmp.consent);\n }\n\n // Listen for CMP initialization\n initListener = () => {\n const cmp = actualWindow[globalName] as CookieFirstAPI | undefined;\n handleConsent(cmp?.consent ?? null);\n };\n actualWindow.addEventListener('cf_init', initListener);\n\n // Listen for consent changes\n consentListener = (e: Event) => {\n const customEvent = e as CustomEvent<CookieFirstConsent>;\n handleConsent(customEvent.detail);\n };\n actualWindow.addEventListener('cf_consent', consentListener);\n }\n\n return {\n type: 'cookiefirst',\n config: fullConfig,\n push: elb,\n destroy: async () => {\n // Remove event listeners on cleanup\n if (actualWindow && initListener) {\n actualWindow.removeEventListener('cf_init', initListener);\n }\n if (actualWindow && consentListener) {\n actualWindow.removeEventListener('cf_consent', consentListener);\n }\n },\n };\n};\n\nexport default sourceCookieFirst;\n"],"mappings":"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","names":["_a","_b","cmp"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@walkeros/web-source-cmp-cookiefirst",
|
|
3
|
+
"description": "CookieFirst consent management source for walkerOS",
|
|
4
|
+
"version": "1.1.0-next-1771252576264",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./examples": {
|
|
16
|
+
"types": "./dist/examples/index.d.ts",
|
|
17
|
+
"import": "./dist/examples/index.mjs",
|
|
18
|
+
"require": "./dist/examples/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./dev": {
|
|
21
|
+
"types": "./dist/dev.d.ts",
|
|
22
|
+
"import": "./dist/dev.mjs",
|
|
23
|
+
"require": "./dist/dev.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist/**"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup --silent",
|
|
31
|
+
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
32
|
+
"dev": "jest --watchAll --colors",
|
|
33
|
+
"lint": "tsc && eslint \"**/*.ts*\"",
|
|
34
|
+
"test": "jest",
|
|
35
|
+
"update": "npx npm-check-updates -u && npm update"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@walkeros/core": "1.4.0-next-1771252576264",
|
|
39
|
+
"@walkeros/collector": "1.3.0-next-1771252576264"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {},
|
|
42
|
+
"repository": {
|
|
43
|
+
"url": "git+https://github.com/elbwalker/walkerOS.git",
|
|
44
|
+
"directory": "packages/web/sources/cmps/cookiefirst"
|
|
45
|
+
},
|
|
46
|
+
"author": "elbwalker <hello@elbwalker.com>",
|
|
47
|
+
"homepage": "https://github.com/elbwalker/walkerOS#readme",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/elbwalker/walkerOS/issues"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"walker",
|
|
53
|
+
"walkerOS",
|
|
54
|
+
"source",
|
|
55
|
+
"web",
|
|
56
|
+
"cookiefirst",
|
|
57
|
+
"consent",
|
|
58
|
+
"cmp"
|
|
59
|
+
],
|
|
60
|
+
"funding": [
|
|
61
|
+
{
|
|
62
|
+
"type": "GitHub Sponsors",
|
|
63
|
+
"url": "https://github.com/sponsors/elbwalker"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|