@financial-times/cmp-client 3.1.4 → 3.3.0-beta.4

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.
Files changed (45) hide show
  1. package/README.md +17 -2
  2. package/dist/cmp-static.js +660 -0
  3. package/dist/index.cjs +202 -2719
  4. package/dist/index.js +202 -2719
  5. package/dist/src/cmp-static.d.ts +2 -0
  6. package/dist/src/cmp-static.d.ts.map +1 -0
  7. package/dist/src/consent-ready/index.d.ts.map +1 -1
  8. package/dist/src/consent-ready/utils/__fixtures__/helpers.d.ts +27 -0
  9. package/dist/src/consent-ready/utils/__fixtures__/helpers.d.ts.map +1 -0
  10. package/dist/src/consent-ready/utils/__fixtures__/strings.d.ts +4 -8
  11. package/dist/src/consent-ready/utils/__fixtures__/strings.d.ts.map +1 -1
  12. package/dist/src/consent-ready/utils/__tests__/consent.test.d.ts +2 -0
  13. package/dist/src/consent-ready/utils/__tests__/consent.test.d.ts.map +1 -0
  14. package/dist/src/consent-ready/utils/consent.d.ts +6 -0
  15. package/dist/src/consent-ready/utils/consent.d.ts.map +1 -0
  16. package/dist/src/consent-ready/utils/get-consent-payload.d.ts +7 -7
  17. package/dist/src/consent-ready/utils/get-consent-payload.d.ts.map +1 -1
  18. package/dist/src/consent-ready/utils/get-parsed-consent.d.ts +6 -5
  19. package/dist/src/consent-ready/utils/get-parsed-consent.d.ts.map +1 -1
  20. package/dist/src/consent-ready/utils/validators.d.ts +0 -1
  21. package/dist/src/consent-ready/utils/validators.d.ts.map +1 -1
  22. package/dist/src/html/cmp-footer-link.d.ts +8 -4
  23. package/dist/src/html/cmp-footer-link.d.ts.map +1 -1
  24. package/dist/src/html/cmp-scripts.d.ts.map +1 -1
  25. package/dist/src/index.d.ts +1 -1
  26. package/dist/src/index.d.ts.map +1 -1
  27. package/dist/src/lib/constants.d.ts +33 -2
  28. package/dist/src/lib/constants.d.ts.map +1 -1
  29. package/dist/src/lib/properties.d.ts +36 -0
  30. package/dist/src/lib/properties.d.ts.map +1 -1
  31. package/dist/src/tracking/index.d.ts +1 -1
  32. package/dist/src/tracking/index.d.ts.map +1 -1
  33. package/dist/src/tracking/state.d.ts +6 -0
  34. package/dist/src/tracking/state.d.ts.map +1 -1
  35. package/dist/src/utils/__tests__/url.test.d.ts +2 -0
  36. package/dist/src/utils/__tests__/url.test.d.ts.map +1 -0
  37. package/dist/src/utils/url.d.ts +126 -0
  38. package/dist/src/utils/url.d.ts.map +1 -0
  39. package/package.json +11 -11
  40. package/typings/globals.d.ts +4 -0
  41. package/typings/types.d.ts +54 -3
  42. package/dist/src/consent-ready/utils/has-consent-changed.d.ts +0 -3
  43. package/dist/src/consent-ready/utils/has-consent-changed.d.ts.map +0 -1
  44. package/dist/src/html/__tests__/cmp-footer-links.test.d.ts +0 -2
  45. package/dist/src/html/__tests__/cmp-footer-links.test.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,10 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => {
4
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
- return value;
6
- };
7
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
8
1
  const events = {
9
2
  onMessageChoiceSelect: (...args) => {
10
3
  console.log("[debug] onMessageChoiceSelect", args);
@@ -28,8 +21,8 @@ const events = {
28
21
  console.log("[debug] onSPPMObjectReady", args);
29
22
  },
30
23
  onConsentReady: async (...args) => {
31
- const [legislation2, consentUUID, consentString, consentMeta] = args;
32
- console.log("[debug] onConsentReady", { legislation: legislation2, consentString, consentMeta, consentUUID });
24
+ const [legislation, consentUUID, consentString, consentMeta] = args;
25
+ console.log("[debug] onConsentReady", { legislation, consentString, consentMeta, consentUUID });
33
26
  },
34
27
  onError: (...args) => {
35
28
  console.log("[debug] onError", args);
@@ -38,9 +31,9 @@ const events = {
38
31
  function logCmpEvents() {
39
32
  window._sp_queue = window._sp_queue ?? [];
40
33
  window._sp_queue.push(() => {
41
- var _a2, _b2;
34
+ var _a, _b;
42
35
  for (const [eventId, eventHandler] of Object.entries(events)) {
43
- (_b2 = (_a2 = window._sp_).addEventListener) == null ? void 0 : _b2.call(_a2, eventId, eventHandler);
36
+ (_b = (_a = window._sp_).addEventListener) == null ? void 0 : _b.call(_a, eventId, eventHandler);
44
37
  }
45
38
  });
46
39
  }
@@ -58,67 +51,103 @@ const FT_DOTCOM_TEST = {
58
51
  ...defaults,
59
52
  accountId: 1906,
60
53
  baseEndpoint: "https://consent-manager.ft.com",
61
- propertyHref: "https://local.ft.com"
54
+ propertyHref: "https://local.ft.com",
55
+ _clientOptions: {
56
+ privacyManagerId: 827767,
57
+ manageCookiesLinkOverride: "ft.com/preferences/manage-cookies"
58
+ }
62
59
  };
63
60
  const FT_DOTCOM_PROD = {
64
61
  ...defaults,
65
62
  accountId: 1906,
66
63
  baseEndpoint: "https://consent-manager.ft.com",
67
- propertyId: 31642
64
+ propertyId: 31642,
65
+ _clientOptions: {
66
+ privacyManagerId: 827767,
67
+ manageCookiesLinkOverride: "ft.com/preferences/manage-cookies",
68
+ rootDomain: "ft.com"
69
+ }
68
70
  };
69
71
  const SP_PWMNET = {
70
72
  ...defaults,
71
73
  accountId: 1906,
72
74
  baseEndpoint: "https://consent-manager.pwmnet.com",
73
- propertyId: 33414
75
+ propertyId: 33414,
76
+ _clientOptions: {
77
+ rootDomain: "pwmnet.com"
78
+ }
74
79
  };
75
80
  const SP_FDI_INTELLIGENCE = {
76
81
  ...defaults,
77
82
  accountId: 1906,
78
83
  baseEndpoint: "https://consent-manager.fdiintelligence.com",
79
- propertyId: 34061
84
+ propertyId: 34061,
85
+ _clientOptions: {
86
+ rootDomain: "fdiintelligence.com"
87
+ }
80
88
  };
81
89
  const SP_THE_BANKER = {
82
90
  ...defaults,
83
91
  accountId: 1906,
84
92
  baseEndpoint: "https://consent-manager.thebanker.com",
85
- propertyId: 34060
93
+ propertyId: 34060,
94
+ _clientOptions: {
95
+ rootDomain: "thebanker.com"
96
+ }
86
97
  };
87
98
  const SP_BANKING_RR = {
88
99
  ...defaults,
89
100
  accountId: 1906,
90
101
  baseEndpoint: "https://consent-manager.bankingriskandregulation.com",
91
- propertyId: 34059
102
+ propertyId: 34059,
103
+ _clientOptions: {
104
+ rootDomain: "bankingriskandregulation.com"
105
+ }
92
106
  };
93
107
  const SP_SUSTAINABLE_VIEWS = {
94
108
  ...defaults,
95
109
  accountId: 1906,
96
110
  baseEndpoint: "https://consent-manager.sustainableviews.com",
97
- propertyId: 34058
111
+ propertyId: 34058,
112
+ _clientOptions: {
113
+ rootDomain: "sustainableviews.com"
114
+ }
98
115
  };
99
116
  const SP_FT_ADVISER = {
100
117
  ...defaults,
101
118
  accountId: 1906,
102
119
  baseEndpoint: "https://consent-manager.ftadviser.com",
103
- propertyId: 33416
120
+ propertyId: 33416,
121
+ _clientOptions: {
122
+ rootDomain: "ftadviser.com"
123
+ }
104
124
  };
105
125
  const SP_INVESTORS_CHRONICLE = {
106
126
  ...defaults,
107
127
  accountId: 1906,
108
128
  baseEndpoint: "https://consent-manager.investorschronicle.co.uk",
109
- propertyId: 33415
129
+ propertyId: 33415,
130
+ _clientOptions: {
131
+ rootDomain: "investorschronicle.co.uk"
132
+ }
110
133
  };
111
134
  const MM_IGNITES_ASIA = {
112
135
  ...defaults,
113
136
  accountId: 1906,
114
137
  baseEndpoint: "https://cdn.privacy-mgmt.com",
115
- propertyId: 33947
138
+ propertyId: 33947,
139
+ _clientOptions: {
140
+ rootDomain: "ignitesasia.com"
141
+ }
116
142
  };
117
143
  const MM_IGNITES_EUROPE = {
118
144
  ...defaults,
119
145
  accountId: 1906,
120
146
  baseEndpoint: "https://cdn.privacy-mgmt.com",
121
- propertyId: 33946
147
+ propertyId: 33946,
148
+ _clientOptions: {
149
+ rootDomain: "igniteseurope.com"
150
+ }
122
151
  };
123
152
  const properties = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
124
153
  __proto__: null,
@@ -134,18 +163,20 @@ const properties = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
134
163
  SP_SUSTAINABLE_VIEWS,
135
164
  SP_THE_BANKER
136
165
  }, Symbol.toStringTag, { value: "Module" }));
137
- function updateFooterLinkCMP() {
138
- const cookieLink = document.querySelector(
139
- "[href='https://www.ft.com/preferences/manage-cookies']"
140
- );
141
- if (cookieLink) {
142
- cookieLink.href = "#";
143
- cookieLink.setAttribute("onclick", "window._sp_.gdpr.loadPrivacyManagerModal(827767);");
144
- cookieLink.dataset.cmpLink = "updated";
145
- return true;
166
+ function updateFooterLinkCMP(propertyConfig = FT_DOTCOM_PROD) {
167
+ const { privacyManagerId, manageCookiesLinkOverride, manageCookiesSelector } = propertyConfig._clientOptions || {};
168
+ const footer = document.querySelector(manageCookiesSelector ?? "#site-footer");
169
+ if (footer && manageCookiesLinkOverride) {
170
+ footer.addEventListener("click", (event) => {
171
+ var _a, _b, _c;
172
+ const link = event.target.closest("a");
173
+ if ((_a = link == null ? void 0 : link.getAttribute("href")) == null ? void 0 : _a.endsWith(manageCookiesLinkOverride)) {
174
+ event.preventDefault();
175
+ (_c = (_b = window._sp_) == null ? void 0 : _b.gdpr) == null ? void 0 : _c.loadPrivacyManagerModal(privacyManagerId);
176
+ }
177
+ });
146
178
  } else {
147
- console.warn("CMP Footer Link was not found and not updated");
148
- return false;
179
+ console.warn("No footer found for", manageCookiesSelector);
149
180
  }
150
181
  }
151
182
  const request = (url, { credentials = "omit" } = {}) => {
@@ -224,10 +255,6 @@ const CONSENT_COOKIE_NAME = "FTConsent";
224
255
  const SOURCEPOINT_FOW_ID = "sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk";
225
256
  const FT_COOKIE_DOMAIN = ".ft.com";
226
257
  const FT_CONSENT_PROXY_HOST = "https://consent.ft.com";
227
- const legislation = {
228
- CCPA: "ccpa",
229
- GDPR: "gdpr"
230
- };
231
258
  const iabCustomCategories = {
232
259
  permutiveAds: {
233
260
  purposes: [2, 4, 8, 9],
@@ -247,6 +274,12 @@ const iabCustomCategories = {
247
274
  customVendors: [],
248
275
  specialFeatures: []
249
276
  },
277
+ programmaticAds: {
278
+ purposes: [2],
279
+ iabVendors: [],
280
+ customVendors: [],
281
+ specialFeatures: []
282
+ },
250
283
  personalisedMarketing: {
251
284
  purposes: [1, 4, 8, 9, 10],
252
285
  iabVendors: [],
@@ -254,6 +287,7 @@ const iabCustomCategories = {
254
287
  specialFeatures: []
255
288
  }
256
289
  };
290
+ const iabCategoryNames = Object.keys(iabCustomCategories);
257
291
  function createContentScript(cmpScript, content) {
258
292
  const s = document.createElement("script");
259
293
  s.dataset.cmpScript = cmpScript;
@@ -269,8 +303,8 @@ const scriptSources = {
269
303
  cmpFrames: "https://consent-manager.ft.com/unified/wrapperMessagingWithoutDetection.js"
270
304
  };
271
305
  const scriptContent = {
272
- tcfStub: `"use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){var t=function(){var t,e,o=[],n=window,r=n;for(;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=r.parent}t||(!function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"setGdprApplies"===n[0]?n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)&&null!==o?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=t:t()}();`,
273
- uspStub: `"use strict";(function () { var e = false; var c = window; var t = document; function r() { if (!c.frames["__uspapiLocator"]) { if (t.body) { var a = t.body; var e = t.createElement("iframe"); e.style.cssText = "display:none"; e.name = "__uspapiLocator"; a.appendChild(e) } else { setTimeout(r, 5) } } } r(); function p() { var a = arguments; __uspapi.a = __uspapi.a || []; if (!a.length) { return __uspapi.a } else if (a[0] === "ping") { a[2]({ gdprAppliesGlobally: e, cmpLoaded: false }, true) } else { __uspapi.a.push([].slice.apply(a)) } } function l(t) { var r = typeof t.data === "string"; try { var a = r ? JSON.parse(t.data) : t.data; if (a.__cmpCall) { var n = a.__cmpCall; c.__uspapi(n.command, n.parameter, function (a, e) { var c = { __cmpReturn: { returnValue: a, success: e, callId: n.callId } }; t.source.postMessage(r ? JSON.stringify(c) : c, "*") }) } } catch (a) { } } if (typeof __uspapi !== "function") { c.__uspapi = p; __uspapi.msgHandler = l; c.addEventListener("message", l, false) } })();`
306
+ tcfStub: `"use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){var t=function(){var t,e,o=[],n=window,r=n;for(;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=r.parent}t||(!function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",r.title = "__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"setGdprApplies"===n[0]?n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)&&null!==o?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=t:t()}();`,
307
+ uspStub: `"use strict";(function () { var e = false; var c = window; var t = document; function r() { if (!c.frames["__uspapiLocator"]) { if (t.body) { var a = t.body; var e = t.createElement("iframe"); e.style.cssText = "display:none"; e.name = "__uspapiLocator"; e.title = "__uspapiLocator";a.appendChild(e) } else { setTimeout(r, 5) } } } r(); function p() { var a = arguments; __uspapi.a = __uspapi.a || []; if (!a.length) { return __uspapi.a } else if (a[0] === "ping") { a[2]({ gdprAppliesGlobally: e, cmpLoaded: false }, true) } else { __uspapi.a.push([].slice.apply(a)) } } function l(t) { var r = typeof t.data === "string"; try { var a = r ? JSON.parse(t.data) : t.data; if (a.__cmpCall) { var n = a.__cmpCall; c.__uspapi(n.command, n.parameter, function (a, e) { var c = { __cmpReturn: { returnValue: a, success: e, callId: n.callId } }; t.source.postMessage(r ? JSON.stringify(c) : c, "*") }) } } catch (a) { } } if (typeof __uspapi !== "function") { c.__uspapi = p; __uspapi.msgHandler = l; c.addEventListener("message", l, false) } })();`
274
308
  };
275
309
  function getCmpScripts() {
276
310
  const fragment = document.createDocumentFragment();
@@ -280,11 +314,12 @@ function getCmpScripts() {
280
314
  return fragment;
281
315
  }
282
316
  function bootstrapCmp(config) {
283
- window._sp_ = { config };
317
+ const { _clientOptions, ...spConfig } = config;
318
+ window._sp_ = { config: spConfig };
284
319
  window._sp_queue ?? (window._sp_queue = []);
285
320
  document.head.appendChild(getCmpScripts());
286
321
  }
287
- function getConsentPayload(parsedConsent, { shouldUpdateConsentStore, formOfWordsId, cookieDomain }) {
322
+ function getConsentPayload(parsedConsent, updateConsentStore, { formOfWordsId, cookieDomain }) {
288
323
  const categoryNames = Object.keys(parsedConsent);
289
324
  const data = categoryNames.reduce(
290
325
  (payload, categoryName) => {
@@ -300,9 +335,7 @@ function getConsentPayload(parsedConsent, { shouldUpdateConsentStore, formOfWord
300
335
  },
301
336
  {}
302
337
  );
303
- if (!shouldUpdateConsentStore) {
304
- return { data, cookieDomain };
305
- } else {
338
+ if (updateConsentStore) {
306
339
  return {
307
340
  setConsentCookie: true,
308
341
  formOfWordsId,
@@ -311,2549 +344,46 @@ function getConsentPayload(parsedConsent, { shouldUpdateConsentStore, formOfWord
311
344
  data
312
345
  };
313
346
  }
347
+ return { data, cookieDomain };
314
348
  }
315
- class DecodingError extends Error {
316
- /**
317
- * constructor - constructs an DecodingError
318
- *
319
- * @param {string} msg - Decoding Error Message
320
- * @return {undefined}
321
- */
322
- constructor(msg) {
323
- super(msg);
324
- this.name = "DecodingError";
325
- }
326
- }
327
- class EncodingError extends Error {
328
- /**
329
- * constructor - constructs an EncodingError
330
- *
331
- * @param {string} msg - Encoding Error Message
332
- * @return {undefined}
333
- */
334
- constructor(msg) {
335
- super(msg);
336
- this.name = "EncodingError";
337
- }
338
- }
339
- class GVLError extends Error {
340
- /**
341
- * constructor - constructs a GVLError
342
- *
343
- * @param {string} msg - Error message to display
344
- * @return {undefined}
345
- */
346
- constructor(msg) {
347
- super(msg);
348
- this.name = "GVLError";
349
- }
350
- }
351
- class TCModelError extends Error {
352
- /**
353
- * constructor - constructs an TCModelError
354
- *
355
- * @param {string} fieldName - the errored field
356
- * @param {string} passedValue - what was passed
357
- * @return {undefined}
358
- */
359
- constructor(fieldName, passedValue, msg = "") {
360
- super(`invalid value ${passedValue} passed for ${fieldName} ${msg}`);
361
- this.name = "TCModelError";
362
- }
363
- }
364
- class Base64Url {
365
- /**
366
- * encodes an arbitrary-length bitfield string into base64url
367
- *
368
- * @static
369
- * @param {string} str - arbitrary-length bitfield string to be encoded to base64url
370
- * @return {string} - base64url encoded result
371
- */
372
- static encode(str) {
373
- if (!/^[0-1]+$/.test(str)) {
374
- throw new EncodingError("Invalid bitField");
375
- }
376
- const padding = str.length % this.LCM;
377
- str += padding ? "0".repeat(this.LCM - padding) : "";
378
- let result = "";
379
- for (let i = 0; i < str.length; i += this.BASIS) {
380
- result += this.DICT[parseInt(str.substr(i, this.BASIS), 2)];
381
- }
382
- return result;
383
- }
384
- /**
385
- * decodes a base64url encoded bitfield string
386
- *
387
- * @static
388
- * @param {string} str - base64url encoded bitfield string to be decoded
389
- * @return {string} - bitfield string
390
- */
391
- static decode(str) {
392
- if (!/^[A-Za-z0-9\-_]+$/.test(str)) {
393
- throw new DecodingError("Invalidly encoded Base64URL string");
394
- }
395
- let result = "";
396
- for (let i = 0; i < str.length; i++) {
397
- const strBits = this.REVERSE_DICT.get(str[i]).toString(2);
398
- result += "0".repeat(this.BASIS - strBits.length) + strBits;
399
- }
400
- return result;
401
- }
402
- }
403
- /**
404
- * Base 64 URL character set. Different from standard Base64 char set
405
- * in that '+' and '/' are replaced with '-' and '_'.
406
- */
407
- __publicField(Base64Url, "DICT", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
408
- __publicField(Base64Url, "REVERSE_DICT", /* @__PURE__ */ new Map([
409
- ["A", 0],
410
- ["B", 1],
411
- ["C", 2],
412
- ["D", 3],
413
- ["E", 4],
414
- ["F", 5],
415
- ["G", 6],
416
- ["H", 7],
417
- ["I", 8],
418
- ["J", 9],
419
- ["K", 10],
420
- ["L", 11],
421
- ["M", 12],
422
- ["N", 13],
423
- ["O", 14],
424
- ["P", 15],
425
- ["Q", 16],
426
- ["R", 17],
427
- ["S", 18],
428
- ["T", 19],
429
- ["U", 20],
430
- ["V", 21],
431
- ["W", 22],
432
- ["X", 23],
433
- ["Y", 24],
434
- ["Z", 25],
435
- ["a", 26],
436
- ["b", 27],
437
- ["c", 28],
438
- ["d", 29],
439
- ["e", 30],
440
- ["f", 31],
441
- ["g", 32],
442
- ["h", 33],
443
- ["i", 34],
444
- ["j", 35],
445
- ["k", 36],
446
- ["l", 37],
447
- ["m", 38],
448
- ["n", 39],
449
- ["o", 40],
450
- ["p", 41],
451
- ["q", 42],
452
- ["r", 43],
453
- ["s", 44],
454
- ["t", 45],
455
- ["u", 46],
456
- ["v", 47],
457
- ["w", 48],
458
- ["x", 49],
459
- ["y", 50],
460
- ["z", 51],
461
- ["0", 52],
462
- ["1", 53],
463
- ["2", 54],
464
- ["3", 55],
465
- ["4", 56],
466
- ["5", 57],
467
- ["6", 58],
468
- ["7", 59],
469
- ["8", 60],
470
- ["9", 61],
471
- ["-", 62],
472
- ["_", 63]
473
- ]));
474
- /**
475
- * log2(64) = 6
476
- */
477
- __publicField(Base64Url, "BASIS", 6);
478
- __publicField(Base64Url, "LCM", 24);
479
- const _ConsentLanguages = class _ConsentLanguages {
480
- has(key) {
481
- return _ConsentLanguages.langSet.has(key);
482
- }
483
- parseLanguage(lang) {
484
- lang = lang.toUpperCase();
485
- const primaryLanguage = lang.split("-")[0];
486
- if (lang.length >= 2 && primaryLanguage.length == 2) {
487
- if (_ConsentLanguages.langSet.has(lang)) {
488
- return lang;
489
- } else if (_ConsentLanguages.langSet.has(primaryLanguage)) {
490
- return primaryLanguage;
491
- }
492
- const fullPrimaryLang = primaryLanguage + "-" + primaryLanguage;
493
- if (_ConsentLanguages.langSet.has(fullPrimaryLang)) {
494
- return fullPrimaryLang;
495
- }
496
- for (const supportedLang of _ConsentLanguages.langSet) {
497
- if (supportedLang.indexOf(lang) !== -1 || supportedLang.indexOf(primaryLanguage) !== -1) {
498
- return supportedLang;
499
- }
500
- }
501
- }
502
- throw new Error(`unsupported language ${lang}`);
503
- }
504
- forEach(callback) {
505
- _ConsentLanguages.langSet.forEach(callback);
506
- }
507
- get size() {
508
- return _ConsentLanguages.langSet.size;
509
- }
510
- };
511
- __publicField(_ConsentLanguages, "langSet", /* @__PURE__ */ new Set([
512
- "AR",
513
- "BG",
514
- "BS",
515
- "CA",
516
- "CS",
517
- "DA",
518
- "DE",
519
- "EL",
520
- "EN",
521
- "ES",
522
- "ET",
523
- "EU",
524
- "FI",
525
- "FR",
526
- "GL",
527
- "HR",
528
- "HU",
529
- "IT",
530
- "JA",
531
- "LT",
532
- "LV",
533
- "MT",
534
- "NL",
535
- "NO",
536
- "PL",
537
- "PT-BR",
538
- "PT-PT",
539
- "RO",
540
- "RU",
541
- "SK",
542
- "SL",
543
- "SR-LATN",
544
- "SR-CYRL",
545
- "SV",
546
- "TR",
547
- "ZH"
548
- ]));
549
- let ConsentLanguages = _ConsentLanguages;
550
- class Fields {
551
- }
552
- __publicField(Fields, "cmpId", "cmpId");
553
- __publicField(Fields, "cmpVersion", "cmpVersion");
554
- __publicField(Fields, "consentLanguage", "consentLanguage");
555
- __publicField(Fields, "consentScreen", "consentScreen");
556
- __publicField(Fields, "created", "created");
557
- __publicField(Fields, "supportOOB", "supportOOB");
558
- __publicField(Fields, "isServiceSpecific", "isServiceSpecific");
559
- __publicField(Fields, "lastUpdated", "lastUpdated");
560
- __publicField(Fields, "numCustomPurposes", "numCustomPurposes");
561
- __publicField(Fields, "policyVersion", "policyVersion");
562
- __publicField(Fields, "publisherCountryCode", "publisherCountryCode");
563
- __publicField(Fields, "publisherCustomConsents", "publisherCustomConsents");
564
- __publicField(Fields, "publisherCustomLegitimateInterests", "publisherCustomLegitimateInterests");
565
- __publicField(Fields, "publisherLegitimateInterests", "publisherLegitimateInterests");
566
- __publicField(Fields, "publisherConsents", "publisherConsents");
567
- __publicField(Fields, "publisherRestrictions", "publisherRestrictions");
568
- __publicField(Fields, "purposeConsents", "purposeConsents");
569
- __publicField(Fields, "purposeLegitimateInterests", "purposeLegitimateInterests");
570
- __publicField(Fields, "purposeOneTreatment", "purposeOneTreatment");
571
- __publicField(Fields, "specialFeatureOptins", "specialFeatureOptins");
572
- __publicField(Fields, "useNonStandardTexts", "useNonStandardTexts");
573
- __publicField(Fields, "vendorConsents", "vendorConsents");
574
- __publicField(Fields, "vendorLegitimateInterests", "vendorLegitimateInterests");
575
- __publicField(Fields, "vendorListVersion", "vendorListVersion");
576
- __publicField(Fields, "vendorsAllowed", "vendorsAllowed");
577
- __publicField(Fields, "vendorsDisclosed", "vendorsDisclosed");
578
- __publicField(Fields, "version", "version");
579
- class Cloneable {
580
- /**
581
- * clone - returns a copy of the classes with new values and not references
582
- *
583
- * @return {T}
584
- */
585
- clone() {
586
- const myClone = new this.constructor();
587
- const keys = Object.keys(this);
588
- keys.forEach((key) => {
589
- const value = this.deepClone(this[key]);
590
- if (value !== void 0) {
591
- myClone[key] = value;
592
- }
593
- });
594
- return myClone;
595
- }
596
- /**
597
- * deepClone - recursive function that makes copies of reference values
598
- *
599
- * @param {unknown} item
600
- * @return {unknown}
601
- */
602
- deepClone(item) {
603
- const itsType = typeof item;
604
- if (itsType === "number" || itsType === "string" || itsType === "boolean") {
605
- return item;
606
- } else if (item !== null && itsType === "object") {
607
- if (typeof item.clone === "function") {
608
- return item.clone();
609
- } else if (item instanceof Date) {
610
- return new Date(item.getTime());
611
- } else if (item[Symbol.iterator] !== void 0) {
612
- const ar = [];
613
- for (const subItem of item) {
614
- ar.push(this.deepClone(subItem));
615
- }
616
- if (item instanceof Array) {
617
- return ar;
618
- } else {
619
- return new item.constructor(ar);
620
- }
621
- } else {
622
- const retr = {};
623
- for (const prop in item) {
624
- if (item.hasOwnProperty(prop)) {
625
- retr[prop] = this.deepClone(item[prop]);
626
- }
627
- }
628
- return retr;
629
- }
630
- }
631
- }
632
- }
633
- var RestrictionType;
634
- (function(RestrictionType2) {
635
- RestrictionType2[RestrictionType2["NOT_ALLOWED"] = 0] = "NOT_ALLOWED";
636
- RestrictionType2[RestrictionType2["REQUIRE_CONSENT"] = 1] = "REQUIRE_CONSENT";
637
- RestrictionType2[RestrictionType2["REQUIRE_LI"] = 2] = "REQUIRE_LI";
638
- })(RestrictionType || (RestrictionType = {}));
639
- const _PurposeRestriction = class _PurposeRestriction extends Cloneable {
640
- /**
641
- * constructor
642
- *
643
- * @param {number} purposeId? - may optionally pass the purposeId into the
644
- * constructor
645
- * @param {RestrictionType} restrictionType? - may
646
- * optionally pass the restrictionType into the constructor
647
- * @return {undefined}
648
- */
649
- constructor(purposeId, restrictionType) {
650
- super();
651
- __publicField(this, "purposeId_");
652
- __publicField(this, "restrictionType");
653
- if (purposeId !== void 0) {
654
- this.purposeId = purposeId;
655
- }
656
- if (restrictionType !== void 0) {
657
- this.restrictionType = restrictionType;
658
- }
659
- }
660
- static unHash(hash) {
661
- const splitUp = hash.split(this.hashSeparator);
662
- const purpRestriction = new _PurposeRestriction();
663
- if (splitUp.length !== 2) {
664
- throw new TCModelError("hash", hash);
665
- }
666
- purpRestriction.purposeId = parseInt(splitUp[0], 10);
667
- purpRestriction.restrictionType = parseInt(splitUp[1], 10);
668
- return purpRestriction;
669
- }
670
- get hash() {
671
- if (!this.isValid()) {
672
- throw new Error("cannot hash invalid PurposeRestriction");
673
- }
674
- return `${this.purposeId}${_PurposeRestriction.hashSeparator}${this.restrictionType}`;
675
- }
676
- /**
677
- * @return {number} The purpose Id associated with a publisher
678
- * purpose-by-vendor restriction that resulted in a different consent or LI
679
- * status than the consent or LI purposes allowed lists.
680
- */
681
- get purposeId() {
682
- return this.purposeId_;
683
- }
684
- /**
685
- * @param {number} idNum - The purpose Id associated with a publisher
686
- * purpose-by-vendor restriction that resulted in a different consent or LI
687
- * status than the consent or LI purposes allowed lists.
688
- */
689
- set purposeId(idNum) {
690
- this.purposeId_ = idNum;
691
- }
692
- isValid() {
693
- return Number.isInteger(this.purposeId) && this.purposeId > 0 && (this.restrictionType === RestrictionType.NOT_ALLOWED || this.restrictionType === RestrictionType.REQUIRE_CONSENT || this.restrictionType === RestrictionType.REQUIRE_LI);
694
- }
695
- isSameAs(otherPR) {
696
- return this.purposeId === otherPR.purposeId && this.restrictionType === otherPR.restrictionType;
697
- }
698
- };
699
- __publicField(_PurposeRestriction, "hashSeparator", "-");
700
- let PurposeRestriction = _PurposeRestriction;
701
- class PurposeRestrictionVector extends Cloneable {
702
- constructor() {
703
- super(...arguments);
704
- /**
705
- * if this originatd from an encoded string we'll need a place to store the
706
- * bit length; it can be set and got from here
707
- */
708
- __publicField(this, "bitLength", 0);
709
- /**
710
- * a map indexed by a string which will be a 'hash' of the purpose and
711
- * restriction type.
712
- */
713
- __publicField(this, "map", /* @__PURE__ */ new Map());
714
- __publicField(this, "gvl_");
715
- }
716
- has(hash) {
717
- return this.map.has(hash);
718
- }
719
- isOkToHave(restrictionType, purposeId, vendorId) {
720
- var _a2;
721
- let result = true;
722
- if ((_a2 = this.gvl) == null ? void 0 : _a2.vendors) {
723
- const vendor = this.gvl.vendors[vendorId];
724
- if (vendor) {
725
- if (restrictionType === RestrictionType.NOT_ALLOWED) {
726
- result = vendor.legIntPurposes.includes(purposeId) || vendor.purposes.includes(purposeId);
727
- } else if (vendor.flexiblePurposes.length) {
728
- switch (restrictionType) {
729
- case RestrictionType.REQUIRE_CONSENT:
730
- result = vendor.flexiblePurposes.includes(purposeId) && vendor.legIntPurposes.includes(purposeId);
731
- break;
732
- case RestrictionType.REQUIRE_LI:
733
- result = vendor.flexiblePurposes.includes(purposeId) && vendor.purposes.includes(purposeId);
734
- break;
735
- }
736
- } else {
737
- result = false;
738
- }
739
- } else {
740
- result = false;
741
- }
742
- }
743
- return result;
744
- }
745
- /**
746
- * add - adds a given Vendor ID under a given Purpose Restriction
747
- *
748
- * @param {number} vendorId
749
- * @param {PurposeRestriction} purposeRestriction
750
- * @return {void}
751
- */
752
- add(vendorId, purposeRestriction) {
753
- if (this.isOkToHave(purposeRestriction.restrictionType, purposeRestriction.purposeId, vendorId)) {
754
- const hash = purposeRestriction.hash;
755
- if (!this.has(hash)) {
756
- this.map.set(hash, /* @__PURE__ */ new Set());
757
- this.bitLength = 0;
758
- }
759
- this.map.get(hash).add(vendorId);
760
- }
761
- }
762
- /**
763
- * restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
764
- *
765
- * @param {PurposeRestriction} purposeRestriction
766
- * @return {void}
767
- */
768
- restrictPurposeToLegalBasis(purposeRestriction) {
769
- const vendors = Array.from(this.gvl.vendorIds);
770
- const hash = purposeRestriction.hash;
771
- const lastEntry = vendors[vendors.length - 1];
772
- const values = [...Array(lastEntry).keys()].map((i) => i + 1);
773
- if (!this.has(hash)) {
774
- this.map.set(hash, new Set(values));
775
- this.bitLength = 0;
776
- } else {
777
- for (let i = 1; i <= lastEntry; i++) {
778
- this.map.get(hash).add(i);
779
- }
780
- }
781
- }
782
- /**
783
- * getVendors - returns array of vendor ids optionally narrowed by a given
784
- * Purpose Restriction. If no purpose restriction is passed then all vendor
785
- * ids will be returned. One can expect this result to be a unique set of
786
- * ids no duplicates.
787
- *
788
- * @param {PurposeRestriction} [purposeRestriction] - optionally passed to
789
- * get only Vendor IDs restricted under the given Purpose Restriction
790
- * @return {number[]} - Unique ID set of vendors
791
- */
792
- getVendors(purposeRestriction) {
793
- let vendorIds = [];
794
- if (purposeRestriction) {
795
- const hash = purposeRestriction.hash;
796
- if (this.has(hash)) {
797
- vendorIds = Array.from(this.map.get(hash));
798
- }
799
- } else {
800
- const vendorSet = /* @__PURE__ */ new Set();
801
- this.map.forEach((set) => {
802
- set.forEach((vendorId) => {
803
- vendorSet.add(vendorId);
804
- });
805
- });
806
- vendorIds = Array.from(vendorSet);
807
- }
808
- return vendorIds.sort((a, b) => a - b);
809
- }
810
- getRestrictionType(vendorId, purposeId) {
811
- let rType;
812
- this.getRestrictions(vendorId).forEach((purposeRestriction) => {
813
- if (purposeRestriction.purposeId === purposeId) {
814
- if (rType === void 0 || rType > purposeRestriction.restrictionType) {
815
- rType = purposeRestriction.restrictionType;
816
- }
817
- }
818
- });
819
- return rType;
820
- }
821
- /**
822
- * vendorHasRestriction - determines whether a given Vendor ID is under a
823
- * given Purpose Restriction
824
- *
825
- * @param {number} vendorId
826
- * @param {PurposeRestriction} purposeRestriction
827
- * @return {boolean} - true if the give Vendor ID is under the given Purpose
828
- * Restriction
829
- */
830
- vendorHasRestriction(vendorId, purposeRestriction) {
831
- let has = false;
832
- const restrictions = this.getRestrictions(vendorId);
833
- for (let i = 0; i < restrictions.length && !has; i++) {
834
- has = purposeRestriction.isSameAs(restrictions[i]);
835
- }
836
- return has;
837
- }
838
- /**
839
- * getMaxVendorId - gets the Maximum Vendor ID regardless of Purpose
840
- * Restriction
841
- *
842
- * @return {number} - maximum Vendor ID
843
- */
844
- getMaxVendorId() {
845
- let retr = 0;
846
- this.map.forEach((set) => {
847
- retr = Math.max(Array.from(set)[set.size - 1], retr);
848
- });
849
- return retr;
850
- }
851
- getRestrictions(vendorId) {
852
- const retr = [];
853
- this.map.forEach((set, hash) => {
854
- if (vendorId) {
855
- if (set.has(vendorId)) {
856
- retr.push(PurposeRestriction.unHash(hash));
857
- }
858
- } else {
859
- retr.push(PurposeRestriction.unHash(hash));
860
- }
861
- });
862
- return retr;
863
- }
864
- getPurposes() {
865
- const purposeIds = /* @__PURE__ */ new Set();
866
- this.map.forEach((set, hash) => {
867
- purposeIds.add(PurposeRestriction.unHash(hash).purposeId);
868
- });
869
- return Array.from(purposeIds);
870
- }
871
- /**
872
- * remove - removes Vendor ID from a Purpose Restriction
873
- *
874
- * @param {number} vendorId
875
- * @param {PurposeRestriction} purposeRestriction
876
- * @return {void}
877
- */
878
- remove(vendorId, purposeRestriction) {
879
- const hash = purposeRestriction.hash;
880
- const set = this.map.get(hash);
881
- if (set) {
882
- set.delete(vendorId);
883
- if (set.size == 0) {
884
- this.map.delete(hash);
885
- this.bitLength = 0;
886
- }
887
- }
888
- }
889
- /**
890
- * Essential for being able to determine whether we can actually set a
891
- * purpose restriction since they have to have a flexible legal basis
892
- *
893
- * @param {GVL} value - the GVL instance
894
- */
895
- set gvl(value) {
896
- if (!this.gvl_) {
897
- this.gvl_ = value;
898
- this.map.forEach((set, hash) => {
899
- const purposeRestriction = PurposeRestriction.unHash(hash);
900
- const vendors = Array.from(set);
901
- vendors.forEach((vendorId) => {
902
- if (!this.isOkToHave(purposeRestriction.restrictionType, purposeRestriction.purposeId, vendorId)) {
903
- set.delete(vendorId);
904
- }
905
- });
906
- });
907
- }
908
- }
909
- /**
910
- * gvl returns local copy of the GVL these restrictions apply to
911
- *
912
- * @return {GVL}
913
- */
914
- get gvl() {
915
- return this.gvl_;
916
- }
917
- /**
918
- * isEmpty - whether or not this vector has any restrictions in it
919
- *
920
- * @return {boolean}
921
- */
922
- isEmpty() {
923
- return this.map.size === 0;
924
- }
925
- /**
926
- * numRestrictions - returns the number of Purpose Restrictions.
927
- *
928
- * @return {number}
929
- */
930
- get numRestrictions() {
931
- return this.map.size;
932
- }
933
- }
934
- var DeviceDisclosureStorageAccessType;
935
- (function(DeviceDisclosureStorageAccessType2) {
936
- DeviceDisclosureStorageAccessType2["COOKIE"] = "cookie";
937
- DeviceDisclosureStorageAccessType2["WEB"] = "web";
938
- DeviceDisclosureStorageAccessType2["APP"] = "app";
939
- })(DeviceDisclosureStorageAccessType || (DeviceDisclosureStorageAccessType = {}));
940
- var Segment;
941
- (function(Segment2) {
942
- Segment2["CORE"] = "core";
943
- Segment2["VENDORS_DISCLOSED"] = "vendorsDisclosed";
944
- Segment2["VENDORS_ALLOWED"] = "vendorsAllowed";
945
- Segment2["PUBLISHER_TC"] = "publisherTC";
946
- })(Segment || (Segment = {}));
947
- class SegmentIDs {
948
- }
949
- /**
950
- * 0 = default - reserved for core string (does not need to be present in the core string)
951
- * 1 = OOB vendors disclosed
952
- * 2 = OOB vendors allowed
953
- * 3 = PublisherTC
954
- */
955
- __publicField(SegmentIDs, "ID_TO_KEY", [
956
- Segment.CORE,
957
- Segment.VENDORS_DISCLOSED,
958
- Segment.VENDORS_ALLOWED,
959
- Segment.PUBLISHER_TC
960
- ]);
961
- __publicField(SegmentIDs, "KEY_TO_ID", {
962
- [Segment.CORE]: 0,
963
- [Segment.VENDORS_DISCLOSED]: 1,
964
- [Segment.VENDORS_ALLOWED]: 2,
965
- [Segment.PUBLISHER_TC]: 3
966
- });
967
- class Vector extends Cloneable {
968
- constructor() {
969
- super(...arguments);
970
- /**
971
- * if this originatd from an encoded string we'll need a place to store the
972
- * bit length; it can be set and got from here
973
- */
974
- __publicField(this, "bitLength", 0);
975
- __publicField(this, "maxId_", 0);
976
- __publicField(this, "set_", /* @__PURE__ */ new Set());
977
- }
978
- *[Symbol.iterator]() {
979
- for (let i = 1; i <= this.maxId; i++) {
980
- yield [i, this.has(i)];
981
- }
982
- }
983
- /**
984
- * values()
985
- *
986
- * @return {IterableIterator<number>} - returns an iterator of the positive
987
- * values in the set
988
- */
989
- values() {
990
- return this.set_.values();
991
- }
992
- /**
993
- * maxId
994
- *
995
- * @return {number} - the highest id in this Vector
996
- */
997
- get maxId() {
998
- return this.maxId_;
999
- }
1000
- /**
1001
- * get
1002
- *
1003
- * @param {number} id - key for value to check
1004
- * @return {boolean} - value of that key, if never set it will be false
1005
- */
1006
- has(id) {
1007
- return this.set_.has(id);
1008
- }
1009
- /**
1010
- * unset
1011
- *
1012
- * @param {SingleIDOrCollection} id - id or ids to unset
1013
- * @return {void}
1014
- */
1015
- unset(id) {
1016
- if (Array.isArray(id)) {
1017
- id.forEach((id2) => this.unset(id2));
1018
- } else if (typeof id === "object") {
1019
- this.unset(Object.keys(id).map((strId) => Number(strId)));
1020
- } else {
1021
- this.set_.delete(Number(id));
1022
- this.bitLength = 0;
1023
- if (id === this.maxId) {
1024
- this.maxId_ = 0;
1025
- this.set_.forEach((id2) => {
1026
- this.maxId_ = Math.max(this.maxId, id2);
1027
- });
1028
- }
1029
- }
1030
- }
1031
- isIntMap(item) {
1032
- let result = typeof item === "object";
1033
- result = result && Object.keys(item).every((key) => {
1034
- let itemResult = Number.isInteger(parseInt(key, 10));
1035
- itemResult = itemResult && this.isValidNumber(item[key].id);
1036
- itemResult = itemResult && item[key].name !== void 0;
1037
- return itemResult;
1038
- });
1039
- return result;
1040
- }
1041
- isValidNumber(item) {
1042
- return parseInt(item, 10) > 0;
1043
- }
1044
- isSet(item) {
1045
- let result = false;
1046
- if (item instanceof Set) {
1047
- result = Array.from(item).every(this.isValidNumber);
1048
- }
1049
- return result;
1050
- }
1051
- /**
1052
- * set - sets an item assumed to be a truthy value by its presence
1053
- *
1054
- * @param {SingleIDOrCollection} item - May be a single id (positive integer)
1055
- * or collection of ids in a set, GVL Int Map, or Array.
1056
- *
1057
- * @return {void}
1058
- */
1059
- set(item) {
1060
- if (Array.isArray(item)) {
1061
- item.forEach((item2) => this.set(item2));
1062
- } else if (this.isSet(item)) {
1063
- this.set(Array.from(item));
1064
- } else if (this.isIntMap(item)) {
1065
- this.set(Object.keys(item).map((strId) => Number(strId)));
1066
- } else if (this.isValidNumber(item)) {
1067
- this.set_.add(item);
1068
- this.maxId_ = Math.max(this.maxId, item);
1069
- this.bitLength = 0;
1070
- } else {
1071
- throw new TCModelError("set()", item, "must be positive integer array, positive integer, Set<number>, or IntMap");
1072
- }
1073
- }
1074
- empty() {
1075
- this.set_ = /* @__PURE__ */ new Set();
1076
- }
1077
- /**
1078
- * forEach - to traverse from id=1 to id=maxId in a sequential non-sparse manner
1079
- *
1080
- *
1081
- * @param {forEachCallback} callback - callback to execute
1082
- * @return {void}
1083
- *
1084
- * @callback forEachCallback
1085
- * @param {boolean} value - whether or not this id exists in the vector
1086
- * @param {number} id - the id number of the current iteration
1087
- */
1088
- forEach(callback) {
1089
- for (let i = 1; i <= this.maxId; i++) {
1090
- callback(this.has(i), i);
1091
- }
1092
- }
1093
- get size() {
1094
- return this.set_.size;
1095
- }
1096
- setAll(intMap) {
1097
- this.set(intMap);
1098
- }
1099
- }
1100
- class BitLength {
1101
- }
1102
- _a = Fields.cmpId, _b = Fields.cmpVersion, _c = Fields.consentLanguage, _d = Fields.consentScreen, _e = Fields.created, _f = Fields.isServiceSpecific, _g = Fields.lastUpdated, _h = Fields.policyVersion, _i = Fields.publisherCountryCode, _j = Fields.publisherLegitimateInterests, _k = Fields.publisherConsents, _l = Fields.purposeConsents, _m = Fields.purposeLegitimateInterests, _n = Fields.purposeOneTreatment, _o = Fields.specialFeatureOptins, _p = Fields.useNonStandardTexts, _q = Fields.vendorListVersion, _r = Fields.version;
1103
- __publicField(BitLength, _a, 12);
1104
- __publicField(BitLength, _b, 12);
1105
- __publicField(BitLength, _c, 12);
1106
- __publicField(BitLength, _d, 6);
1107
- __publicField(BitLength, _e, 36);
1108
- __publicField(BitLength, _f, 1);
1109
- __publicField(BitLength, _g, 36);
1110
- __publicField(BitLength, _h, 6);
1111
- __publicField(BitLength, _i, 12);
1112
- __publicField(BitLength, _j, 24);
1113
- __publicField(BitLength, _k, 24);
1114
- __publicField(BitLength, _l, 24);
1115
- __publicField(BitLength, _m, 24);
1116
- __publicField(BitLength, _n, 1);
1117
- __publicField(BitLength, _o, 12);
1118
- __publicField(BitLength, _p, 1);
1119
- __publicField(BitLength, _q, 12);
1120
- __publicField(BitLength, _r, 6);
1121
- __publicField(BitLength, "anyBoolean", 1);
1122
- __publicField(BitLength, "encodingType", 1);
1123
- __publicField(BitLength, "maxId", 16);
1124
- __publicField(BitLength, "numCustomPurposes", 6);
1125
- __publicField(BitLength, "numEntries", 12);
1126
- __publicField(BitLength, "numRestrictions", 12);
1127
- __publicField(BitLength, "purposeId", 6);
1128
- __publicField(BitLength, "restrictionType", 2);
1129
- __publicField(BitLength, "segmentType", 3);
1130
- __publicField(BitLength, "singleOrRange", 1);
1131
- __publicField(BitLength, "vendorId", 16);
1132
- class BooleanEncoder {
1133
- static encode(value) {
1134
- return String(Number(value));
1135
- }
1136
- static decode(value) {
1137
- return value === "1";
1138
- }
1139
- }
1140
- class IntEncoder {
1141
- static encode(value, numBits) {
1142
- let bitString;
1143
- if (typeof value === "string") {
1144
- value = parseInt(value, 10);
1145
- }
1146
- bitString = value.toString(2);
1147
- if (bitString.length > numBits || value < 0) {
1148
- throw new EncodingError(`${value} too large to encode into ${numBits}`);
1149
- }
1150
- if (bitString.length < numBits) {
1151
- bitString = "0".repeat(numBits - bitString.length) + bitString;
1152
- }
1153
- return bitString;
1154
- }
1155
- static decode(value, numBits) {
1156
- if (numBits !== value.length) {
1157
- throw new DecodingError("invalid bit length");
1158
- }
1159
- return parseInt(value, 2);
1160
- }
1161
- }
1162
- class DateEncoder {
1163
- static encode(value, numBits) {
1164
- return IntEncoder.encode(Math.round(value.getTime() / 100), numBits);
1165
- }
1166
- static decode(value, numBits) {
1167
- if (numBits !== value.length) {
1168
- throw new DecodingError("invalid bit length");
1169
- }
1170
- const date = /* @__PURE__ */ new Date();
1171
- date.setTime(IntEncoder.decode(value, numBits) * 100);
1172
- return date;
1173
- }
1174
- }
1175
- class FixedVectorEncoder {
1176
- static encode(value, numBits) {
1177
- let bitString = "";
1178
- for (let i = 1; i <= numBits; i++) {
1179
- bitString += BooleanEncoder.encode(value.has(i));
1180
- }
1181
- return bitString;
1182
- }
1183
- static decode(value, numBits) {
1184
- if (value.length !== numBits) {
1185
- throw new DecodingError("bitfield encoding length mismatch");
1186
- }
1187
- const vector = new Vector();
1188
- for (let i = 1; i <= numBits; i++) {
1189
- if (BooleanEncoder.decode(value[i - 1])) {
1190
- vector.set(i);
1191
- }
1192
- }
1193
- vector.bitLength = value.length;
1194
- return vector;
1195
- }
1196
- }
1197
- class LangEncoder {
1198
- static encode(value, numBits) {
1199
- value = value.toUpperCase();
1200
- const ASCII_START = 65;
1201
- const firstLetter = value.charCodeAt(0) - ASCII_START;
1202
- const secondLetter = value.charCodeAt(1) - ASCII_START;
1203
- if (firstLetter < 0 || firstLetter > 25 || secondLetter < 0 || secondLetter > 25) {
1204
- throw new EncodingError(`invalid language code: ${value}`);
1205
- }
1206
- if (numBits % 2 === 1) {
1207
- throw new EncodingError(`numBits must be even, ${numBits} is not valid`);
1208
- }
1209
- numBits = numBits / 2;
1210
- const firstLetterBString = IntEncoder.encode(firstLetter, numBits);
1211
- const secondLetterBString = IntEncoder.encode(secondLetter, numBits);
1212
- return firstLetterBString + secondLetterBString;
1213
- }
1214
- static decode(value, numBits) {
1215
- let retr;
1216
- if (numBits === value.length && !(value.length % 2)) {
1217
- const ASCII_START = 65;
1218
- const mid = value.length / 2;
1219
- const firstLetter = IntEncoder.decode(value.slice(0, mid), mid) + ASCII_START;
1220
- const secondLetter = IntEncoder.decode(value.slice(mid), mid) + ASCII_START;
1221
- retr = String.fromCharCode(firstLetter) + String.fromCharCode(secondLetter);
1222
- } else {
1223
- throw new DecodingError("invalid bit length for language");
1224
- }
1225
- return retr;
1226
- }
1227
- }
1228
- class PurposeRestrictionVectorEncoder {
1229
- static encode(prVector) {
1230
- let bitString = IntEncoder.encode(prVector.numRestrictions, BitLength.numRestrictions);
1231
- if (!prVector.isEmpty()) {
1232
- const nextGvlVendor = (vendorId, lastVendorId) => {
1233
- for (let nextId = vendorId + 1; nextId <= lastVendorId; nextId++) {
1234
- if (prVector.gvl.vendorIds.has(nextId)) {
1235
- return nextId;
1236
- }
1237
- }
1238
- return vendorId;
1239
- };
1240
- prVector.getRestrictions().forEach((purpRestriction) => {
1241
- bitString += IntEncoder.encode(purpRestriction.purposeId, BitLength.purposeId);
1242
- bitString += IntEncoder.encode(purpRestriction.restrictionType, BitLength.restrictionType);
1243
- const vendors = prVector.getVendors(purpRestriction);
1244
- const len = vendors.length;
1245
- let numEntries = 0;
1246
- let startId = 0;
1247
- let rangeField = "";
1248
- for (let i = 0; i < len; i++) {
1249
- const vendorId = vendors[i];
1250
- if (startId === 0) {
1251
- numEntries++;
1252
- startId = vendorId;
1253
- }
1254
- if (i === len - 1 || vendors[i + 1] > nextGvlVendor(vendorId, vendors[len - 1])) {
1255
- const isRange = !(vendorId === startId);
1256
- rangeField += BooleanEncoder.encode(isRange);
1257
- rangeField += IntEncoder.encode(startId, BitLength.vendorId);
1258
- if (isRange) {
1259
- rangeField += IntEncoder.encode(vendorId, BitLength.vendorId);
1260
- }
1261
- startId = 0;
1262
- }
1263
- }
1264
- bitString += IntEncoder.encode(numEntries, BitLength.numEntries);
1265
- bitString += rangeField;
1266
- });
1267
- }
1268
- return bitString;
1269
- }
1270
- static decode(encodedString) {
1271
- let index = 0;
1272
- const vector = new PurposeRestrictionVector();
1273
- const numRestrictions = IntEncoder.decode(encodedString.substr(index, BitLength.numRestrictions), BitLength.numRestrictions);
1274
- index += BitLength.numRestrictions;
1275
- for (let i = 0; i < numRestrictions; i++) {
1276
- const purposeId = IntEncoder.decode(encodedString.substr(index, BitLength.purposeId), BitLength.purposeId);
1277
- index += BitLength.purposeId;
1278
- const restrictionType = IntEncoder.decode(encodedString.substr(index, BitLength.restrictionType), BitLength.restrictionType);
1279
- index += BitLength.restrictionType;
1280
- const purposeRestriction = new PurposeRestriction(purposeId, restrictionType);
1281
- const numEntries = IntEncoder.decode(encodedString.substr(index, BitLength.numEntries), BitLength.numEntries);
1282
- index += BitLength.numEntries;
1283
- for (let j = 0; j < numEntries; j++) {
1284
- const isARange = BooleanEncoder.decode(encodedString.substr(index, BitLength.anyBoolean));
1285
- index += BitLength.anyBoolean;
1286
- const startOrOnlyVendorId = IntEncoder.decode(encodedString.substr(index, BitLength.vendorId), BitLength.vendorId);
1287
- index += BitLength.vendorId;
1288
- if (isARange) {
1289
- const endVendorId = IntEncoder.decode(encodedString.substr(index, BitLength.vendorId), BitLength.vendorId);
1290
- index += BitLength.vendorId;
1291
- if (endVendorId < startOrOnlyVendorId) {
1292
- throw new DecodingError(`Invalid RangeEntry: endVendorId ${endVendorId} is less than ${startOrOnlyVendorId}`);
1293
- }
1294
- for (let k = startOrOnlyVendorId; k <= endVendorId; k++) {
1295
- vector.add(k, purposeRestriction);
1296
- }
1297
- } else {
1298
- vector.add(startOrOnlyVendorId, purposeRestriction);
1299
- }
1300
- }
1301
- }
1302
- vector.bitLength = index;
1303
- return vector;
1304
- }
1305
- }
1306
- var VectorEncodingType;
1307
- (function(VectorEncodingType2) {
1308
- VectorEncodingType2[VectorEncodingType2["FIELD"] = 0] = "FIELD";
1309
- VectorEncodingType2[VectorEncodingType2["RANGE"] = 1] = "RANGE";
1310
- })(VectorEncodingType || (VectorEncodingType = {}));
1311
- class VendorVectorEncoder {
1312
- static encode(value) {
1313
- const ranges = [];
1314
- let range = [];
1315
- let retrString = IntEncoder.encode(value.maxId, BitLength.maxId);
1316
- let bitField = "";
1317
- let rangeIsSmaller;
1318
- const headerLength = BitLength.maxId + BitLength.encodingType;
1319
- const bitFieldLength = headerLength + value.maxId;
1320
- const minRangeLength = BitLength.vendorId * 2 + BitLength.singleOrRange + BitLength.numEntries;
1321
- let rangeLength = headerLength + BitLength.numEntries;
1322
- value.forEach((curValue, i) => {
1323
- bitField += BooleanEncoder.encode(curValue);
1324
- rangeIsSmaller = value.maxId > minRangeLength && rangeLength < bitFieldLength;
1325
- if (rangeIsSmaller && curValue) {
1326
- const nextValue = value.has(i + 1);
1327
- if (!nextValue) {
1328
- range.push(i);
1329
- rangeLength += BitLength.vendorId;
1330
- ranges.push(range);
1331
- range = [];
1332
- } else if (range.length === 0) {
1333
- range.push(i);
1334
- rangeLength += BitLength.singleOrRange;
1335
- rangeLength += BitLength.vendorId;
1336
- }
1337
- }
1338
- });
1339
- if (rangeIsSmaller) {
1340
- retrString += String(VectorEncodingType.RANGE);
1341
- retrString += this.buildRangeEncoding(ranges);
1342
- } else {
1343
- retrString += String(VectorEncodingType.FIELD);
1344
- retrString += bitField;
1345
- }
1346
- return retrString;
1347
- }
1348
- static decode(value, version2) {
1349
- let vector;
1350
- let index = 0;
1351
- const maxId = IntEncoder.decode(value.substr(index, BitLength.maxId), BitLength.maxId);
1352
- index += BitLength.maxId;
1353
- const encodingType = IntEncoder.decode(value.charAt(index), BitLength.encodingType);
1354
- index += BitLength.encodingType;
1355
- if (encodingType === VectorEncodingType.RANGE) {
1356
- vector = new Vector();
1357
- if (version2 === 1) {
1358
- if (value.substr(index, 1) === "1") {
1359
- throw new DecodingError("Unable to decode default consent=1");
1360
- }
1361
- index++;
1362
- }
1363
- const numEntries = IntEncoder.decode(value.substr(index, BitLength.numEntries), BitLength.numEntries);
1364
- index += BitLength.numEntries;
1365
- for (let i = 0; i < numEntries; i++) {
1366
- const isIdRange = BooleanEncoder.decode(value.charAt(index));
1367
- index += BitLength.singleOrRange;
1368
- const firstId = IntEncoder.decode(value.substr(index, BitLength.vendorId), BitLength.vendorId);
1369
- index += BitLength.vendorId;
1370
- if (isIdRange) {
1371
- const secondId = IntEncoder.decode(value.substr(index, BitLength.vendorId), BitLength.vendorId);
1372
- index += BitLength.vendorId;
1373
- for (let j = firstId; j <= secondId; j++) {
1374
- vector.set(j);
1375
- }
1376
- } else {
1377
- vector.set(firstId);
1378
- }
1379
- }
1380
- } else {
1381
- const bitField = value.substr(index, maxId);
1382
- index += maxId;
1383
- vector = FixedVectorEncoder.decode(bitField, maxId);
1384
- }
1385
- vector.bitLength = index;
1386
- return vector;
1387
- }
1388
- static buildRangeEncoding(ranges) {
1389
- const numEntries = ranges.length;
1390
- let rangeString = IntEncoder.encode(numEntries, BitLength.numEntries);
1391
- ranges.forEach((range) => {
1392
- const single = range.length === 1;
1393
- rangeString += BooleanEncoder.encode(!single);
1394
- rangeString += IntEncoder.encode(range[0], BitLength.vendorId);
1395
- if (!single) {
1396
- rangeString += IntEncoder.encode(range[1], BitLength.vendorId);
1397
- }
1398
- });
1399
- return rangeString;
1400
- }
1401
- }
1402
- function FieldEncoderMap() {
1403
- return {
1404
- [Fields.version]: IntEncoder,
1405
- [Fields.created]: DateEncoder,
1406
- [Fields.lastUpdated]: DateEncoder,
1407
- [Fields.cmpId]: IntEncoder,
1408
- [Fields.cmpVersion]: IntEncoder,
1409
- [Fields.consentScreen]: IntEncoder,
1410
- [Fields.consentLanguage]: LangEncoder,
1411
- [Fields.vendorListVersion]: IntEncoder,
1412
- [Fields.policyVersion]: IntEncoder,
1413
- [Fields.isServiceSpecific]: BooleanEncoder,
1414
- [Fields.useNonStandardTexts]: BooleanEncoder,
1415
- [Fields.specialFeatureOptins]: FixedVectorEncoder,
1416
- [Fields.purposeConsents]: FixedVectorEncoder,
1417
- [Fields.purposeLegitimateInterests]: FixedVectorEncoder,
1418
- [Fields.purposeOneTreatment]: BooleanEncoder,
1419
- [Fields.publisherCountryCode]: LangEncoder,
1420
- [Fields.vendorConsents]: VendorVectorEncoder,
1421
- [Fields.vendorLegitimateInterests]: VendorVectorEncoder,
1422
- [Fields.publisherRestrictions]: PurposeRestrictionVectorEncoder,
1423
- segmentType: IntEncoder,
1424
- [Fields.vendorsDisclosed]: VendorVectorEncoder,
1425
- [Fields.vendorsAllowed]: VendorVectorEncoder,
1426
- [Fields.publisherConsents]: FixedVectorEncoder,
1427
- [Fields.publisherLegitimateInterests]: FixedVectorEncoder,
1428
- [Fields.numCustomPurposes]: IntEncoder,
1429
- [Fields.publisherCustomConsents]: FixedVectorEncoder,
1430
- [Fields.publisherCustomLegitimateInterests]: FixedVectorEncoder
1431
- };
1432
- }
1433
- class FieldSequence {
1434
- constructor() {
1435
- __publicField(this, "1", {
1436
- [Segment.CORE]: [
1437
- Fields.version,
1438
- Fields.created,
1439
- Fields.lastUpdated,
1440
- Fields.cmpId,
1441
- Fields.cmpVersion,
1442
- Fields.consentScreen,
1443
- Fields.consentLanguage,
1444
- Fields.vendorListVersion,
1445
- Fields.purposeConsents,
1446
- Fields.vendorConsents
1447
- ]
1448
- });
1449
- __publicField(this, "2", {
1450
- [Segment.CORE]: [
1451
- Fields.version,
1452
- Fields.created,
1453
- Fields.lastUpdated,
1454
- Fields.cmpId,
1455
- Fields.cmpVersion,
1456
- Fields.consentScreen,
1457
- Fields.consentLanguage,
1458
- Fields.vendorListVersion,
1459
- Fields.policyVersion,
1460
- Fields.isServiceSpecific,
1461
- Fields.useNonStandardTexts,
1462
- Fields.specialFeatureOptins,
1463
- Fields.purposeConsents,
1464
- Fields.purposeLegitimateInterests,
1465
- Fields.purposeOneTreatment,
1466
- Fields.publisherCountryCode,
1467
- Fields.vendorConsents,
1468
- Fields.vendorLegitimateInterests,
1469
- Fields.publisherRestrictions
1470
- ],
1471
- [Segment.PUBLISHER_TC]: [
1472
- Fields.publisherConsents,
1473
- Fields.publisherLegitimateInterests,
1474
- Fields.numCustomPurposes,
1475
- Fields.publisherCustomConsents,
1476
- Fields.publisherCustomLegitimateInterests
1477
- ],
1478
- [Segment.VENDORS_ALLOWED]: [
1479
- Fields.vendorsAllowed
1480
- ],
1481
- [Segment.VENDORS_DISCLOSED]: [
1482
- Fields.vendorsDisclosed
1483
- ]
1484
- });
1485
- }
1486
- }
1487
- class SegmentSequence {
1488
- constructor(tcModel, options) {
1489
- __publicField(this, "1", [
1490
- Segment.CORE
1491
- ]);
1492
- __publicField(this, "2", [
1493
- Segment.CORE
1494
- ]);
1495
- if (tcModel.version === 2) {
1496
- if (tcModel.isServiceSpecific) {
1497
- this["2"].push(Segment.PUBLISHER_TC);
1498
- } else {
1499
- const isForVendors = !!(options && options.isForVendors);
1500
- if (!isForVendors || tcModel[Fields.supportOOB] === true) {
1501
- this["2"].push(Segment.VENDORS_DISCLOSED);
1502
- }
1503
- if (isForVendors) {
1504
- if (tcModel[Fields.supportOOB] && tcModel[Fields.vendorsAllowed].size > 0) {
1505
- this["2"].push(Segment.VENDORS_ALLOWED);
1506
- }
1507
- this["2"].push(Segment.PUBLISHER_TC);
1508
- }
1509
- }
1510
- }
1511
- }
1512
- }
1513
- class SegmentEncoder {
1514
- static encode(tcModel, segment) {
1515
- let sequence;
1516
- try {
1517
- sequence = this.fieldSequence[String(tcModel.version)][segment];
1518
- } catch (err) {
1519
- throw new EncodingError(`Unable to encode version: ${tcModel.version}, segment: ${segment}`);
1520
- }
1521
- let bitField = "";
1522
- if (segment !== Segment.CORE) {
1523
- bitField = IntEncoder.encode(SegmentIDs.KEY_TO_ID[segment], BitLength.segmentType);
1524
- }
1525
- const fieldEncoderMap = FieldEncoderMap();
1526
- sequence.forEach((key) => {
1527
- const value = tcModel[key];
1528
- const encoder = fieldEncoderMap[key];
1529
- let numBits = BitLength[key];
1530
- if (numBits === void 0) {
1531
- if (this.isPublisherCustom(key)) {
1532
- numBits = Number(tcModel[Fields.numCustomPurposes]);
1533
- }
1534
- }
1535
- try {
1536
- bitField += encoder.encode(value, numBits);
1537
- } catch (err) {
1538
- throw new EncodingError(`Error encoding ${segment}->${key}: ${err.message}`);
1539
- }
1540
- });
1541
- return Base64Url.encode(bitField);
1542
- }
1543
- static decode(encodedString, tcModel, segment) {
1544
- const bitField = Base64Url.decode(encodedString);
1545
- let bStringIdx = 0;
1546
- if (segment === Segment.CORE) {
1547
- tcModel.version = IntEncoder.decode(bitField.substr(bStringIdx, BitLength[Fields.version]), BitLength[Fields.version]);
1548
- }
1549
- if (segment !== Segment.CORE) {
1550
- bStringIdx += BitLength.segmentType;
1551
- }
1552
- const sequence = this.fieldSequence[String(tcModel.version)][segment];
1553
- const fieldEncoderMap = FieldEncoderMap();
1554
- sequence.forEach((key) => {
1555
- const encoder = fieldEncoderMap[key];
1556
- let numBits = BitLength[key];
1557
- if (numBits === void 0) {
1558
- if (this.isPublisherCustom(key)) {
1559
- numBits = Number(tcModel[Fields.numCustomPurposes]);
1560
- }
1561
- }
1562
- if (numBits !== 0) {
1563
- const bits = bitField.substr(bStringIdx, numBits);
1564
- if (encoder === VendorVectorEncoder) {
1565
- tcModel[key] = encoder.decode(bits, tcModel.version);
1566
- } else {
1567
- tcModel[key] = encoder.decode(bits, numBits);
1568
- }
1569
- if (Number.isInteger(numBits)) {
1570
- bStringIdx += numBits;
1571
- } else if (Number.isInteger(tcModel[key].bitLength)) {
1572
- bStringIdx += tcModel[key].bitLength;
1573
- } else {
1574
- throw new DecodingError(key);
1575
- }
1576
- }
1577
- });
1578
- return tcModel;
1579
- }
1580
- static isPublisherCustom(key) {
1581
- return key.indexOf("publisherCustom") === 0;
1582
- }
1583
- }
1584
- __publicField(SegmentEncoder, "fieldSequence", new FieldSequence());
1585
- class SemanticPreEncoder {
1586
- static process(tcModel, options) {
1587
- const gvl = tcModel.gvl;
1588
- if (!gvl) {
1589
- throw new EncodingError("Unable to encode TCModel without a GVL");
1590
- }
1591
- if (!gvl.isReady) {
1592
- throw new EncodingError("Unable to encode TCModel tcModel.gvl.readyPromise is not resolved");
1593
- }
1594
- tcModel = tcModel.clone();
1595
- tcModel.consentLanguage = gvl.language.slice(0, 2).toUpperCase();
1596
- if ((options == null ? void 0 : options.version) > 0 && (options == null ? void 0 : options.version) <= this.processor.length) {
1597
- tcModel.version = options.version;
1598
- } else {
1599
- tcModel.version = this.processor.length;
1600
- }
1601
- const processorFunctionIndex = tcModel.version - 1;
1602
- if (!this.processor[processorFunctionIndex]) {
1603
- throw new EncodingError(`Invalid version: ${tcModel.version}`);
1604
- }
1605
- return this.processor[processorFunctionIndex](tcModel, gvl);
1606
- }
1607
- }
1608
- __publicField(SemanticPreEncoder, "processor", [
1609
- (tcModel) => tcModel,
1610
- (tcModel, gvl) => {
1611
- tcModel.publisherRestrictions.gvl = gvl;
1612
- tcModel.purposeLegitimateInterests.unset([1, 3, 4, 5, 6]);
1613
- const vectorToIntMap = /* @__PURE__ */ new Map();
1614
- vectorToIntMap.set("legIntPurposes", tcModel.vendorLegitimateInterests);
1615
- vectorToIntMap.set("purposes", tcModel.vendorConsents);
1616
- vectorToIntMap.forEach((vector, gvlVendorKey) => {
1617
- vector.forEach((value, vendorId) => {
1618
- if (value) {
1619
- const vendor = gvl.vendors[vendorId];
1620
- if (!vendor || vendor.deletedDate) {
1621
- vector.unset(vendorId);
1622
- } else if (vendor[gvlVendorKey].length === 0) {
1623
- if (gvlVendorKey === "legIntPurposes" && vendor["purposes"].length === 0 && vendor["legIntPurposes"].length === 0 && vendor["specialPurposes"].length > 0)
1624
- ;
1625
- else {
1626
- if (tcModel.isServiceSpecific) {
1627
- if (vendor.flexiblePurposes.length === 0) {
1628
- vector.unset(vendorId);
1629
- } else {
1630
- const restrictions = tcModel.publisherRestrictions.getRestrictions(vendorId);
1631
- let isValid = false;
1632
- for (let i = 0, len = restrictions.length; i < len && !isValid; i++) {
1633
- isValid = restrictions[i].restrictionType === RestrictionType.REQUIRE_CONSENT && gvlVendorKey === "purposes" || restrictions[i].restrictionType === RestrictionType.REQUIRE_LI && gvlVendorKey === "legIntPurposes";
1634
- }
1635
- if (!isValid) {
1636
- vector.unset(vendorId);
1637
- }
1638
- }
1639
- } else {
1640
- vector.unset(vendorId);
1641
- }
1642
- }
1643
- }
1644
- }
1645
- });
1646
- });
1647
- tcModel.vendorsDisclosed.set(gvl.vendors);
1648
- return tcModel;
1649
- }
1650
- ]);
1651
- class Json {
1652
- static absCall(url, body, sendCookies, timeout) {
1653
- return new Promise((resolve, reject) => {
1654
- const req = new XMLHttpRequest();
1655
- const onLoad = () => {
1656
- if (req.readyState == XMLHttpRequest.DONE) {
1657
- if (req.status >= 200 && req.status < 300) {
1658
- let response = req.response;
1659
- if (typeof response === "string") {
1660
- try {
1661
- response = JSON.parse(response);
1662
- } catch (e) {
1663
- }
1664
- }
1665
- resolve(response);
1666
- } else {
1667
- reject(new Error(`HTTP Status: ${req.status} response type: ${req.responseType}`));
1668
- }
1669
- }
1670
- };
1671
- const onError = () => {
1672
- reject(new Error("error"));
1673
- };
1674
- const onAbort = () => {
1675
- reject(new Error("aborted"));
1676
- };
1677
- const onTimeout = () => {
1678
- reject(new Error("Timeout " + timeout + "ms " + url));
1679
- };
1680
- req.withCredentials = sendCookies;
1681
- req.addEventListener("load", onLoad);
1682
- req.addEventListener("error", onError);
1683
- req.addEventListener("abort", onAbort);
1684
- if (body === null) {
1685
- req.open("GET", url, true);
1686
- } else {
1687
- req.open("POST", url, true);
1688
- }
1689
- req.responseType = "json";
1690
- req.timeout = timeout;
1691
- req.ontimeout = onTimeout;
1692
- req.send(body);
1693
- });
1694
- }
1695
- /**
1696
- * @static
1697
- * @param {string} url - full path to POST to
1698
- * @param {object} body - JSON object to post
1699
- * @param {boolean} sendCookies - Whether or not to send the XMLHttpRequest with credentials or not
1700
- * @param {number} [timeout] - optional timeout in milliseconds
1701
- * @return {Promise<object>} - if the server responds the response will be returned here
1702
- */
1703
- static post(url, body, sendCookies = false, timeout = 0) {
1704
- return this.absCall(url, JSON.stringify(body), sendCookies, timeout);
1705
- }
1706
- /**
1707
- * @static
1708
- * @param {string} url - full path to the json
1709
- * @param {boolean} sendCookies - Whether or not to send the XMLHttpRequest with credentials or not
1710
- * @param {number} [timeout] - optional timeout in milliseconds
1711
- * @return {Promise<object>} - resolves with parsed JSON
1712
- */
1713
- static fetch(url, sendCookies = false, timeout = 0) {
1714
- return this.absCall(url, null, sendCookies, timeout);
1715
- }
1716
- }
1717
- const _GVL = class _GVL extends Cloneable {
1718
- /**
1719
- * @param {VersionOrVendorList} [versionOrVendorList] - can be either a
1720
- * [[VendorList]] object or a version number represented as a string or
1721
- * number to download. If nothing is passed the latest version of the GVL
1722
- * will be loaded
1723
- */
1724
- constructor(versionOrVendorList) {
1725
- super();
1726
- /**
1727
- * @param {Promise} resolved when this GVL object is populated with the data
1728
- * or rejected if there is an error.
1729
- */
1730
- __publicField(this, "readyPromise");
1731
- /**
1732
- * @param {number} gvlSpecificationVersion - schema version for the GVL that is used
1733
- */
1734
- __publicField(this, "gvlSpecificationVersion");
1735
- /**
1736
- * @param {number} incremented with each published file change
1737
- */
1738
- __publicField(this, "vendorListVersion");
1739
- /**
1740
- * @param {number} tcfPolicyVersion - The TCF MO will increment this value
1741
- * whenever a GVL change (such as adding a new Purpose or Feature or a change
1742
- * in Purpose wording) legally invalidates existing TC Strings and requires
1743
- * CMPs to re-establish transparency and consent from users. If the policy
1744
- * version number in the latest GVL is different from the value in your TC
1745
- * String, then you need to re-establish transparency and consent for that
1746
- * user. A version 1 format TC String is considered to have a version value
1747
- * of 1.
1748
- */
1749
- __publicField(this, "tcfPolicyVersion");
1750
- /**
1751
- * @param {string | Date} lastUpdated - the date in which the vendor list
1752
- * json file was last updated.
1753
- */
1754
- __publicField(this, "lastUpdated");
1755
- /**
1756
- * @param {IntMap<Purpose>} a collection of [[Purpose]]s
1757
- */
1758
- __publicField(this, "purposes");
1759
- /**
1760
- * @param {IntMap<Purpose>} a collection of [[Purpose]]s
1761
- */
1762
- __publicField(this, "specialPurposes");
1763
- /**
1764
- * @param {IntMap<Feature>} a collection of [[Feature]]s
1765
- */
1766
- __publicField(this, "features");
1767
- /**
1768
- * @param {IntMap<Feature>} a collection of [[Feature]]s
1769
- */
1770
- __publicField(this, "specialFeatures");
1771
- /**
1772
- * @param {boolean} internal reference of when the GVL is ready to be used
1773
- */
1774
- __publicField(this, "isReady_", false);
1775
- /**
1776
- * @param {IntMap<Vendor>} a collection of [[Vendor]]s
1777
- */
1778
- __publicField(this, "vendors_");
1779
- __publicField(this, "vendorIds");
1780
- /**
1781
- * @param {IntMap<Vendor>} a collection of [[Vendor]]. Used as a backup if a whitelist is sets
1782
- */
1783
- __publicField(this, "fullVendorList");
1784
- /**
1785
- * @param {ByPurposeVendorMap} vendors by purpose
1786
- */
1787
- __publicField(this, "byPurposeVendorMap");
1788
- /**
1789
- * @param {IDSetMap} vendors by special purpose
1790
- */
1791
- __publicField(this, "bySpecialPurposeVendorMap");
1792
- /**
1793
- * @param {IDSetMap} vendors by feature
1794
- */
1795
- __publicField(this, "byFeatureVendorMap");
1796
- /**
1797
- * @param {IDSetMap} vendors by special feature
1798
- */
1799
- __publicField(this, "bySpecialFeatureVendorMap");
1800
- /**
1801
- * @param {IntMap<Stack>} a collection of [[Stack]]s
1802
- */
1803
- __publicField(this, "stacks");
1804
- /**
1805
- * @param {IntMap<DataCategory>} a collection of [[DataCategory]]s
1806
- */
1807
- __publicField(this, "dataCategories");
1808
- __publicField(this, "lang_");
1809
- __publicField(this, "cacheLang_");
1810
- __publicField(this, "isLatest", false);
1811
- let url = _GVL.baseUrl;
1812
- this.lang_ = _GVL.DEFAULT_LANGUAGE;
1813
- this.cacheLang_ = _GVL.DEFAULT_LANGUAGE;
1814
- if (this.isVendorList(versionOrVendorList)) {
1815
- this.populate(versionOrVendorList);
1816
- this.readyPromise = Promise.resolve();
1817
- } else {
1818
- if (!url) {
1819
- throw new GVLError("must specify GVL.baseUrl before loading GVL json");
1820
- }
1821
- if (versionOrVendorList > 0) {
1822
- const version2 = versionOrVendorList;
1823
- if (_GVL.CACHE.has(version2)) {
1824
- this.populate(_GVL.CACHE.get(version2));
1825
- this.readyPromise = Promise.resolve();
1826
- } else {
1827
- url += _GVL.versionedFilename.replace("[VERSION]", String(version2));
1828
- this.readyPromise = this.fetchJson(url);
1829
- }
1830
- } else {
1831
- if (_GVL.CACHE.has(_GVL.LATEST_CACHE_KEY)) {
1832
- this.populate(_GVL.CACHE.get(_GVL.LATEST_CACHE_KEY));
1833
- this.readyPromise = Promise.resolve();
1834
- } else {
1835
- this.isLatest = true;
1836
- this.readyPromise = this.fetchJson(url + _GVL.latestFilename);
1837
- }
1838
- }
1839
- }
1840
- }
1841
- /**
1842
- * baseUrl - Entities using the vendor-list.json are required by the iab to
1843
- * host their own copy of it to reduce the load on the iab's infrastructure
1844
- * so a 'base' url must be set to be put together with the versioning scheme
1845
- * of the filenames.
1846
- *
1847
- * @static
1848
- * @param {string} url - the base url to load the vendor-list.json from. This is
1849
- * broken out from the filename because it follows a different scheme for
1850
- * latest file vs versioned files.
1851
- *
1852
- * @throws {GVLError} - If the url is http[s]://vendorlist.consensu.org/...
1853
- * this will throw an error. IAB Europe requires that that CMPs and Vendors
1854
- * cache their own copies of the GVL to minimize load on their
1855
- * infrastructure. For more information regarding caching of the
1856
- * vendor-list.json, please see [the TCF documentation on 'Caching the Global
1857
- * Vendor List'
1858
- * ](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md#caching-the-global-vendor-list)
1859
- */
1860
- static set baseUrl(url) {
1861
- const notValid = /^https?:\/\/vendorlist\.consensu\.org\//;
1862
- if (notValid.test(url)) {
1863
- throw new GVLError("Invalid baseUrl! You may not pull directly from vendorlist.consensu.org and must provide your own cache");
1864
- }
1865
- if (url.length > 0 && url[url.length - 1] !== "/") {
1866
- url += "/";
1867
- }
1868
- this.baseUrl_ = url;
1869
- }
1870
- /**
1871
- * baseUrl - Entities using the vendor-list.json are required by the iab to
1872
- * host their own copy of it to reduce the load on the iab's infrastructure
1873
- * so a 'base' url must be set to be put together with the versioning scheme
1874
- * of the filenames.
1875
- *
1876
- * @static
1877
- * @return {string} - returns the previously set baseUrl, the default is
1878
- * `undefined`
1879
- */
1880
- static get baseUrl() {
1881
- return this.baseUrl_;
1882
- }
1883
- /**
1884
- * emptyLanguageCache
1885
- *
1886
- * @param {string} [lang] - Optional language code to remove from
1887
- * the cache. Should be one of the languages in GVL.consentLanguages set.
1888
- * If not then the whole cache will be deleted.
1889
- * @return {boolean} - true if anything was deleted from the cache
1890
- */
1891
- static emptyLanguageCache(lang) {
1892
- let result = false;
1893
- if (lang == null && _GVL.LANGUAGE_CACHE.size > 0) {
1894
- _GVL.LANGUAGE_CACHE = /* @__PURE__ */ new Map();
1895
- result = true;
1896
- } else if (typeof lang === "string" && this.consentLanguages.has(lang.toUpperCase())) {
1897
- _GVL.LANGUAGE_CACHE.delete(lang.toUpperCase());
1898
- result = true;
1899
- }
1900
- return result;
1901
- }
1902
- /**
1903
- * emptyCache
1904
- *
1905
- * @param {number} [vendorListVersion] - version of the vendor list to delete
1906
- * from the cache. If none is specified then the whole cache is deleted.
1907
- * @return {boolean} - true if anything was deleted from the cache
1908
- */
1909
- static emptyCache(vendorListVersion) {
1910
- let retr = false;
1911
- if (Number.isInteger(vendorListVersion) && vendorListVersion >= 0) {
1912
- _GVL.CACHE.delete(vendorListVersion);
1913
- retr = true;
1914
- } else if (vendorListVersion === void 0) {
1915
- _GVL.CACHE = /* @__PURE__ */ new Map();
1916
- retr = true;
1917
- }
1918
- return retr;
1919
- }
1920
- cacheLanguage() {
1921
- if (!_GVL.LANGUAGE_CACHE.has(this.cacheLang_)) {
1922
- _GVL.LANGUAGE_CACHE.set(this.cacheLang_, {
1923
- purposes: this.purposes,
1924
- specialPurposes: this.specialPurposes,
1925
- features: this.features,
1926
- specialFeatures: this.specialFeatures,
1927
- stacks: this.stacks,
1928
- dataCategories: this.dataCategories
1929
- });
1930
- }
1931
- }
1932
- async fetchJson(url) {
1933
- try {
1934
- this.populate(await Json.fetch(url));
1935
- } catch (err) {
1936
- throw new GVLError(err.message);
1937
- }
1938
- }
1939
- /**
1940
- * getJson - Method for getting the JSON that was downloaded to created this
1941
- * `GVL` object
1942
- *
1943
- * @return {VendorList} - The basic JSON structure without the extra
1944
- * functionality and methods of this class.
1945
- */
1946
- getJson() {
1947
- return JSON.parse(JSON.stringify({
1948
- gvlSpecificationVersion: this.gvlSpecificationVersion,
1949
- vendorListVersion: this.vendorListVersion,
1950
- tcfPolicyVersion: this.tcfPolicyVersion,
1951
- lastUpdated: this.lastUpdated,
1952
- purposes: this.purposes,
1953
- specialPurposes: this.specialPurposes,
1954
- features: this.features,
1955
- specialFeatures: this.specialFeatures,
1956
- stacks: this.stacks,
1957
- dataCategories: this.dataCategories,
1958
- vendors: this.fullVendorList
1959
- }));
1960
- }
1961
- /**
1962
- * changeLanguage - retrieves the purpose language translation and sets the
1963
- * internal language variable
1964
- *
1965
- * @param {string} lang - language code to change language to
1966
- * @return {Promise<void | GVLError>} - returns the `readyPromise` and
1967
- * resolves when this GVL is populated with the data from the language file.
1968
- */
1969
- async changeLanguage(lang) {
1970
- let parsedLanguage = lang;
1971
- try {
1972
- parsedLanguage = _GVL.consentLanguages.parseLanguage(lang);
1973
- } catch (e) {
1974
- throw new GVLError("Error during parsing the language: " + e.message);
1975
- }
1976
- const cacheLang = lang.toUpperCase();
1977
- if (parsedLanguage.toLowerCase() === _GVL.DEFAULT_LANGUAGE.toLowerCase() && !_GVL.LANGUAGE_CACHE.has(cacheLang)) {
1978
- return;
1979
- }
1980
- if (parsedLanguage !== this.lang_) {
1981
- this.lang_ = parsedLanguage;
1982
- if (_GVL.LANGUAGE_CACHE.has(cacheLang)) {
1983
- const cached = _GVL.LANGUAGE_CACHE.get(cacheLang);
1984
- for (const prop in cached) {
1985
- if (cached.hasOwnProperty(prop)) {
1986
- this[prop] = cached[prop];
1987
- }
1988
- }
1989
- } else {
1990
- const url = _GVL.baseUrl + _GVL.languageFilename.replace("[LANG]", this.lang_.toLowerCase());
1991
- try {
1992
- await this.fetchJson(url);
1993
- this.cacheLang_ = cacheLang;
1994
- this.cacheLanguage();
1995
- } catch (err) {
1996
- throw new GVLError("unable to load language: " + err.message);
1997
- }
1998
- }
1999
- }
2000
- }
2001
- get language() {
2002
- return this.lang_;
2003
- }
2004
- isVendorList(gvlObject) {
2005
- return gvlObject !== void 0 && gvlObject.vendors !== void 0;
2006
- }
2007
- populate(gvlObject) {
2008
- this.purposes = gvlObject.purposes;
2009
- this.specialPurposes = gvlObject.specialPurposes;
2010
- this.features = gvlObject.features;
2011
- this.specialFeatures = gvlObject.specialFeatures;
2012
- this.stacks = gvlObject.stacks;
2013
- this.dataCategories = gvlObject.dataCategories;
2014
- if (this.isVendorList(gvlObject)) {
2015
- this.gvlSpecificationVersion = gvlObject.gvlSpecificationVersion;
2016
- this.tcfPolicyVersion = gvlObject.tcfPolicyVersion;
2017
- this.vendorListVersion = gvlObject.vendorListVersion;
2018
- this.lastUpdated = gvlObject.lastUpdated;
2019
- if (typeof this.lastUpdated === "string") {
2020
- this.lastUpdated = new Date(this.lastUpdated);
2021
- }
2022
- this.vendors_ = gvlObject.vendors;
2023
- this.fullVendorList = gvlObject.vendors;
2024
- this.mapVendors();
2025
- this.isReady_ = true;
2026
- if (this.isLatest) {
2027
- _GVL.CACHE.set(_GVL.LATEST_CACHE_KEY, this.getJson());
2028
- }
2029
- if (!_GVL.CACHE.has(this.vendorListVersion)) {
2030
- _GVL.CACHE.set(this.vendorListVersion, this.getJson());
2031
- }
2032
- }
2033
- this.cacheLanguage();
2034
- }
2035
- mapVendors(vendorIds) {
2036
- this.byPurposeVendorMap = {};
2037
- this.bySpecialPurposeVendorMap = {};
2038
- this.byFeatureVendorMap = {};
2039
- this.bySpecialFeatureVendorMap = {};
2040
- Object.keys(this.purposes).forEach((purposeId) => {
2041
- this.byPurposeVendorMap[purposeId] = {
2042
- legInt: /* @__PURE__ */ new Set(),
2043
- consent: /* @__PURE__ */ new Set(),
2044
- flexible: /* @__PURE__ */ new Set()
2045
- };
2046
- });
2047
- Object.keys(this.specialPurposes).forEach((purposeId) => {
2048
- this.bySpecialPurposeVendorMap[purposeId] = /* @__PURE__ */ new Set();
2049
- });
2050
- Object.keys(this.features).forEach((featureId) => {
2051
- this.byFeatureVendorMap[featureId] = /* @__PURE__ */ new Set();
2052
- });
2053
- Object.keys(this.specialFeatures).forEach((featureId) => {
2054
- this.bySpecialFeatureVendorMap[featureId] = /* @__PURE__ */ new Set();
2055
- });
2056
- if (!Array.isArray(vendorIds)) {
2057
- vendorIds = Object.keys(this.fullVendorList).map((vId) => +vId);
2058
- }
2059
- this.vendorIds = new Set(vendorIds);
2060
- this.vendors_ = vendorIds.reduce((vendors, vendorId) => {
2061
- const vendor = this.vendors_[String(vendorId)];
2062
- if (vendor && vendor.deletedDate === void 0) {
2063
- vendor.purposes.forEach((purposeId) => {
2064
- const purpGroup = this.byPurposeVendorMap[String(purposeId)];
2065
- purpGroup.consent.add(vendorId);
2066
- });
2067
- vendor.specialPurposes.forEach((purposeId) => {
2068
- this.bySpecialPurposeVendorMap[String(purposeId)].add(vendorId);
2069
- });
2070
- vendor.legIntPurposes.forEach((purposeId) => {
2071
- this.byPurposeVendorMap[String(purposeId)].legInt.add(vendorId);
2072
- });
2073
- if (vendor.flexiblePurposes) {
2074
- vendor.flexiblePurposes.forEach((purposeId) => {
2075
- this.byPurposeVendorMap[String(purposeId)].flexible.add(vendorId);
2076
- });
2077
- }
2078
- vendor.features.forEach((featureId) => {
2079
- this.byFeatureVendorMap[String(featureId)].add(vendorId);
2080
- });
2081
- vendor.specialFeatures.forEach((featureId) => {
2082
- this.bySpecialFeatureVendorMap[String(featureId)].add(vendorId);
2083
- });
2084
- vendors[vendorId] = vendor;
2085
- }
2086
- return vendors;
2087
- }, {});
2088
- }
2089
- getFilteredVendors(purposeOrFeature, id, subType, special) {
2090
- const properPurposeOrFeature = purposeOrFeature.charAt(0).toUpperCase() + purposeOrFeature.slice(1);
2091
- let vendorSet;
2092
- const retr = {};
2093
- if (purposeOrFeature === "purpose" && subType) {
2094
- vendorSet = this["by" + properPurposeOrFeature + "VendorMap"][String(id)][subType];
2095
- } else {
2096
- vendorSet = this["by" + (special ? "Special" : "") + properPurposeOrFeature + "VendorMap"][String(id)];
2097
- }
2098
- vendorSet.forEach((vendorId) => {
2099
- retr[String(vendorId)] = this.vendors[String(vendorId)];
2100
- });
2101
- return retr;
2102
- }
2103
- /**
2104
- * getVendorsWithConsentPurpose
2105
- *
2106
- * @param {number} purposeId
2107
- * @return {IntMap<Vendor>} - list of vendors that have declared the consent purpose id
2108
- */
2109
- getVendorsWithConsentPurpose(purposeId) {
2110
- return this.getFilteredVendors("purpose", purposeId, "consent");
2111
- }
2112
- /**
2113
- * getVendorsWithLegIntPurpose
2114
- *
2115
- * @param {number} purposeId
2116
- * @return {IntMap<Vendor>} - list of vendors that have declared the legInt (Legitimate Interest) purpose id
2117
- */
2118
- getVendorsWithLegIntPurpose(purposeId) {
2119
- return this.getFilteredVendors("purpose", purposeId, "legInt");
2120
- }
2121
- /**
2122
- * getVendorsWithFlexiblePurpose
2123
- *
2124
- * @param {number} purposeId
2125
- * @return {IntMap<Vendor>} - list of vendors that have declared the flexible purpose id
2126
- */
2127
- getVendorsWithFlexiblePurpose(purposeId) {
2128
- return this.getFilteredVendors("purpose", purposeId, "flexible");
2129
- }
2130
- /**
2131
- * getVendorsWithSpecialPurpose
2132
- *
2133
- * @param {number} specialPurposeId
2134
- * @return {IntMap<Vendor>} - list of vendors that have declared the special purpose id
2135
- */
2136
- getVendorsWithSpecialPurpose(specialPurposeId) {
2137
- return this.getFilteredVendors("purpose", specialPurposeId, void 0, true);
2138
- }
2139
- /**
2140
- * getVendorsWithFeature
2141
- *
2142
- * @param {number} featureId
2143
- * @return {IntMap<Vendor>} - list of vendors that have declared the feature id
2144
- */
2145
- getVendorsWithFeature(featureId) {
2146
- return this.getFilteredVendors("feature", featureId);
2147
- }
2148
- /**
2149
- * getVendorsWithSpecialFeature
2150
- *
2151
- * @param {number} specialFeatureId
2152
- * @return {IntMap<Vendor>} - list of vendors that have declared the special feature id
2153
- */
2154
- getVendorsWithSpecialFeature(specialFeatureId) {
2155
- return this.getFilteredVendors("feature", specialFeatureId, void 0, true);
2156
- }
2157
- /**
2158
- * vendors
2159
- *
2160
- * @return {IntMap<Vendor>} - the list of vendors as it would on the JSON file
2161
- * except if `narrowVendorsTo` was called, it would be that narrowed list
2162
- */
2163
- get vendors() {
2164
- return this.vendors_;
2165
- }
2166
- /**
2167
- * narrowVendorsTo - narrows vendors represented in this GVL to the list of ids passed in
2168
- *
2169
- * @param {number[]} vendorIds - list of ids to narrow this GVL to
2170
- * @return {void}
2171
- */
2172
- narrowVendorsTo(vendorIds) {
2173
- this.mapVendors(vendorIds);
2174
- }
2175
- /**
2176
- * isReady - Whether or not this instance is ready to be used. This will be
2177
- * immediately and synchronously true if a vendorlist object is passed into
2178
- * the constructor or once the JSON vendorllist is retrieved.
2179
- *
2180
- * @return {boolean} whether or not the instance is ready to be interacted
2181
- * with and all the data is populated
2182
- */
2183
- get isReady() {
2184
- return this.isReady_;
2185
- }
2186
- /**
2187
- * clone - overrides base `clone()` method since GVL is a special class that
2188
- * represents a JSON structure with some additional functionality.
2189
- *
2190
- * @return {GVL}
2191
- */
2192
- clone() {
2193
- const result = new _GVL(this.getJson());
2194
- if (this.lang_ !== _GVL.DEFAULT_LANGUAGE) {
2195
- result.changeLanguage(this.lang_);
2196
- }
2197
- return result;
2198
- }
2199
- static isInstanceOf(questionableInstance) {
2200
- const isSo = typeof questionableInstance === "object";
2201
- return isSo && typeof questionableInstance.narrowVendorsTo === "function";
2202
- }
2203
- };
2204
- __publicField(_GVL, "LANGUAGE_CACHE", /* @__PURE__ */ new Map());
2205
- __publicField(_GVL, "CACHE", /* @__PURE__ */ new Map());
2206
- __publicField(_GVL, "LATEST_CACHE_KEY", 0);
2207
- __publicField(_GVL, "DEFAULT_LANGUAGE", "EN");
2208
- /**
2209
- * Set of available consent languages published by the IAB
2210
- */
2211
- __publicField(_GVL, "consentLanguages", new ConsentLanguages());
2212
- __publicField(_GVL, "baseUrl_");
2213
- /**
2214
- * @static
2215
- * @param {string} - the latest is assumed to be vendor-list.json because
2216
- * that is what the iab uses, but it could be different... if you want
2217
- */
2218
- __publicField(_GVL, "latestFilename", "vendor-list.json");
2219
- /**
2220
- * @static
2221
- * @param {string} - the versioned name is assumed to be
2222
- * vendor-list-v[VERSION].json where [VERSION] will be replaced with the
2223
- * specified version. But it could be different... if you want just make
2224
- * sure to include the [VERSION] macro if you have a numbering scheme, it's a
2225
- * simple string substitution.
2226
- *
2227
- * eg.
2228
- * ```javascript
2229
- * GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
2230
- * GVL.versionedFilename = "vendorlist?getVersion=[VERSION]";
2231
- * ```
2232
- */
2233
- __publicField(_GVL, "versionedFilename", "archives/vendor-list-v[VERSION].json");
2234
- /**
2235
- * @param {string} - Translations of the names and descriptions for Purposes,
2236
- * Special Purposes, Features, and Special Features to non-English languages
2237
- * are contained in a file where attributes containing English content
2238
- * (except vendor declaration information) are translated. The iab publishes
2239
- * one following the scheme below where the LANG is the iso639-1 language
2240
- * code. For a list of available translations
2241
- * [please go here](https://register.consensu.org/Translation).
2242
- *
2243
- * eg.
2244
- * ```javascript
2245
- * GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
2246
- * GVL.languageFilename = "purposes?getPurposes=[LANG]";
2247
- * ```
2248
- */
2249
- __publicField(_GVL, "languageFilename", "purposes-[LANG].json");
2250
- let GVL = _GVL;
2251
- class TCModel extends Cloneable {
2252
- /**
2253
- * Constructs the TCModel. Passing a [[GVL]] is optional when constructing
2254
- * as this TCModel may be constructed from decoding an existing encoded
2255
- * TCString.
2256
- *
2257
- * @param {GVL} [gvl]
2258
- */
2259
- constructor(gvl) {
2260
- super();
2261
- __publicField(this, "isServiceSpecific_", false);
2262
- __publicField(this, "supportOOB_", true);
2263
- __publicField(this, "useNonStandardTexts_", false);
2264
- __publicField(this, "purposeOneTreatment_", false);
2265
- __publicField(this, "publisherCountryCode_", "AA");
2266
- __publicField(this, "version_", 2);
2267
- __publicField(this, "consentScreen_", 0);
2268
- __publicField(this, "policyVersion_", 4);
2269
- __publicField(this, "consentLanguage_", "EN");
2270
- __publicField(this, "cmpId_", 0);
2271
- __publicField(this, "cmpVersion_", 0);
2272
- __publicField(this, "vendorListVersion_", 0);
2273
- __publicField(this, "numCustomPurposes_", 0);
2274
- // Member Variable for GVL
2275
- __publicField(this, "gvl_");
2276
- __publicField(this, "created");
2277
- __publicField(this, "lastUpdated");
2278
- /**
2279
- * The TCF designates certain Features as special, that is, a CMP must afford
2280
- * the user a means to opt in to their use. These Special Features are
2281
- * published and numbered in the GVL separately from normal Features.
2282
- * Provides for up to 12 special features.
2283
- */
2284
- __publicField(this, "specialFeatureOptins", new Vector());
2285
- /**
2286
- * Renamed from `PurposesAllowed` in TCF v1.1
2287
- * The user’s consent value for each Purpose established on the legal basis
2288
- * of consent. Purposes are published in the Global Vendor List (see. [[GVL]]).
2289
- */
2290
- __publicField(this, "purposeConsents", new Vector());
2291
- /**
2292
- * The user’s permission for each Purpose established on the legal basis of
2293
- * legitimate interest. If the user has exercised right-to-object for a
2294
- * purpose.
2295
- */
2296
- __publicField(this, "purposeLegitimateInterests", new Vector());
2297
- /**
2298
- * The user’s consent value for each Purpose established on the legal basis
2299
- * of consent, for the publisher. Purposes are published in the Global
2300
- * Vendor List.
2301
- */
2302
- __publicField(this, "publisherConsents", new Vector());
2303
- /**
2304
- * The user’s permission for each Purpose established on the legal basis of
2305
- * legitimate interest. If the user has exercised right-to-object for a
2306
- * purpose.
2307
- */
2308
- __publicField(this, "publisherLegitimateInterests", new Vector());
2309
- /**
2310
- * The user’s consent value for each Purpose established on the legal basis
2311
- * of consent, for the publisher. Purposes are published in the Global
2312
- * Vendor List.
2313
- */
2314
- __publicField(this, "publisherCustomConsents", new Vector());
2315
- /**
2316
- * The user’s permission for each Purpose established on the legal basis of
2317
- * legitimate interest. If the user has exercised right-to-object for a
2318
- * purpose that is established in the publisher's custom purposes.
2319
- */
2320
- __publicField(this, "publisherCustomLegitimateInterests", new Vector());
2321
- /**
2322
- * set by a publisher if they wish to collect consent and LI Transparency for
2323
- * purposes outside of the TCF
2324
- */
2325
- __publicField(this, "customPurposes");
2326
- /**
2327
- * Each [[Vendor]] is keyed by id. Their consent value is true if it is in
2328
- * the Vector
2329
- */
2330
- __publicField(this, "vendorConsents", new Vector());
2331
- /**
2332
- * Each [[Vendor]] is keyed by id. Whether their Legitimate Interests
2333
- * Disclosures have been established is stored as boolean.
2334
- * see: [[Vector]]
2335
- */
2336
- __publicField(this, "vendorLegitimateInterests", new Vector());
2337
- /**
2338
- * The value included for disclosed vendors signals which vendors have been
2339
- * disclosed to the user in the interface surfaced by the CMP. This section
2340
- * content is required when writing a TC string to the global (consensu)
2341
- * scope. When a CMP has read from and is updating a TC string from the
2342
- * global consensu.org storage, the CMP MUST retain the existing disclosure
2343
- * information and only add information for vendors that it has disclosed
2344
- * that had not been disclosed by other CMPs in prior interactions with this
2345
- * device/user agent.
2346
- */
2347
- __publicField(this, "vendorsDisclosed", new Vector());
2348
- /**
2349
- * Signals which vendors the publisher permits to use OOB legal bases.
2350
- */
2351
- __publicField(this, "vendorsAllowed", new Vector());
2352
- __publicField(this, "publisherRestrictions", new PurposeRestrictionVector());
2353
- if (gvl) {
2354
- this.gvl = gvl;
2355
- }
2356
- this.updated();
2357
- }
2358
- /**
2359
- * sets the [[GVL]] with side effects of also setting the `vendorListVersion`, `policyVersion`, and `consentLanguage`
2360
- * @param {GVL} gvl
2361
- */
2362
- set gvl(gvl) {
2363
- if (!GVL.isInstanceOf(gvl)) {
2364
- gvl = new GVL(gvl);
2365
- }
2366
- this.gvl_ = gvl;
2367
- this.publisherRestrictions.gvl = gvl;
2368
- }
2369
- /**
2370
- * @return {GVL} the gvl instance set on this TCModel instance
2371
- */
2372
- get gvl() {
2373
- return this.gvl_;
2374
- }
2375
- /**
2376
- * @param {number} integer - A unique ID will be assigned to each Consent
2377
- * Manager Provider (CMP) from the iab.
2378
- *
2379
- * @throws {TCModelError} if the value is not an integer greater than 1 as those are not valid.
2380
- */
2381
- set cmpId(integer) {
2382
- integer = Number(integer);
2383
- if (Number.isInteger(integer) && integer > 1) {
2384
- this.cmpId_ = integer;
2385
- } else {
2386
- throw new TCModelError("cmpId", integer);
2387
- }
2388
- }
2389
- get cmpId() {
2390
- return this.cmpId_;
2391
- }
2392
- /**
2393
- * Each change to an operating CMP should receive a
2394
- * new version number, for logging proof of consent. CmpVersion defined by
2395
- * each CMP.
2396
- *
2397
- * @param {number} integer
2398
- *
2399
- * @throws {TCModelError} if the value is not an integer greater than 1 as those are not valid.
2400
- */
2401
- set cmpVersion(integer) {
2402
- integer = Number(integer);
2403
- if (Number.isInteger(integer) && integer > -1) {
2404
- this.cmpVersion_ = integer;
2405
- } else {
2406
- throw new TCModelError("cmpVersion", integer);
2407
- }
2408
- }
2409
- get cmpVersion() {
2410
- return this.cmpVersion_;
2411
- }
2412
- /**
2413
- * The screen number is CMP and CmpVersion
2414
- * specific, and is for logging proof of consent.(For example, a CMP could
2415
- * keep records so that a publisher can request information about the context
2416
- * in which consent was gathered.)
2417
- *
2418
- * @param {number} integer
2419
- *
2420
- * @throws {TCModelError} if the value is not an integer greater than 0 as those are not valid.
2421
- */
2422
- set consentScreen(integer) {
2423
- integer = Number(integer);
2424
- if (Number.isInteger(integer) && integer > -1) {
2425
- this.consentScreen_ = integer;
2426
- } else {
2427
- throw new TCModelError("consentScreen", integer);
2428
- }
2429
- }
2430
- get consentScreen() {
2431
- return this.consentScreen_;
2432
- }
2433
- /**
2434
- * @param {string} lang - [two-letter ISO 639-1 language
2435
- * code](http://www.loc.gov/standards/iso639-2/php/code_list.php) in which
2436
- * the CMP UI was presented
2437
- *
2438
- * @throws {TCModelError} if the value is not a length-2 string of alpha characters
2439
- */
2440
- set consentLanguage(lang) {
2441
- this.consentLanguage_ = lang;
2442
- }
2443
- get consentLanguage() {
2444
- return this.consentLanguage_;
2445
- }
2446
- /**
2447
- * @param {string} countryCode - [two-letter ISO 3166-1 alpha-2 country
2448
- * code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) of the publisher,
2449
- * determined by the CMP-settings of the publisher.
2450
- *
2451
- * @throws {TCModelError} if the value is not a length-2 string of alpha characters
2452
- */
2453
- set publisherCountryCode(countryCode) {
2454
- if (/^([A-z]){2}$/.test(countryCode)) {
2455
- this.publisherCountryCode_ = countryCode.toUpperCase();
2456
- } else {
2457
- throw new TCModelError("publisherCountryCode", countryCode);
2458
- }
2459
- }
2460
- get publisherCountryCode() {
2461
- return this.publisherCountryCode_;
2462
- }
2463
- /**
2464
- * Version of the GVL used to create this TCModel. Global
2465
- * Vendor List versions will be released periodically.
2466
- *
2467
- * @param {number} integer
2468
- *
2469
- * @throws {TCModelError} if the value is not an integer greater than 0 as those are not valid.
2470
- */
2471
- set vendorListVersion(integer) {
2472
- integer = Number(integer) >> 0;
2473
- if (integer < 0) {
2474
- throw new TCModelError("vendorListVersion", integer);
2475
- } else {
2476
- this.vendorListVersion_ = integer;
2477
- }
2478
- }
2479
- get vendorListVersion() {
2480
- if (this.gvl) {
2481
- return this.gvl.vendorListVersion;
2482
- } else {
2483
- return this.vendorListVersion_;
2484
- }
2485
- }
2486
- /**
2487
- * From the corresponding field in the GVL that was
2488
- * used for obtaining consent. A new policy version invalidates existing
2489
- * strings and requires CMPs to re-establish transparency and consent from
2490
- * users.
2491
- *
2492
- * If a TCF policy version number is different from the one from the latest
2493
- * GVL, the CMP must re-establish transparency and consent.
2494
- *
2495
- * @param {number} num - You do not need to set this. This comes
2496
- * directly from the [[GVL]].
2497
- *
2498
- */
2499
- set policyVersion(num) {
2500
- this.policyVersion_ = parseInt(num, 10);
2501
- if (this.policyVersion_ < 0) {
2502
- throw new TCModelError("policyVersion", num);
2503
- }
2504
- }
2505
- get policyVersion() {
2506
- if (this.gvl) {
2507
- return this.gvl.tcfPolicyVersion;
2508
- } else {
2509
- return this.policyVersion_;
2510
- }
2511
- }
2512
- set version(num) {
2513
- this.version_ = parseInt(num, 10);
2514
- }
2515
- get version() {
2516
- return this.version_;
2517
- }
2518
- /**
2519
- * Whether the signals encoded in this TC String were from site-specific
2520
- * storage `true` versus ‘global’ consensu.org shared storage `false`. A
2521
- * string intended to be stored in global/shared scope but the CMP is unable
2522
- * to store due to a user agent not accepting third-party cookies would be
2523
- * considered site-specific `true`.
2524
- *
2525
- * @param {boolean} bool - value to set. Some changes to other fields in this
2526
- * model will automatically change this value like adding publisher
2527
- * restrictions.
2528
- */
2529
- set isServiceSpecific(bool) {
2530
- this.isServiceSpecific_ = bool;
2531
- }
2532
- get isServiceSpecific() {
2533
- return this.isServiceSpecific_;
2534
- }
2535
- /**
2536
- * Non-standard stacks means that a CMP is using publisher-customized stack
2537
- * descriptions. Stacks (in terms of purposes in a stack) are pre-set by the
2538
- * IAB. As are titles. Descriptions are pre-set, but publishers can customize
2539
- * them. If they do, they need to set this bit to indicate that they've
2540
- * customized descriptions.
2541
- *
2542
- * @param {boolean} bool - value to set
2543
- */
2544
- set useNonStandardTexts(bool) {
2545
- this.useNonStandardTexts_ = bool;
2546
- }
2547
- get useNonStandardTexts() {
2548
- return this.useNonStandardTexts_;
2549
- }
2550
- /**
2551
- * Whether or not this publisher supports OOB signaling. On Global TC String
2552
- * OOB Vendors Disclosed will be included if the publish wishes to no allow
2553
- * these vendors they should set this to false.
2554
- * @param {boolean} bool - value to set
2555
- */
2556
- set supportOOB(bool) {
2557
- this.supportOOB_ = bool;
2558
- }
2559
- get supportOOB() {
2560
- return this.supportOOB_;
2561
- }
2562
- /**
2563
- * `false` There is no special Purpose 1 status.
2564
- * Purpose 1 was disclosed normally (consent) as expected by Policy. `true`
2565
- * Purpose 1 not disclosed at all. CMPs use PublisherCC to indicate the
2566
- * publisher’s country of establishment to help Vendors determine whether the
2567
- * vendor requires Purpose 1 consent. In global scope TC strings, this field
2568
- * must always have a value of `false`. When a CMP encounters a global scope
2569
- * string with `purposeOneTreatment=true` then that string should be
2570
- * considered invalid and the CMP must re-establish transparency and consent.
2571
- *
2572
- * @param {boolean} bool
2573
- */
2574
- set purposeOneTreatment(bool) {
2575
- this.purposeOneTreatment_ = bool;
2576
- }
2577
- get purposeOneTreatment() {
2578
- return this.purposeOneTreatment_;
2579
- }
2580
- /**
2581
- * setAllVendorConsents - sets all vendors on the GVL Consent (true)
2582
- *
2583
- * @return {void}
2584
- */
2585
- setAllVendorConsents() {
2586
- this.vendorConsents.set(this.gvl.vendors);
2587
- }
2588
- /**
2589
- * unsetAllVendorConsents - unsets all vendors on the GVL Consent (false)
2590
- *
2591
- * @return {void}
2592
- */
2593
- unsetAllVendorConsents() {
2594
- this.vendorConsents.empty();
2595
- }
2596
- /**
2597
- * setAllVendorsDisclosed - sets all vendors on the GVL Vendors Disclosed (true)
2598
- *
2599
- * @return {void}
2600
- */
2601
- setAllVendorsDisclosed() {
2602
- this.vendorsDisclosed.set(this.gvl.vendors);
2603
- }
2604
- /**
2605
- * unsetAllVendorsDisclosed - unsets all vendors on the GVL Consent (false)
2606
- *
2607
- * @return {void}
2608
- */
2609
- unsetAllVendorsDisclosed() {
2610
- this.vendorsDisclosed.empty();
2611
- }
2612
- /**
2613
- * setAllVendorsAllowed - sets all vendors on the GVL Consent (true)
2614
- *
2615
- * @return {void}
2616
- */
2617
- setAllVendorsAllowed() {
2618
- this.vendorsAllowed.set(this.gvl.vendors);
2619
- }
2620
- /**
2621
- * unsetAllVendorsAllowed - unsets all vendors on the GVL Consent (false)
2622
- *
2623
- * @return {void}
2624
- */
2625
- unsetAllVendorsAllowed() {
2626
- this.vendorsAllowed.empty();
2627
- }
2628
- /**
2629
- * setAllVendorLegitimateInterests - sets all vendors on the GVL LegitimateInterests (true)
2630
- *
2631
- * @return {void}
2632
- */
2633
- setAllVendorLegitimateInterests() {
2634
- this.vendorLegitimateInterests.set(this.gvl.vendors);
2635
- }
2636
- /**
2637
- * unsetAllVendorLegitimateInterests - unsets all vendors on the GVL LegitimateInterests (false)
2638
- *
2639
- * @return {void}
2640
- */
2641
- unsetAllVendorLegitimateInterests() {
2642
- this.vendorLegitimateInterests.empty();
2643
- }
2644
- /**
2645
- * setAllPurposeConsents - sets all purposes on the GVL Consent (true)
2646
- *
2647
- * @return {void}
2648
- */
2649
- setAllPurposeConsents() {
2650
- this.purposeConsents.set(this.gvl.purposes);
2651
- }
2652
- /**
2653
- * unsetAllPurposeConsents - unsets all purposes on the GVL Consent (false)
2654
- *
2655
- * @return {void}
2656
- */
2657
- unsetAllPurposeConsents() {
2658
- this.purposeConsents.empty();
2659
- }
2660
- /**
2661
- * setAllPurposeLegitimateInterests - sets all purposes on the GVL LI Transparency (true)
2662
- *
2663
- * @return {void}
2664
- */
2665
- setAllPurposeLegitimateInterests() {
2666
- this.purposeLegitimateInterests.set(this.gvl.purposes);
2667
- }
2668
- /**
2669
- * unsetAllPurposeLegitimateInterests - unsets all purposes on the GVL LI Transparency (false)
2670
- *
2671
- * @return {void}
2672
- */
2673
- unsetAllPurposeLegitimateInterests() {
2674
- this.purposeLegitimateInterests.empty();
2675
- }
2676
- /**
2677
- * setAllSpecialFeatureOptins - sets all special featuresOptins on the GVL (true)
2678
- *
2679
- * @return {void}
2680
- */
2681
- setAllSpecialFeatureOptins() {
2682
- this.specialFeatureOptins.set(this.gvl.specialFeatures);
2683
- }
2684
- /**
2685
- * unsetAllSpecialFeatureOptins - unsets all special featuresOptins on the GVL (true)
2686
- *
2687
- * @return {void}
2688
- */
2689
- unsetAllSpecialFeatureOptins() {
2690
- this.specialFeatureOptins.empty();
2691
- }
2692
- setAll() {
2693
- this.setAllVendorConsents();
2694
- this.setAllPurposeLegitimateInterests();
2695
- this.setAllSpecialFeatureOptins();
2696
- this.setAllPurposeConsents();
2697
- this.setAllVendorLegitimateInterests();
2698
- }
2699
- unsetAll() {
2700
- this.unsetAllVendorConsents();
2701
- this.unsetAllPurposeLegitimateInterests();
2702
- this.unsetAllSpecialFeatureOptins();
2703
- this.unsetAllPurposeConsents();
2704
- this.unsetAllVendorLegitimateInterests();
2705
- }
2706
- get numCustomPurposes() {
2707
- let len = this.numCustomPurposes_;
2708
- if (typeof this.customPurposes === "object") {
2709
- const purposeIds = Object.keys(this.customPurposes).sort((a, b) => Number(a) - Number(b));
2710
- len = parseInt(purposeIds.pop(), 10);
2711
- }
2712
- return len;
2713
- }
2714
- set numCustomPurposes(num) {
2715
- this.numCustomPurposes_ = parseInt(num, 10);
2716
- if (this.numCustomPurposes_ < 0) {
2717
- throw new TCModelError("numCustomPurposes", num);
2718
- }
2719
- }
2720
- /**
2721
- * updated - updates the created and lastUpdated dates with a 'now' day-level UTC timestamp
2722
- *
2723
- * @return {void}
2724
- */
2725
- updated() {
2726
- const date = /* @__PURE__ */ new Date();
2727
- const utcDate = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
2728
- this.created = utcDate;
2729
- this.lastUpdated = utcDate;
2730
- }
2731
- }
2732
- /**
2733
- * Set of available consent languages published by the IAB
2734
- */
2735
- __publicField(TCModel, "consentLanguages", GVL.consentLanguages);
2736
- class TCString {
2737
- /**
2738
- * encodes a model into a TCString
2739
- *
2740
- * @param {TCModel} tcModel - model to convert into encoded string
2741
- * @param {EncodingOptions} options - for encoding options other than default
2742
- * @return {string} - base64url encoded Transparency and Consent String
2743
- */
2744
- static encode(tcModel, options) {
2745
- let out = "";
2746
- let sequence;
2747
- tcModel = SemanticPreEncoder.process(tcModel, options);
2748
- if (Array.isArray(options == null ? void 0 : options.segments)) {
2749
- sequence = options.segments;
2750
- } else {
2751
- sequence = new SegmentSequence(tcModel, options)["" + tcModel.version];
2752
- }
2753
- sequence.forEach((segment, idx) => {
2754
- let dotMaybe = "";
2755
- if (idx < sequence.length - 1) {
2756
- dotMaybe = ".";
2757
- }
2758
- out += SegmentEncoder.encode(tcModel, segment) + dotMaybe;
2759
- });
2760
- return out;
2761
- }
2762
- /**
2763
- * Decodes a string into a TCModel
2764
- *
2765
- * @param {string} encodedTCString - base64url encoded Transparency and
2766
- * Consent String to decode - can also be a single or group of segments of
2767
- * the string
2768
- * @param {string} [tcModel] - model to enhance with the information. If
2769
- * none is passed a new instance of TCModel will be created.
2770
- * @return {TCModel} - Returns populated TCModel
2771
- */
2772
- static decode(encodedTCString, tcModel) {
2773
- const segments = encodedTCString.split(".");
2774
- const len = segments.length;
2775
- if (!tcModel) {
2776
- tcModel = new TCModel();
2777
- }
2778
- for (let i = 0; i < len; i++) {
2779
- const segString = segments[i];
2780
- const firstChar = Base64Url.decode(segString.charAt(0));
2781
- const segTypeBits = firstChar.substr(0, BitLength.segmentType);
2782
- const segment = SegmentIDs.ID_TO_KEY[IntEncoder.decode(segTypeBits, BitLength.segmentType).toString()];
2783
- SegmentEncoder.decode(segString, tcModel, segment);
2784
- }
2785
- return tcModel;
2786
- }
2787
- }
2788
- function isValidGdprValue(val) {
2789
- if (val === null) {
2790
- return true;
2791
- }
2792
- try {
2793
- TCString.decode(val);
2794
- return true;
2795
- } catch (error) {
2796
- return false;
2797
- }
2798
- }
2799
- function isValidUspString(val) {
2800
- if (val === null) {
2801
- return true;
2802
- }
2803
- const regex = /^[1-9][YN-][YN-][YN-]$/;
2804
- return regex.test(val);
2805
- }
2806
- function validateRawConsentState(input) {
2807
- if (typeof input !== "object" || input === null) {
2808
- throw new Error("Invalid consent state object");
2809
- }
2810
- if (!isValidGdprValue(input.gdpr)) {
2811
- throw new Error("Invalid TC string provided");
2812
- }
2813
- if (!isValidUspString(input.ccpa)) {
2814
- throw new Error("Invalid USP string provided");
2815
- }
2816
- if (!["ccpa", "gdpr"].includes(input.activeLegislation)) {
2817
- throw new Error("Active legislation is required");
2818
- }
2819
- if (input.gdpr === void 0 && input.ccpa === void 0) {
2820
- throw new Error("Either GDPR or CCPA consent must be provided");
2821
- }
2822
- return true;
2823
- }
2824
- function validateIabConsentCategory(categoryName) {
2825
- if (!categoryName || categoryName in iabCustomCategories === false) {
2826
- throw new Error("Provided custom category identifier does not exist. Please check");
2827
- }
2828
- }
2829
- function checkConsentFor(categoryName, consentState) {
2830
- validateIabConsentCategory(categoryName);
2831
- validateRawConsentState(consentState);
2832
- const { gdpr, ccpa, activeLegislation } = consentState;
349
+ function checkConsentFor(categoryName, { purpose, vendor, specialFeatureOptins }) {
2833
350
  const customCategory = iabCustomCategories[categoryName];
2834
- if (activeLegislation === legislation.CCPA) {
2835
- const userHasNotOptedOut = (ccpa == null ? void 0 : ccpa[2]) === "N";
2836
- return userHasNotOptedOut;
2837
- }
2838
- const decodedGdprConsent = TCString.decode(gdpr);
2839
- const { purposeConsents, vendorConsents, specialFeatureOptins } = decodedGdprConsent;
2840
351
  const requiredPurposesConsented = customCategory.purposes.every(
2841
- (requiredPurpose) => purposeConsents.has(requiredPurpose)
352
+ (requiredPurpose) => (purpose == null ? void 0 : purpose.consents[requiredPurpose]) === true
2842
353
  );
2843
354
  const requiredIabVendorsConsented = customCategory.iabVendors.every(
2844
- (requiredVendor) => vendorConsents.has(requiredVendor)
355
+ (requiredVendor) => (vendor == null ? void 0 : vendor.consents[requiredVendor]) === true
2845
356
  );
2846
357
  const requiredSpecialFeaturesConsented = customCategory.specialFeatures.every(
2847
- (requiredFeature) => specialFeatureOptins.has(requiredFeature)
358
+ (requiredFeature) => (specialFeatureOptins == null ? void 0 : specialFeatureOptins[requiredFeature]) === true
2848
359
  );
2849
360
  return requiredPurposesConsented && requiredIabVendorsConsented && requiredSpecialFeaturesConsented;
2850
361
  }
2851
- function getParsedConsent(rawConsentState) {
2852
- const categoryNames = Object.keys(iabCustomCategories);
2853
- return categoryNames.reduce((parsedConsent, categoryName) => {
2854
- parsedConsent[categoryName] = checkConsentFor(categoryName, rawConsentState);
2855
- return parsedConsent;
2856
- }, {});
362
+ function parseCCPAConsent(ccpa) {
363
+ const userHasNotOptedOut = (ccpa == null ? void 0 : ccpa[2]) === "N";
364
+ const parsedConsent = {};
365
+ for (const categoryName of iabCategoryNames) {
366
+ parsedConsent[categoryName] = userHasNotOptedOut;
367
+ }
368
+ return parsedConsent;
369
+ }
370
+ async function parseGDPRConsent() {
371
+ const tcData = await new Promise((resolve, reject) => {
372
+ var _a;
373
+ try {
374
+ (_a = window.__tcfapi) == null ? void 0 : _a.call(window, "addEventListener", 2, resolve);
375
+ } catch (error) {
376
+ reject(error);
377
+ }
378
+ });
379
+ const parsedConsent = {};
380
+ for (const categoryName of iabCategoryNames) {
381
+ parsedConsent[categoryName] = checkConsentFor(categoryName, tcData);
382
+ }
383
+ return parsedConsent;
384
+ }
385
+ async function getParsedConsent(activeLegislation, consentString) {
386
+ return activeLegislation === "ccpa" ? parseCCPAConsent(consentString) : await parseGDPRConsent();
2857
387
  }
2858
388
  function getConsentCookieValue() {
2859
389
  const cookies = Object.fromEntries(
@@ -2871,14 +401,22 @@ function getConsentCookieValue() {
2871
401
  })
2872
402
  );
2873
403
  }
2874
- function hasConsentChanged(parsedConsent) {
404
+ function hasConsentChanged(parsedConsent, previousConsent) {
2875
405
  const categories = Object.keys(parsedConsent);
2876
- const previousConsent = getConsentCookieValue();
2877
406
  return categories.some((category) => {
2878
407
  const adaptedCategoryName = `${category.toLowerCase()}Onsite`;
2879
408
  return parsedConsent[category] !== previousConsent[adaptedCategoryName];
2880
409
  });
2881
410
  }
411
+ function shouldUpdateConsentStore({ userId, useConsentStore }) {
412
+ return !!userId && useConsentStore === true;
413
+ }
414
+ function getConsentEndpoint(updateConsentStore, props) {
415
+ if (updateConsentStore) {
416
+ return `${props.consentProxyHost}/__consent/consent-record/${SOURCEPOINT_FOW_SCOPE}/${props.userId}`;
417
+ }
418
+ return `${props.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${props.cookieDomain}`;
419
+ }
2882
420
  async function saveConsent(consentEndpoint, payload) {
2883
421
  try {
2884
422
  const response = await fetch(consentEndpoint, {
@@ -2897,78 +435,29 @@ async function saveConsent(consentEndpoint, payload) {
2897
435
  }
2898
436
  }
2899
437
  function consentReadyHandlerFn(props) {
2900
- const { userId, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore } = props;
2901
- return async function consentReadyHandler(legislation2, _consentUUID, consentString, consentMeta) {
2902
- const activeLegislation = consentMeta.applies ? legislation2 : "gdpr";
2903
- if (activeLegislation !== legislation2 || !consentString) {
438
+ return async function consentReadyHandler(legislation, _consentUUID, consentString, consentMeta) {
439
+ const activeLegislation = consentMeta.applies ? legislation : "gdpr";
440
+ if (activeLegislation !== legislation || !consentString) {
2904
441
  return;
2905
442
  }
2906
- const parsedConsent = getParsedConsent({
2907
- activeLegislation,
2908
- gdpr: activeLegislation === "gdpr" ? consentString : null,
2909
- ccpa: activeLegislation === "ccpa" ? consentString : null
2910
- });
2911
- const consentHasChanged = hasConsentChanged(parsedConsent);
443
+ const parsedConsent = await getParsedConsent(activeLegislation, consentString);
444
+ const consentHasChanged = hasConsentChanged(parsedConsent, getConsentCookieValue());
2912
445
  if (!consentHasChanged) {
2913
446
  return;
2914
447
  }
2915
- let consentEndpoint = `${consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${cookieDomain}`;
2916
- const shouldUpdateConsentStore = !!userId && useConsentStore;
2917
- if (shouldUpdateConsentStore) {
2918
- consentEndpoint = `${consentProxyHost}/__consent/consent-record/${SOURCEPOINT_FOW_SCOPE}/${userId}`;
2919
- }
2920
- const payload = getConsentPayload(parsedConsent, {
2921
- formOfWordsId,
2922
- cookieDomain,
2923
- shouldUpdateConsentStore
2924
- });
448
+ const updateConsentStore = shouldUpdateConsentStore(props);
449
+ const consentEndpoint = getConsentEndpoint(updateConsentStore, props);
450
+ const payload = getConsentPayload(parsedConsent, updateConsentStore, props);
2925
451
  await saveConsent(consentEndpoint, payload);
2926
452
  document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
2927
453
  };
2928
454
  }
2929
- let getRandomValues;
2930
- const rnds8 = new Uint8Array(16);
2931
- function rng() {
2932
- if (!getRandomValues) {
2933
- getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
2934
- if (!getRandomValues) {
2935
- throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
2936
- }
2937
- }
2938
- return getRandomValues(rnds8);
2939
- }
2940
- const byteToHex = [];
2941
- for (let i = 0; i < 256; ++i) {
2942
- byteToHex.push((i + 256).toString(16).slice(1));
2943
- }
2944
- function unsafeStringify(arr, offset = 0) {
2945
- return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
2946
- }
2947
- const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
2948
- const native = {
2949
- randomUUID
2950
- };
2951
- function v4(options, buf, offset) {
2952
- if (native.randomUUID && !buf && !options) {
2953
- return native.randomUUID();
2954
- }
2955
- options = options || {};
2956
- const rnds = options.random || (options.rng || rng)();
2957
- rnds[6] = rnds[6] & 15 | 64;
2958
- rnds[8] = rnds[8] & 63 | 128;
2959
- if (buf) {
2960
- offset = offset || 0;
2961
- for (let i = 0; i < 16; ++i) {
2962
- buf[offset + i] = rnds[i];
2963
- }
2964
- return buf;
2965
- }
2966
- return unsafeStringify(rnds);
2967
- }
2968
455
  const COOKIE_MESSAGE = "cookie-message";
2969
456
  const PRIVACY_MANAGER = "manage-cookies";
2970
457
  const INITIAL_STATE = Object.freeze({
2971
- activeComponent: COOKIE_MESSAGE
458
+ activeComponent: COOKIE_MESSAGE,
459
+ messageId: 0,
460
+ privacyManagerId: 0
2972
461
  });
2973
462
  let privateState = INITIAL_STATE;
2974
463
  function isPlainObject(obj) {
@@ -2982,20 +471,17 @@ const setState = (newState) => {
2982
471
  }
2983
472
  privateState = { ...privateState, ...newState };
2984
473
  };
2985
- const ACCEPT_ALL_CHOICE = 11;
2986
- const MANAGE_PREFS_CHOICE = 12;
2987
- const REJECT_ALL_CHOICE = 13;
2988
474
  const cookieToggleFlags = ["adsDisableInternalCMP", "pwm.cmp", "messageSlotBottom"];
2989
- function initTracking(context) {
2990
- const componentId = v4();
475
+ function initTracking(context, cmpBaseEndpoint) {
2991
476
  const flags = extractRelevantFlags(context.flags);
2992
477
  window._sp_queue = window._sp_queue ?? [];
2993
478
  window._sp_queue.push(() => {
2994
- var _a2, _b2;
479
+ var _a, _b;
2995
480
  for (const [eventId, eventHandler] of Object.entries(trackingEventHandlers)) {
2996
- (_b2 = (_a2 = window._sp_).addEventListener) == null ? void 0 : _b2.call(_a2, eventId, eventHandler({ ...context, flags, componentId }));
481
+ (_b = (_a = window._sp_).addEventListener) == null ? void 0 : _b.call(_a, eventId, eventHandler({ ...context, flags }));
2997
482
  }
2998
483
  });
484
+ setupPmTracking({ ...context, flags }, cmpBaseEndpoint);
2999
485
  }
3000
486
  function extractRelevantFlags(flags) {
3001
487
  const output = {};
@@ -3022,19 +508,23 @@ function track(payload) {
3022
508
  function dispatchComponentEvent({
3023
509
  trackingProps,
3024
510
  action,
3025
- triggerAction,
3026
- messageType
511
+ triggerAction
3027
512
  }) {
513
+ let componentId;
3028
514
  const state = getState();
3029
- const { componentId, product, app, flags } = trackingProps;
515
+ const { product, app, flags } = trackingProps;
516
+ if (state.activeComponent === COOKIE_MESSAGE) {
517
+ componentId = state.messageId;
518
+ } else {
519
+ componentId = state.privacyManagerId;
520
+ }
3030
521
  const event = {
3031
522
  detail: {
3032
523
  component: {
3033
524
  id: componentId,
3034
525
  name: state.activeComponent,
3035
526
  type: "overlay",
3036
- subtype: "cmp",
3037
- componentContentId: state[messageType]
527
+ subtype: "cmp"
3038
528
  },
3039
529
  category: "component",
3040
530
  action,
@@ -3045,94 +535,87 @@ function dispatchComponentEvent({
3045
535
  {
3046
536
  cookie_toggle_flag: flags
3047
537
  }
3048
- ]
538
+ ],
539
+ url: window.document.location.href || null
3049
540
  }
3050
541
  };
3051
542
  track(event);
3052
543
  }
3053
544
  const trackingEventHandlers = {
3054
- onMessageChoiceSelect: (trackingProps) => (messageType, _choiceId, choiceTypeId) => {
3055
- if (choiceTypeId === ACCEPT_ALL_CHOICE) {
3056
- dispatchComponentEvent({
3057
- trackingProps,
3058
- action: "click",
3059
- triggerAction: "accept_all",
3060
- messageType
3061
- });
3062
- }
3063
- if (choiceTypeId === MANAGE_PREFS_CHOICE) {
3064
- dispatchComponentEvent({
3065
- trackingProps,
3066
- action: "click",
3067
- triggerAction: "manage_cookies",
3068
- messageType
3069
- });
3070
- setState({
3071
- activeComponent: PRIVACY_MANAGER
3072
- });
3073
- }
3074
- if (choiceTypeId === REJECT_ALL_CHOICE) {
545
+ onMessageChoiceSelect: (trackingProps) => (_messageType, _choiceId, choiceTypeId) => {
546
+ const choiceTypeTriggerMap = {
547
+ 11: "accept_all",
548
+ 12: "manage_cookies",
549
+ 13: "reject_all"
550
+ };
551
+ const triggerAction = choiceTypeTriggerMap[choiceTypeId];
552
+ if (triggerAction) {
3075
553
  dispatchComponentEvent({
3076
554
  trackingProps,
3077
555
  action: "click",
3078
- triggerAction: "reject_all",
3079
- messageType
556
+ triggerAction
3080
557
  });
3081
558
  }
3082
559
  },
3083
- onMessageReady: (trackingProps) => (messageType) => {
560
+ onMessageReady: (trackingProps) => () => {
3084
561
  dispatchComponentEvent({
3085
562
  trackingProps,
3086
- action: "view",
3087
- messageType
563
+ action: "view"
3088
564
  });
3089
565
  },
3090
- onPrivacyManagerAction: (trackingProps) => (messageType, pmData) => {
3091
- const { purposeConsent, vendorConsent } = pmData;
3092
- const isAcceptAll = purposeConsent === "all" && vendorConsent === "all";
3093
- const isRejectAll = purposeConsent === "none" && vendorConsent === "none";
3094
- setState({
3095
- activeComponent: PRIVACY_MANAGER
3096
- });
3097
- if (isAcceptAll) {
3098
- dispatchComponentEvent({
3099
- trackingProps,
3100
- action: "click",
3101
- triggerAction: "accept_all",
3102
- messageType
3103
- });
3104
- } else if (isRejectAll) {
3105
- dispatchComponentEvent({
3106
- trackingProps,
3107
- action: "click",
3108
- triggerAction: "reject_all",
3109
- messageType
3110
- });
3111
- } else {
3112
- dispatchComponentEvent({
3113
- trackingProps,
3114
- action: "click",
3115
- triggerAction: "save_and_close",
3116
- messageType
566
+ onMessageReceiveData: () => (_messageType, data) => {
567
+ const { messageId } = data;
568
+ if (messageId) {
569
+ setState({
570
+ messageId
3117
571
  });
3118
572
  }
3119
573
  },
3120
- onMessageReceiveData: () => (messageType, data) => {
3121
- const { messageId } = data;
3122
- setState({
3123
- [messageType]: messageId
3124
- });
3125
- },
3126
- onError: (trackingProps) => (messageType, errorCode) => {
574
+ onError: (trackingProps) => (_messageType, errorCode) => {
3127
575
  dispatchComponentEvent({
3128
576
  trackingProps,
3129
577
  action: "error",
3130
- triggerAction: errorCode,
3131
- messageType
578
+ triggerAction: errorCode
579
+ });
580
+ },
581
+ onPMCancel: () => () => {
582
+ setState({
583
+ activeComponent: COOKIE_MESSAGE
3132
584
  });
3133
585
  }
3134
586
  };
3135
- const version = "3.1.4";
587
+ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
588
+ window.addEventListener(
589
+ "message",
590
+ function(event) {
591
+ if (event.origin !== cmpBaseEndpoint)
592
+ return;
593
+ const actionTypeMap = {
594
+ 1: "save_and_close",
595
+ 11: "accept_all",
596
+ 13: "reject_all"
597
+ };
598
+ const { data: { fromPM, actionType, messageId = "0" } = {} } = event;
599
+ if (!fromPM)
600
+ return;
601
+ if (+messageId) {
602
+ setState({
603
+ activeComponent: PRIVACY_MANAGER,
604
+ privacyManagerId: +messageId
605
+ });
606
+ }
607
+ if (!actionType || !actionTypeMap[actionType])
608
+ return;
609
+ dispatchComponentEvent({
610
+ trackingProps,
611
+ action: "click",
612
+ triggerAction: actionTypeMap[actionType]
613
+ });
614
+ },
615
+ false
616
+ );
617
+ }
618
+ const version = "3.3.0-beta.4";
3136
619
  async function initSourcepointCmp({
3137
620
  propertyConfig = FT_DOTCOM_PROD,
3138
621
  userId,
@@ -3170,9 +653,9 @@ async function initSourcepointCmp({
3170
653
  }
3171
654
  bootstrapCmp(propertyConfig);
3172
655
  window._sp_queue.push(() => {
3173
- var _a2, _b2;
3174
- (_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
3175
- _a2,
656
+ var _a, _b;
657
+ (_b = (_a = window._sp_) == null ? void 0 : _a.addEventListener) == null ? void 0 : _b.call(
658
+ _a,
3176
659
  "onConsentReady",
3177
660
  consentReadyHandlerFn({
3178
661
  userId,
@@ -3183,7 +666,7 @@ async function initSourcepointCmp({
3183
666
  })
3184
667
  );
3185
668
  });
3186
- initTracking(trackingContext);
669
+ initTracking(trackingContext, propertyConfig.baseEndpoint);
3187
670
  }
3188
671
  export {
3189
672
  debug,