@pubtech-ai/core 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/encoder/field/PurposeRestrictionVectorEncoder.js +1 -1
- package/lib/cjs/model/PurposeRestrictionVector.d.ts +1 -2
- package/lib/cjs/model/PurposeRestrictionVector.js +1 -1
- package/lib/mjs/encoder/field/PurposeRestrictionVectorEncoder.js +12 -9
- package/lib/mjs/model/PurposeRestrictionVector.d.ts +1 -2
- package/lib/mjs/model/PurposeRestrictionVector.js +34 -31
- package/package.json +2 -2
|
@@ -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);if(!e.isEmpty()){var t=Array.from(e.gvl.vendorIds),r=function(e,n){var r=t.indexOf(e);
|
|
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);if(t.indexOf(n)-r>0){var o=t.indexOf(e+1);return t[o]}return e};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 B=o[c];if(0===d&&(s++,d=B),c===i-1||o[c+1]>r(B,o[i-1])){var g=!(B===d);_+=BooleanEncoder_js_1.BooleanEncoder.encode(g),_+=IntEncoder_js_1.IntEncoder.encode(d,BitLength_js_1.BitLength.vendorId),g&&(_+=IntEncoder_js_1.IntEncoder.encode(B,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=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;
|
|
@@ -28,10 +28,9 @@ export declare class PurposeRestrictionVector extends Cloneable<PurposeRestricti
|
|
|
28
28
|
* restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
|
|
29
29
|
*
|
|
30
30
|
* @param {PurposeRestriction} purposeRestriction
|
|
31
|
-
* @param {number[]|null|undefined} vendorsIds
|
|
32
31
|
* @return {void}
|
|
33
32
|
*/
|
|
34
|
-
restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction
|
|
33
|
+
restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction): void;
|
|
35
34
|
/**
|
|
36
35
|
* getVendors - returns array of vendor ids optionally narrowed by a given
|
|
37
36
|
* Purpose Restriction. If no purpose restriction is passed then all vendor
|
|
@@ -1 +1 @@
|
|
|
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)}}(),
|
|
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)}}(),__read=this&&this.__read||function(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var o,s,i=r.call(t),n=[];try{for(;(void 0===e||e-- >0)&&!(o=i.next()).done;)n.push(o.value)}catch(t){s={error:t}}finally{try{o&&!o.done&&(r=i.return)&&r.call(i)}finally{if(s)throw s.error}}return n},__spreadArray=this&&this.__spreadArray||function(t,e,r){if(r||2===arguments.length)for(var o,s=0,i=e.length;s<i;s++)!o&&s in e||(o||(o=Array.prototype.slice.call(e,0,s)),o[s]=e[s]);return t.concat(o||Array.prototype.slice.call(e))};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,s=!0;if(null===(o=this.gvl)||void 0===o?void 0:o.vendors){var i=this.gvl.vendors[r];if(i)if(t===RestrictionType_js_1.RestrictionType.NOT_ALLOWED)s=i.legIntPurposes.includes(e)||i.purposes.includes(e);else if(i.flexiblePurposes.length)switch(t){case RestrictionType_js_1.RestrictionType.REQUIRE_CONSENT:s=i.flexiblePurposes.includes(e)&&i.legIntPurposes.includes(e);break;case RestrictionType_js_1.RestrictionType.REQUIRE_LI:s=i.flexiblePurposes.includes(e)&&i.purposes.includes(e)}else s=!1;else s=!1}return s},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){var e=Array.from(this.gvl.vendorIds),r=t.hash,o=e[e.length-1],s=__spreadArray([],__read(Array(o).keys()),!1).map((function(t){return t+1}));if(this.has(r))for(var i=1;i<=o;i++)this.map.get(r).add(i);else this.map.set(r,new Set(s)),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){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),s=0;s<o.length&&!r;s++)r=e.isSameAs(o[s]);return r},e.prototype.getMaxVendorId=function(){var t=0;return this.map.forEach((function(e){t=Math.max(Array.from(e)[e.size-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;
|
|
@@ -10,11 +10,14 @@ export class PurposeRestrictionVectorEncoder {
|
|
|
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
12
|
const gvlVendorIds = Array.from(prVector.gvl.vendorIds);
|
|
13
|
-
const
|
|
13
|
+
const nextGvlVendor = (vendorId, lastVendorId) => {
|
|
14
14
|
const firstIndex = gvlVendorIds.indexOf(vendorId);
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const lastIndex = gvlVendorIds.indexOf(lastVendorId);
|
|
16
|
+
if (lastIndex - firstIndex > 0) {
|
|
17
|
+
const nextIndex = gvlVendorIds.indexOf(vendorId + 1);
|
|
18
|
+
return gvlVendorIds[nextIndex];
|
|
19
|
+
}
|
|
20
|
+
return vendorId;
|
|
18
21
|
};
|
|
19
22
|
// create each restriction group
|
|
20
23
|
prVector.getRestrictions().forEach((purpRestriction) => {
|
|
@@ -40,7 +43,7 @@ export class PurposeRestrictionVectorEncoder {
|
|
|
40
43
|
/**
|
|
41
44
|
* either end of the loop or there are GVL vendor IDs before the next one
|
|
42
45
|
*/
|
|
43
|
-
if (i === len - 1 ||
|
|
46
|
+
if (i === len - 1 || vendors[i + 1] > nextGvlVendor(vendorId, vendors[len - 1])) {
|
|
44
47
|
/**
|
|
45
48
|
* it's a range entry if we've got something other than the start
|
|
46
49
|
* ID
|
|
@@ -93,12 +96,12 @@ export class PurposeRestrictionVectorEncoder {
|
|
|
93
96
|
if (endVendorId < startOrOnlyVendorId) {
|
|
94
97
|
throw new DecodingError(`Invalid RangeEntry: endVendorId ${endVendorId} is less than ${startOrOnlyVendorId}`);
|
|
95
98
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
for (let k = startOrOnlyVendorId; k <= endVendorId; k++) {
|
|
100
|
+
vector.add(k, purposeRestriction);
|
|
101
|
+
}
|
|
99
102
|
}
|
|
100
103
|
else {
|
|
101
|
-
vector.
|
|
104
|
+
vector.add(startOrOnlyVendorId, purposeRestriction);
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
}
|
|
@@ -28,10 +28,9 @@ export declare class PurposeRestrictionVector extends Cloneable<PurposeRestricti
|
|
|
28
28
|
* restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
|
|
29
29
|
*
|
|
30
30
|
* @param {PurposeRestriction} purposeRestriction
|
|
31
|
-
* @param {number[]|null|undefined} vendorsIds
|
|
32
31
|
* @return {void}
|
|
33
32
|
*/
|
|
34
|
-
restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction
|
|
33
|
+
restrictPurposeToLegalBasis(purposeRestriction: PurposeRestriction): void;
|
|
35
34
|
/**
|
|
36
35
|
* getVendors - returns array of vendor ids optionally narrowed by a given
|
|
37
36
|
* Purpose Restriction. If no purpose restriction is passed then all vendor
|
|
@@ -38,10 +38,10 @@ export class PurposeRestrictionVector extends Cloneable {
|
|
|
38
38
|
else if (vendor.flexiblePurposes.length) {
|
|
39
39
|
switch (restrictionType) {
|
|
40
40
|
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
* If the vendor has the purposeId in flexiblePurposes and it is
|
|
42
|
+
* listed as a legitimate interest purpose we can set the
|
|
43
|
+
* override to require consent.
|
|
44
|
+
*/
|
|
45
45
|
case RestrictionType.REQUIRE_CONSENT:
|
|
46
46
|
result = (vendor.flexiblePurposes.includes(purposeId) && vendor.legIntPurposes.includes(purposeId));
|
|
47
47
|
break;
|
|
@@ -93,24 +93,28 @@ export class PurposeRestrictionVector extends Cloneable {
|
|
|
93
93
|
* restrictPurposeToLegalBasis - adds all Vendors under a given Purpose Restriction
|
|
94
94
|
*
|
|
95
95
|
* @param {PurposeRestriction} purposeRestriction
|
|
96
|
-
* @param {number[]|null|undefined} vendorsIds
|
|
97
96
|
* @return {void}
|
|
98
97
|
*/
|
|
99
|
-
restrictPurposeToLegalBasis(purposeRestriction
|
|
98
|
+
restrictPurposeToLegalBasis(purposeRestriction) {
|
|
99
|
+
const vendors = Array.from(this.gvl.vendorIds);
|
|
100
100
|
const hash = purposeRestriction.hash;
|
|
101
|
+
const lastEntry = vendors[vendors.length - 1];
|
|
102
|
+
/**
|
|
103
|
+
* Create an ordered array of vendor IDs from `1` (the minimum value for Vendor ID) to `lastEntry`
|
|
104
|
+
*/
|
|
105
|
+
const values = [...Array(lastEntry).keys()].map((i) => i + 1);
|
|
101
106
|
if (!this.has(hash)) {
|
|
102
|
-
this.map.set(hash, new Set(
|
|
107
|
+
this.map.set(hash, new Set(values)); // use static method `build` to create a `BST` from the ordered array of IDs
|
|
103
108
|
this.bitLength = 0;
|
|
104
109
|
}
|
|
105
110
|
else {
|
|
106
|
-
|
|
107
|
-
for (const vendorId of vendorsIds) {
|
|
111
|
+
for (let i = 1; i <= lastEntry; i++) {
|
|
108
112
|
/**
|
|
109
113
|
* Previously I had a check here to remove a duplicate value, but because
|
|
110
114
|
* we're using a tree the value is guaranteed to be unique so there is no
|
|
111
115
|
* need to add an additional de-duplication here.
|
|
112
116
|
*/
|
|
113
|
-
|
|
117
|
+
this.map.get(hash).add(i);
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
}
|
|
@@ -134,8 +138,8 @@ export class PurposeRestrictionVector extends Cloneable {
|
|
|
134
138
|
}
|
|
135
139
|
else {
|
|
136
140
|
const vendorSet = new Set();
|
|
137
|
-
this.map.forEach((
|
|
138
|
-
|
|
141
|
+
this.map.forEach((set) => {
|
|
142
|
+
set.forEach((vendorId) => {
|
|
139
143
|
vendorSet.add(vendorId);
|
|
140
144
|
});
|
|
141
145
|
});
|
|
@@ -178,30 +182,29 @@ export class PurposeRestrictionVector extends Cloneable {
|
|
|
178
182
|
* @return {number} - maximum Vendor ID
|
|
179
183
|
*/
|
|
180
184
|
getMaxVendorId() {
|
|
181
|
-
let
|
|
182
|
-
this.map.forEach((
|
|
183
|
-
|
|
184
|
-
result = Math.max(vendorIds[vendorIds.length - 1], result);
|
|
185
|
+
let retr = 0;
|
|
186
|
+
this.map.forEach((set) => {
|
|
187
|
+
retr = Math.max(Array.from(set)[set.size - 1], retr);
|
|
185
188
|
});
|
|
186
|
-
return
|
|
189
|
+
return retr;
|
|
187
190
|
}
|
|
188
191
|
getRestrictions(vendorId) {
|
|
189
|
-
const
|
|
190
|
-
this.map.forEach((
|
|
192
|
+
const retr = [];
|
|
193
|
+
this.map.forEach((set, hash) => {
|
|
191
194
|
if (vendorId) {
|
|
192
|
-
if (
|
|
193
|
-
|
|
195
|
+
if (set.has(vendorId)) {
|
|
196
|
+
retr.push(PurposeRestriction.unHash(hash));
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
else {
|
|
197
|
-
|
|
200
|
+
retr.push(PurposeRestriction.unHash(hash));
|
|
198
201
|
}
|
|
199
202
|
});
|
|
200
|
-
return
|
|
203
|
+
return retr;
|
|
201
204
|
}
|
|
202
205
|
getPurposes() {
|
|
203
206
|
const purposeIds = new Set();
|
|
204
|
-
this.map.forEach((
|
|
207
|
+
this.map.forEach((set, hash) => {
|
|
205
208
|
purposeIds.add(PurposeRestriction.unHash(hash).purposeId);
|
|
206
209
|
});
|
|
207
210
|
return Array.from(purposeIds);
|
|
@@ -215,11 +218,11 @@ export class PurposeRestrictionVector extends Cloneable {
|
|
|
215
218
|
*/
|
|
216
219
|
remove(vendorId, purposeRestriction) {
|
|
217
220
|
const hash = purposeRestriction.hash;
|
|
218
|
-
const
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
+
const set = this.map.get(hash);
|
|
222
|
+
if (set) {
|
|
223
|
+
set.delete(vendorId);
|
|
221
224
|
// if it's empty let's delete the key so it doesn't show up empty
|
|
222
|
-
if (
|
|
225
|
+
if (set.size == 0) {
|
|
223
226
|
this.map.delete(hash);
|
|
224
227
|
this.bitLength = 0;
|
|
225
228
|
}
|
|
@@ -238,12 +241,12 @@ export class PurposeRestrictionVector extends Cloneable {
|
|
|
238
241
|
* if we have restrictions set before the gvl is set then we'll have to
|
|
239
242
|
* go through and remove some if they're not valid
|
|
240
243
|
*/
|
|
241
|
-
this.map.forEach((
|
|
244
|
+
this.map.forEach((set, hash) => {
|
|
242
245
|
const purposeRestriction = PurposeRestriction.unHash(hash);
|
|
243
|
-
const vendors = Array.from(
|
|
246
|
+
const vendors = Array.from(set);
|
|
244
247
|
vendors.forEach((vendorId) => {
|
|
245
248
|
if (!this.isOkToHave(purposeRestriction.restrictionType, purposeRestriction.purposeId, vendorId)) {
|
|
246
|
-
|
|
249
|
+
set.delete(vendorId);
|
|
247
250
|
}
|
|
248
251
|
});
|
|
249
252
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubtech-ai/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
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": "2.
|
|
31
|
+
"@pubtech-ai/testing": "2.2.0",
|
|
32
32
|
"@istanbuljs/nyc-config-typescript": "^0.1.3",
|
|
33
33
|
"@types/sinon": "^10.0.11",
|
|
34
34
|
"@types/sinon-chai": "3.2.8",
|