@pubtech-ai/core 1.7.2 → 2.0.1

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.PurposeRestrictionVectorEncoder=void 0;var BitLength_js_1=require("../BitLength.js"),BooleanEncoder_js_1=require("./BooleanEncoder.js"),index_js_1=require("../../errors/index.js"),IntEncoder_js_1=require("./IntEncoder.js"),index_js_2=require("../../model/index.js"),PurposeRestrictionVectorEncoder=function(){function e(){}return e.encode=function(e){var n=IntEncoder_js_1.IntEncoder.encode(e.numRestrictions,BitLength_js_1.BitLength.numRestrictions);return e.isEmpty()||e.getRestrictions().forEach((function(t){n+=IntEncoder_js_1.IntEncoder.encode(t.purposeId,BitLength_js_1.BitLength.purposeId),n+=IntEncoder_js_1.IntEncoder.encode(t.restrictionType,BitLength_js_1.BitLength.restrictionType);for(var r=e.getVendors(t),o=r.length,i=0,s=0,d="",_=function(n){var t=r[n];0===s&&(i++,s=t);var _=r[o-1],c=e.gvl.vendorIds;if(n===o-1||r[n+1]>function(e){for(;++e<=_&&!c.has(e););return e}(t)){var B=!(t===s);d+=BooleanEncoder_js_1.BooleanEncoder.encode(B),d+=IntEncoder_js_1.IntEncoder.encode(s,BitLength_js_1.BitLength.vendorId),B&&(d+=IntEncoder_js_1.IntEncoder.encode(t,BitLength_js_1.BitLength.vendorId)),s=0}},c=0;c<o;c++)_(c);n+=IntEncoder_js_1.IntEncoder.encode(i,BitLength_js_1.BitLength.numEntries),n+=d})),n},e.decode=function(e){var n=0,t=new index_js_2.PurposeRestrictionVector,r=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.numRestrictions),BitLength_js_1.BitLength.numRestrictions);n+=BitLength_js_1.BitLength.numRestrictions;for(var o=0;o<r;o++){var i=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.purposeId),BitLength_js_1.BitLength.purposeId);n+=BitLength_js_1.BitLength.purposeId;var s=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.restrictionType),BitLength_js_1.BitLength.restrictionType);n+=BitLength_js_1.BitLength.restrictionType;var d=new index_js_2.PurposeRestriction(i,s),_=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.numEntries),BitLength_js_1.BitLength.numEntries);n+=BitLength_js_1.BitLength.numEntries;for(var c=0;c<_;c++){var B=BooleanEncoder_js_1.BooleanEncoder.decode(e.substr(n,BitLength_js_1.BitLength.anyBoolean));n+=BitLength_js_1.BitLength.anyBoolean;var g=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.vendorId),BitLength_js_1.BitLength.vendorId);if(n+=BitLength_js_1.BitLength.vendorId,B){var h=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.vendorId),BitLength_js_1.BitLength.vendorId);if(n+=BitLength_js_1.BitLength.vendorId,h<g)throw new index_js_1.DecodingError("Invalid RangeEntry: endVendorId ".concat(h," is less than ").concat(g));for(var L=g;L<=h;L++)t.add(L,d)}else t.add(g,d)}}return t.bitLength=n,t},e}();exports.PurposeRestrictionVectorEncoder=PurposeRestrictionVectorEncoder;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.PurposeRestrictionVectorEncoder=void 0;var BitLength_js_1=require("../BitLength.js"),BooleanEncoder_js_1=require("./BooleanEncoder.js"),index_js_1=require("../../errors/index.js"),IntEncoder_js_1=require("./IntEncoder.js"),index_js_2=require("../../model/index.js"),PurposeRestrictionVectorEncoder=function(){function e(){}return e.encode=function(e){var n=IntEncoder_js_1.IntEncoder.encode(e.numRestrictions,BitLength_js_1.BitLength.numRestrictions);if(!e.isEmpty()){var t=Array.from(e.gvl.vendorIds),r=function(e,n){var r=t.indexOf(e);return t.indexOf(n)-r>1};e.getRestrictions().forEach((function(t){n+=IntEncoder_js_1.IntEncoder.encode(t.purposeId,BitLength_js_1.BitLength.purposeId),n+=IntEncoder_js_1.IntEncoder.encode(t.restrictionType,BitLength_js_1.BitLength.restrictionType);for(var o=e.getVendors(t),i=o.length,s=0,d=0,_="",c=0;c<i;c++){var g=o[c];if(0===d&&(s++,d=g),c===i-1||r(g,o[c+1])){var B=!(g===d);_+=BooleanEncoder_js_1.BooleanEncoder.encode(B),_+=IntEncoder_js_1.IntEncoder.encode(d,BitLength_js_1.BitLength.vendorId),B&&(_+=IntEncoder_js_1.IntEncoder.encode(g,BitLength_js_1.BitLength.vendorId)),d=0}}n+=IntEncoder_js_1.IntEncoder.encode(s,BitLength_js_1.BitLength.numEntries),n+=_}))}return n},e.decode=function(e){var n=0,t=new index_js_2.PurposeRestrictionVector,r=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.numRestrictions),BitLength_js_1.BitLength.numRestrictions);n+=BitLength_js_1.BitLength.numRestrictions;for(var o=0;o<r;o++){var i=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.purposeId),BitLength_js_1.BitLength.purposeId);n+=BitLength_js_1.BitLength.purposeId;var s=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.restrictionType),BitLength_js_1.BitLength.restrictionType);n+=BitLength_js_1.BitLength.restrictionType;var d=new index_js_2.PurposeRestriction(i,s),_=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.numEntries),BitLength_js_1.BitLength.numEntries);n+=BitLength_js_1.BitLength.numEntries;for(var c=function(r){var o=BooleanEncoder_js_1.BooleanEncoder.decode(e.substr(n,BitLength_js_1.BitLength.anyBoolean));n+=BitLength_js_1.BitLength.anyBoolean;var i=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.vendorId),BitLength_js_1.BitLength.vendorId);if(n+=BitLength_js_1.BitLength.vendorId,o){var s=IntEncoder_js_1.IntEncoder.decode(e.substr(n,BitLength_js_1.BitLength.vendorId),BitLength_js_1.BitLength.vendorId);if(n+=BitLength_js_1.BitLength.vendorId,s<i)throw new index_js_1.DecodingError("Invalid RangeEntry: endVendorId ".concat(s," is less than ").concat(i));var _=Array.from({length:s-i+1},(function(e,n){return i+n}));t.restrictPurposeToLegalBasis(d,_)}else t.restrictPurposeToLegalBasis(d,[i])},g=0;g<_;g++)c()}return t.bitLength=n,t},e}();exports.PurposeRestrictionVectorEncoder=PurposeRestrictionVectorEncoder;
@@ -11,8 +11,6 @@ export declare class PurposeRestrictionVector extends Cloneable<PurposeRestricti
11
11
  /**
12
12
  * a map indexed by a string which will be a 'hash' of the purpose and
13
13
  * restriction type.
14
- *
15
- * Using a BST to keep vendors in a sorted order for encoding later
16
14
  */
17
15
  private map;
18
16
  private gvl_;
@@ -30,9 +28,10 @@ export declare class PurposeRestrictionVector extends Cloneable<PurposeRestricti
30
28
  * restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
31
29
  *
32
30
  * @param {PurposeRestriction} purposeRestriction
31
+ * @param {number[]|null|undefined} vendorsIds
33
32
  * @return {void}
34
33
  */
35
- restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction): void;
34
+ restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction, vendorsIds?: number[]): void;
36
35
  /**
37
36
  * getVendors - returns array of vendor ids optionally narrowed by a given
38
37
  * Purpose Restriction. If no purpose restriction is passed then all vendor
@@ -1 +1 @@
1
- "use strict";var __extends=this&&this.__extends||function(){var e=function(t,r){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])})(t,r)};return function(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function o(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}}(),__values=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],o=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&o>=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},__read=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var o,n,i=r.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(o=i.next()).done;)s.push(o.value)}catch(e){n={error:e}}finally{try{o&&!o.done&&(r=i.return)&&r.call(i)}finally{if(n)throw n.error}}return s},__spreadArray=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var o,n=0,i=t.length;n<i;n++)!o&&n in t||(o||(o=Array.prototype.slice.call(t,0,n)),o[n]=t[n]);return e.concat(o||Array.prototype.slice.call(t))};Object.defineProperty(exports,"__esModule",{value:!0}),exports.PurposeRestrictionVector=void 0;var PurposeRestriction_js_1=require("./PurposeRestriction.js"),BinarySearchTree_js_1=require("./BinarySearchTree.js"),RestrictionType_js_1=require("./RestrictionType.js"),Cloneable_js_1=require("../Cloneable.js"),PurposeRestrictionVector=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.bitLength=0,t.map=new Map,t}return __extends(t,e),t.prototype.has=function(e){return this.map.has(e)},t.prototype.isOkToHave=function(e,t,r){var o,n=!0;if(null===(o=this.gvl)||void 0===o?void 0:o.vendors){var i=this.gvl.vendors[r];if(i)if(e===RestrictionType_js_1.RestrictionType.NOT_ALLOWED)n=i.legIntPurposes.includes(t)||i.purposes.includes(t);else if(i.flexiblePurposes.length)switch(e){case RestrictionType_js_1.RestrictionType.REQUIRE_CONSENT:n=i.flexiblePurposes.includes(t)&&i.legIntPurposes.includes(t);break;case RestrictionType_js_1.RestrictionType.REQUIRE_LI:n=i.flexiblePurposes.includes(t)&&i.purposes.includes(t)}else n=!1;else n=!1}return n},t.prototype.add=function(e,t){if(this.isOkToHave(t.restrictionType,t.purposeId,e)){var r=t.hash;this.has(r)||(this.map.set(r,new BinarySearchTree_js_1.BinarySearchTree),this.bitLength=0),this.map.get(r).add(e)}},t.prototype.restrictPurposeToLegalBasis=function(e){for(var t=this.gvl.vendorIds,r=e.hash,o=function(){var e,r,o;try{for(var n=__values(t),i=n.next();!i.done;i=n.next())o=i.value}catch(t){e={error:t}}finally{try{i&&!i.done&&(r=n.return)&&r.call(n)}finally{if(e)throw e.error}}return o}(),n=__spreadArray([],__read(Array(o).keys()),!1).map((function(e){return e+1})),i=1;i<=o;i++)this.has(r)||(this.map.set(r,BinarySearchTree_js_1.BinarySearchTree.build(n)),this.bitLength=0),this.map.get(r).add(i)},t.prototype.getVendors=function(e){var t=[];if(e){var r=e.hash;this.has(r)&&(t=this.map.get(r).get())}else{var o=new Set;this.map.forEach((function(e){e.get().forEach((function(e){o.add(e)}))})),t=Array.from(o)}return t},t.prototype.getRestrictionType=function(e,t){var r;return this.getRestrictions(e).forEach((function(e){e.purposeId===t&&(void 0===r||r>e.restrictionType)&&(r=e.restrictionType)})),r},t.prototype.vendorHasRestriction=function(e,t){for(var r=!1,o=this.getRestrictions(e),n=0;n<o.length&&!r;n++)r=t.isSameAs(o[n]);return r},t.prototype.getMaxVendorId=function(){var e=0;return this.map.forEach((function(t){e=Math.max(t.max(),e)})),e},t.prototype.getRestrictions=function(e){var t=[];return this.map.forEach((function(r,o){e?r.contains(e)&&t.push(PurposeRestriction_js_1.PurposeRestriction.unHash(o)):t.push(PurposeRestriction_js_1.PurposeRestriction.unHash(o))})),t},t.prototype.getPurposes=function(){var e=new Set;return this.map.forEach((function(t,r){e.add(PurposeRestriction_js_1.PurposeRestriction.unHash(r).purposeId)})),Array.from(e)},t.prototype.remove=function(e,t){var r=t.hash,o=this.map.get(r);o&&(o.remove(e),o.isEmpty()&&(this.map.delete(r),this.bitLength=0))},Object.defineProperty(t.prototype,"gvl",{get:function(){return this.gvl_},set:function(e){var t=this;this.gvl_||(this.gvl_=e,this.map.forEach((function(e,r){var o=PurposeRestriction_js_1.PurposeRestriction.unHash(r);e.get().forEach((function(r){t.isOkToHave(o.restrictionType,o.purposeId,r)||e.remove(r)}))})))},enumerable:!1,configurable:!0}),t.prototype.isEmpty=function(){return 0===this.map.size},Object.defineProperty(t.prototype,"numRestrictions",{get:function(){return this.map.size},enumerable:!1,configurable:!0}),t}(Cloneable_js_1.Cloneable);exports.PurposeRestrictionVector=PurposeRestrictionVector;
1
+ "use strict";var __extends=this&&this.__extends||function(){var t=function(e,r){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(e,r)};return function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function o(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}}(),__values=this&&this.__values||function(t){var e="function"==typeof Symbol&&Symbol.iterator,r=e&&t[e],o=0;if(r)return r.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&o>=t.length&&(t=void 0),{value:t&&t[o++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(exports,"__esModule",{value:!0}),exports.PurposeRestrictionVector=void 0;var PurposeRestriction_js_1=require("./PurposeRestriction.js"),RestrictionType_js_1=require("./RestrictionType.js"),Cloneable_js_1=require("../Cloneable.js"),PurposeRestrictionVector=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.bitLength=0,e.map=new Map,e}return __extends(e,t),e.prototype.has=function(t){return this.map.has(t)},e.prototype.isOkToHave=function(t,e,r){var o,i=!0;if(null===(o=this.gvl)||void 0===o?void 0:o.vendors){var n=this.gvl.vendors[r];if(n)if(t===RestrictionType_js_1.RestrictionType.NOT_ALLOWED)i=n.legIntPurposes.includes(e)||n.purposes.includes(e);else if(n.flexiblePurposes.length)switch(t){case RestrictionType_js_1.RestrictionType.REQUIRE_CONSENT:i=n.flexiblePurposes.includes(e)&&n.legIntPurposes.includes(e);break;case RestrictionType_js_1.RestrictionType.REQUIRE_LI:i=n.flexiblePurposes.includes(e)&&n.purposes.includes(e)}else i=!1;else i=!1}return i},e.prototype.add=function(t,e){if(this.isOkToHave(e.restrictionType,e.purposeId,t)){var r=e.hash;this.has(r)||(this.map.set(r,new Set),this.bitLength=0),this.map.get(r).add(t)}},e.prototype.restrictPurposeToLegalBasis=function(t,e){var r,o;void 0===e&&(e=Array.from(this.gvl.vendorIds));var i=t.hash;if(this.has(i)){var n=this.map.get(i);try{for(var s=__values(e),a=s.next();!a.done;a=s.next()){var u=a.value;n.add(u)}}catch(t){r={error:t}}finally{try{a&&!a.done&&(o=s.return)&&o.call(s)}finally{if(r)throw r.error}}}else this.map.set(i,new Set(e)),this.bitLength=0},e.prototype.getVendors=function(t){var e=[];if(t){var r=t.hash;this.has(r)&&(e=Array.from(this.map.get(r)))}else{var o=new Set;this.map.forEach((function(t){Array.from(t).forEach((function(t){o.add(t)}))})),e=Array.from(o)}return e.sort((function(t,e){return t-e}))},e.prototype.getRestrictionType=function(t,e){var r;return this.getRestrictions(t).forEach((function(t){t.purposeId===e&&(void 0===r||r>t.restrictionType)&&(r=t.restrictionType)})),r},e.prototype.vendorHasRestriction=function(t,e){for(var r=!1,o=this.getRestrictions(t),i=0;i<o.length&&!r;i++)r=e.isSameAs(o[i]);return r},e.prototype.getMaxVendorId=function(){var t=0;return this.map.forEach((function(e){var r=Array.from(e);t=Math.max(r[r.length-1],t)})),t},e.prototype.getRestrictions=function(t){var e=[];return this.map.forEach((function(r,o){t?r.has(t)&&e.push(PurposeRestriction_js_1.PurposeRestriction.unHash(o)):e.push(PurposeRestriction_js_1.PurposeRestriction.unHash(o))})),e},e.prototype.getPurposes=function(){var t=new Set;return this.map.forEach((function(e,r){t.add(PurposeRestriction_js_1.PurposeRestriction.unHash(r).purposeId)})),Array.from(t)},e.prototype.remove=function(t,e){var r=e.hash,o=this.map.get(r);o&&(o.delete(t),0==o.size&&(this.map.delete(r),this.bitLength=0))},Object.defineProperty(e.prototype,"gvl",{get:function(){return this.gvl_},set:function(t){var e=this;this.gvl_||(this.gvl_=t,this.map.forEach((function(t,r){var o=PurposeRestriction_js_1.PurposeRestriction.unHash(r);Array.from(t).forEach((function(r){e.isOkToHave(o.restrictionType,o.purposeId,r)||t.delete(r)}))})))},enumerable:!1,configurable:!0}),e.prototype.isEmpty=function(){return 0===this.map.size},Object.defineProperty(e.prototype,"numRestrictions",{get:function(){return this.map.size},enumerable:!1,configurable:!0}),e}(Cloneable_js_1.Cloneable);exports.PurposeRestrictionVector=PurposeRestrictionVector;
@@ -1,4 +1,3 @@
1
- export * from './BinarySearchTree.js';
2
1
  export * from './ConsentLanguages.js';
3
2
  export * from './Fields.js';
4
3
  export * from './IntMap.js';
@@ -1 +1 @@
1
- "use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,r,t,o){void 0===o&&(o=t),Object.defineProperty(e,o,{enumerable:!0,get:function(){return r[t]}})}:function(e,r,t,o){void 0===o&&(o=t),e[o]=r[t]}),__exportStar=this&&this.__exportStar||function(e,r){for(var t in e)"default"===t||Object.prototype.hasOwnProperty.call(r,t)||__createBinding(r,e,t)};Object.defineProperty(exports,"__esModule",{value:!0}),__exportStar(require("./BinarySearchTree.js"),exports),__exportStar(require("./ConsentLanguages.js"),exports),__exportStar(require("./Fields.js"),exports),__exportStar(require("./IntMap.js"),exports),__exportStar(require("./KeyMap.js"),exports),__exportStar(require("./PurposeRestriction.js"),exports),__exportStar(require("./PurposeRestrictionVector.js"),exports),__exportStar(require("./DeviceDisclosureStorageAccessType.js"),exports),__exportStar(require("./DeviceDisclosure.js"),exports),__exportStar(require("./RestrictionType.js"),exports),__exportStar(require("./Segment.js"),exports),__exportStar(require("./SegmentIDs.js"),exports),__exportStar(require("./Vector.js"),exports),__exportStar(require("./gvl/index.js"),exports);
1
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,r,t,o){void 0===o&&(o=t),Object.defineProperty(e,o,{enumerable:!0,get:function(){return r[t]}})}:function(e,r,t,o){void 0===o&&(o=t),e[o]=r[t]}),__exportStar=this&&this.__exportStar||function(e,r){for(var t in e)"default"===t||Object.prototype.hasOwnProperty.call(r,t)||__createBinding(r,e,t)};Object.defineProperty(exports,"__esModule",{value:!0}),__exportStar(require("./ConsentLanguages.js"),exports),__exportStar(require("./Fields.js"),exports),__exportStar(require("./IntMap.js"),exports),__exportStar(require("./KeyMap.js"),exports),__exportStar(require("./PurposeRestriction.js"),exports),__exportStar(require("./PurposeRestrictionVector.js"),exports),__exportStar(require("./DeviceDisclosureStorageAccessType.js"),exports),__exportStar(require("./DeviceDisclosure.js"),exports),__exportStar(require("./RestrictionType.js"),exports),__exportStar(require("./Segment.js"),exports),__exportStar(require("./SegmentIDs.js"),exports),__exportStar(require("./Vector.js"),exports),__exportStar(require("./gvl/index.js"),exports);
@@ -9,6 +9,13 @@ export class PurposeRestrictionVectorEncoder {
9
9
  let bitString = IntEncoder.encode(prVector.numRestrictions, BitLength.numRestrictions);
10
10
  // if the vector is empty we'll just return a string with just the numRestricitons being 0
11
11
  if (!prVector.isEmpty()) {
12
+ const gvlVendorIds = Array.from(prVector.gvl.vendorIds);
13
+ const gvlHasVendorBetween = (vendorId, nextVendorId) => {
14
+ const firstIndex = gvlVendorIds.indexOf(vendorId);
15
+ const nextIndex = gvlVendorIds.indexOf(nextVendorId);
16
+ const res = nextIndex - firstIndex;
17
+ return res > 1;
18
+ };
12
19
  // create each restriction group
13
20
  prVector.getRestrictions().forEach((purpRestriction) => {
14
21
  // every restriction group has the purposeId and the restrictionType;
@@ -30,18 +37,10 @@ export class PurposeRestrictionVectorEncoder {
30
37
  numEntries++;
31
38
  startId = vendorId;
32
39
  }
33
- // we know that `len` is greater than zero because we entered the loop
34
- const lastVendorId = vendors[len - 1];
35
- const gvlVendorIds = prVector.gvl.vendorIds;
36
- const nextGvlVendor = (vendorId) => {
37
- while (++vendorId <= lastVendorId && !gvlVendorIds.has(vendorId)) {
38
- }
39
- return vendorId;
40
- };
41
40
  /**
42
41
  * either end of the loop or there are GVL vendor IDs before the next one
43
42
  */
44
- if (i === len - 1 || vendors[i + 1] > nextGvlVendor(vendorId)) {
43
+ if (i === len - 1 || gvlHasVendorBetween(vendorId, vendors[i + 1])) {
45
44
  /**
46
45
  * it's a range entry if we've got something other than the start
47
46
  * ID
@@ -94,12 +93,12 @@ export class PurposeRestrictionVectorEncoder {
94
93
  if (endVendorId < startOrOnlyVendorId) {
95
94
  throw new DecodingError(`Invalid RangeEntry: endVendorId ${endVendorId} is less than ${startOrOnlyVendorId}`);
96
95
  }
97
- for (let k = startOrOnlyVendorId; k <= endVendorId; k++) {
98
- vector.add(k, purposeRestriction);
99
- }
96
+ // required to preserve the default behavior (includes also vendors ids that doesn't exist)
97
+ const vendorIds = Array.from({ length: endVendorId - startOrOnlyVendorId + 1 }, (_, index) => startOrOnlyVendorId + index);
98
+ vector.restrictPurposeToLegalBasis(purposeRestriction, vendorIds);
100
99
  }
101
100
  else {
102
- vector.add(startOrOnlyVendorId, purposeRestriction);
101
+ vector.restrictPurposeToLegalBasis(purposeRestriction, [startOrOnlyVendorId]);
103
102
  }
104
103
  }
105
104
  }
@@ -11,8 +11,6 @@ export declare class PurposeRestrictionVector extends Cloneable<PurposeRestricti
11
11
  /**
12
12
  * a map indexed by a string which will be a 'hash' of the purpose and
13
13
  * restriction type.
14
- *
15
- * Using a BST to keep vendors in a sorted order for encoding later
16
14
  */
17
15
  private map;
18
16
  private gvl_;
@@ -30,9 +28,10 @@ export declare class PurposeRestrictionVector extends Cloneable<PurposeRestricti
30
28
  * restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
31
29
  *
32
30
  * @param {PurposeRestriction} purposeRestriction
31
+ * @param {number[]|null|undefined} vendorsIds
33
32
  * @return {void}
34
33
  */
35
- restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction): void;
34
+ restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction, vendorsIds?: number[]): void;
36
35
  /**
37
36
  * getVendors - returns array of vendor ids optionally narrowed by a given
38
37
  * Purpose Restriction. If no purpose restriction is passed then all vendor
@@ -1,5 +1,4 @@
1
1
  import { PurposeRestriction } from './PurposeRestriction.js';
2
- import { BinarySearchTree } from './BinarySearchTree.js';
3
2
  import { RestrictionType } from './RestrictionType.js';
4
3
  import { Cloneable } from '../Cloneable.js';
5
4
  export class PurposeRestrictionVector extends Cloneable {
@@ -11,8 +10,6 @@ export class PurposeRestrictionVector extends Cloneable {
11
10
  /**
12
11
  * a map indexed by a string which will be a 'hash' of the purpose and
13
12
  * restriction type.
14
- *
15
- * Using a BST to keep vendors in a sorted order for encoding later
16
13
  */
17
14
  map = new Map();
18
15
  gvl_;
@@ -81,7 +78,7 @@ export class PurposeRestrictionVector extends Cloneable {
81
78
  if (this.isOkToHave(purposeRestriction.restrictionType, purposeRestriction.purposeId, vendorId)) {
82
79
  const hash = purposeRestriction.hash;
83
80
  if (!this.has(hash)) {
84
- this.map.set(hash, new BinarySearchTree());
81
+ this.map.set(hash, new Set());
85
82
  this.bitLength = 0;
86
83
  }
87
84
  /**
@@ -96,32 +93,25 @@ export class PurposeRestrictionVector extends Cloneable {
96
93
  * restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
97
94
  *
98
95
  * @param {PurposeRestriction} purposeRestriction
96
+ * @param {number[]|null|undefined} vendorsIds
99
97
  * @return {void}
100
98
  */
101
- restrictPurposeToLegalBasis(purposeRestriction) {
102
- const vendors = this.gvl.vendorIds;
99
+ restrictPurposeToLegalBasis(purposeRestriction, vendorsIds = Array.from(this.gvl.vendorIds)) {
103
100
  const hash = purposeRestriction.hash;
104
- const lastEntry = (function () {
105
- let value;
106
- for (value of vendors)
107
- ;
108
- return value;
109
- })();
110
- /**
111
- * Create an ordered array of vendor IDs from `1` (the minimum value for Vendor ID) to `lastEntry`
112
- */
113
- const values = [...Array(lastEntry).keys()].map((i) => i + 1);
114
- for (let i = 1; i <= lastEntry; i++) {
115
- if (!this.has(hash)) {
116
- this.map.set(hash, BinarySearchTree.build(values)); // use static method `build` to create a `BST` from the ordered array of IDs
117
- this.bitLength = 0;
101
+ if (!this.has(hash)) {
102
+ this.map.set(hash, new Set(vendorsIds));
103
+ this.bitLength = 0;
104
+ }
105
+ else {
106
+ const currentMap = this.map.get(hash);
107
+ for (const vendorId of vendorsIds) {
108
+ /**
109
+ * Previously I had a check here to remove a duplicate value, but because
110
+ * we're using a tree the value is guaranteed to be unique so there is no
111
+ * need to add an additional de-duplication here.
112
+ */
113
+ currentMap.add(vendorId);
118
114
  }
119
- /**
120
- * Previously I had a check here to remove a duplicate value, but because
121
- * we're using a tree the value is guaranteed to be unique so there is no
122
- * need to add an additional de-duplication here.
123
- */
124
- this.map.get(hash).add(i);
125
115
  }
126
116
  }
127
117
  /**
@@ -139,19 +129,19 @@ export class PurposeRestrictionVector extends Cloneable {
139
129
  if (purposeRestriction) {
140
130
  const hash = purposeRestriction.hash;
141
131
  if (this.has(hash)) {
142
- vendorIds = this.map.get(hash).get();
132
+ vendorIds = Array.from(this.map.get(hash));
143
133
  }
144
134
  }
145
135
  else {
146
136
  const vendorSet = new Set();
147
- this.map.forEach((bst) => {
148
- bst.get().forEach((vendorId) => {
137
+ this.map.forEach((vendorIds) => {
138
+ Array.from(vendorIds).forEach((vendorId) => {
149
139
  vendorSet.add(vendorId);
150
140
  });
151
141
  });
152
142
  vendorIds = Array.from(vendorSet);
153
143
  }
154
- return vendorIds;
144
+ return vendorIds.sort((a, b) => a - b);
155
145
  }
156
146
  getRestrictionType(vendorId, purposeId) {
157
147
  let rType;
@@ -188,29 +178,30 @@ export class PurposeRestrictionVector extends Cloneable {
188
178
  * @return {number} - maximum Vendor ID
189
179
  */
190
180
  getMaxVendorId() {
191
- let retr = 0;
192
- this.map.forEach((bst) => {
193
- retr = Math.max(bst.max(), retr);
181
+ let result = 0;
182
+ this.map.forEach((purposeRestrictionVendorIds) => {
183
+ const vendorIds = Array.from(purposeRestrictionVendorIds);
184
+ result = Math.max(vendorIds[vendorIds.length - 1], result);
194
185
  });
195
- return retr;
186
+ return result;
196
187
  }
197
188
  getRestrictions(vendorId) {
198
- const retr = [];
199
- this.map.forEach((bst, hash) => {
189
+ const result = [];
190
+ this.map.forEach((vendorIds, hash) => {
200
191
  if (vendorId) {
201
- if (bst.contains(vendorId)) {
202
- retr.push(PurposeRestriction.unHash(hash));
192
+ if (vendorIds.has(vendorId)) {
193
+ result.push(PurposeRestriction.unHash(hash));
203
194
  }
204
195
  }
205
196
  else {
206
- retr.push(PurposeRestriction.unHash(hash));
197
+ result.push(PurposeRestriction.unHash(hash));
207
198
  }
208
199
  });
209
- return retr;
200
+ return result;
210
201
  }
211
202
  getPurposes() {
212
203
  const purposeIds = new Set();
213
- this.map.forEach((bst, hash) => {
204
+ this.map.forEach((vendorIds, hash) => {
214
205
  purposeIds.add(PurposeRestriction.unHash(hash).purposeId);
215
206
  });
216
207
  return Array.from(purposeIds);
@@ -224,11 +215,11 @@ export class PurposeRestrictionVector extends Cloneable {
224
215
  */
225
216
  remove(vendorId, purposeRestriction) {
226
217
  const hash = purposeRestriction.hash;
227
- const bst = this.map.get(hash);
228
- if (bst) {
229
- bst.remove(vendorId);
218
+ const vendorIds = this.map.get(hash);
219
+ if (vendorIds) {
220
+ vendorIds.delete(vendorId);
230
221
  // if it's empty let's delete the key so it doesn't show up empty
231
- if (bst.isEmpty()) {
222
+ if (vendorIds.size == 0) {
232
223
  this.map.delete(hash);
233
224
  this.bitLength = 0;
234
225
  }
@@ -247,12 +238,12 @@ export class PurposeRestrictionVector extends Cloneable {
247
238
  * if we have restrictions set before the gvl is set then we'll have to
248
239
  * go through and remove some if they're not valid
249
240
  */
250
- this.map.forEach((bst, hash) => {
241
+ this.map.forEach((vendorIds, hash) => {
251
242
  const purposeRestriction = PurposeRestriction.unHash(hash);
252
- const vendors = bst.get();
243
+ const vendors = Array.from(vendorIds);
253
244
  vendors.forEach((vendorId) => {
254
245
  if (!this.isOkToHave(purposeRestriction.restrictionType, purposeRestriction.purposeId, vendorId)) {
255
- bst.remove(vendorId);
246
+ vendorIds.delete(vendorId);
256
247
  }
257
248
  });
258
249
  });
@@ -1,4 +1,3 @@
1
- export * from './BinarySearchTree.js';
2
1
  export * from './ConsentLanguages.js';
3
2
  export * from './Fields.js';
4
3
  export * from './IntMap.js';
@@ -1,4 +1,3 @@
1
- export * from './BinarySearchTree.js';
2
1
  export * from './ConsentLanguages.js';
3
2
  export * from './Fields.js';
4
3
  export * from './IntMap.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pubtech-ai/core",
3
- "version": "1.7.2",
3
+ "version": "2.0.1",
4
4
  "description": "Ensures consistent encoding and decoding of TC Signals for the iab. Transparency and Consent Framework (TCF).",
5
5
  "author": "Mayank Mishra <mayank@iabtechlab.com>",
6
6
  "homepage": "https://iabtcf.com/",
@@ -28,7 +28,7 @@
28
28
  "test-cov": "rm -rf coverage; nyc --reporter=html mocha"
29
29
  },
30
30
  "devDependencies": {
31
- "@pubtech-ai/testing": "1.7.2",
31
+ "@pubtech-ai/testing": "2.0.1",
32
32
  "@istanbuljs/nyc-config-typescript": "^0.1.3",
33
33
  "@types/sinon": "^10.0.11",
34
34
  "@types/sinon-chai": "3.2.8",
@@ -1,30 +0,0 @@
1
- import { Cloneable } from '../Cloneable.js';
2
- interface TreeNode {
3
- value: number;
4
- right: TreeNode | null;
5
- left: TreeNode | null;
6
- }
7
- declare type TreeNodeMaybe = TreeNode | null;
8
- export declare class BinarySearchTree extends Cloneable<BinarySearchTree> {
9
- private root;
10
- getRoot(): TreeNodeMaybe;
11
- isEmpty(): boolean;
12
- add(value: number): void;
13
- /**
14
- * performs Morris in-order traversal
15
- * @return {number[]} sorted array
16
- */
17
- get(): number[];
18
- contains(value: number): boolean;
19
- min(current?: TreeNodeMaybe): number;
20
- max(current?: TreeNodeMaybe): number;
21
- remove(value: number, current?: TreeNodeMaybe): void;
22
- /**
23
- * Build Binary Search Tree from the ordered number array.
24
- * The depth of the tree will be the `log2` of the array length.
25
- * @param {number[]} values number array in ascending order
26
- * @return {BinarySearchTree} Binary Search Tree
27
- */
28
- static build(values?: number[]): BinarySearchTree | null;
29
- }
30
- export {};
@@ -1 +0,0 @@
1
- "use strict";var __extends=this&&this.__extends||function(){var t=function(e,r){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(e,r)};return function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function o(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.BinarySearchTree=void 0;var Cloneable_js_1=require("../Cloneable.js"),BinarySearchTree=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.root=null,e}return __extends(e,t),e.prototype.getRoot=function(){return this.root},e.prototype.isEmpty=function(){return!this.root},e.prototype.add=function(t){var e,r={value:t,left:null,right:null};if(this.isEmpty())this.root=r;else for(e=this.root;;)if(t<e.value){if(null===e.left){e.left=r;break}e=e.left}else{if(!(t>e.value))break;if(null===e.right){e.right=r;break}e=e.right}},e.prototype.get=function(){for(var t=[],e=this.root;e;)if(e.left){for(var r=e.left;r.right&&r.right!=e;)r=r.right;r.right==e?(r.right=null,t.push(e.value),e=e.right):(r.right=e,e=e.left)}else t.push(e.value),e=e.right;return t},e.prototype.contains=function(t){for(var e=!1,r=this.root;r;){if(r.value===t){e=!0;break}t>r.value?r=r.right:t<r.value&&(r=r.left)}return e},e.prototype.min=function(t){var e;for(void 0===t&&(t=this.root);t;)t.left?t=t.left:(e=t.value,t=null);return e},e.prototype.max=function(t){var e;for(void 0===t&&(t=this.root);t;)t.right?t=t.right:(e=t.value,t=null);return e},e.prototype.remove=function(t,e){void 0===e&&(e=this.root);for(var r=null,o="left";e;)if(t<e.value)r=e,e=e.left,o="left";else if(t>e.value)r=e,e=e.right,o="right";else{if(e.left||e.right)if(e.left)if(e.right){var i=this.min(e.right);this.remove(i,e.right),e.value=i}else r?r[o]=e.left:this.root=e.left;else r?r[o]=e.right:this.root=e.right;else r?r[o]=null:this.root=null;e=null}},e.build=function(t){if(t&&0!==t.length){if(1===t.length)return(r=new e).add(t[0]),r;var r,o=t.length>>1;(r=new e).add(t[o]);var i=r.getRoot();if(i){if(o+1<t.length){var l=e.build(t.slice(o+1));i.right=l?l.getRoot():null}if(o-1>0){var n=e.build(t.slice(0,o-1));i.left=n?n.getRoot():null}}return r}return null},e}(Cloneable_js_1.Cloneable);exports.BinarySearchTree=BinarySearchTree;
@@ -1,30 +0,0 @@
1
- import { Cloneable } from '../Cloneable.js';
2
- interface TreeNode {
3
- value: number;
4
- right: TreeNode | null;
5
- left: TreeNode | null;
6
- }
7
- declare type TreeNodeMaybe = TreeNode | null;
8
- export declare class BinarySearchTree extends Cloneable<BinarySearchTree> {
9
- private root;
10
- getRoot(): TreeNodeMaybe;
11
- isEmpty(): boolean;
12
- add(value: number): void;
13
- /**
14
- * performs Morris in-order traversal
15
- * @return {number[]} sorted array
16
- */
17
- get(): number[];
18
- contains(value: number): boolean;
19
- min(current?: TreeNodeMaybe): number;
20
- max(current?: TreeNodeMaybe): number;
21
- remove(value: number, current?: TreeNodeMaybe): void;
22
- /**
23
- * Build Binary Search Tree from the ordered number array.
24
- * The depth of the tree will be the `log2` of the array length.
25
- * @param {number[]} values number array in ascending order
26
- * @return {BinarySearchTree} Binary Search Tree
27
- */
28
- static build(values?: number[]): BinarySearchTree | null;
29
- }
30
- export {};
@@ -1,267 +0,0 @@
1
- import { Cloneable } from '../Cloneable.js';
2
- export class BinarySearchTree extends Cloneable {
3
- root = null;
4
- getRoot() {
5
- return this.root;
6
- }
7
- isEmpty() {
8
- // if root is undefined or null then by definition this is empty
9
- return !(this.root);
10
- }
11
- add(value) {
12
- // create new node object
13
- const node = {
14
- value: value,
15
- left: null,
16
- right: null,
17
- };
18
- let current;
19
- // first item?
20
- if (this.isEmpty()) {
21
- this.root = node;
22
- }
23
- else {
24
- // start at the root
25
- current = this.root;
26
- // infinite loop, figure out where to put it
27
- while (true) {
28
- // if the value is less than current value; go left
29
- if (value < current.value) {
30
- // if it's empty, we can insert
31
- if (current.left === null) {
32
- // insert on the left
33
- current.left = node;
34
- // our work is done here
35
- break;
36
- }
37
- else {
38
- /**
39
- * if there's something there already, we'll reset the pointer and
40
- * wait for the next loop to do something ie. keep traversing
41
- */
42
- current = current.left;
43
- }
44
- }
45
- else if (value > current.value) {
46
- // if the value is greater than our current value; go right
47
- if (current.right === null) {
48
- // there's nothing to the right, so put it here
49
- current.right = node;
50
- break;
51
- }
52
- else {
53
- /**
54
- * if there's something there already, we'll reset the pointer and
55
- * wait for the next loop to do something ie. keep traversing
56
- */
57
- current = current.right;
58
- }
59
- }
60
- else {
61
- /**
62
- * If it's neither greater than the right or less than the right then
63
- * it is equal to the current nodes value. In that case we won't do
64
- * anything with it because we will only insert unique values.
65
- */
66
- break;
67
- }
68
- }
69
- }
70
- }
71
- /**
72
- * performs Morris in-order traversal
73
- * @return {number[]} sorted array
74
- */
75
- get() {
76
- const retr = [];
77
- let current = this.root;
78
- while (current) {
79
- if (!current.left) {
80
- retr.push(current.value); // if there is no left child, visit current node
81
- current = current.right; // then we go the right branch
82
- }
83
- else {
84
- // find the right most leaf of root.left node.
85
- let pre = current.left;
86
- // when pre.right == null, it means we go to the right most leaf
87
- // when pre.right == current, it means the right most leaf has been visited in the last round
88
- while (pre.right && pre.right != current) {
89
- pre = pre.right;
90
- }
91
- // this means the pre.right has been set, it's time to go to current node
92
- if (pre.right == current) {
93
- pre.right = null;
94
- // means the current node is pointed by left right most child
95
- // the left branch has been visited, it's time to push the current node
96
- retr.push(current.value);
97
- current = current.right;
98
- }
99
- else {
100
- // the fist time to visit the pre node, make its right child point to current node
101
- pre.right = current;
102
- current = current.left;
103
- }
104
- }
105
- }
106
- return retr;
107
- }
108
- contains(value) {
109
- let retr = false;
110
- let current = this.root;
111
- while (current) {
112
- if (current.value === value) {
113
- retr = true;
114
- break;
115
- }
116
- else if (value > current.value) {
117
- current = current.right;
118
- }
119
- else if (value < current.value) {
120
- current = current.left;
121
- }
122
- }
123
- return retr;
124
- }
125
- min(current = this.root) {
126
- let retr;
127
- while (current) {
128
- if (current.left) {
129
- current = current.left;
130
- }
131
- else {
132
- retr = current.value;
133
- current = null;
134
- }
135
- }
136
- return retr;
137
- }
138
- max(current = this.root) {
139
- let retr;
140
- while (current) {
141
- if (current.right) {
142
- current = current.right;
143
- }
144
- else {
145
- retr = current.value;
146
- current = null;
147
- }
148
- }
149
- return retr;
150
- }
151
- remove(value, current = this.root) {
152
- // we start at the root, so the parent is null
153
- let parent = null;
154
- let parentSide = 'left';
155
- while (current) {
156
- if (value < current.value) {
157
- // set our parent to the current value
158
- parent = current;
159
- // value is less than current value, so go left
160
- current = current.left;
161
- parentSide = 'left';
162
- }
163
- else if (value > current.value) {
164
- // set our parent to the current value
165
- parent = current;
166
- // value is greater than current value, so go right
167
- current = current.right;
168
- parentSide = 'right';
169
- }
170
- else {
171
- /**
172
- * if it's neither greater than or less than, then it's equal so BINGO!
173
- * we've found it
174
- *
175
- * If we have children, we've got to figure out what to do with
176
- * them once we are no longer around... Woah, code is like real
177
- * life...
178
- *
179
- * There are three cases we care about when it comes to this removal
180
- * process:
181
- *
182
- * 1. No children -- If not children we just delete an do nothing
183
- * else, no harm no foul.
184
- *
185
- * 2. One child -- Just link the parent's link to current to the
186
- * child.
187
- *
188
- * 3. Two children -- Find the minimum value from the right subtree
189
- * replace us with the minimum value and of course remove that
190
- * minimum value from the right stubtree
191
- */
192
- if (!current.left && !current.right) {
193
- // case 1 there are no children easy peasy lemon squeezy
194
- if (parent) {
195
- parent[parentSide] = null;
196
- }
197
- else {
198
- this.root = null;
199
- }
200
- }
201
- else if (!current.left) {
202
- // no left side only right, so link right
203
- if (parent) {
204
- parent[parentSide] = current.right;
205
- }
206
- else {
207
- this.root = current.right;
208
- }
209
- }
210
- else if (!current.right) {
211
- // no right side only left, so link left
212
- if (parent) {
213
- parent[parentSide] = current.left;
214
- }
215
- else {
216
- this.root = current.left;
217
- }
218
- }
219
- else {
220
- /**
221
- * case 3 just like real life, if you delete a parent the more kids
222
- * that parent has the more complicated things get... in this case we
223
- * have two children. We're gonna have to figure out who goes where.
224
- */
225
- const minVal = this.min(current.right);
226
- // little bit of recursion...
227
- this.remove(minVal, current.right);
228
- current.value = minVal;
229
- }
230
- current = null;
231
- }
232
- }
233
- }
234
- /**
235
- * Build Binary Search Tree from the ordered number array.
236
- * The depth of the tree will be the `log2` of the array length.
237
- * @param {number[]} values number array in ascending order
238
- * @return {BinarySearchTree} Binary Search Tree
239
- */
240
- static build(values) {
241
- if (!values || values.length === 0) {
242
- return null;
243
- }
244
- else if (values.length === 1) {
245
- const tree = new BinarySearchTree();
246
- tree.add(values[0]);
247
- return tree;
248
- }
249
- else {
250
- const rootIndex = values.length >> 1;
251
- const tree = new BinarySearchTree();
252
- tree.add(values[rootIndex]);
253
- const root = tree.getRoot();
254
- if (root) {
255
- if (rootIndex + 1 < values.length) {
256
- const rightTree = BinarySearchTree.build(values.slice(rootIndex + 1));
257
- root.right = rightTree ? rightTree.getRoot() : null;
258
- }
259
- if (rootIndex - 1 > 0) {
260
- const leftTree = BinarySearchTree.build(values.slice(0, rootIndex - 1));
261
- root.left = leftTree ? leftTree.getRoot() : null;
262
- }
263
- }
264
- return tree;
265
- }
266
- }
267
- }