@pubtech-ai/core 1.7.2 → 2.0.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/GVL.js +1 -1
- package/lib/cjs/encoder/field/PurposeRestrictionVectorEncoder.js +1 -1
- package/lib/cjs/model/PurposeRestrictionVector.d.ts +2 -3
- package/lib/cjs/model/PurposeRestrictionVector.js +1 -1
- package/lib/cjs/model/index.d.ts +0 -1
- package/lib/cjs/model/index.js +1 -1
- package/lib/mjs/GVL.js +17 -19
- package/lib/mjs/encoder/field/PurposeRestrictionVectorEncoder.js +12 -13
- package/lib/mjs/model/PurposeRestrictionVector.d.ts +2 -3
- package/lib/mjs/model/PurposeRestrictionVector.js +39 -48
- package/lib/mjs/model/index.d.ts +0 -1
- package/lib/mjs/model/index.js +0 -1
- package/package.json +2 -2
- package/lib/cjs/model/BinarySearchTree.d.ts +0 -30
- package/lib/cjs/model/BinarySearchTree.js +0 -1
- package/lib/mjs/model/BinarySearchTree.d.ts +0 -30
- package/lib/mjs/model/BinarySearchTree.js +0 -267
package/lib/cjs/GVL.js
CHANGED
|
@@ -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 n(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}}(),__awaiter=this&&this.__awaiter||function(e,t,r,n){return new(r||(r=Promise))((function(s,o){function i(e){try{u(n.next(e))}catch(e){o(e)}}function a(e){try{u(n.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?s(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,a)}u((n=n.apply(e,t||[])).next())}))},__generator=this&&this.__generator||function(e,t){var r,n,s,o,i={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;i;)try{if(r=1,n&&(s=2&o[0]?n.return:o[0]?n.throw||((s=n.return)&&s.call(n),0):n.next)&&!(s=s.call(n,o[1])).done)return s;switch(n=0,s&&(o=[2&o[0],s.value]),o[0]){case 0:case 1:s=o;break;case 4:return i.label++,{value:o[1],done:!1};case 5:i.label++,n=o[1],o=[0];continue;case 7:o=i.ops.pop(),i.trys.pop();continue;default:if(!(s=i.trys,(s=s.length>0&&s[s.length-1])||6!==o[0]&&2!==o[0])){i=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]<s[3])){i.label=o[1];break}if(6===o[0]&&i.label<s[1]){i.label=s[1],s=o;break}if(s&&i.label<s[2]){i.label=s[2],i.ops.push(o);break}s[2]&&i.ops.pop(),i.trys.pop();continue}o=t.call(e,i)}catch(e){o=[6,e],n=0}finally{r=s=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.GVL=void 0;var Cloneable_js_1=require("./Cloneable.js"),index_js_1=require("./errors/index.js"),Json_js_1=require("./Json.js"),index_js_2=require("./model/index.js"),GVL=function(e){function t(r){var n=e.call(this)||this;n.isReady_=!1,n.isLatest=!1;var s=t.baseUrl;if(n.lang_=t.DEFAULT_LANGUAGE,n.cacheLang_=t.DEFAULT_LANGUAGE,n.isVendorList(r))n.populate(r),n.readyPromise=Promise.resolve();else{if(!s)throw new index_js_1.GVLError("must specify GVL.baseUrl before loading GVL json");if(r>0){var o=r;t.CACHE.has(o)?(n.populate(t.CACHE.get(o)),n.readyPromise=Promise.resolve()):(s+=t.versionedFilename.replace("[VERSION]",String(o)),n.readyPromise=n.fetchJson(s))}else t.CACHE.has(t.LATEST_CACHE_KEY)?(n.populate(t.CACHE.get(t.LATEST_CACHE_KEY)),n.readyPromise=Promise.resolve()):(n.isLatest=!0,n.readyPromise=n.fetchJson(s+t.latestFilename))}return n}return __extends(t,e),Object.defineProperty(t,"baseUrl",{get:function(){return this.baseUrl_},set:function(e){if(/^https?:\/\/vendorlist\.consensu\.org\//.test(e))throw new index_js_1.GVLError("Invalid baseUrl! You may not pull directly from vendorlist.consensu.org and must provide your own cache");e.length>0&&"/"!==e[e.length-1]&&(e+="/"),this.baseUrl_=e},enumerable:!1,configurable:!0}),t.emptyLanguageCache=function(e){var r=!1;return null==e&&t.LANGUAGE_CACHE.size>0?(t.LANGUAGE_CACHE=new Map,r=!0):"string"==typeof e&&this.consentLanguages.has(e.toUpperCase())&&(t.LANGUAGE_CACHE.delete(e.toUpperCase()),r=!0),r},t.emptyCache=function(e){var r=!1;return Number.isInteger(e)&&e>=0?(t.CACHE.delete(e),r=!0):void 0===e&&(t.CACHE=new Map,r=!0),r},t.prototype.cacheLanguage=function(){t.LANGUAGE_CACHE.has(this.cacheLang_)||t.LANGUAGE_CACHE.set(this.cacheLang_,{purposes:this.purposes,specialPurposes:this.specialPurposes,features:this.features,specialFeatures:this.specialFeatures,stacks:this.stacks,dataCategories:this.dataCategories})},t.prototype.fetchJson=function(e){return __awaiter(this,void 0,void 0,(function(){var t,r;return __generator(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),t=this.populate,[4,Json_js_1.Json.fetch(e)];case 1:return t.apply(this,[n.sent()]),[3,3];case 2:throw r=n.sent(),new index_js_1.GVLError(r.message);case 3:return[2]}}))}))},t.prototype.getJson=function(){return JSON.parse(JSON.stringify({gvlSpecificationVersion:this.gvlSpecificationVersion,vendorListVersion:this.vendorListVersion,tcfPolicyVersion:this.tcfPolicyVersion,lastUpdated:this.lastUpdated,purposes:this.purposes,specialPurposes:this.specialPurposes,features:this.features,specialFeatures:this.specialFeatures,stacks:this.stacks,dataCategories:this.dataCategories,vendors:this.fullVendorList}))},t.prototype.changeLanguage=function(e){return __awaiter(this,void 0,void 0,(function(){var r,n,s,o,i,a;return __generator(this,(function(u){switch(u.label){case 0:r=e;try{r=t.consentLanguages.parseLanguage(e)}catch(e){throw new index_js_1.GVLError("Error during parsing the language: "+e.message)}if(n=e.toUpperCase(),
|
|
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 n(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}}(),__awaiter=this&&this.__awaiter||function(e,t,r,n){return new(r||(r=Promise))((function(s,o){function i(e){try{u(n.next(e))}catch(e){o(e)}}function a(e){try{u(n.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?s(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,a)}u((n=n.apply(e,t||[])).next())}))},__generator=this&&this.__generator||function(e,t){var r,n,s,o,i={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;i;)try{if(r=1,n&&(s=2&o[0]?n.return:o[0]?n.throw||((s=n.return)&&s.call(n),0):n.next)&&!(s=s.call(n,o[1])).done)return s;switch(n=0,s&&(o=[2&o[0],s.value]),o[0]){case 0:case 1:s=o;break;case 4:return i.label++,{value:o[1],done:!1};case 5:i.label++,n=o[1],o=[0];continue;case 7:o=i.ops.pop(),i.trys.pop();continue;default:if(!(s=i.trys,(s=s.length>0&&s[s.length-1])||6!==o[0]&&2!==o[0])){i=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]<s[3])){i.label=o[1];break}if(6===o[0]&&i.label<s[1]){i.label=s[1],s=o;break}if(s&&i.label<s[2]){i.label=s[2],i.ops.push(o);break}s[2]&&i.ops.pop(),i.trys.pop();continue}o=t.call(e,i)}catch(e){o=[6,e],n=0}finally{r=s=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.GVL=void 0;var Cloneable_js_1=require("./Cloneable.js"),index_js_1=require("./errors/index.js"),Json_js_1=require("./Json.js"),index_js_2=require("./model/index.js"),GVL=function(e){function t(r){var n=e.call(this)||this;n.isReady_=!1,n.isLatest=!1;var s=t.baseUrl;if(n.lang_=t.DEFAULT_LANGUAGE,n.cacheLang_=t.DEFAULT_LANGUAGE,n.isVendorList(r))n.populate(r),n.readyPromise=Promise.resolve();else{if(!s)throw new index_js_1.GVLError("must specify GVL.baseUrl before loading GVL json");if(r>0){var o=r;t.CACHE.has(o)?(n.populate(t.CACHE.get(o)),n.readyPromise=Promise.resolve()):(s+=t.versionedFilename.replace("[VERSION]",String(o)),n.readyPromise=n.fetchJson(s))}else t.CACHE.has(t.LATEST_CACHE_KEY)?(n.populate(t.CACHE.get(t.LATEST_CACHE_KEY)),n.readyPromise=Promise.resolve()):(n.isLatest=!0,n.readyPromise=n.fetchJson(s+t.latestFilename))}return n}return __extends(t,e),Object.defineProperty(t,"baseUrl",{get:function(){return this.baseUrl_},set:function(e){if(/^https?:\/\/vendorlist\.consensu\.org\//.test(e))throw new index_js_1.GVLError("Invalid baseUrl! You may not pull directly from vendorlist.consensu.org and must provide your own cache");e.length>0&&"/"!==e[e.length-1]&&(e+="/"),this.baseUrl_=e},enumerable:!1,configurable:!0}),t.emptyLanguageCache=function(e){var r=!1;return null==e&&t.LANGUAGE_CACHE.size>0?(t.LANGUAGE_CACHE=new Map,r=!0):"string"==typeof e&&this.consentLanguages.has(e.toUpperCase())&&(t.LANGUAGE_CACHE.delete(e.toUpperCase()),r=!0),r},t.emptyCache=function(e){var r=!1;return Number.isInteger(e)&&e>=0?(t.CACHE.delete(e),r=!0):void 0===e&&(t.CACHE=new Map,r=!0),r},t.prototype.cacheLanguage=function(){t.LANGUAGE_CACHE.has(this.cacheLang_)||t.LANGUAGE_CACHE.set(this.cacheLang_,{purposes:this.purposes,specialPurposes:this.specialPurposes,features:this.features,specialFeatures:this.specialFeatures,stacks:this.stacks,dataCategories:this.dataCategories})},t.prototype.fetchJson=function(e){return __awaiter(this,void 0,void 0,(function(){var t,r;return __generator(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),t=this.populate,[4,Json_js_1.Json.fetch(e)];case 1:return t.apply(this,[n.sent()]),[3,3];case 2:throw r=n.sent(),new index_js_1.GVLError(r.message);case 3:return[2]}}))}))},t.prototype.getJson=function(){return JSON.parse(JSON.stringify({gvlSpecificationVersion:this.gvlSpecificationVersion,vendorListVersion:this.vendorListVersion,tcfPolicyVersion:this.tcfPolicyVersion,lastUpdated:this.lastUpdated,purposes:this.purposes,specialPurposes:this.specialPurposes,features:this.features,specialFeatures:this.specialFeatures,stacks:this.stacks,dataCategories:this.dataCategories,vendors:this.fullVendorList}))},t.prototype.changeLanguage=function(e){return __awaiter(this,void 0,void 0,(function(){var r,n,s,o,i,a;return __generator(this,(function(u){switch(u.label){case 0:r=e;try{r=t.consentLanguages.parseLanguage(e)}catch(e){throw new index_js_1.GVLError("Error during parsing the language: "+e.message)}if(n=e.toUpperCase(),this.lang_=r,!t.LANGUAGE_CACHE.has(n))return[3,1];for(o in s=t.LANGUAGE_CACHE.get(n))s.hasOwnProperty(o)&&(this[o]=s[o]);return[3,5];case 1:i=t.baseUrl+t.languageFilename.replace("[LANG]",this.lang_.toLowerCase()),u.label=2;case 2:return u.trys.push([2,4,,5]),[4,this.fetchJson(i)];case 3:return u.sent(),this.cacheLang_=n,this.cacheLanguage(),[3,5];case 4:throw a=u.sent(),new index_js_1.GVLError("unable to load language: "+a.message);case 5:return[2]}}))}))},Object.defineProperty(t.prototype,"language",{get:function(){return this.lang_},enumerable:!1,configurable:!0}),t.prototype.isVendorList=function(e){return void 0!==e&&void 0!==e.vendors},t.prototype.populate=function(e){this.purposes=e.purposes,this.specialPurposes=e.specialPurposes,this.features=e.features,this.specialFeatures=e.specialFeatures,this.stacks=e.stacks,this.dataCategories=e.dataCategories,this.isVendorList(e)&&(this.gvlSpecificationVersion=e.gvlSpecificationVersion,this.tcfPolicyVersion=e.tcfPolicyVersion,this.vendorListVersion=e.vendorListVersion,this.lastUpdated=e.lastUpdated,"string"==typeof this.lastUpdated&&(this.lastUpdated=new Date(this.lastUpdated)),this.vendors_=e.vendors,this.fullVendorList=e.vendors,this.mapVendors(),this.isReady_=!0,this.isLatest&&t.CACHE.set(t.LATEST_CACHE_KEY,this.getJson()),t.CACHE.has(this.vendorListVersion)||t.CACHE.set(this.vendorListVersion,this.getJson())),this.cacheLanguage()},t.prototype.mapVendors=function(e){var t=this;this.byPurposeVendorMap={},this.bySpecialPurposeVendorMap={},this.byFeatureVendorMap={},this.bySpecialFeatureVendorMap={},Object.keys(this.purposes).forEach((function(e){t.byPurposeVendorMap[e]={legInt:new Set,consent:new Set,flexible:new Set}})),Object.keys(this.specialPurposes).forEach((function(e){t.bySpecialPurposeVendorMap[e]=new Set})),Object.keys(this.features).forEach((function(e){t.byFeatureVendorMap[e]=new Set})),Object.keys(this.specialFeatures).forEach((function(e){t.bySpecialFeatureVendorMap[e]=new Set})),Array.isArray(e)||(e=Object.keys(this.fullVendorList).map((function(e){return+e}))),this.vendorIds=new Set(e),this.vendors_=e.reduce((function(e,r){var n=t.vendors_[String(r)];return n&&void 0===n.deletedDate&&(n.purposes.forEach((function(e){t.byPurposeVendorMap[String(e)].consent.add(r)})),n.specialPurposes.forEach((function(e){t.bySpecialPurposeVendorMap[String(e)].add(r)})),n.legIntPurposes.forEach((function(e){t.byPurposeVendorMap[String(e)].legInt.add(r)})),n.flexiblePurposes&&n.flexiblePurposes.forEach((function(e){t.byPurposeVendorMap[String(e)].flexible.add(r)})),n.features.forEach((function(e){t.byFeatureVendorMap[String(e)].add(r)})),n.specialFeatures.forEach((function(e){t.bySpecialFeatureVendorMap[String(e)].add(r)})),e[r]=n),e}),{})},t.prototype.getFilteredVendors=function(e,t,r,n){var s=this,o=e.charAt(0).toUpperCase()+e.slice(1),i={};return("purpose"===e&&r?this["by"+o+"VendorMap"][String(t)][r]:this["by"+(n?"Special":"")+o+"VendorMap"][String(t)]).forEach((function(e){i[String(e)]=s.vendors[String(e)]})),i},t.prototype.getVendorsWithConsentPurpose=function(e){return this.getFilteredVendors("purpose",e,"consent")},t.prototype.getVendorsWithLegIntPurpose=function(e){return this.getFilteredVendors("purpose",e,"legInt")},t.prototype.getVendorsWithFlexiblePurpose=function(e){return this.getFilteredVendors("purpose",e,"flexible")},t.prototype.getVendorsWithSpecialPurpose=function(e){return this.getFilteredVendors("purpose",e,void 0,!0)},t.prototype.getVendorsWithFeature=function(e){return this.getFilteredVendors("feature",e)},t.prototype.getVendorsWithSpecialFeature=function(e){return this.getFilteredVendors("feature",e,void 0,!0)},Object.defineProperty(t.prototype,"vendors",{get:function(){return this.vendors_},enumerable:!1,configurable:!0}),t.prototype.narrowVendorsTo=function(e){this.mapVendors(e)},Object.defineProperty(t.prototype,"isReady",{get:function(){return this.isReady_},enumerable:!1,configurable:!0}),t.prototype.clone=function(){var e=new t(this.getJson());return this.lang_!==t.DEFAULT_LANGUAGE&&e.changeLanguage(this.lang_),e},t.isInstanceOf=function(e){return"object"==typeof e&&"function"==typeof e.narrowVendorsTo},t.LANGUAGE_CACHE=new Map,t.CACHE=new Map,t.LATEST_CACHE_KEY=0,t.DEFAULT_LANGUAGE="EN",t.consentLanguages=new index_js_2.ConsentLanguages,t.latestFilename="vendor-list.json",t.versionedFilename="archives/vendor-list-v[VERSION].json",t.languageFilename="purposes-[LANG].json",t}(Cloneable_js_1.Cloneable);exports.GVL=GVL;
|
|
@@ -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);
|
|
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
|
|
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;
|
package/lib/cjs/model/index.d.ts
CHANGED
package/lib/cjs/model/index.js
CHANGED
|
@@ -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("./
|
|
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);
|
package/lib/mjs/GVL.js
CHANGED
|
@@ -336,27 +336,25 @@ export class GVL extends Cloneable {
|
|
|
336
336
|
throw new GVLError('Error during parsing the language: ' + e.message);
|
|
337
337
|
}
|
|
338
338
|
const cacheLang = lang.toUpperCase();
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
this[prop] = cached[prop];
|
|
346
|
-
}
|
|
339
|
+
this.lang_ = parsedLanguage;
|
|
340
|
+
if (GVL.LANGUAGE_CACHE.has(cacheLang)) {
|
|
341
|
+
const cached = GVL.LANGUAGE_CACHE.get(cacheLang);
|
|
342
|
+
for (const prop in cached) {
|
|
343
|
+
if (cached.hasOwnProperty(prop)) {
|
|
344
|
+
this[prop] = cached[prop];
|
|
347
345
|
}
|
|
348
346
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
// load Language specified
|
|
350
|
+
const url = GVL.baseUrl + GVL.languageFilename.replace('[LANG]', this.lang_.toLowerCase());
|
|
351
|
+
try {
|
|
352
|
+
await this.fetchJson(url);
|
|
353
|
+
this.cacheLang_ = cacheLang;
|
|
354
|
+
this.cacheLanguage();
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
throw new GVLError('unable to load language: ' + err.message);
|
|
360
358
|
}
|
|
361
359
|
}
|
|
362
360
|
}
|
|
@@ -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]
|
|
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
|
-
|
|
98
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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)
|
|
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((
|
|
148
|
-
|
|
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
|
|
192
|
-
this.map.forEach((
|
|
193
|
-
|
|
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
|
|
186
|
+
return result;
|
|
196
187
|
}
|
|
197
188
|
getRestrictions(vendorId) {
|
|
198
|
-
const
|
|
199
|
-
this.map.forEach((
|
|
189
|
+
const result = [];
|
|
190
|
+
this.map.forEach((vendorIds, hash) => {
|
|
200
191
|
if (vendorId) {
|
|
201
|
-
if (
|
|
202
|
-
|
|
192
|
+
if (vendorIds.has(vendorId)) {
|
|
193
|
+
result.push(PurposeRestriction.unHash(hash));
|
|
203
194
|
}
|
|
204
195
|
}
|
|
205
196
|
else {
|
|
206
|
-
|
|
197
|
+
result.push(PurposeRestriction.unHash(hash));
|
|
207
198
|
}
|
|
208
199
|
});
|
|
209
|
-
return
|
|
200
|
+
return result;
|
|
210
201
|
}
|
|
211
202
|
getPurposes() {
|
|
212
203
|
const purposeIds = new Set();
|
|
213
|
-
this.map.forEach((
|
|
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
|
|
228
|
-
if (
|
|
229
|
-
|
|
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 (
|
|
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((
|
|
241
|
+
this.map.forEach((vendorIds, hash) => {
|
|
251
242
|
const purposeRestriction = PurposeRestriction.unHash(hash);
|
|
252
|
-
const vendors =
|
|
243
|
+
const vendors = Array.from(vendorIds);
|
|
253
244
|
vendors.forEach((vendorId) => {
|
|
254
245
|
if (!this.isOkToHave(purposeRestriction.restrictionType, purposeRestriction.purposeId, vendorId)) {
|
|
255
|
-
|
|
246
|
+
vendorIds.delete(vendorId);
|
|
256
247
|
}
|
|
257
248
|
});
|
|
258
249
|
});
|
package/lib/mjs/model/index.d.ts
CHANGED
package/lib/mjs/model/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubtech-ai/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.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": "
|
|
31
|
+
"@pubtech-ai/testing": "2.0.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",
|
|
@@ -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
|
-
}
|