@pubtech-ai/core 1.6.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.
Files changed (237) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +527 -0
  3. package/lib/cjs/Cloneable.d.ts +27 -0
  4. package/lib/cjs/Cloneable.js +1 -0
  5. package/lib/cjs/GVL.d.ts +295 -0
  6. package/lib/cjs/GVL.js +1 -0
  7. package/lib/cjs/Json.d.ts +20 -0
  8. package/lib/cjs/Json.js +1 -0
  9. package/lib/cjs/TCModel.d.ts +337 -0
  10. package/lib/cjs/TCModel.js +1 -0
  11. package/lib/cjs/TCString.d.ts +27 -0
  12. package/lib/cjs/TCString.js +1 -0
  13. package/lib/cjs/encoder/Base64Url.d.ts +29 -0
  14. package/lib/cjs/encoder/Base64Url.js +1 -0
  15. package/lib/cjs/encoder/BitLength.d.ts +32 -0
  16. package/lib/cjs/encoder/BitLength.js +1 -0
  17. package/lib/cjs/encoder/EncodingOptions.d.ts +6 -0
  18. package/lib/cjs/encoder/EncodingOptions.js +1 -0
  19. package/lib/cjs/encoder/SegmentEncoder.d.ts +8 -0
  20. package/lib/cjs/encoder/SegmentEncoder.js +1 -0
  21. package/lib/cjs/encoder/SemanticPreEncoder.d.ts +6 -0
  22. package/lib/cjs/encoder/SemanticPreEncoder.js +1 -0
  23. package/lib/cjs/encoder/field/BooleanEncoder.d.ts +4 -0
  24. package/lib/cjs/encoder/field/BooleanEncoder.js +1 -0
  25. package/lib/cjs/encoder/field/DateEncoder.d.ts +4 -0
  26. package/lib/cjs/encoder/field/DateEncoder.js +1 -0
  27. package/lib/cjs/encoder/field/FieldEncoderMap.d.ts +1 -0
  28. package/lib/cjs/encoder/field/FieldEncoderMap.js +1 -0
  29. package/lib/cjs/encoder/field/FixedVectorEncoder.d.ts +5 -0
  30. package/lib/cjs/encoder/field/FixedVectorEncoder.js +1 -0
  31. package/lib/cjs/encoder/field/IntEncoder.d.ts +4 -0
  32. package/lib/cjs/encoder/field/IntEncoder.js +1 -0
  33. package/lib/cjs/encoder/field/LangEncoder.d.ts +4 -0
  34. package/lib/cjs/encoder/field/LangEncoder.js +1 -0
  35. package/lib/cjs/encoder/field/PurposeRestrictionVectorEncoder.d.ts +5 -0
  36. package/lib/cjs/encoder/field/PurposeRestrictionVectorEncoder.js +1 -0
  37. package/lib/cjs/encoder/field/VectorEncodingType.d.ts +4 -0
  38. package/lib/cjs/encoder/field/VectorEncodingType.js +1 -0
  39. package/lib/cjs/encoder/field/VendorVectorEncoder.d.ts +6 -0
  40. package/lib/cjs/encoder/field/VendorVectorEncoder.js +1 -0
  41. package/lib/cjs/encoder/field/index.d.ts +9 -0
  42. package/lib/cjs/encoder/field/index.js +1 -0
  43. package/lib/cjs/encoder/index.d.ts +7 -0
  44. package/lib/cjs/encoder/index.js +1 -0
  45. package/lib/cjs/encoder/sequence/FieldSequence.d.ts +5 -0
  46. package/lib/cjs/encoder/sequence/FieldSequence.js +1 -0
  47. package/lib/cjs/encoder/sequence/SegmentSequence.d.ts +9 -0
  48. package/lib/cjs/encoder/sequence/SegmentSequence.js +1 -0
  49. package/lib/cjs/encoder/sequence/SequenceVersionMap.d.ts +7 -0
  50. package/lib/cjs/encoder/sequence/SequenceVersionMap.js +1 -0
  51. package/lib/cjs/encoder/sequence/index.d.ts +3 -0
  52. package/lib/cjs/encoder/sequence/index.js +1 -0
  53. package/lib/cjs/errors/DecodingError.d.ts +15 -0
  54. package/lib/cjs/errors/DecodingError.js +1 -0
  55. package/lib/cjs/errors/EncodingError.d.ts +15 -0
  56. package/lib/cjs/errors/EncodingError.js +1 -0
  57. package/lib/cjs/errors/GVLError.d.ts +15 -0
  58. package/lib/cjs/errors/GVLError.js +1 -0
  59. package/lib/cjs/errors/TCModelError.d.ts +16 -0
  60. package/lib/cjs/errors/TCModelError.js +1 -0
  61. package/lib/cjs/errors/index.d.ts +4 -0
  62. package/lib/cjs/errors/index.js +1 -0
  63. package/lib/cjs/index.d.ts +8 -0
  64. package/lib/cjs/index.js +1 -0
  65. package/lib/cjs/model/BinarySearchTree.d.ts +30 -0
  66. package/lib/cjs/model/BinarySearchTree.js +1 -0
  67. package/lib/cjs/model/ConsentLanguages.d.ts +6 -0
  68. package/lib/cjs/model/ConsentLanguages.js +1 -0
  69. package/lib/cjs/model/DeviceDisclosure.d.ts +9 -0
  70. package/lib/cjs/model/DeviceDisclosure.js +1 -0
  71. package/lib/cjs/model/DeviceDisclosureStorageAccessType.d.ts +5 -0
  72. package/lib/cjs/model/DeviceDisclosureStorageAccessType.js +1 -0
  73. package/lib/cjs/model/Fields.d.ts +29 -0
  74. package/lib/cjs/model/Fields.js +1 -0
  75. package/lib/cjs/model/IntMap.d.ts +13 -0
  76. package/lib/cjs/model/IntMap.js +1 -0
  77. package/lib/cjs/model/KeyMap.d.ts +12 -0
  78. package/lib/cjs/model/KeyMap.js +1 -0
  79. package/lib/cjs/model/PurposeRestriction.d.ts +33 -0
  80. package/lib/cjs/model/PurposeRestriction.js +1 -0
  81. package/lib/cjs/model/PurposeRestrictionVector.d.ts +100 -0
  82. package/lib/cjs/model/PurposeRestrictionVector.js +1 -0
  83. package/lib/cjs/model/RestrictionType.d.ts +19 -0
  84. package/lib/cjs/model/RestrictionType.js +1 -0
  85. package/lib/cjs/model/Segment.d.ts +6 -0
  86. package/lib/cjs/model/Segment.js +1 -0
  87. package/lib/cjs/model/SegmentIDs.d.ts +12 -0
  88. package/lib/cjs/model/SegmentIDs.js +1 -0
  89. package/lib/cjs/model/Vector.d.ts +72 -0
  90. package/lib/cjs/model/Vector.js +1 -0
  91. package/lib/cjs/model/gvl/ByPurposeVendorMap.d.ts +7 -0
  92. package/lib/cjs/model/gvl/ByPurposeVendorMap.js +1 -0
  93. package/lib/cjs/model/gvl/DataCategory.d.ts +4 -0
  94. package/lib/cjs/model/gvl/DataCategory.js +1 -0
  95. package/lib/cjs/model/gvl/DataRetention.d.ts +6 -0
  96. package/lib/cjs/model/gvl/DataRetention.js +1 -0
  97. package/lib/cjs/model/gvl/Declarations.d.ts +13 -0
  98. package/lib/cjs/model/gvl/Declarations.js +1 -0
  99. package/lib/cjs/model/gvl/Feature.d.ts +5 -0
  100. package/lib/cjs/model/gvl/Feature.js +1 -0
  101. package/lib/cjs/model/gvl/GVLMapItem.d.ts +4 -0
  102. package/lib/cjs/model/gvl/GVLMapItem.js +1 -0
  103. package/lib/cjs/model/gvl/IDSetMap.d.ts +2 -0
  104. package/lib/cjs/model/gvl/IDSetMap.js +1 -0
  105. package/lib/cjs/model/gvl/Purpose.d.ts +5 -0
  106. package/lib/cjs/model/gvl/Purpose.js +1 -0
  107. package/lib/cjs/model/gvl/Stack.d.ts +6 -0
  108. package/lib/cjs/model/gvl/Stack.js +1 -0
  109. package/lib/cjs/model/gvl/Vendor.d.ts +24 -0
  110. package/lib/cjs/model/gvl/Vendor.js +1 -0
  111. package/lib/cjs/model/gvl/VendorList.d.ts +10 -0
  112. package/lib/cjs/model/gvl/VendorList.js +1 -0
  113. package/lib/cjs/model/gvl/VendorUrl.d.ts +5 -0
  114. package/lib/cjs/model/gvl/VendorUrl.js +1 -0
  115. package/lib/cjs/model/gvl/index.d.ts +10 -0
  116. package/lib/cjs/model/gvl/index.js +1 -0
  117. package/lib/cjs/model/index.d.ts +14 -0
  118. package/lib/cjs/model/index.js +1 -0
  119. package/lib/cjs/package.json +3 -0
  120. package/lib/mjs/Cloneable.d.ts +27 -0
  121. package/lib/mjs/Cloneable.js +76 -0
  122. package/lib/mjs/GVL.d.ts +295 -0
  123. package/lib/mjs/GVL.js +591 -0
  124. package/lib/mjs/Json.d.ts +20 -0
  125. package/lib/mjs/Json.js +74 -0
  126. package/lib/mjs/TCModel.d.ts +337 -0
  127. package/lib/mjs/TCModel.js +512 -0
  128. package/lib/mjs/TCString.d.ts +27 -0
  129. package/lib/mjs/TCString.js +71 -0
  130. package/lib/mjs/encoder/Base64Url.d.ts +29 -0
  131. package/lib/mjs/encoder/Base64Url.js +80 -0
  132. package/lib/mjs/encoder/BitLength.d.ts +32 -0
  133. package/lib/mjs/encoder/BitLength.js +32 -0
  134. package/lib/mjs/encoder/EncodingOptions.d.ts +6 -0
  135. package/lib/mjs/encoder/EncodingOptions.js +1 -0
  136. package/lib/mjs/encoder/SegmentEncoder.d.ts +8 -0
  137. package/lib/mjs/encoder/SegmentEncoder.js +106 -0
  138. package/lib/mjs/encoder/SemanticPreEncoder.d.ts +6 -0
  139. package/lib/mjs/encoder/SemanticPreEncoder.js +133 -0
  140. package/lib/mjs/encoder/field/BooleanEncoder.d.ts +4 -0
  141. package/lib/mjs/encoder/field/BooleanEncoder.js +9 -0
  142. package/lib/mjs/encoder/field/DateEncoder.d.ts +4 -0
  143. package/lib/mjs/encoder/field/DateEncoder.js +15 -0
  144. package/lib/mjs/encoder/field/FieldEncoderMap.d.ts +1 -0
  145. package/lib/mjs/encoder/field/FieldEncoderMap.js +39 -0
  146. package/lib/mjs/encoder/field/FixedVectorEncoder.d.ts +5 -0
  147. package/lib/mjs/encoder/field/FixedVectorEncoder.js +25 -0
  148. package/lib/mjs/encoder/field/IntEncoder.d.ts +4 -0
  149. package/lib/mjs/encoder/field/IntEncoder.js +25 -0
  150. package/lib/mjs/encoder/field/LangEncoder.d.ts +4 -0
  151. package/lib/mjs/encoder/field/LangEncoder.js +36 -0
  152. package/lib/mjs/encoder/field/PurposeRestrictionVectorEncoder.d.ts +5 -0
  153. package/lib/mjs/encoder/field/PurposeRestrictionVectorEncoder.js +109 -0
  154. package/lib/mjs/encoder/field/VectorEncodingType.d.ts +4 -0
  155. package/lib/mjs/encoder/field/VectorEncodingType.js +5 -0
  156. package/lib/mjs/encoder/field/VendorVectorEncoder.d.ts +6 -0
  157. package/lib/mjs/encoder/field/VendorVectorEncoder.js +156 -0
  158. package/lib/mjs/encoder/field/index.d.ts +9 -0
  159. package/lib/mjs/encoder/field/index.js +9 -0
  160. package/lib/mjs/encoder/index.d.ts +7 -0
  161. package/lib/mjs/encoder/index.js +7 -0
  162. package/lib/mjs/encoder/sequence/FieldSequence.d.ts +5 -0
  163. package/lib/mjs/encoder/sequence/FieldSequence.js +53 -0
  164. package/lib/mjs/encoder/sequence/SegmentSequence.d.ts +9 -0
  165. package/lib/mjs/encoder/sequence/SegmentSequence.js +52 -0
  166. package/lib/mjs/encoder/sequence/SequenceVersionMap.d.ts +7 -0
  167. package/lib/mjs/encoder/sequence/SequenceVersionMap.js +1 -0
  168. package/lib/mjs/encoder/sequence/index.d.ts +3 -0
  169. package/lib/mjs/encoder/sequence/index.js +4 -0
  170. package/lib/mjs/errors/DecodingError.d.ts +15 -0
  171. package/lib/mjs/errors/DecodingError.js +18 -0
  172. package/lib/mjs/errors/EncodingError.d.ts +15 -0
  173. package/lib/mjs/errors/EncodingError.js +18 -0
  174. package/lib/mjs/errors/GVLError.d.ts +15 -0
  175. package/lib/mjs/errors/GVLError.js +18 -0
  176. package/lib/mjs/errors/TCModelError.d.ts +16 -0
  177. package/lib/mjs/errors/TCModelError.js +19 -0
  178. package/lib/mjs/errors/index.d.ts +4 -0
  179. package/lib/mjs/errors/index.js +4 -0
  180. package/lib/mjs/index.d.ts +8 -0
  181. package/lib/mjs/index.js +9 -0
  182. package/lib/mjs/model/BinarySearchTree.d.ts +30 -0
  183. package/lib/mjs/model/BinarySearchTree.js +267 -0
  184. package/lib/mjs/model/ConsentLanguages.d.ts +6 -0
  185. package/lib/mjs/model/ConsentLanguages.js +42 -0
  186. package/lib/mjs/model/DeviceDisclosure.d.ts +9 -0
  187. package/lib/mjs/model/DeviceDisclosure.js +1 -0
  188. package/lib/mjs/model/DeviceDisclosureStorageAccessType.d.ts +5 -0
  189. package/lib/mjs/model/DeviceDisclosureStorageAccessType.js +6 -0
  190. package/lib/mjs/model/Fields.d.ts +29 -0
  191. package/lib/mjs/model/Fields.js +29 -0
  192. package/lib/mjs/model/IntMap.d.ts +13 -0
  193. package/lib/mjs/model/IntMap.js +1 -0
  194. package/lib/mjs/model/KeyMap.d.ts +12 -0
  195. package/lib/mjs/model/KeyMap.js +1 -0
  196. package/lib/mjs/model/PurposeRestriction.d.ts +33 -0
  197. package/lib/mjs/model/PurposeRestriction.js +69 -0
  198. package/lib/mjs/model/PurposeRestrictionVector.d.ts +100 -0
  199. package/lib/mjs/model/PurposeRestrictionVector.js +286 -0
  200. package/lib/mjs/model/RestrictionType.d.ts +19 -0
  201. package/lib/mjs/model/RestrictionType.js +20 -0
  202. package/lib/mjs/model/Segment.d.ts +6 -0
  203. package/lib/mjs/model/Segment.js +7 -0
  204. package/lib/mjs/model/SegmentIDs.d.ts +12 -0
  205. package/lib/mjs/model/SegmentIDs.js +21 -0
  206. package/lib/mjs/model/Vector.d.ts +72 -0
  207. package/lib/mjs/model/Vector.js +161 -0
  208. package/lib/mjs/model/gvl/ByPurposeVendorMap.d.ts +7 -0
  209. package/lib/mjs/model/gvl/ByPurposeVendorMap.js +1 -0
  210. package/lib/mjs/model/gvl/DataCategory.d.ts +4 -0
  211. package/lib/mjs/model/gvl/DataCategory.js +1 -0
  212. package/lib/mjs/model/gvl/DataRetention.d.ts +6 -0
  213. package/lib/mjs/model/gvl/DataRetention.js +1 -0
  214. package/lib/mjs/model/gvl/Declarations.d.ts +13 -0
  215. package/lib/mjs/model/gvl/Declarations.js +1 -0
  216. package/lib/mjs/model/gvl/Feature.d.ts +5 -0
  217. package/lib/mjs/model/gvl/Feature.js +2 -0
  218. package/lib/mjs/model/gvl/GVLMapItem.d.ts +4 -0
  219. package/lib/mjs/model/gvl/GVLMapItem.js +1 -0
  220. package/lib/mjs/model/gvl/IDSetMap.d.ts +2 -0
  221. package/lib/mjs/model/gvl/IDSetMap.js +1 -0
  222. package/lib/mjs/model/gvl/Purpose.d.ts +5 -0
  223. package/lib/mjs/model/gvl/Purpose.js +1 -0
  224. package/lib/mjs/model/gvl/Stack.d.ts +6 -0
  225. package/lib/mjs/model/gvl/Stack.js +1 -0
  226. package/lib/mjs/model/gvl/Vendor.d.ts +24 -0
  227. package/lib/mjs/model/gvl/Vendor.js +1 -0
  228. package/lib/mjs/model/gvl/VendorList.d.ts +10 -0
  229. package/lib/mjs/model/gvl/VendorList.js +1 -0
  230. package/lib/mjs/model/gvl/VendorUrl.d.ts +5 -0
  231. package/lib/mjs/model/gvl/VendorUrl.js +1 -0
  232. package/lib/mjs/model/gvl/index.d.ts +10 -0
  233. package/lib/mjs/model/gvl/index.js +11 -0
  234. package/lib/mjs/model/index.d.ts +14 -0
  235. package/lib/mjs/model/index.js +14 -0
  236. package/lib/mjs/package.json +3 -0
  237. package/package.json +95 -0
package/lib/mjs/GVL.js ADDED
@@ -0,0 +1,591 @@
1
+ import { Cloneable } from './Cloneable.js';
2
+ import { GVLError } from './errors/index.js';
3
+ import { Json } from './Json.js';
4
+ import { ConsentLanguages } from './model/index.js';
5
+ /**
6
+ * class with utilities for managing the global vendor list. Will use JSON to
7
+ * fetch the vendor list from specified url and will serialize it into this
8
+ * object and provide accessors. Provides ways to group vendors on the list by
9
+ * purpose and feature.
10
+ */
11
+ export class GVL extends Cloneable {
12
+ static LANGUAGE_CACHE = new Map();
13
+ static CACHE = new Map();
14
+ static LATEST_CACHE_KEY = 0;
15
+ static DEFAULT_LANGUAGE = 'EN';
16
+ /**
17
+ * Set of available consent languages published by the IAB
18
+ */
19
+ static consentLanguages = new ConsentLanguages();
20
+ static baseUrl_;
21
+ /**
22
+ * baseUrl - Entities using the vendor-list.json are required by the iab to
23
+ * host their own copy of it to reduce the load on the iab's infrastructure
24
+ * so a 'base' url must be set to be put together with the versioning scheme
25
+ * of the filenames.
26
+ *
27
+ * @static
28
+ * @param {string} url - the base url to load the vendor-list.json from. This is
29
+ * broken out from the filename because it follows a different scheme for
30
+ * latest file vs versioned files.
31
+ *
32
+ * @throws {GVLError} - If the url is http[s]://vendorlist.consensu.org/...
33
+ * this will throw an error. IAB Europe requires that that CMPs and Vendors
34
+ * cache their own copies of the GVL to minimize load on their
35
+ * infrastructure. For more information regarding caching of the
36
+ * vendor-list.json, please see [the TCF documentation on 'Caching the Global
37
+ * Vendor List'
38
+ * ](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md#caching-the-global-vendor-list)
39
+ */
40
+ static set baseUrl(url) {
41
+ const notValid = /^https?:\/\/vendorlist\.consensu\.org\//;
42
+ if (notValid.test(url)) {
43
+ throw new GVLError('Invalid baseUrl! You may not pull directly from vendorlist.consensu.org and must provide your own cache');
44
+ }
45
+ // if a trailing slash was forgotten
46
+ if (url.length > 0 && url[url.length - 1] !== '/') {
47
+ url += '/';
48
+ }
49
+ this.baseUrl_ = url;
50
+ }
51
+ ;
52
+ /**
53
+ * baseUrl - Entities using the vendor-list.json are required by the iab to
54
+ * host their own copy of it to reduce the load on the iab's infrastructure
55
+ * so a 'base' url must be set to be put together with the versioning scheme
56
+ * of the filenames.
57
+ *
58
+ * @static
59
+ * @return {string} - returns the previously set baseUrl, the default is
60
+ * `undefined`
61
+ */
62
+ static get baseUrl() {
63
+ return this.baseUrl_;
64
+ }
65
+ /**
66
+ * @static
67
+ * @param {string} - the latest is assumed to be vendor-list.json because
68
+ * that is what the iab uses, but it could be different... if you want
69
+ */
70
+ static latestFilename = 'vendor-list.json';
71
+ /**
72
+ * @static
73
+ * @param {string} - the versioned name is assumed to be
74
+ * vendor-list-v[VERSION].json where [VERSION] will be replaced with the
75
+ * specified version. But it could be different... if you want just make
76
+ * sure to include the [VERSION] macro if you have a numbering scheme, it's a
77
+ * simple string substitution.
78
+ *
79
+ * eg.
80
+ * ```javascript
81
+ * GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
82
+ * GVL.versionedFilename = "vendorlist?getVersion=[VERSION]";
83
+ * ```
84
+ */
85
+ static versionedFilename = 'archives/vendor-list-v[VERSION].json';
86
+ /**
87
+ * @param {string} - Translations of the names and descriptions for Purposes,
88
+ * Special Purposes, Features, and Special Features to non-English languages
89
+ * are contained in a file where attributes containing English content
90
+ * (except vendor declaration information) are translated. The iab publishes
91
+ * one following the scheme below where the LANG is the iso639-1 language
92
+ * code. For a list of available translations
93
+ * [please go here](https://register.consensu.org/Translation).
94
+ *
95
+ * eg.
96
+ * ```javascript
97
+ * GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
98
+ * GVL.languageFilename = "purposes?getPurposes=[LANG]";
99
+ * ```
100
+ */
101
+ static languageFilename = 'purposes-[LANG].json';
102
+ /**
103
+ * @param {Promise} resolved when this GVL object is populated with the data
104
+ * or rejected if there is an error.
105
+ */
106
+ readyPromise;
107
+ /**
108
+ * @param {number} gvlSpecificationVersion - schema version for the GVL that is used
109
+ */
110
+ gvlSpecificationVersion;
111
+ /**
112
+ * @param {number} incremented with each published file change
113
+ */
114
+ vendorListVersion;
115
+ /**
116
+ * @param {number} tcfPolicyVersion - The TCF MO will increment this value
117
+ * whenever a GVL change (such as adding a new Purpose or Feature or a change
118
+ * in Purpose wording) legally invalidates existing TC Strings and requires
119
+ * CMPs to re-establish transparency and consent from users. If the policy
120
+ * version number in the latest GVL is different from the value in your TC
121
+ * String, then you need to re-establish transparency and consent for that
122
+ * user. A version 1 format TC String is considered to have a version value
123
+ * of 1.
124
+ */
125
+ tcfPolicyVersion;
126
+ /**
127
+ * @param {string | Date} lastUpdated - the date in which the vendor list
128
+ * json file was last updated.
129
+ */
130
+ lastUpdated;
131
+ /**
132
+ * @param {IntMap<Purpose>} a collection of [[Purpose]]s
133
+ */
134
+ purposes;
135
+ /**
136
+ * @param {IntMap<Purpose>} a collection of [[Purpose]]s
137
+ */
138
+ specialPurposes;
139
+ /**
140
+ * @param {IntMap<Feature>} a collection of [[Feature]]s
141
+ */
142
+ features;
143
+ /**
144
+ * @param {IntMap<Feature>} a collection of [[Feature]]s
145
+ */
146
+ specialFeatures;
147
+ /**
148
+ * @param {boolean} internal reference of when the GVL is ready to be used
149
+ */
150
+ isReady_ = false;
151
+ /**
152
+ * @param {IntMap<Vendor>} a collection of [[Vendor]]s
153
+ */
154
+ vendors_;
155
+ vendorIds;
156
+ /**
157
+ * @param {IntMap<Vendor>} a collection of [[Vendor]]. Used as a backup if a whitelist is sets
158
+ */
159
+ fullVendorList;
160
+ /**
161
+ * @param {ByPurposeVendorMap} vendors by purpose
162
+ */
163
+ byPurposeVendorMap;
164
+ /**
165
+ * @param {IDSetMap} vendors by special purpose
166
+ */
167
+ bySpecialPurposeVendorMap;
168
+ /**
169
+ * @param {IDSetMap} vendors by feature
170
+ */
171
+ byFeatureVendorMap;
172
+ /**
173
+ * @param {IDSetMap} vendors by special feature
174
+ */
175
+ bySpecialFeatureVendorMap;
176
+ /**
177
+ * @param {IntMap<Stack>} a collection of [[Stack]]s
178
+ */
179
+ stacks;
180
+ /**
181
+ * @param {IntMap<DataCategory>} a collection of [[DataCategory]]s
182
+ */
183
+ dataCategories;
184
+ lang_;
185
+ isLatest = false;
186
+ /**
187
+ * @param {VersionOrVendorList} [versionOrVendorList] - can be either a
188
+ * [[VendorList]] object or a version number represented as a string or
189
+ * number to download. If nothing is passed the latest version of the GVL
190
+ * will be loaded
191
+ */
192
+ constructor(versionOrVendorList) {
193
+ super();
194
+ /**
195
+ * should have been configured before and instance was created and will
196
+ * persist through the app
197
+ */
198
+ let url = GVL.baseUrl;
199
+ this.lang_ = GVL.DEFAULT_LANGUAGE;
200
+ if (this.isVendorList(versionOrVendorList)) {
201
+ this.populate(versionOrVendorList);
202
+ this.readyPromise = Promise.resolve();
203
+ }
204
+ else {
205
+ if (!url) {
206
+ throw new GVLError('must specify GVL.baseUrl before loading GVL json');
207
+ }
208
+ if (versionOrVendorList > 0) {
209
+ const version = versionOrVendorList;
210
+ if (GVL.CACHE.has(version)) {
211
+ this.populate(GVL.CACHE.get(version));
212
+ this.readyPromise = Promise.resolve();
213
+ }
214
+ else {
215
+ // load version specified
216
+ url += GVL.versionedFilename.replace('[VERSION]', String(version));
217
+ this.readyPromise = this.fetchJson(url);
218
+ }
219
+ }
220
+ else {
221
+ /**
222
+ * whatever it is (or isn't)... it doesn't matter we'll just get the
223
+ * latest. In this case we may have cached the latest version at key 0.
224
+ * If we have then we'll just use that instead of making a request.
225
+ * Otherwise we'll have to load it (and then we'll cache it for next
226
+ * time)
227
+ */
228
+ if (GVL.CACHE.has(GVL.LATEST_CACHE_KEY)) {
229
+ this.populate(GVL.CACHE.get(GVL.LATEST_CACHE_KEY));
230
+ this.readyPromise = Promise.resolve();
231
+ }
232
+ else {
233
+ this.isLatest = true;
234
+ this.readyPromise = this.fetchJson(url + GVL.latestFilename);
235
+ }
236
+ }
237
+ }
238
+ }
239
+ /**
240
+ * emptyLanguageCache
241
+ *
242
+ * @param {string} [lang] - Optional ISO 639-1 langauge code to remove from
243
+ * the cache. Should be one of the languages in GVL.consentLanguages set.
244
+ * If not then the whole cache will be deleted.
245
+ * @return {boolean} - true if anything was deleted from the cache
246
+ */
247
+ static emptyLanguageCache(lang) {
248
+ let retr = false;
249
+ if (lang === undefined && GVL.LANGUAGE_CACHE.size > 0) {
250
+ GVL.LANGUAGE_CACHE = new Map();
251
+ retr = true;
252
+ }
253
+ else if (typeof lang === 'string' && this.consentLanguages.has(lang.toUpperCase())) {
254
+ GVL.LANGUAGE_CACHE.delete(lang.toUpperCase());
255
+ retr = true;
256
+ }
257
+ return retr;
258
+ }
259
+ /**
260
+ * emptyCache
261
+ *
262
+ * @param {number} [vendorListVersion] - version of the vendor list to delete
263
+ * from the cache. If none is specified then the whole cache is deleted.
264
+ * @return {boolean} - true if anything was deleted from the cache
265
+ */
266
+ static emptyCache(vendorListVersion) {
267
+ let retr = false;
268
+ if (Number.isInteger(vendorListVersion) && vendorListVersion >= 0) {
269
+ GVL.CACHE.delete(vendorListVersion);
270
+ retr = true;
271
+ }
272
+ else if (vendorListVersion === undefined) {
273
+ GVL.CACHE = new Map();
274
+ retr = true;
275
+ }
276
+ return retr;
277
+ }
278
+ cacheLanguage() {
279
+ if (!GVL.LANGUAGE_CACHE.has(this.lang_)) {
280
+ GVL.LANGUAGE_CACHE.set(this.lang_, {
281
+ purposes: this.purposes,
282
+ specialPurposes: this.specialPurposes,
283
+ features: this.features,
284
+ specialFeatures: this.specialFeatures,
285
+ stacks: this.stacks,
286
+ dataCategories: this.dataCategories,
287
+ });
288
+ }
289
+ }
290
+ async fetchJson(url) {
291
+ try {
292
+ this.populate(await Json.fetch(url));
293
+ }
294
+ catch (err) {
295
+ throw new GVLError(err.message);
296
+ }
297
+ }
298
+ /**
299
+ * getJson - Method for getting the JSON that was downloaded to created this
300
+ * `GVL` object
301
+ *
302
+ * @return {VendorList} - The basic JSON structure without the extra
303
+ * functionality and methods of this class.
304
+ */
305
+ getJson() {
306
+ return JSON.parse(JSON.stringify({
307
+ gvlSpecificationVersion: this.gvlSpecificationVersion,
308
+ vendorListVersion: this.vendorListVersion,
309
+ tcfPolicyVersion: this.tcfPolicyVersion,
310
+ lastUpdated: this.lastUpdated,
311
+ purposes: this.purposes,
312
+ specialPurposes: this.specialPurposes,
313
+ features: this.features,
314
+ specialFeatures: this.specialFeatures,
315
+ stacks: this.stacks,
316
+ dataCategories: this.dataCategories,
317
+ vendors: this.fullVendorList,
318
+ }));
319
+ }
320
+ /**
321
+ * changeLanguage - retrieves the purpose language translation and sets the
322
+ * internal language variable
323
+ *
324
+ * @param {string} lang - ISO 639-1 langauge code to change language to
325
+ * @return {Promise<void | GVLError>} - returns the `readyPromise` and
326
+ * resolves when this GVL is populated with the data from the language file.
327
+ */
328
+ async changeLanguage(lang) {
329
+ const langUpper = lang.toUpperCase();
330
+ if (GVL.consentLanguages.has(langUpper)) {
331
+ if (langUpper !== this.lang_) {
332
+ this.lang_ = langUpper;
333
+ if (GVL.LANGUAGE_CACHE.has(langUpper)) {
334
+ const cached = GVL.LANGUAGE_CACHE.get(langUpper);
335
+ for (const prop in cached) {
336
+ if (cached.hasOwnProperty(prop)) {
337
+ this[prop] = cached[prop];
338
+ }
339
+ }
340
+ }
341
+ else {
342
+ // load Language specified
343
+ const url = GVL.baseUrl + GVL.languageFilename.replace('[LANG]', lang);
344
+ try {
345
+ await this.fetchJson(url);
346
+ this.cacheLanguage();
347
+ }
348
+ catch (err) {
349
+ throw new GVLError('unable to load language: ' + err.message);
350
+ }
351
+ }
352
+ }
353
+ }
354
+ else {
355
+ throw new GVLError(`unsupported language ${lang}`);
356
+ }
357
+ }
358
+ get language() {
359
+ return this.lang_;
360
+ }
361
+ isVendorList(gvlObject) {
362
+ return gvlObject !== undefined && gvlObject.vendors !== undefined;
363
+ }
364
+ populate(gvlObject) {
365
+ /**
366
+ * these are populated regardless of whether it's a Declarations file or
367
+ * a VendorList
368
+ */
369
+ this.purposes = gvlObject.purposes;
370
+ this.specialPurposes = gvlObject.specialPurposes;
371
+ this.features = gvlObject.features;
372
+ this.specialFeatures = gvlObject.specialFeatures;
373
+ this.stacks = gvlObject.stacks;
374
+ this.dataCategories = gvlObject.dataCategories;
375
+ if (this.isVendorList(gvlObject)) {
376
+ this.gvlSpecificationVersion = gvlObject.gvlSpecificationVersion;
377
+ this.tcfPolicyVersion = gvlObject.tcfPolicyVersion;
378
+ this.vendorListVersion = gvlObject.vendorListVersion;
379
+ this.lastUpdated = gvlObject.lastUpdated;
380
+ if (typeof this.lastUpdated === 'string') {
381
+ this.lastUpdated = new Date(this.lastUpdated);
382
+ }
383
+ this.vendors_ = gvlObject.vendors;
384
+ this.fullVendorList = gvlObject.vendors;
385
+ this.mapVendors();
386
+ this.isReady_ = true;
387
+ if (this.isLatest) {
388
+ /**
389
+ * If the "LATEST" was requested then this flag will be set to true.
390
+ * In that case we'll cache the GVL at the special key
391
+ */
392
+ GVL.CACHE.set(GVL.LATEST_CACHE_KEY, this.getJson());
393
+ }
394
+ /**
395
+ * Whether or not it's the "LATEST" we'll cache the gvl at the version it
396
+ * is declared to be (if it's not already). to avoid downloading it again
397
+ * in the future.
398
+ */
399
+ if (!GVL.CACHE.has(this.vendorListVersion)) {
400
+ GVL.CACHE.set(this.vendorListVersion, this.getJson());
401
+ }
402
+ }
403
+ this.cacheLanguage();
404
+ }
405
+ mapVendors(vendorIds) {
406
+ // create new instances of the maps
407
+ this.byPurposeVendorMap = {};
408
+ this.bySpecialPurposeVendorMap = {};
409
+ this.byFeatureVendorMap = {};
410
+ this.bySpecialFeatureVendorMap = {};
411
+ // initializes data structure for purpose map
412
+ Object.keys(this.purposes).forEach((purposeId) => {
413
+ this.byPurposeVendorMap[purposeId] = {
414
+ legInt: new Set(),
415
+ consent: new Set(),
416
+ flexible: new Set(),
417
+ };
418
+ });
419
+ // initializes data structure for special purpose map
420
+ Object.keys(this.specialPurposes).forEach((purposeId) => {
421
+ this.bySpecialPurposeVendorMap[purposeId] = new Set();
422
+ });
423
+ // initializes data structure for feature map
424
+ Object.keys(this.features).forEach((featureId) => {
425
+ this.byFeatureVendorMap[featureId] = new Set();
426
+ });
427
+ // initializes data structure for feature map
428
+ Object.keys(this.specialFeatures).forEach((featureId) => {
429
+ this.bySpecialFeatureVendorMap[featureId] = new Set();
430
+ });
431
+ if (!Array.isArray(vendorIds)) {
432
+ vendorIds = Object.keys(this.fullVendorList).map((vId) => +vId);
433
+ }
434
+ this.vendorIds = new Set(vendorIds);
435
+ // assigns vendor ids to their respective maps
436
+ this.vendors_ = vendorIds.reduce((vendors, vendorId) => {
437
+ const vendor = this.vendors_[String(vendorId)];
438
+ if (vendor && vendor.deletedDate === undefined) {
439
+ vendor.purposes.forEach((purposeId) => {
440
+ const purpGroup = this.byPurposeVendorMap[String(purposeId)];
441
+ purpGroup.consent.add(vendorId);
442
+ });
443
+ vendor.specialPurposes.forEach((purposeId) => {
444
+ this.bySpecialPurposeVendorMap[String(purposeId)].add(vendorId);
445
+ });
446
+ vendor.legIntPurposes.forEach((purposeId) => {
447
+ this.byPurposeVendorMap[String(purposeId)].legInt.add(vendorId);
448
+ });
449
+ // could not be there
450
+ if (vendor.flexiblePurposes) {
451
+ vendor.flexiblePurposes.forEach((purposeId) => {
452
+ this.byPurposeVendorMap[String(purposeId)].flexible.add(vendorId);
453
+ });
454
+ }
455
+ vendor.features.forEach((featureId) => {
456
+ this.byFeatureVendorMap[String(featureId)].add(vendorId);
457
+ });
458
+ vendor.specialFeatures.forEach((featureId) => {
459
+ this.bySpecialFeatureVendorMap[String(featureId)].add(vendorId);
460
+ });
461
+ vendors[vendorId] = vendor;
462
+ }
463
+ return vendors;
464
+ }, {});
465
+ }
466
+ getFilteredVendors(purposeOrFeature, id, subType, special) {
467
+ const properPurposeOrFeature = purposeOrFeature.charAt(0).toUpperCase() + purposeOrFeature.slice(1);
468
+ let vendorSet;
469
+ const retr = {};
470
+ if (purposeOrFeature === 'purpose' && subType) {
471
+ vendorSet = this['by' + properPurposeOrFeature + 'VendorMap'][String(id)][subType];
472
+ }
473
+ else {
474
+ vendorSet = this['by' + (special ? 'Special' : '') + properPurposeOrFeature + 'VendorMap'][String(id)];
475
+ }
476
+ vendorSet.forEach((vendorId) => {
477
+ retr[String(vendorId)] = this.vendors[String(vendorId)];
478
+ });
479
+ return retr;
480
+ }
481
+ /**
482
+ * getVendorsWithConsentPurpose
483
+ *
484
+ * @param {number} purposeId
485
+ * @return {IntMap<Vendor>} - list of vendors that have declared the consent purpose id
486
+ */
487
+ getVendorsWithConsentPurpose(purposeId) {
488
+ return this.getFilteredVendors('purpose', purposeId, 'consent');
489
+ }
490
+ /**
491
+ * getVendorsWithLegIntPurpose
492
+ *
493
+ * @param {number} purposeId
494
+ * @return {IntMap<Vendor>} - list of vendors that have declared the legInt (Legitimate Interest) purpose id
495
+ */
496
+ getVendorsWithLegIntPurpose(purposeId) {
497
+ return this.getFilteredVendors('purpose', purposeId, 'legInt');
498
+ }
499
+ /**
500
+ * getVendorsWithFlexiblePurpose
501
+ *
502
+ * @param {number} purposeId
503
+ * @return {IntMap<Vendor>} - list of vendors that have declared the flexible purpose id
504
+ */
505
+ getVendorsWithFlexiblePurpose(purposeId) {
506
+ return this.getFilteredVendors('purpose', purposeId, 'flexible');
507
+ }
508
+ /**
509
+ * getVendorsWithSpecialPurpose
510
+ *
511
+ * @param {number} specialPurposeId
512
+ * @return {IntMap<Vendor>} - list of vendors that have declared the special purpose id
513
+ */
514
+ getVendorsWithSpecialPurpose(specialPurposeId) {
515
+ return this.getFilteredVendors('purpose', specialPurposeId, undefined, true);
516
+ }
517
+ /**
518
+ * getVendorsWithFeature
519
+ *
520
+ * @param {number} featureId
521
+ * @return {IntMap<Vendor>} - list of vendors that have declared the feature id
522
+ */
523
+ getVendorsWithFeature(featureId) {
524
+ return this.getFilteredVendors('feature', featureId);
525
+ }
526
+ /**
527
+ * getVendorsWithSpecialFeature
528
+ *
529
+ * @param {number} specialFeatureId
530
+ * @return {IntMap<Vendor>} - list of vendors that have declared the special feature id
531
+ */
532
+ getVendorsWithSpecialFeature(specialFeatureId) {
533
+ return this.getFilteredVendors('feature', specialFeatureId, undefined, true);
534
+ }
535
+ /**
536
+ * vendors
537
+ *
538
+ * @return {IntMap<Vendor>} - the list of vendors as it would on the JSON file
539
+ * except if `narrowVendorsTo` was called, it would be that narrowed list
540
+ */
541
+ get vendors() {
542
+ return this.vendors_;
543
+ }
544
+ /**
545
+ * narrowVendorsTo - narrows vendors represented in this GVL to the list of ids passed in
546
+ *
547
+ * @param {number[]} vendorIds - list of ids to narrow this GVL to
548
+ * @return {void}
549
+ */
550
+ narrowVendorsTo(vendorIds) {
551
+ this.mapVendors(vendorIds);
552
+ }
553
+ /**
554
+ * isReady - Whether or not this instance is ready to be used. This will be
555
+ * immediately and synchronously true if a vendorlist object is passed into
556
+ * the constructor or once the JSON vendorllist is retrieved.
557
+ *
558
+ * @return {boolean} whether or not the instance is ready to be interacted
559
+ * with and all the data is populated
560
+ */
561
+ get isReady() {
562
+ return this.isReady_;
563
+ }
564
+ /**
565
+ * clone - overrides base `clone()` method since GVL is a special class that
566
+ * represents a JSON structure with some additional functionality.
567
+ *
568
+ * @return {GVL}
569
+ */
570
+ clone() {
571
+ const result = new GVL(this.getJson());
572
+ /*
573
+ * If the current language of the GVL is not the default language, we set the language of
574
+ * the clone to the current language since a new GVL is always created with the default
575
+ * language. */
576
+ if (this.lang_ !== GVL.DEFAULT_LANGUAGE) {
577
+ /*
578
+ * Since the GVL language was changed, this means that an asynchronous changeLanguage
579
+ * call was made prior to cloning the GVL. The new language specified has been cached
580
+ * by the GVL and this changeLanguage call made as a part of cloning the GVL will be
581
+ * synchronous. The code will look for the language definitions in the cache instead
582
+ * of creating a http request. */
583
+ result.changeLanguage(this.lang_);
584
+ }
585
+ return result;
586
+ }
587
+ static isInstanceOf(questionableInstance) {
588
+ const isSo = typeof questionableInstance === 'object';
589
+ return (isSo && typeof questionableInstance.narrowVendorsTo === 'function');
590
+ }
591
+ }
@@ -0,0 +1,20 @@
1
+ export declare class Json {
2
+ private static absCall;
3
+ /**
4
+ * @static
5
+ * @param {string} url - full path to POST to
6
+ * @param {object} body - JSON object to post
7
+ * @param {boolean} sendCookies - Whether or not to send the XMLHttpRequest with credentials or not
8
+ * @param {number} [timeout] - optional timeout in milliseconds
9
+ * @return {Promise<object>} - if the server responds the response will be returned here
10
+ */
11
+ static post(url: string, body: object, sendCookies?: boolean, timeout?: number): Promise<object>;
12
+ /**
13
+ * @static
14
+ * @param {string} url - full path to the json
15
+ * @param {boolean} sendCookies - Whether or not to send the XMLHttpRequest with credentials or not
16
+ * @param {number} [timeout] - optional timeout in milliseconds
17
+ * @return {Promise<object>} - resolves with parsed JSON
18
+ */
19
+ static fetch(url: string, sendCookies?: boolean, timeout?: number): Promise<object>;
20
+ }
@@ -0,0 +1,74 @@
1
+ export class Json {
2
+ static absCall(url, body, sendCookies, timeout) {
3
+ return new Promise((resolve, reject) => {
4
+ const req = new XMLHttpRequest();
5
+ const onLoad = () => {
6
+ // is the response done
7
+ if (req.readyState == XMLHttpRequest.DONE) {
8
+ /**
9
+ * For our purposes if it's not a 200 range response, then it's a
10
+ * failure.
11
+ */
12
+ if (req.status >= 200 && req.status < 300) {
13
+ let response = req.response;
14
+ if (typeof response === 'string') {
15
+ try {
16
+ response = JSON.parse(response);
17
+ }
18
+ catch (e) { }
19
+ }
20
+ resolve(response);
21
+ }
22
+ else {
23
+ reject(new Error(`HTTP Status: ${req.status} response type: ${req.responseType}`));
24
+ }
25
+ }
26
+ };
27
+ const onError = () => {
28
+ reject(new Error('error'));
29
+ };
30
+ const onAbort = () => {
31
+ reject(new Error('aborted'));
32
+ };
33
+ const onTimeout = () => {
34
+ reject(new Error('Timeout ' + timeout + 'ms ' + url));
35
+ };
36
+ req.withCredentials = sendCookies;
37
+ req.addEventListener('load', onLoad);
38
+ req.addEventListener('error', onError);
39
+ req.addEventListener('abort', onAbort);
40
+ if (body === null) {
41
+ req.open('GET', url, true);
42
+ }
43
+ else {
44
+ req.open('POST', url, true);
45
+ }
46
+ req.responseType = 'json';
47
+ // IE has a problem if this is before the open
48
+ req.timeout = timeout;
49
+ req.ontimeout = onTimeout;
50
+ req.send(body);
51
+ });
52
+ }
53
+ /**
54
+ * @static
55
+ * @param {string} url - full path to POST to
56
+ * @param {object} body - JSON object to post
57
+ * @param {boolean} sendCookies - Whether or not to send the XMLHttpRequest with credentials or not
58
+ * @param {number} [timeout] - optional timeout in milliseconds
59
+ * @return {Promise<object>} - if the server responds the response will be returned here
60
+ */
61
+ static post(url, body, sendCookies = false, timeout = 0) {
62
+ return this.absCall(url, JSON.stringify(body), sendCookies, timeout);
63
+ }
64
+ /**
65
+ * @static
66
+ * @param {string} url - full path to the json
67
+ * @param {boolean} sendCookies - Whether or not to send the XMLHttpRequest with credentials or not
68
+ * @param {number} [timeout] - optional timeout in milliseconds
69
+ * @return {Promise<object>} - resolves with parsed JSON
70
+ */
71
+ static fetch(url, sendCookies = false, timeout = 0) {
72
+ return this.absCall(url, null, sendCookies, timeout);
73
+ }
74
+ }