@el7ven/cookie-kit 0.3.1 → 0.3.3
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/package.json +21 -1
- package/src/core/AnalyticsManager.js +400 -0
- package/src/core/ConsentManager.js +710 -0
- package/src/core/ConsentMode.js +109 -0
- package/src/core/FocusTrap.js +130 -0
- package/src/core/GeoDetector.js +144 -0
- package/src/core/ScriptLoader.js +229 -0
- package/src/core/StorageAdapter.js +179 -0
- package/src/core/index.js +4 -4
- package/src/geo/GeoDetector.js +536 -0
- package/src/geo/RegionRules.js +126 -0
- package/src/geo/index.js +16 -0
- package/src/index.js +55 -17
- package/src/locales/en.js +54 -0
- package/src/locales/index.js +20 -0
- package/src/locales/ro.js +54 -0
- package/src/plugins/CMPPlugin.js +187 -0
- package/src/plugins/PluginManager.js +234 -0
- package/src/plugins/index.js +7 -0
- package/src/providers/GoogleConsentModeProvider.js +278 -0
- package/src/providers/index.js +6 -0
- package/src/rewriting/ScriptRewriter.js +278 -0
- package/src/rewriting/index.js +6 -0
- package/src/scripts/ScriptLoader.js +310 -0
- package/src/scripts/ScriptManager.js +278 -0
- package/src/scripts/ScriptRegistry.js +175 -0
- package/src/scripts/ScriptScanner.js +178 -0
- package/src/scripts/index.js +9 -0
- package/src/trackers/TrackerDetector.js +488 -0
- package/src/trackers/TrackerPatterns.js +307 -0
- package/src/trackers/TrackerRegistry.js +172 -0
- package/src/trackers/index.js +15 -0
- package/src/utils/cookies.js +37 -0
- package/src/utils/dom.js +58 -0
- package/src/utils/helpers.js +89 -0
- package/src/vue/CookieConsent.vue +4 -12
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe Storage Adapter — handles localStorage failures (Safari private mode, quota exceeded)
|
|
3
|
+
* @module StorageAdapter
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class StorageAdapter {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.storageType = config.storageType || 'localStorage'
|
|
9
|
+
this.storageKey = config.storageKey || 'cookie_consent'
|
|
10
|
+
this.cookieExpireDays = config.consentExpireDays || 365
|
|
11
|
+
this._testStorage()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Test if storage is available (Safari private mode blocks localStorage)
|
|
16
|
+
*/
|
|
17
|
+
_testStorage() {
|
|
18
|
+
this.isLocalStorageAvailable = false
|
|
19
|
+
this.isCookieAvailable = false
|
|
20
|
+
|
|
21
|
+
// Test localStorage
|
|
22
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
23
|
+
try {
|
|
24
|
+
const testKey = '__storage_test__'
|
|
25
|
+
localStorage.setItem(testKey, 'test')
|
|
26
|
+
localStorage.removeItem(testKey)
|
|
27
|
+
this.isLocalStorageAvailable = true
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.warn('[StorageAdapter] localStorage not available:', e.message)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Test cookies
|
|
34
|
+
if (typeof document !== 'undefined') {
|
|
35
|
+
try {
|
|
36
|
+
document.cookie = '__cookie_test__=test; path=/; SameSite=Lax'
|
|
37
|
+
this.isCookieAvailable = document.cookie.includes('__cookie_test__')
|
|
38
|
+
document.cookie = '__cookie_test__=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.warn('[StorageAdapter] Cookies not available:', e.message)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get data from storage
|
|
47
|
+
*/
|
|
48
|
+
get(key = null) {
|
|
49
|
+
const storageKey = key || this.storageKey
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
// Try localStorage first
|
|
53
|
+
if (this.storageType === 'localStorage' || this.storageType === 'both') {
|
|
54
|
+
if (this.isLocalStorageAvailable) {
|
|
55
|
+
const value = localStorage.getItem(storageKey)
|
|
56
|
+
if (value) return value
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Fallback to cookies
|
|
61
|
+
if (this.storageType === 'cookie' || this.storageType === 'both') {
|
|
62
|
+
if (this.isCookieAvailable) {
|
|
63
|
+
return this._readCookie(storageKey)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return null
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error('[StorageAdapter] Error reading storage:', e)
|
|
70
|
+
return null
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Set data to storage
|
|
76
|
+
*/
|
|
77
|
+
set(key, value) {
|
|
78
|
+
const storageKey = typeof key === 'string' ? key : this.storageKey
|
|
79
|
+
const data = typeof key === 'string' ? value : key
|
|
80
|
+
|
|
81
|
+
// Validate data before saving
|
|
82
|
+
if (data === null || data === undefined) {
|
|
83
|
+
console.warn('[StorageAdapter] Attempted to save null/undefined data, skipping')
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (typeof data === 'string' && (data === 'null' || data === 'undefined')) {
|
|
88
|
+
console.warn('[StorageAdapter] Attempted to save literal "null"/"undefined" string, skipping')
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
// Try localStorage
|
|
94
|
+
if (this.storageType === 'localStorage' || this.storageType === 'both') {
|
|
95
|
+
if (this.isLocalStorageAvailable) {
|
|
96
|
+
try {
|
|
97
|
+
localStorage.setItem(storageKey, data)
|
|
98
|
+
} catch (e) {
|
|
99
|
+
// Quota exceeded — try to clear old data
|
|
100
|
+
if (e.name === 'QuotaExceededError') {
|
|
101
|
+
console.warn('[StorageAdapter] localStorage quota exceeded, falling back to cookies')
|
|
102
|
+
this.isLocalStorageAvailable = false
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Fallback to cookies
|
|
109
|
+
if (this.storageType === 'cookie' || this.storageType === 'both') {
|
|
110
|
+
if (this.isCookieAvailable) {
|
|
111
|
+
this._writeCookie(storageKey, data, this.cookieExpireDays)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return true
|
|
116
|
+
} catch (e) {
|
|
117
|
+
console.error('[StorageAdapter] Error writing storage:', e)
|
|
118
|
+
return false
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Remove data from storage
|
|
124
|
+
*/
|
|
125
|
+
remove(key = null) {
|
|
126
|
+
const storageKey = key || this.storageKey
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
// Remove from localStorage
|
|
130
|
+
if (this.storageType === 'localStorage' || this.storageType === 'both') {
|
|
131
|
+
if (this.isLocalStorageAvailable) {
|
|
132
|
+
localStorage.removeItem(storageKey)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Remove from cookies
|
|
137
|
+
if (this.storageType === 'cookie' || this.storageType === 'both') {
|
|
138
|
+
if (this.isCookieAvailable) {
|
|
139
|
+
this._writeCookie(storageKey, '', -1)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return true
|
|
144
|
+
} catch (e) {
|
|
145
|
+
console.error('[StorageAdapter] Error removing storage:', e)
|
|
146
|
+
return false
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Check if storage is available
|
|
152
|
+
*/
|
|
153
|
+
isAvailable() {
|
|
154
|
+
return this.isLocalStorageAvailable || this.isCookieAvailable
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get storage type being used
|
|
159
|
+
*/
|
|
160
|
+
getActiveStorageType() {
|
|
161
|
+
if (this.isLocalStorageAvailable) return 'localStorage'
|
|
162
|
+
if (this.isCookieAvailable) return 'cookie'
|
|
163
|
+
return 'none'
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// --- Cookie helpers ---
|
|
167
|
+
|
|
168
|
+
_readCookie(name) {
|
|
169
|
+
if (typeof document === 'undefined') return null
|
|
170
|
+
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'))
|
|
171
|
+
return match ? decodeURIComponent(match[2]) : null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
_writeCookie(name, value, days) {
|
|
175
|
+
if (typeof document === 'undefined') return
|
|
176
|
+
const expires = new Date(Date.now() + days * 864e5).toUTCString()
|
|
177
|
+
document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; SameSite=Lax`
|
|
178
|
+
}
|
|
179
|
+
}
|
package/src/core/index.js
CHANGED
|
@@ -225,7 +225,7 @@ export class CookieKitCore {
|
|
|
225
225
|
const next = {}
|
|
226
226
|
Object.keys(this.config.categories).forEach(id => {
|
|
227
227
|
const category = this.config.categories[id]
|
|
228
|
-
if (category?.enabled
|
|
228
|
+
if (category?.enabled === true) {
|
|
229
229
|
next[id] = !!category.required
|
|
230
230
|
}
|
|
231
231
|
})
|
|
@@ -270,7 +270,7 @@ export class CookieKitCore {
|
|
|
270
270
|
acceptAll(source = 'banner') {
|
|
271
271
|
const categories = {}
|
|
272
272
|
Object.keys(this.config.categories).forEach(id => {
|
|
273
|
-
if (this.config.categories[id]?.enabled
|
|
273
|
+
if (this.config.categories[id]?.enabled === true) {
|
|
274
274
|
categories[id] = true
|
|
275
275
|
}
|
|
276
276
|
})
|
|
@@ -281,7 +281,7 @@ export class CookieKitCore {
|
|
|
281
281
|
const categories = {}
|
|
282
282
|
Object.keys(this.config.categories).forEach(id => {
|
|
283
283
|
const category = this.config.categories[id]
|
|
284
|
-
if (category?.enabled
|
|
284
|
+
if (category?.enabled === true) {
|
|
285
285
|
categories[id] = !!category.required
|
|
286
286
|
}
|
|
287
287
|
})
|
|
@@ -293,7 +293,7 @@ export class CookieKitCore {
|
|
|
293
293
|
const categories = {}
|
|
294
294
|
Object.keys(this.config.categories).forEach(id => {
|
|
295
295
|
const category = this.config.categories[id]
|
|
296
|
-
if (category?.enabled
|
|
296
|
+
if (category?.enabled === true) {
|
|
297
297
|
categories[id] = selectedSet.has(id) || !!category.required
|
|
298
298
|
}
|
|
299
299
|
})
|