@modernconsent/core 0.0.1 → 1.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/README.md +144 -0
- package/dist/chunk-ENHZCUQ7.js +44 -0
- package/dist/chunk-ENHZCUQ7.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +54 -35
- package/dist/index.js.map +1 -1
- package/dist/{resolver-CKoWIVlu.d.ts → resolver-CssVkauA.d.ts} +35 -35
- package/dist/resolver.d.ts +1 -1
- package/dist/resolver.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-UZ3JLA4T.js +0 -23
- package/dist/chunk-UZ3JLA4T.js.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# @modernconsent/core
|
|
2
|
+
|
|
3
|
+
Lightweight consent engine for the web. Manages consent state, cookie persistence, GDPR audit trails and event emission — without any UI.
|
|
4
|
+
|
|
5
|
+
Part of the [ModernConsent](https://github.com/kschnekenburger/modern-consent) project.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @modernconsent/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import {
|
|
17
|
+
consentState,
|
|
18
|
+
hasAnswered,
|
|
19
|
+
servicesList,
|
|
20
|
+
setConsent,
|
|
21
|
+
acceptAll,
|
|
22
|
+
denyAll,
|
|
23
|
+
emitter,
|
|
24
|
+
} from '@modernconsent/core';
|
|
25
|
+
|
|
26
|
+
// Read reactive state
|
|
27
|
+
consentState.get(); // { 'google-analytics': true, 'meta-pixel': false }
|
|
28
|
+
hasAnswered.get(); // true
|
|
29
|
+
servicesList.get(); // [{ id, name, description, category, loaded, requireConsent }]
|
|
30
|
+
|
|
31
|
+
// Mutate consent
|
|
32
|
+
setConsent('google-analytics', true);
|
|
33
|
+
acceptAll();
|
|
34
|
+
denyAll();
|
|
35
|
+
|
|
36
|
+
// Subscribe to changes
|
|
37
|
+
const unsub = consentState.subscribe(state => {
|
|
38
|
+
console.log('Consent changed:', state);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Listen to events
|
|
42
|
+
emitter.on('consent:update', data => {
|
|
43
|
+
console.log(data.vendor, data.status); // 'google-analytics', 'granted'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
emitter.on('consent:saved', data => {
|
|
47
|
+
console.log(data.consentId, data.timestamp, data.consent);
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
All options are passed via `window.modernConsent('config', { ... })`:
|
|
54
|
+
|
|
55
|
+
| Option | Type | Default | Description |
|
|
56
|
+
| ------------------- | ----------------------- | -------------------- | ------------------------------------------------------------------------- |
|
|
57
|
+
| `cookieName` | `string` | `'mc_consent_state'` | Name of the consent cookie |
|
|
58
|
+
| `cookieDomain` | `string` | — | Domain scope (e.g. `.example.com`) |
|
|
59
|
+
| `consentMode` | `boolean` | `false` | Enable Google Consent Mode v2 |
|
|
60
|
+
| `consentVersion` | `string` | — | Version for GDPR audit. Changing it re-prompts the user |
|
|
61
|
+
| `consentOnly` | `boolean` | `false` | Consent-only mode — no vendor `init()` calls. For Tag Manager integration |
|
|
62
|
+
| `pushDataLayer` | `boolean` | `false` | Push events to `window.dataLayer` (GTM) |
|
|
63
|
+
| `displayMode` | `'vendor' \| 'purpose'` | `'vendor'` | How the widget displays controls |
|
|
64
|
+
| `functionalPurpose` | `boolean` | `false` | Show mandatory "Site operation" block |
|
|
65
|
+
|
|
66
|
+
## Consent-Only Mode
|
|
67
|
+
|
|
68
|
+
For GTM / TagCommander users who manage scripts externally:
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
window.modernConsent('config', {
|
|
72
|
+
consentOnly: true,
|
|
73
|
+
pushDataLayer: true, // optional, for GTM native triggers
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Integration points:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
// Read state
|
|
81
|
+
window.modernConsent.getConsent();
|
|
82
|
+
|
|
83
|
+
// Listen to changes
|
|
84
|
+
window.modernConsent.on('consent:update', e => {
|
|
85
|
+
console.log(e.vendor, e.status);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// consentLayer (always active)
|
|
89
|
+
window.consentLayer;
|
|
90
|
+
|
|
91
|
+
// dataLayer (opt-in)
|
|
92
|
+
window.dataLayer;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Cookie Format
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"consent": { "google-analytics": true, "meta-pixel": false },
|
|
100
|
+
"answered": true,
|
|
101
|
+
"timestamp": 1711468800000,
|
|
102
|
+
"version": "v1",
|
|
103
|
+
"consentId": "550e8400-e29b-41d4-a716-446655440000"
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Public API
|
|
108
|
+
|
|
109
|
+
| Method | Returns | Description |
|
|
110
|
+
| --------------------- | -------------- | ---------------------- |
|
|
111
|
+
| `('config', options)` | — | Merge configuration |
|
|
112
|
+
| `('vendor', vendor)` | — | Register a vendor |
|
|
113
|
+
| `.openPanel()` | — | Open the consent panel |
|
|
114
|
+
| `.getConsent()` | `ConsentState` | Current consent state |
|
|
115
|
+
| `.on(event, cb)` | `() => void` | Subscribe to events |
|
|
116
|
+
|
|
117
|
+
## Stores
|
|
118
|
+
|
|
119
|
+
Reactive stores with pub/sub pattern:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { consentState, hasAnswered, servicesList, isPanelOpen } from '@modernconsent/core';
|
|
123
|
+
|
|
124
|
+
// Read
|
|
125
|
+
consentState.get();
|
|
126
|
+
|
|
127
|
+
// Write
|
|
128
|
+
consentState.set({ 'my-vendor': true });
|
|
129
|
+
|
|
130
|
+
// Subscribe (fires immediately with current value)
|
|
131
|
+
const unsub = consentState.subscribe(value => { ... });
|
|
132
|
+
unsub(); // cleanup
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Related Packages
|
|
136
|
+
|
|
137
|
+
| Package | Description |
|
|
138
|
+
| -------------------------------------------------------------------------------- | ----------------------------------------- |
|
|
139
|
+
| [`@modernconsent/widget`](https://www.npmjs.com/package/@modernconsent/widget) | Web Component UI (banner + details panel) |
|
|
140
|
+
| [`@modernconsent/vendors`](https://www.npmjs.com/package/@modernconsent/vendors) | 24 built-in vendor modules |
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
+
|
|
22
|
+
// src/resolver.ts
|
|
23
|
+
var _resolvers = [];
|
|
24
|
+
function addResolver(resolver) {
|
|
25
|
+
_resolvers.push(resolver);
|
|
26
|
+
return () => {
|
|
27
|
+
const idx = _resolvers.indexOf(resolver);
|
|
28
|
+
if (idx !== -1) _resolvers.splice(idx, 1);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function resolveVendor(name) {
|
|
32
|
+
for (let i = _resolvers.length - 1; i >= 0; i--) {
|
|
33
|
+
const result = _resolvers[i](name);
|
|
34
|
+
if (result) return result;
|
|
35
|
+
}
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
38
|
+
function __resetResolvers() {
|
|
39
|
+
_resolvers.length = 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { __publicField, __resetResolvers, __spreadProps, __spreadValues, addResolver, resolveVendor };
|
|
43
|
+
//# sourceMappingURL=chunk-ENHZCUQ7.js.map
|
|
44
|
+
//# sourceMappingURL=chunk-ENHZCUQ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AASA,IAAM,aAA+B,EAAC;AAS/B,SAAS,YAAY,QAAA,EAAsC;AAChE,EAAA,UAAA,CAAW,KAAK,QAAQ,CAAA;AACxB,EAAA,OAAO,MAAM;AACX,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,OAAA,CAAQ,QAAQ,CAAA;AACvC,IAAA,IAAI,GAAA,KAAQ,EAAA,EAAI,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC1C,CAAA;AACF;AAMO,SAAS,cAAc,IAAA,EAAwC;AACpE,EAAA,KAAA,IAAS,IAAI,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC/C,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,CAAC,CAAA,CAAE,IAAI,CAAA;AACjC,IAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,gBAAA,GAAyB;AACvC,EAAA,UAAA,CAAW,MAAA,GAAS,CAAA;AACtB","file":"chunk-ENHZCUQ7.js","sourcesContent":["// core/src/resolver.ts\nimport type { VendorLoader } from './registry';\n\n/**\n * A resolver maps a vendor name to a loader function.\n * Return `undefined` to pass resolution to the next resolver in the chain.\n */\nexport type VendorResolver = (name: string) => VendorLoader | undefined;\n\nconst _resolvers: VendorResolver[] = [];\n\n/**\n * Register a vendor resolver. Resolvers are tried in LIFO order\n * (last registered = highest priority), following the convention\n * from Vite/Rollup where later plugins override earlier ones.\n *\n * @returns A cleanup function that removes this resolver from the chain.\n */\nexport function addResolver(resolver: VendorResolver): () => void {\n _resolvers.push(resolver);\n return () => {\n const idx = _resolvers.indexOf(resolver);\n if (idx !== -1) _resolvers.splice(idx, 1);\n };\n}\n\n/**\n * Resolve a vendor name to a loader by walking the resolver chain (LIFO).\n * Returns `undefined` if no resolver can handle the name.\n */\nexport function resolveVendor(name: string): VendorLoader | undefined {\n for (let i = _resolvers.length - 1; i >= 0; i--) {\n const result = _resolvers[i](name);\n if (result) return result;\n }\n return undefined;\n}\n\n/** @internal — test helper only */\nexport function __resetResolvers(): void {\n _resolvers.length = 0;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { m as ConfigCommand, q as ConsentEventMap, C as ConsentState, l as McCommand, M as McConfig, k as McVendor, S as ServiceMetadata, a as Store, V as Vendor, n as VendorCommand, j as VendorConfig, g as VendorLoader, e as activateService, b as addResolver, f as clearVendorArtifacts, c as consentState, p as emitter, h as hasAnswered, t as initMcLayer, i as isPanelOpen, o as openPanel, d as registerService, r as resolveVendor, s as servicesList } from './resolver-
|
|
1
|
+
export { m as ConfigCommand, q as ConsentEventMap, C as ConsentState, l as McCommand, M as McConfig, k as McVendor, S as ServiceMetadata, a as Store, V as Vendor, n as VendorCommand, j as VendorConfig, g as VendorLoader, e as activateService, b as addResolver, f as clearVendorArtifacts, c as consentState, p as emitter, h as hasAnswered, t as initMcLayer, i as isPanelOpen, o as openPanel, d as registerService, r as resolveVendor, s as servicesList } from './resolver-CssVkauA.js';
|
|
2
2
|
|
|
3
3
|
declare global {
|
|
4
4
|
interface Window {
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { addResolver, resolveVendor } from './chunk-
|
|
2
|
-
export { addResolver, resolveVendor } from './chunk-
|
|
1
|
+
import { __publicField, addResolver, __spreadValues, resolveVendor, __spreadProps } from './chunk-ENHZCUQ7.js';
|
|
2
|
+
export { addResolver, resolveVendor } from './chunk-ENHZCUQ7.js';
|
|
3
3
|
|
|
4
4
|
// src/utils/store.ts
|
|
5
5
|
var Store = class {
|
|
6
|
-
value;
|
|
7
|
-
subscribers = /* @__PURE__ */ new Set();
|
|
8
6
|
constructor(initialValue) {
|
|
7
|
+
__publicField(this, "value");
|
|
8
|
+
__publicField(this, "subscribers", /* @__PURE__ */ new Set());
|
|
9
9
|
this.value = initialValue;
|
|
10
10
|
}
|
|
11
11
|
get() {
|
|
@@ -82,9 +82,9 @@ var isPanelOpen = new Store(false);
|
|
|
82
82
|
var openPanel = () => isPanelOpen.set(true);
|
|
83
83
|
var _cookieUnsubs = [];
|
|
84
84
|
var initState = (config) => {
|
|
85
|
-
const cookieName = config
|
|
86
|
-
const cookieDomain = config
|
|
87
|
-
const consentVersion = config
|
|
85
|
+
const cookieName = (config == null ? void 0 : config.cookieName) || DEFAULT_STORAGE_KEY;
|
|
86
|
+
const cookieDomain = config == null ? void 0 : config.cookieDomain;
|
|
87
|
+
const consentVersion = config == null ? void 0 : config.consentVersion;
|
|
88
88
|
let initialData = { consent: {}, answered: false };
|
|
89
89
|
if (typeof window !== "undefined") {
|
|
90
90
|
const stored = getCookie(cookieName);
|
|
@@ -128,11 +128,12 @@ var loaders = /* @__PURE__ */ new Map();
|
|
|
128
128
|
var loadedVendors = /* @__PURE__ */ new Map();
|
|
129
129
|
var vendorsConfig = /* @__PURE__ */ new Map();
|
|
130
130
|
function clearVendorArtifacts(id) {
|
|
131
|
+
var _a;
|
|
131
132
|
const vendor = loadedVendors.get(id);
|
|
132
|
-
if (!vendor
|
|
133
|
+
if (!(vendor == null ? void 0 : vendor.artifacts)) return;
|
|
133
134
|
const config = vendorsConfig.get(id);
|
|
134
135
|
const cookieNames = typeof vendor.artifacts === "function" ? vendor.artifacts(config) : vendor.artifacts;
|
|
135
|
-
const domain = window._modernConsentConfig
|
|
136
|
+
const domain = (_a = window._modernConsentConfig) == null ? void 0 : _a.cookieDomain;
|
|
136
137
|
cookieNames.forEach((name) => {
|
|
137
138
|
document.cookie = `${name}=; max-age=0; path=/`;
|
|
138
139
|
if (domain) {
|
|
@@ -150,11 +151,16 @@ function registerService(args) {
|
|
|
150
151
|
if (config !== void 0) {
|
|
151
152
|
vendorsConfig.set(id, config);
|
|
152
153
|
}
|
|
153
|
-
if (vendor
|
|
154
|
-
|
|
154
|
+
if (vendor == null ? void 0 : vendor.setup) {
|
|
155
|
+
try {
|
|
156
|
+
vendor.setup(config);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
console.error(`[modern-consent] setup() failed for "${id}":`, err);
|
|
159
|
+
}
|
|
155
160
|
}
|
|
156
|
-
if (vendor
|
|
161
|
+
if ((vendor == null ? void 0 : vendor.link) && vendor.link.length > 0) {
|
|
157
162
|
vendor.link.forEach((link) => {
|
|
163
|
+
var _a;
|
|
158
164
|
if (link.condition && !link.condition({ vendorConfig: config, consentConfig: window._modernConsentConfig })) {
|
|
159
165
|
return;
|
|
160
166
|
}
|
|
@@ -163,7 +169,7 @@ function registerService(args) {
|
|
|
163
169
|
registerService({
|
|
164
170
|
id: link.vendor,
|
|
165
171
|
category,
|
|
166
|
-
config: link.config
|
|
172
|
+
config: (_a = link.config) != null ? _a : {},
|
|
167
173
|
loader: linkedLoader
|
|
168
174
|
});
|
|
169
175
|
} else {
|
|
@@ -208,6 +214,7 @@ function checkAutoActivation(id) {
|
|
|
208
214
|
}
|
|
209
215
|
}
|
|
210
216
|
async function activateService(id) {
|
|
217
|
+
var _a, _b;
|
|
211
218
|
if (typeof window === "undefined") return;
|
|
212
219
|
let vendor = loadedVendors.get(id);
|
|
213
220
|
if (!vendor) {
|
|
@@ -219,17 +226,17 @@ async function activateService(id) {
|
|
|
219
226
|
}
|
|
220
227
|
}
|
|
221
228
|
if (!vendor) return;
|
|
222
|
-
const isSoft = window._modernConsentConfig
|
|
229
|
+
const isSoft = ((_a = window._modernConsentConfig) == null ? void 0 : _a.consentOnly) === true;
|
|
223
230
|
const list = servicesList.get();
|
|
224
231
|
const meta = list.find((s) => s.id === id);
|
|
225
232
|
if (!isSoft && vendor.init && meta && !meta.loaded) {
|
|
226
233
|
vendor.init(vendorsConfig.get(id));
|
|
227
|
-
servicesList.update((l) => l.map((s) => s.id === id ? {
|
|
228
|
-
vendor.event
|
|
234
|
+
servicesList.update((l) => l.map((s) => s.id === id ? __spreadProps(__spreadValues({}, s), { loaded: true }) : s));
|
|
235
|
+
(_b = vendor.event) == null ? void 0 : _b.forEach((ev) => {
|
|
229
236
|
if (ev.name === "onAccept") {
|
|
230
237
|
try {
|
|
231
238
|
ev.callback();
|
|
232
|
-
} catch {
|
|
239
|
+
} catch (e) {
|
|
233
240
|
}
|
|
234
241
|
}
|
|
235
242
|
});
|
|
@@ -238,7 +245,7 @@ async function activateService(id) {
|
|
|
238
245
|
setTimeout(() => {
|
|
239
246
|
document.querySelectorAll(vendor.domSelector).forEach((el) => {
|
|
240
247
|
const htmlElement = el;
|
|
241
|
-
if (htmlElement.dataset.loaded !== "true" && vendor
|
|
248
|
+
if (htmlElement.dataset.loaded !== "true" && (vendor == null ? void 0 : vendor.render)) {
|
|
242
249
|
htmlElement.innerHTML = vendor.render(htmlElement.dataset);
|
|
243
250
|
htmlElement.dataset.loaded = "true";
|
|
244
251
|
htmlElement.classList.remove("mc-placeholder-pending");
|
|
@@ -250,20 +257,27 @@ async function activateService(id) {
|
|
|
250
257
|
|
|
251
258
|
// src/emitter.ts
|
|
252
259
|
var ConsentEmitter = class {
|
|
253
|
-
|
|
260
|
+
constructor() {
|
|
261
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Map());
|
|
262
|
+
}
|
|
254
263
|
on(event, cb) {
|
|
255
264
|
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
256
265
|
this.listeners.get(event).add(cb);
|
|
257
|
-
return () =>
|
|
266
|
+
return () => {
|
|
267
|
+
var _a;
|
|
268
|
+
return (_a = this.listeners.get(event)) == null ? void 0 : _a.delete(cb);
|
|
269
|
+
};
|
|
258
270
|
}
|
|
259
271
|
off(event, cb) {
|
|
260
|
-
|
|
272
|
+
var _a;
|
|
273
|
+
(_a = this.listeners.get(event)) == null ? void 0 : _a.delete(cb);
|
|
261
274
|
}
|
|
262
275
|
emit(event, data) {
|
|
263
|
-
|
|
276
|
+
var _a;
|
|
277
|
+
(_a = this.listeners.get(event)) == null ? void 0 : _a.forEach((cb) => {
|
|
264
278
|
try {
|
|
265
279
|
cb(data);
|
|
266
|
-
} catch {
|
|
280
|
+
} catch (e) {
|
|
267
281
|
}
|
|
268
282
|
});
|
|
269
283
|
}
|
|
@@ -272,6 +286,7 @@ var emitter = new ConsentEmitter();
|
|
|
272
286
|
|
|
273
287
|
// src/consent.ts
|
|
274
288
|
function pushConsentEvent(consent) {
|
|
289
|
+
var _a;
|
|
275
290
|
if (typeof window === "undefined") return;
|
|
276
291
|
const event = {
|
|
277
292
|
event: "consent_update",
|
|
@@ -279,22 +294,24 @@ function pushConsentEvent(consent) {
|
|
|
279
294
|
};
|
|
280
295
|
window.consentLayer = window.consentLayer || [];
|
|
281
296
|
window.consentLayer.push(event);
|
|
282
|
-
if (window._modernConsentConfig
|
|
297
|
+
if ((_a = window._modernConsentConfig) == null ? void 0 : _a.pushDataLayer) {
|
|
283
298
|
window.dataLayer = window.dataLayer || [];
|
|
284
299
|
window.dataLayer.push(event);
|
|
285
300
|
}
|
|
286
301
|
}
|
|
287
302
|
function emitConsentSaved(consent) {
|
|
303
|
+
var _a;
|
|
288
304
|
emitter.emit("consent:saved", {
|
|
289
305
|
consentId: generateUUID(),
|
|
290
306
|
timestamp: Date.now(),
|
|
291
|
-
version: typeof window !== "undefined" ? window._modernConsentConfig
|
|
307
|
+
version: typeof window !== "undefined" ? (_a = window._modernConsentConfig) == null ? void 0 : _a.consentVersion : void 0,
|
|
292
308
|
consent
|
|
293
309
|
});
|
|
294
310
|
}
|
|
295
311
|
function setConsent(id, allowed) {
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
var _a, _b, _c;
|
|
313
|
+
const wasPreviouslyLoaded = (_b = (_a = servicesList.get().find((s) => s.id === id)) == null ? void 0 : _a.loaded) != null ? _b : false;
|
|
314
|
+
consentState.update((s) => __spreadProps(__spreadValues({}, s), { [id]: allowed }));
|
|
298
315
|
hasAnswered.set(true);
|
|
299
316
|
emitter.emit("consent:update", {
|
|
300
317
|
vendor: id,
|
|
@@ -309,7 +326,7 @@ function setConsent(id, allowed) {
|
|
|
309
326
|
}
|
|
310
327
|
if (wasPreviouslyLoaded) {
|
|
311
328
|
clearVendorArtifacts(id);
|
|
312
|
-
const isConsentOnly = typeof window !== "undefined" && window._modernConsentConfig
|
|
329
|
+
const isConsentOnly = typeof window !== "undefined" && ((_c = window._modernConsentConfig) == null ? void 0 : _c.consentOnly) === true;
|
|
313
330
|
if (!isConsentOnly && typeof window !== "undefined") window.location.reload();
|
|
314
331
|
}
|
|
315
332
|
}
|
|
@@ -330,6 +347,7 @@ function acceptAll() {
|
|
|
330
347
|
emitConsentSaved(updates);
|
|
331
348
|
}
|
|
332
349
|
function denyAll() {
|
|
350
|
+
var _a;
|
|
333
351
|
const list = servicesList.get();
|
|
334
352
|
const updates = {};
|
|
335
353
|
let needsReload = false;
|
|
@@ -346,7 +364,7 @@ function denyAll() {
|
|
|
346
364
|
});
|
|
347
365
|
pushConsentEvent(updates);
|
|
348
366
|
emitConsentSaved(updates);
|
|
349
|
-
const isConsentOnly = typeof window !== "undefined" && window._modernConsentConfig
|
|
367
|
+
const isConsentOnly = typeof window !== "undefined" && ((_a = window._modernConsentConfig) == null ? void 0 : _a.consentOnly) === true;
|
|
350
368
|
if (needsReload && !isConsentOnly && typeof window !== "undefined") {
|
|
351
369
|
window.location.reload();
|
|
352
370
|
}
|
|
@@ -367,9 +385,9 @@ function handleVendor(event) {
|
|
|
367
385
|
artifacts
|
|
368
386
|
} = event;
|
|
369
387
|
let loader;
|
|
370
|
-
if (init
|
|
388
|
+
if (init != null ? init : setup) {
|
|
371
389
|
loader = async () => ({
|
|
372
|
-
name: label
|
|
390
|
+
name: label != null ? label : name,
|
|
373
391
|
description,
|
|
374
392
|
category,
|
|
375
393
|
requireConsent,
|
|
@@ -396,7 +414,8 @@ function initMcLayer() {
|
|
|
396
414
|
w._modernConsentConfig = {};
|
|
397
415
|
addResolver((_name) => {
|
|
398
416
|
return async () => {
|
|
399
|
-
|
|
417
|
+
var _a, _b;
|
|
418
|
+
const cdnBase = (_a = w._modernConsentConfig) == null ? void 0 : _a.cdnBase;
|
|
400
419
|
if (!cdnBase) {
|
|
401
420
|
throw new Error(
|
|
402
421
|
`[modern-consent] Vendor "${_name}" not found. Configure cdnBase to enable CDN loading, or provide an inline init().`
|
|
@@ -407,7 +426,7 @@ function initMcLayer() {
|
|
|
407
426
|
/* @vite-ignore */
|
|
408
427
|
url
|
|
409
428
|
);
|
|
410
|
-
return mod.default
|
|
429
|
+
return (_b = mod.default) != null ? _b : mod;
|
|
411
430
|
};
|
|
412
431
|
});
|
|
413
432
|
existingQueue.forEach((args) => {
|
|
@@ -417,7 +436,7 @@ function initMcLayer() {
|
|
|
417
436
|
return;
|
|
418
437
|
}
|
|
419
438
|
if (command === "config") {
|
|
420
|
-
w._modernConsentConfig = {
|
|
439
|
+
w._modernConsentConfig = __spreadValues(__spreadValues({}, w._modernConsentConfig), payload);
|
|
421
440
|
return;
|
|
422
441
|
}
|
|
423
442
|
handleVendor(payload);
|
|
@@ -432,7 +451,7 @@ function initMcLayer() {
|
|
|
432
451
|
if (command === "vendor") {
|
|
433
452
|
handleVendor(payload);
|
|
434
453
|
} else if (command === "config") {
|
|
435
|
-
w._modernConsentConfig = {
|
|
454
|
+
w._modernConsentConfig = __spreadValues(__spreadValues({}, w._modernConsentConfig), payload);
|
|
436
455
|
}
|
|
437
456
|
if (!Array.isArray(w.mcLayer)) w.mcLayer = [];
|
|
438
457
|
w.mcLayer.push(args);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/store.ts","../src/utils/uuid.ts","../src/state.ts","../src/registry.ts","../src/emitter.ts","../src/consent.ts","../src/layer.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\n\nexport class Store<T> {\n private value: T;\n private subscribers: Set<Subscriber<T>> = new Set();\n\n constructor(initialValue: T) {\n this.value = initialValue;\n }\n\n get(): T {\n return this.value;\n }\n\n set(newValue: T): void {\n if (this.value !== newValue) {\n this.value = newValue;\n this.notify();\n }\n }\n\n update(updater: (value: T) => T): void {\n this.set(updater(this.value));\n }\n\n subscribe(callback: Subscriber<T>): Unsubscriber {\n this.subscribers.add(callback);\n callback(this.value); // Appel immédiat\n return () => this.subscribers.delete(callback);\n }\n\n private notify(): void {\n this.subscribers.forEach(cb => cb(this.value));\n }\n}\n","function manualUUIDv4(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n // Set version 4 (0100) and variant 10xx bits per RFC 4122\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20),\n ].join('-');\n}\n\nexport const generateUUID = (): string =>\n typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : manualUUIDv4();\n","// core/src/state.ts\nimport { Store } from './utils/store';\nimport { generateUUID } from './utils/uuid';\n\nexport interface ConsentState {\n [serviceId: string]: boolean;\n}\n\nexport interface ServiceMetadata {\n id: string;\n name: string;\n description: string;\n category: string;\n /** Human-readable label for the purpose/category in 'purpose' displayMode. */\n purposeLabel?: string | Record<string, string>;\n /** Optional description for the purpose/category in 'purpose' displayMode. */\n purposeDescription?: string | Record<string, string>;\n loaded: boolean;\n requireConsent: boolean;\n}\n\ninterface StoredState {\n consent: ConsentState;\n answered: boolean;\n /** Unix timestamp (ms) of when consent was last given — for GDPR audit trail. */\n timestamp?: number;\n /** Version of the consent banner at the time of consent. */\n version?: string;\n /** Unique identifier per consent action — for GDPR audit trail. */\n consentId?: string;\n}\n\nconst DEFAULT_STORAGE_KEY = 'mc_consent_state';\n\ninterface CookieOptions {\n days?: number;\n path?: string;\n domain?: string;\n sameSite?: 'Lax' | 'Strict' | 'None';\n secure?: boolean;\n}\n\nfunction escapeCookieName(name: string): string {\n return name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nconst getCookie = (name: string): string | null => {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(?:^|; )${escapeCookieName(name)}=([^;]*)`));\n return match ? decodeURIComponent(match[1]) : null;\n};\n\nconst setCookie = (name: string, value: string, options: CookieOptions = {}) => {\n if (typeof document === 'undefined') return;\n\n const { days = 365, path = '/', domain, sameSite = 'Lax', secure = false } = options;\n\n const expires = new Date();\n expires.setDate(expires.getDate() + days);\n\n let cookieString =\n `${name}=${encodeURIComponent(value)};` +\n `expires=${expires.toUTCString()};` +\n `path=${path};` +\n `SameSite=${sameSite}`;\n\n if (domain) {\n const hostname = typeof window !== 'undefined' ? window.location.hostname : '';\n if (hostname && !hostname.endsWith(domain.replace(/^\\./, ''))) {\n console.warn(\n `[modern-consent] cookieDomain \"${domain}\" does not match current hostname \"${hostname}\". ` +\n `The cookie will be silently rejected by the browser. ` +\n `Remove cookieDomain for local development.`,\n );\n }\n cookieString += `;domain=${domain}`;\n }\n if (secure || sameSite === 'None') cookieString += `;Secure`;\n\n document.cookie = cookieString;\n};\n\nexport const consentState = new Store<ConsentState>({});\nexport const hasAnswered = new Store<boolean>(false);\nexport const servicesList = new Store<ServiceMetadata[]>([]);\nexport const isPanelOpen = new Store<boolean>(false);\nexport const openPanel = () => isPanelOpen.set(true);\n\n// Tracked so that calling initState multiple times never stacks duplicate subscribers\nlet _cookieUnsubs: (() => void)[] = [];\n\nexport const initState = (config: any) => {\n const cookieName: string = config?.cookieName || DEFAULT_STORAGE_KEY;\n const cookieDomain: string | undefined = config?.cookieDomain;\n const consentVersion: string | undefined = config?.consentVersion;\n\n let initialData: StoredState = { consent: {}, answered: false };\n\n if (typeof window !== 'undefined') {\n const stored = getCookie(cookieName);\n if (stored) {\n try {\n initialData = JSON.parse(stored) as StoredState;\n } catch (e) {\n console.error('[modern-consent] Error parsing consent cookie', e);\n }\n }\n }\n\n consentState.set(initialData.consent || {});\n hasAnswered.set(initialData.answered || false);\n\n // Re-prompt when consentVersion changes (GDPR: policy update invalidates prior consent)\n if (initialData.answered && consentVersion && initialData.version !== consentVersion) {\n hasAnswered.set(false);\n isPanelOpen.set(true);\n }\n\n if (typeof window !== 'undefined') {\n // Clean up previous subscriptions before creating new ones\n _cookieUnsubs.forEach(fn => fn());\n _cookieUnsubs = [];\n\n const saveToCookie = () => {\n const state: StoredState = {\n consent: consentState.get(),\n answered: hasAnswered.get(),\n timestamp: Date.now(),\n version: consentVersion,\n consentId: generateUUID(),\n };\n setCookie(cookieName, JSON.stringify(state), {\n domain: cookieDomain,\n secure: window.location.protocol === 'https:',\n });\n };\n\n _cookieUnsubs.push(consentState.subscribe(saveToCookie));\n _cookieUnsubs.push(hasAnswered.subscribe(saveToCookie));\n }\n};\n","import { consentState, hasAnswered, isPanelOpen, servicesList } from './state';\nimport { resolveVendor } from './resolver';\nimport type { McConfig } from './layer';\n\ndeclare global {\n interface Window {\n _modernConsentConfig: McConfig;\n }\n}\n\nexport type VendorConfig = unknown;\n\nexport interface Vendor<TConfig = void> {\n name: string;\n description: string;\n category: string;\n /**\n * Human-readable label for the purpose/category in 'purpose' displayMode.\n * Can be a string or a Record<lang, string> for i18n support.\n * @example purposeLabel: { fr: \"Mesure d'audience\", en: \"Audience measurement\" }\n */\n purposeLabel?: string | Record<string, string>;\n /**\n * Description for the purpose/category in 'purpose' displayMode.\n * Can be a string or a Record<lang, string> for i18n support.\n */\n purposeDescription?: string | Record<string, string>;\n setup?: (config: TConfig) => void;\n domSelector?: string;\n init?: (config: TConfig) => void;\n /** Cookie names set by this vendor — cleared when consent is revoked. */\n artifacts?: string[] | ((config: TConfig) => string[]);\n render?: (dataset: DOMStringMap) => string;\n requireConsent: boolean;\n event?: {\n name: string;\n callback: () => void;\n }[];\n link?: {\n vendor: string;\n /** Config passed to the linked vendor. Defaults to {} if omitted. */\n config?: VendorConfig;\n condition: (params: { vendorConfig: any; consentConfig: any }) => boolean;\n }[];\n}\n\nexport type VendorLoader = () => Promise<Vendor<any>>;\n\nconst loaders = new Map<string, VendorLoader>();\nconst loadedVendors = new Map<string, Vendor<VendorConfig>>();\nconst vendorsConfig = new Map<string, VendorConfig>();\n\n// Re-export resolveVendor from resolver.ts for backward compatibility\nexport { resolveVendor } from './resolver';\n\n/** @internal — test helper only */\nexport function __resetRegistry() {\n loaders.clear();\n loadedVendors.clear();\n vendorsConfig.clear();\n}\n\n/**\n * Clears all cookies declared in vendor.artifacts.\n * Called before reload or on denyAll to clean up vendor-set cookies.\n */\nexport function clearVendorArtifacts(id: string): void {\n const vendor = loadedVendors.get(id);\n if (!vendor?.artifacts) return;\n\n const config = vendorsConfig.get(id);\n const cookieNames =\n typeof vendor.artifacts === 'function' ? vendor.artifacts(config) : vendor.artifacts;\n\n const domain = window._modernConsentConfig?.cookieDomain;\n\n cookieNames.forEach(name => {\n document.cookie = `${name}=; max-age=0; path=/`;\n if (domain) {\n document.cookie = `${name}=; max-age=0; path=/; domain=${domain}`;\n }\n });\n}\n\nexport function registerService(args: {\n id: string;\n category: string;\n loader: VendorLoader;\n config: VendorConfig;\n}) {\n const { id, category, loader, config = {} } = args;\n\n // Prevent double-registration for the same service id\n if (loaders.has(id)) return;\n loaders.set(id, loader);\n\n loader()\n .then((module: any) => {\n const vendor: Vendor<any> = module.default || module;\n loadedVendors.set(id, vendor);\n if (config !== undefined) {\n vendorsConfig.set(id, config);\n }\n\n if (vendor?.setup) {\n vendor.setup(config);\n }\n\n if (vendor?.link && vendor.link.length > 0) {\n vendor.link.forEach(link => {\n if (\n link.condition &&\n !link.condition({ vendorConfig: config, consentConfig: window._modernConsentConfig })\n ) {\n return;\n }\n const linkedLoader = resolveVendor(link.vendor);\n if (linkedLoader) {\n registerService({\n id: link.vendor,\n category,\n config: link.config ?? {},\n loader: linkedLoader,\n });\n } else {\n console.warn(`[modern-consent] Dependency \"${link.vendor}\" not found for \"${id}\"`);\n }\n });\n }\n\n servicesList.update(list => {\n if (list.some(s => s.id === id)) return list;\n return [\n ...list,\n {\n id,\n name: vendor.name,\n description: vendor.description,\n category: vendor.category,\n purposeLabel: vendor.purposeLabel,\n purposeDescription: vendor.purposeDescription,\n loaded: false,\n requireConsent: vendor.requireConsent,\n },\n ];\n });\n\n checkAutoActivation(id);\n })\n .catch(err => {\n console.error(`[modern-consent] Failed to load vendor \"${id}\":`, err);\n });\n}\n\n/**\n * Vérifie si on doit activer le service ou ouvrir le panel (nouveau service détecté)\n */\nfunction checkAutoActivation(id: string) {\n const vendor = loadedVendors.get(id);\n\n // Services that don't require consent activate immediately\n if (vendor && !vendor.requireConsent) {\n activateService(id);\n return;\n }\n\n const currentConsent = consentState.get();\n const answered = hasAnswered.get();\n\n if (answered && currentConsent[id] === undefined) {\n isPanelOpen.set(true);\n }\n\n if (currentConsent[id]) {\n activateService(id);\n }\n}\n\n/**\n * Active le service (Script + DOM)\n */\nexport async function activateService(id: string) {\n if (typeof window === 'undefined') return;\n\n let vendor = loadedVendors.get(id);\n\n if (!vendor) {\n const loader = loaders.get(id);\n if (loader) {\n const module: any = await loader();\n vendor = module.default || module;\n if (vendor) loadedVendors.set(id, vendor);\n }\n }\n\n if (!vendor) return;\n\n const isSoft = window._modernConsentConfig?.consentOnly === true;\n const list = servicesList.get();\n const meta = list.find(s => s.id === id);\n\n if (!isSoft && vendor.init && meta && !meta.loaded) {\n vendor.init(vendorsConfig.get(id));\n servicesList.update(l => l.map(s => (s.id === id ? { ...s, loaded: true } : s)));\n\n // Trigger onAccept events after successful activation\n vendor.event?.forEach(ev => {\n if (ev.name === 'onAccept') {\n try {\n ev.callback();\n } catch {\n /* don't let event errors break activation */\n }\n }\n });\n }\n\n if (!isSoft && vendor.domSelector && vendor.render) {\n setTimeout(() => {\n document.querySelectorAll(vendor!.domSelector!).forEach(el => {\n const htmlElement = el as HTMLElement;\n if (htmlElement.dataset.loaded !== 'true' && vendor?.render) {\n htmlElement.innerHTML = vendor.render(htmlElement.dataset);\n htmlElement.dataset.loaded = 'true';\n htmlElement.classList.remove('mc-placeholder-pending');\n }\n });\n }, 50);\n }\n}\n","import type { ConsentState } from './state';\n\nexport type ConsentEventMap = {\n 'consent:update': { vendor: string; status: 'granted' | 'denied'; gcm?: Record<string, boolean> };\n 'consent:saved': {\n consentId: string;\n timestamp: number;\n version?: string;\n consent: ConsentState;\n };\n};\n\ntype Listener<T> = (data: T) => void;\n\nclass ConsentEmitter {\n private listeners = new Map<string, Set<Listener<any>>>();\n\n on<K extends keyof ConsentEventMap>(event: K, cb: Listener<ConsentEventMap[K]>): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n this.listeners.get(event)!.add(cb);\n return () => this.listeners.get(event)?.delete(cb);\n }\n\n off<K extends keyof ConsentEventMap>(event: K, cb: Listener<ConsentEventMap[K]>): void {\n this.listeners.get(event)?.delete(cb);\n }\n\n emit<K extends keyof ConsentEventMap>(event: K, data: ConsentEventMap[K]): void {\n this.listeners.get(event)?.forEach(cb => {\n try {\n cb(data);\n } catch {\n /* don't let listener errors break the core */\n }\n });\n }\n}\n\nexport const emitter = new ConsentEmitter();\n","import { servicesList, consentState, hasAnswered, isPanelOpen } from './state';\nimport type { ConsentState } from './state';\nimport { activateService, clearVendorArtifacts } from './registry';\nimport { emitter } from './emitter';\nimport { generateUUID } from './utils/uuid';\n\ndeclare global {\n interface Window {\n consentLayer: any[];\n dataLayer: any[];\n }\n}\n\n/**\n * Always pushes consent state to `window.consentLayer` (TMS-agnostic).\n * Optionally pushes to `window.dataLayer` when `pushDataLayer` is enabled (GTM convenience).\n */\nfunction pushConsentEvent(consent: ConsentState) {\n if (typeof window === 'undefined') return;\n\n const event = {\n event: 'consent_update',\n consent_state: consent,\n };\n\n // consentLayer — always active, TMS-agnostic\n window.consentLayer = window.consentLayer || [];\n window.consentLayer.push(event);\n\n // dataLayer — opt-in for GTM native triggers\n if (window._modernConsentConfig?.pushDataLayer) {\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(event);\n }\n}\n\nfunction emitConsentSaved(consent: ConsentState) {\n emitter.emit('consent:saved', {\n consentId: generateUUID(),\n timestamp: Date.now(),\n version:\n typeof window !== 'undefined' ? window._modernConsentConfig?.consentVersion : undefined,\n consent,\n });\n}\n\nexport function setConsent(id: string, allowed: boolean) {\n // Check before updating state whether this service was actively running\n const wasPreviouslyLoaded = servicesList.get().find(s => s.id === id)?.loaded ?? false;\n\n consentState.update(s => ({ ...s, [id]: allowed }));\n hasAnswered.set(true);\n\n emitter.emit('consent:update', {\n vendor: id,\n status: allowed ? 'granted' : 'denied',\n });\n\n const updatedConsent = consentState.get();\n pushConsentEvent(updatedConsent);\n emitConsentSaved(updatedConsent);\n\n if (allowed) {\n activateService(id);\n return;\n }\n\n // Only clean up and reload if the service was actively running\n if (wasPreviouslyLoaded) {\n clearVendorArtifacts(id);\n const isConsentOnly =\n typeof window !== 'undefined' && window._modernConsentConfig?.consentOnly === true;\n if (!isConsentOnly && typeof window !== 'undefined') window.location.reload();\n }\n}\n\nexport function acceptAll() {\n const list = servicesList.get();\n const updates: Record<string, boolean> = {};\n\n list.forEach(s => {\n updates[s.id] = true;\n activateService(s.id);\n });\n\n consentState.set(updates);\n hasAnswered.set(true);\n isPanelOpen.set(false);\n\n list.forEach(s => {\n emitter.emit('consent:update', { vendor: s.id, status: 'granted' });\n });\n\n pushConsentEvent(updates);\n emitConsentSaved(updates);\n}\n\nexport function denyAll() {\n const list = servicesList.get();\n const updates: Record<string, boolean> = {};\n let needsReload = false;\n\n list.forEach(s => {\n updates[s.id] = false;\n clearVendorArtifacts(s.id);\n if (s.loaded) needsReload = true;\n });\n\n consentState.set(updates);\n hasAnswered.set(true);\n isPanelOpen.set(false);\n\n list.forEach(s => {\n emitter.emit('consent:update', { vendor: s.id, status: 'denied' });\n });\n\n pushConsentEvent(updates);\n emitConsentSaved(updates);\n\n // Reload only if at least one vendor was actively running —\n // clears vendor scripts from memory after cookie cleanup.\n const isConsentOnly =\n typeof window !== 'undefined' && window._modernConsentConfig?.consentOnly === true;\n if (needsReload && !isConsentOnly && typeof window !== 'undefined') {\n window.location.reload();\n }\n}\n","import { registerService } from './registry';\nimport { addResolver, resolveVendor } from './resolver';\nimport { consentState, initState, isPanelOpen } from './state';\nimport type { ConsentState } from './state';\nimport type { Vendor } from './registry';\nimport { emitter } from './emitter';\n\n/**\n * Command can add in config\n */\nconst validCommands = ['config', 'vendor'] as const;\n\nexport interface McConfig {\n cookieDomain?: string;\n cookieName?: string;\n consentMode?: boolean;\n /** Version string embedded in the stored consent — used for GDPR audit trails. */\n consentVersion?: string;\n /**\n * Base URL where vendor JS files are hosted.\n * Used by the CDN bundle to lazy-load vendors on demand.\n *\n * @example 'https://cdn.monsite.com/mc-vendors'\n * → window.modernConsent('vendor', { name: 'google-analytics' })\n * → fetches https://cdn.monsite.com/mc-vendors/google-analytics.js\n */\n cdnBase?: string;\n /**\n * In Consent-Only mode, the CMP only manages consent decisions + cookie storage.\n * Vendors are never initialized (no call to init()).\n * Use this to manage vendor scripts externally via a Tag Manager (GTM, TagCommander, etc.).\n *\n * Consent changes are always pushed to `window.consentLayer`.\n * Enable `pushDataLayer` to also push to `window.dataLayer` for native GTM triggers.\n */\n consentOnly?: boolean;\n /**\n * When true, consent changes are also pushed to `window.dataLayer` for native\n * GTM trigger support. Disabled by default — GTM users should enable this.\n */\n pushDataLayer?: boolean;\n /**\n * How the details panel displays consent controls:\n * - 'vendor' (default): individual toggle per vendor, grouped by category\n * - 'purpose': toggle per category/purpose, vendors listed as info below\n */\n displayMode?: 'vendor' | 'purpose';\n /**\n * Custom labels for each purpose/category in 'purpose' displayMode.\n * Keys must match the vendor `category` values.\n *\n * @example\n * purposes: {\n * analytics: { label: \"Analyse de session et mesure d'audience\" },\n * Publicité: { label: \"Ciblage Marketing\" },\n * }\n */\n purposes?: Record<\n string,\n {\n /** Human-readable label displayed as the purpose title. */\n label: string;\n /** Optional description shown below the purpose title. */\n description?: string;\n }\n >;\n /**\n * When true, displays a \"Functional / Site operation\" mandatory purpose block\n * at the top of the details panel. This is a visual-only block with no toggle —\n * it informs the user that essential cookies are always active.\n */\n functionalPurpose?: boolean;\n}\n\nexport interface McVendor {\n /**\n * Built-in vendor name (e.g. 'google-analytics') when using npm with\n * built-in loaders, OR a unique ID when providing an inline init().\n */\n name: string;\n /**\n * Category for this vendor (e.g. 'analytics', 'marketing').\n * Optional for built-in vendors — they define their own category.\n * Required for inline vendors (defaults to 'other' if omitted).\n */\n category?: string;\n config?: Record<string, any>;\n\n // --- Inline vendor definition (CDN users / custom vendors) ---\n /** Human-readable label shown in the consent UI. Defaults to `name`. */\n label?: string;\n /** Short description shown in the consent UI. */\n description?: string;\n /** Whether the user must explicitly consent before this vendor activates. @default true */\n requireConsent?: boolean;\n /** Called immediately at page load (e.g. set consent defaults). */\n setup?: (config?: Record<string, any>) => void;\n /** Called when consent is granted. Inject scripts, pixels, etc. here. */\n init?: (config?: Record<string, any>) => void;\n /** Cookie names written by this vendor — cleared when consent is revoked. */\n artifacts?: string[];\n}\n\nexport type ConfigCommand = ['config', McConfig];\nexport type VendorCommand = ['vendor', McVendor];\nexport type McCommand = ConfigCommand | VendorCommand;\n\ntype McAPI = {\n (...args: McCommand): void;\n openPanel: () => void;\n getConsent: () => ConsentState;\n on: typeof emitter.on;\n};\n\ndeclare global {\n interface Window {\n _modernConsentConfig: McConfig;\n mcLayer: McCommand[];\n modernConsent: McAPI;\n }\n}\n\nfunction handleVendor(event: McVendor) {\n const {\n name,\n label,\n description = '',\n category = 'other',\n config = {},\n requireConsent = true,\n setup,\n init,\n artifacts,\n } = event;\n\n let loader: import('./registry').VendorLoader;\n\n if (init ?? setup) {\n // Inline vendor — CDN users provide their own implementation.\n loader = async () => ({\n name: label ?? name,\n description,\n category,\n requireConsent,\n setup,\n init,\n artifacts,\n });\n } else {\n // Look up via the resolver chain (builtin, CDN, or user-registered resolvers).\n const resolved = resolveVendor(name);\n if (!resolved) {\n console.warn(\n `[modern-consent] Unknown vendor \"${name}\". ` +\n `Provide an init() function to define a custom vendor.`,\n );\n return;\n }\n loader = resolved;\n }\n\n registerService({ id: name, category, config, loader });\n}\n\n/**\n * Initialise window.mcLayer et traite la queue éventuelle.\n */\nexport function initMcLayer() {\n if (typeof window === 'undefined') return;\n\n const w = window;\n const existingQueue = Array.isArray(w.mcLayer) ? [...w.mcLayer] : [];\n\n w._modernConsentConfig = {};\n\n // CDN resolver — lowest priority (registered first = LIFO lowest).\n // Returns a loader for any name; cdnBase is checked lazily at activation time.\n addResolver(_name => {\n return async () => {\n const cdnBase = w._modernConsentConfig?.cdnBase;\n if (!cdnBase) {\n throw new Error(\n `[modern-consent] Vendor \"${_name}\" not found. ` +\n `Configure cdnBase to enable CDN loading, or provide an inline init().`,\n );\n }\n const url = `${cdnBase.replace(/\\/$/, '')}/${_name}.js`;\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? mod) as Vendor<any>;\n };\n });\n\n // Process the existing queue — config commands accumulate before vendors are registered\n existingQueue.forEach((args: McCommand) => {\n const [command, payload] = args;\n\n if (!validCommands.includes(command as any)) {\n console.warn(`[modern-consent] \"${command}\" is not a valid command`);\n return;\n }\n\n if (command === 'config') {\n w._modernConsentConfig = { ...w._modernConsentConfig, ...(payload as McConfig) };\n return;\n }\n\n handleVendor(payload as McVendor);\n });\n\n // State is initialised once after config is fully resolved from the queue\n initState(w._modernConsentConfig);\n\n // Live API\n const apiFn = (...args: McCommand) => {\n const [command, payload] = args;\n\n if (!validCommands.includes(command as any)) {\n console.warn(`[modern-consent] \"${command}\" is not a valid command`);\n return;\n }\n\n if (command === 'vendor') {\n handleVendor(payload as McVendor);\n } else if (command === 'config') {\n w._modernConsentConfig = { ...w._modernConsentConfig, ...(payload as McConfig) };\n }\n\n if (!Array.isArray(w.mcLayer)) w.mcLayer = [];\n w.mcLayer.push(args);\n };\n\n w.modernConsent = Object.assign(apiFn, {\n openPanel: () => isPanelOpen.set(true),\n getConsent: () => consentState.get(),\n on: emitter.on.bind(emitter),\n });\n}\n","export type { ConsentState, ServiceMetadata } from './state.ts';\n\nexport { Store } from './utils/store';\n\nexport { consentState, hasAnswered, servicesList, isPanelOpen, openPanel } from './state';\n\n// Vendor Resolution\nexport { addResolver, resolveVendor } from './resolver';\n\nexport {\n registerService,\n activateService,\n clearVendorArtifacts,\n type Vendor,\n type VendorLoader,\n type VendorConfig,\n} from './registry';\n\nexport { setConsent, acceptAll, denyAll } from './consent';\n\nexport type { McConfig, McVendor, McCommand, ConfigCommand, VendorCommand } from './layer';\n\nexport { emitter, type ConsentEventMap } from './emitter';\nexport { generateUUID } from './utils/uuid';\nexport { initMcLayer } from './layer';\n\nimport { initMcLayer } from './layer';\n\nif (typeof window !== 'undefined') {\n initMcLayer();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/store.ts","../src/utils/uuid.ts","../src/state.ts","../src/registry.ts","../src/emitter.ts","../src/consent.ts","../src/layer.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\n\nexport class Store<T> {\n private value: T;\n private subscribers: Set<Subscriber<T>> = new Set();\n\n constructor(initialValue: T) {\n this.value = initialValue;\n }\n\n get(): T {\n return this.value;\n }\n\n set(newValue: T): void {\n if (this.value !== newValue) {\n this.value = newValue;\n this.notify();\n }\n }\n\n update(updater: (value: T) => T): void {\n this.set(updater(this.value));\n }\n\n subscribe(callback: Subscriber<T>): Unsubscriber {\n this.subscribers.add(callback);\n callback(this.value); // Appel immédiat\n return () => this.subscribers.delete(callback);\n }\n\n private notify(): void {\n this.subscribers.forEach(cb => cb(this.value));\n }\n}\n","function manualUUIDv4(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n // Set version 4 (0100) and variant 10xx bits per RFC 4122\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20),\n ].join('-');\n}\n\nexport const generateUUID = (): string =>\n typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : manualUUIDv4();\n","// core/src/state.ts\nimport { Store } from './utils/store';\nimport { generateUUID } from './utils/uuid';\n\nexport interface ConsentState {\n [serviceId: string]: boolean;\n}\n\nexport interface ServiceMetadata {\n id: string;\n name: string;\n description: string;\n category: string;\n /** Human-readable label for the purpose/category in 'purpose' displayMode. */\n purposeLabel?: string | Record<string, string>;\n /** Optional description for the purpose/category in 'purpose' displayMode. */\n purposeDescription?: string | Record<string, string>;\n loaded: boolean;\n requireConsent: boolean;\n}\n\ninterface StoredState {\n consent: ConsentState;\n answered: boolean;\n /** Unix timestamp (ms) of when consent was last given — for GDPR audit trail. */\n timestamp?: number;\n /** Version of the consent banner at the time of consent. */\n version?: string;\n /** Unique identifier per consent action — for GDPR audit trail. */\n consentId?: string;\n}\n\nconst DEFAULT_STORAGE_KEY = 'mc_consent_state';\n\ninterface CookieOptions {\n days?: number;\n path?: string;\n domain?: string;\n sameSite?: 'Lax' | 'Strict' | 'None';\n secure?: boolean;\n}\n\nfunction escapeCookieName(name: string): string {\n return name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nconst getCookie = (name: string): string | null => {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(?:^|; )${escapeCookieName(name)}=([^;]*)`));\n return match ? decodeURIComponent(match[1]) : null;\n};\n\nconst setCookie = (name: string, value: string, options: CookieOptions = {}) => {\n if (typeof document === 'undefined') return;\n\n const { days = 365, path = '/', domain, sameSite = 'Lax', secure = false } = options;\n\n const expires = new Date();\n expires.setDate(expires.getDate() + days);\n\n let cookieString =\n `${name}=${encodeURIComponent(value)};` +\n `expires=${expires.toUTCString()};` +\n `path=${path};` +\n `SameSite=${sameSite}`;\n\n if (domain) {\n const hostname = typeof window !== 'undefined' ? window.location.hostname : '';\n if (hostname && !hostname.endsWith(domain.replace(/^\\./, ''))) {\n console.warn(\n `[modern-consent] cookieDomain \"${domain}\" does not match current hostname \"${hostname}\". ` +\n `The cookie will be silently rejected by the browser. ` +\n `Remove cookieDomain for local development.`,\n );\n }\n cookieString += `;domain=${domain}`;\n }\n if (secure || sameSite === 'None') cookieString += `;Secure`;\n\n document.cookie = cookieString;\n};\n\nexport const consentState = new Store<ConsentState>({});\nexport const hasAnswered = new Store<boolean>(false);\nexport const servicesList = new Store<ServiceMetadata[]>([]);\nexport const isPanelOpen = new Store<boolean>(false);\nexport const openPanel = () => isPanelOpen.set(true);\n\n// Tracked so that calling initState multiple times never stacks duplicate subscribers\nlet _cookieUnsubs: (() => void)[] = [];\n\nexport const initState = (\n config: Pick<import('./layer').McConfig, 'cookieName' | 'cookieDomain' | 'consentVersion'>,\n) => {\n const cookieName: string = config?.cookieName || DEFAULT_STORAGE_KEY;\n const cookieDomain: string | undefined = config?.cookieDomain;\n const consentVersion: string | undefined = config?.consentVersion;\n\n let initialData: StoredState = { consent: {}, answered: false };\n\n if (typeof window !== 'undefined') {\n const stored = getCookie(cookieName);\n if (stored) {\n try {\n initialData = JSON.parse(stored) as StoredState;\n } catch (e) {\n console.error('[modern-consent] Error parsing consent cookie', e);\n }\n }\n }\n\n consentState.set(initialData.consent || {});\n hasAnswered.set(initialData.answered || false);\n\n // Re-prompt when consentVersion changes (GDPR: policy update invalidates prior consent)\n if (initialData.answered && consentVersion && initialData.version !== consentVersion) {\n hasAnswered.set(false);\n isPanelOpen.set(true);\n }\n\n if (typeof window !== 'undefined') {\n // Clean up previous subscriptions before creating new ones\n _cookieUnsubs.forEach(fn => fn());\n _cookieUnsubs = [];\n\n const saveToCookie = () => {\n const state: StoredState = {\n consent: consentState.get(),\n answered: hasAnswered.get(),\n timestamp: Date.now(),\n version: consentVersion,\n consentId: generateUUID(),\n };\n setCookie(cookieName, JSON.stringify(state), {\n domain: cookieDomain,\n secure: window.location.protocol === 'https:',\n });\n };\n\n _cookieUnsubs.push(consentState.subscribe(saveToCookie));\n _cookieUnsubs.push(hasAnswered.subscribe(saveToCookie));\n }\n};\n","import { consentState, hasAnswered, isPanelOpen, servicesList } from './state';\nimport { resolveVendor } from './resolver';\nimport type { McConfig } from './layer';\n\ndeclare global {\n interface Window {\n _modernConsentConfig: McConfig;\n }\n}\n\nexport type VendorConfig = unknown;\n\nexport interface Vendor<TConfig = void> {\n name: string;\n description: string;\n category: string;\n /**\n * Human-readable label for the purpose/category in 'purpose' displayMode.\n * Can be a string or a Record<lang, string> for i18n support.\n * @example purposeLabel: { fr: \"Mesure d'audience\", en: \"Audience measurement\" }\n */\n purposeLabel?: string | Record<string, string>;\n /**\n * Description for the purpose/category in 'purpose' displayMode.\n * Can be a string or a Record<lang, string> for i18n support.\n */\n purposeDescription?: string | Record<string, string>;\n setup?: (config: TConfig) => void;\n domSelector?: string;\n init?: (config: TConfig) => void;\n /** Cookie names set by this vendor — cleared when consent is revoked. */\n artifacts?: string[] | ((config: TConfig) => string[]);\n render?: (dataset: DOMStringMap) => string;\n requireConsent: boolean;\n event?: {\n name: string;\n callback: () => void;\n }[];\n link?: {\n vendor: string;\n /** Config passed to the linked vendor. Defaults to {} if omitted. */\n config?: VendorConfig;\n condition: (params: { vendorConfig: any; consentConfig: any }) => boolean;\n }[];\n}\n\nexport type VendorLoader = () => Promise<Vendor<any>>;\n\nconst loaders = new Map<string, VendorLoader>();\nconst loadedVendors = new Map<string, Vendor<VendorConfig>>();\nconst vendorsConfig = new Map<string, VendorConfig>();\n\n// Re-export resolveVendor from resolver.ts for backward compatibility\nexport { resolveVendor } from './resolver';\n\n/** @internal — test helper only */\nexport function __resetRegistry() {\n loaders.clear();\n loadedVendors.clear();\n vendorsConfig.clear();\n}\n\n/**\n * Clears all cookies declared in vendor.artifacts.\n * Called before reload or on denyAll to clean up vendor-set cookies.\n */\nexport function clearVendorArtifacts(id: string): void {\n const vendor = loadedVendors.get(id);\n if (!vendor?.artifacts) return;\n\n const config = vendorsConfig.get(id);\n const cookieNames =\n typeof vendor.artifacts === 'function' ? vendor.artifacts(config) : vendor.artifacts;\n\n const domain = window._modernConsentConfig?.cookieDomain;\n\n cookieNames.forEach(name => {\n document.cookie = `${name}=; max-age=0; path=/`;\n if (domain) {\n document.cookie = `${name}=; max-age=0; path=/; domain=${domain}`;\n }\n });\n}\n\nexport function registerService(args: {\n id: string;\n category: string;\n loader: VendorLoader;\n config: VendorConfig;\n}) {\n const { id, category, loader, config = {} } = args;\n\n // Prevent double-registration for the same service id\n if (loaders.has(id)) return;\n loaders.set(id, loader);\n\n loader()\n .then((module: any) => {\n const vendor: Vendor<any> = module.default || module;\n loadedVendors.set(id, vendor);\n if (config !== undefined) {\n vendorsConfig.set(id, config);\n }\n\n if (vendor?.setup) {\n try {\n vendor.setup(config);\n } catch (err) {\n console.error(`[modern-consent] setup() failed for \"${id}\":`, err);\n }\n }\n\n if (vendor?.link && vendor.link.length > 0) {\n vendor.link.forEach(link => {\n if (\n link.condition &&\n !link.condition({ vendorConfig: config, consentConfig: window._modernConsentConfig })\n ) {\n return;\n }\n const linkedLoader = resolveVendor(link.vendor);\n if (linkedLoader) {\n registerService({\n id: link.vendor,\n category,\n config: link.config ?? {},\n loader: linkedLoader,\n });\n } else {\n console.warn(`[modern-consent] Dependency \"${link.vendor}\" not found for \"${id}\"`);\n }\n });\n }\n\n servicesList.update(list => {\n if (list.some(s => s.id === id)) return list;\n return [\n ...list,\n {\n id,\n name: vendor.name,\n description: vendor.description,\n category: vendor.category,\n purposeLabel: vendor.purposeLabel,\n purposeDescription: vendor.purposeDescription,\n loaded: false,\n requireConsent: vendor.requireConsent,\n },\n ];\n });\n\n checkAutoActivation(id);\n })\n .catch(err => {\n console.error(`[modern-consent] Failed to load vendor \"${id}\":`, err);\n });\n}\n\n/**\n * Check if the service should auto-activate or if the panel should open (new service detected).\n */\nfunction checkAutoActivation(id: string) {\n const vendor = loadedVendors.get(id);\n\n // Services that don't require consent activate immediately\n if (vendor && !vendor.requireConsent) {\n activateService(id);\n return;\n }\n\n const currentConsent = consentState.get();\n const answered = hasAnswered.get();\n\n if (answered && currentConsent[id] === undefined) {\n isPanelOpen.set(true);\n }\n\n if (currentConsent[id]) {\n activateService(id);\n }\n}\n\n/**\n * Activate the service (script injection + DOM rendering).\n */\nexport async function activateService(id: string) {\n if (typeof window === 'undefined') return;\n\n let vendor = loadedVendors.get(id);\n\n if (!vendor) {\n const loader = loaders.get(id);\n if (loader) {\n const module: any = await loader();\n vendor = module.default || module;\n if (vendor) loadedVendors.set(id, vendor);\n }\n }\n\n if (!vendor) return;\n\n const isSoft = window._modernConsentConfig?.consentOnly === true;\n const list = servicesList.get();\n const meta = list.find(s => s.id === id);\n\n if (!isSoft && vendor.init && meta && !meta.loaded) {\n vendor.init(vendorsConfig.get(id));\n servicesList.update(l => l.map(s => (s.id === id ? { ...s, loaded: true } : s)));\n\n // Trigger onAccept events after successful activation\n vendor.event?.forEach(ev => {\n if (ev.name === 'onAccept') {\n try {\n ev.callback();\n } catch {\n /* don't let event errors break activation */\n }\n }\n });\n }\n\n if (!isSoft && vendor.domSelector && vendor.render) {\n setTimeout(() => {\n document.querySelectorAll(vendor!.domSelector!).forEach(el => {\n const htmlElement = el as HTMLElement;\n if (htmlElement.dataset.loaded !== 'true' && vendor?.render) {\n htmlElement.innerHTML = vendor.render(htmlElement.dataset);\n htmlElement.dataset.loaded = 'true';\n htmlElement.classList.remove('mc-placeholder-pending');\n }\n });\n }, 50);\n }\n}\n","import type { ConsentState } from './state';\n\nexport type ConsentEventMap = {\n 'consent:update': { vendor: string; status: 'granted' | 'denied'; gcm?: Record<string, boolean> };\n 'consent:saved': {\n consentId: string;\n timestamp: number;\n version?: string;\n consent: ConsentState;\n };\n};\n\ntype Listener<T> = (data: T) => void;\n\nclass ConsentEmitter {\n private listeners = new Map<string, Set<Listener<any>>>();\n\n on<K extends keyof ConsentEventMap>(event: K, cb: Listener<ConsentEventMap[K]>): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n this.listeners.get(event)!.add(cb);\n return () => this.listeners.get(event)?.delete(cb);\n }\n\n off<K extends keyof ConsentEventMap>(event: K, cb: Listener<ConsentEventMap[K]>): void {\n this.listeners.get(event)?.delete(cb);\n }\n\n emit<K extends keyof ConsentEventMap>(event: K, data: ConsentEventMap[K]): void {\n this.listeners.get(event)?.forEach(cb => {\n try {\n cb(data);\n } catch {\n /* don't let listener errors break the core */\n }\n });\n }\n}\n\nexport const emitter = new ConsentEmitter();\n","import { servicesList, consentState, hasAnswered, isPanelOpen } from './state';\nimport type { ConsentState } from './state';\nimport { activateService, clearVendorArtifacts } from './registry';\nimport { emitter } from './emitter';\nimport { generateUUID } from './utils/uuid';\n\ndeclare global {\n interface Window {\n consentLayer: any[];\n dataLayer: any[];\n }\n}\n\n/**\n * Always pushes consent state to `window.consentLayer` (TMS-agnostic).\n * Optionally pushes to `window.dataLayer` when `pushDataLayer` is enabled (GTM convenience).\n */\nfunction pushConsentEvent(consent: ConsentState) {\n if (typeof window === 'undefined') return;\n\n const event = {\n event: 'consent_update',\n consent_state: consent,\n };\n\n // consentLayer — always active, TMS-agnostic\n window.consentLayer = window.consentLayer || [];\n window.consentLayer.push(event);\n\n // dataLayer — opt-in for GTM native triggers\n if (window._modernConsentConfig?.pushDataLayer) {\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(event);\n }\n}\n\nfunction emitConsentSaved(consent: ConsentState) {\n emitter.emit('consent:saved', {\n consentId: generateUUID(),\n timestamp: Date.now(),\n version:\n typeof window !== 'undefined' ? window._modernConsentConfig?.consentVersion : undefined,\n consent,\n });\n}\n\nexport function setConsent(id: string, allowed: boolean) {\n // Check before updating state whether this service was actively running\n const wasPreviouslyLoaded = servicesList.get().find(s => s.id === id)?.loaded ?? false;\n\n consentState.update(s => ({ ...s, [id]: allowed }));\n hasAnswered.set(true);\n\n emitter.emit('consent:update', {\n vendor: id,\n status: allowed ? 'granted' : 'denied',\n });\n\n const updatedConsent = consentState.get();\n pushConsentEvent(updatedConsent);\n emitConsentSaved(updatedConsent);\n\n if (allowed) {\n activateService(id);\n return;\n }\n\n // Only clean up and reload if the service was actively running\n if (wasPreviouslyLoaded) {\n clearVendorArtifacts(id);\n const isConsentOnly =\n typeof window !== 'undefined' && window._modernConsentConfig?.consentOnly === true;\n if (!isConsentOnly && typeof window !== 'undefined') window.location.reload();\n }\n}\n\nexport function acceptAll() {\n const list = servicesList.get();\n const updates: Record<string, boolean> = {};\n\n list.forEach(s => {\n updates[s.id] = true;\n activateService(s.id);\n });\n\n consentState.set(updates);\n hasAnswered.set(true);\n isPanelOpen.set(false);\n\n list.forEach(s => {\n emitter.emit('consent:update', { vendor: s.id, status: 'granted' });\n });\n\n pushConsentEvent(updates);\n emitConsentSaved(updates);\n}\n\nexport function denyAll() {\n const list = servicesList.get();\n const updates: Record<string, boolean> = {};\n let needsReload = false;\n\n list.forEach(s => {\n updates[s.id] = false;\n clearVendorArtifacts(s.id);\n if (s.loaded) needsReload = true;\n });\n\n consentState.set(updates);\n hasAnswered.set(true);\n isPanelOpen.set(false);\n\n list.forEach(s => {\n emitter.emit('consent:update', { vendor: s.id, status: 'denied' });\n });\n\n pushConsentEvent(updates);\n emitConsentSaved(updates);\n\n // Reload only if at least one vendor was actively running —\n // clears vendor scripts from memory after cookie cleanup.\n const isConsentOnly =\n typeof window !== 'undefined' && window._modernConsentConfig?.consentOnly === true;\n if (needsReload && !isConsentOnly && typeof window !== 'undefined') {\n window.location.reload();\n }\n}\n","import { registerService } from './registry';\nimport { addResolver, resolveVendor } from './resolver';\nimport { consentState, initState, isPanelOpen } from './state';\nimport type { ConsentState } from './state';\nimport type { Vendor } from './registry';\nimport { emitter } from './emitter';\n\n/**\n * Command can add in config\n */\nconst validCommands = ['config', 'vendor'] as const;\n\nexport interface McConfig {\n cookieDomain?: string;\n cookieName?: string;\n consentMode?: boolean;\n /** Version string embedded in the stored consent — used for GDPR audit trails. */\n consentVersion?: string;\n /**\n * Base URL where vendor JS files are hosted.\n * Used by the CDN bundle to lazy-load vendors on demand.\n *\n * @example 'https://cdn.monsite.com/mc-vendors'\n * → window.modernConsent('vendor', { name: 'google-analytics' })\n * → fetches https://cdn.monsite.com/mc-vendors/google-analytics.js\n */\n cdnBase?: string;\n /**\n * In Consent-Only mode, the CMP only manages consent decisions + cookie storage.\n * Vendors are never initialized (no call to init()).\n * Use this to manage vendor scripts externally via a Tag Manager (GTM, TagCommander, etc.).\n *\n * Consent changes are always pushed to `window.consentLayer`.\n * Enable `pushDataLayer` to also push to `window.dataLayer` for native GTM triggers.\n */\n consentOnly?: boolean;\n /**\n * When true, consent changes are also pushed to `window.dataLayer` for native\n * GTM trigger support. Disabled by default — GTM users should enable this.\n */\n pushDataLayer?: boolean;\n /**\n * How the details panel displays consent controls:\n * - 'vendor' (default): individual toggle per vendor, grouped by category\n * - 'purpose': toggle per category/purpose, vendors listed as info below\n */\n displayMode?: 'vendor' | 'purpose';\n /**\n * Custom labels for each purpose/category in 'purpose' displayMode.\n * Keys must match the vendor `category` values.\n *\n * @example\n * purposes: {\n * analytics: { label: \"Analyse de session et mesure d'audience\" },\n * Publicité: { label: \"Ciblage Marketing\" },\n * }\n */\n purposes?: Record<\n string,\n {\n /** Human-readable label displayed as the purpose title. */\n label: string;\n /** Optional description shown below the purpose title. */\n description?: string;\n }\n >;\n /**\n * When true, displays a \"Functional / Site operation\" mandatory purpose block\n * at the top of the details panel. This is a visual-only block with no toggle —\n * it informs the user that essential cookies are always active.\n */\n functionalPurpose?: boolean;\n}\n\nexport interface McVendor {\n /**\n * Built-in vendor name (e.g. 'google-analytics') when using npm with\n * built-in loaders, OR a unique ID when providing an inline init().\n */\n name: string;\n /**\n * Category for this vendor (e.g. 'analytics', 'marketing').\n * Optional for built-in vendors — they define their own category.\n * Required for inline vendors (defaults to 'other' if omitted).\n */\n category?: string;\n config?: Record<string, any>;\n\n // --- Inline vendor definition (CDN users / custom vendors) ---\n /** Human-readable label shown in the consent UI. Defaults to `name`. */\n label?: string;\n /** Short description shown in the consent UI. */\n description?: string;\n /** Whether the user must explicitly consent before this vendor activates. @default true */\n requireConsent?: boolean;\n /** Called immediately at page load (e.g. set consent defaults). */\n setup?: (config?: Record<string, any>) => void;\n /** Called when consent is granted. Inject scripts, pixels, etc. here. */\n init?: (config?: Record<string, any>) => void;\n /** Cookie names written by this vendor — cleared when consent is revoked. */\n artifacts?: string[];\n}\n\nexport type ConfigCommand = ['config', McConfig];\nexport type VendorCommand = ['vendor', McVendor];\nexport type McCommand = ConfigCommand | VendorCommand;\n\ntype McAPI = {\n (...args: McCommand): void;\n openPanel: () => void;\n getConsent: () => ConsentState;\n on: typeof emitter.on;\n};\n\ndeclare global {\n interface Window {\n _modernConsentConfig: McConfig;\n mcLayer: McCommand[];\n modernConsent: McAPI;\n }\n}\n\nfunction handleVendor(event: McVendor) {\n const {\n name,\n label,\n description = '',\n category = 'other',\n config = {},\n requireConsent = true,\n setup,\n init,\n artifacts,\n } = event;\n\n let loader: import('./registry').VendorLoader;\n\n if (init ?? setup) {\n // Inline vendor — CDN users provide their own implementation.\n loader = async () => ({\n name: label ?? name,\n description,\n category,\n requireConsent,\n setup,\n init,\n artifacts,\n });\n } else {\n // Look up via the resolver chain (builtin, CDN, or user-registered resolvers).\n const resolved = resolveVendor(name);\n if (!resolved) {\n console.warn(\n `[modern-consent] Unknown vendor \"${name}\". ` +\n `Provide an init() function to define a custom vendor.`,\n );\n return;\n }\n loader = resolved;\n }\n\n registerService({ id: name, category, config, loader });\n}\n\n/**\n * Initialise window.mcLayer et traite la queue éventuelle.\n */\nexport function initMcLayer() {\n if (typeof window === 'undefined') return;\n\n const w = window;\n const existingQueue = Array.isArray(w.mcLayer) ? [...w.mcLayer] : [];\n\n w._modernConsentConfig = {};\n\n // CDN resolver — lowest priority (registered first = LIFO lowest).\n // Returns a loader for any name; cdnBase is checked lazily at activation time.\n addResolver(_name => {\n return async () => {\n const cdnBase = w._modernConsentConfig?.cdnBase;\n if (!cdnBase) {\n throw new Error(\n `[modern-consent] Vendor \"${_name}\" not found. ` +\n `Configure cdnBase to enable CDN loading, or provide an inline init().`,\n );\n }\n const url = `${cdnBase.replace(/\\/$/, '')}/${_name}.js`;\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? mod) as Vendor<any>;\n };\n });\n\n // Process the existing queue — config commands accumulate before vendors are registered\n existingQueue.forEach((args: McCommand) => {\n const [command, payload] = args;\n\n if (!validCommands.includes(command as any)) {\n console.warn(`[modern-consent] \"${command}\" is not a valid command`);\n return;\n }\n\n if (command === 'config') {\n w._modernConsentConfig = { ...w._modernConsentConfig, ...(payload as McConfig) };\n return;\n }\n\n handleVendor(payload as McVendor);\n });\n\n // State is initialised once after config is fully resolved from the queue\n initState(w._modernConsentConfig);\n\n // Live API\n const apiFn = (...args: McCommand) => {\n const [command, payload] = args;\n\n if (!validCommands.includes(command as any)) {\n console.warn(`[modern-consent] \"${command}\" is not a valid command`);\n return;\n }\n\n if (command === 'vendor') {\n handleVendor(payload as McVendor);\n } else if (command === 'config') {\n w._modernConsentConfig = { ...w._modernConsentConfig, ...(payload as McConfig) };\n }\n\n if (!Array.isArray(w.mcLayer)) w.mcLayer = [];\n w.mcLayer.push(args);\n };\n\n w.modernConsent = Object.assign(apiFn, {\n openPanel: () => isPanelOpen.set(true),\n getConsent: () => consentState.get(),\n on: emitter.on.bind(emitter),\n });\n}\n","export type { ConsentState, ServiceMetadata } from './state.ts';\n\nexport { Store } from './utils/store';\n\nexport { consentState, hasAnswered, servicesList, isPanelOpen, openPanel } from './state';\n\n// Vendor Resolution\nexport { addResolver, resolveVendor } from './resolver';\n\nexport {\n registerService,\n activateService,\n clearVendorArtifacts,\n type Vendor,\n type VendorLoader,\n type VendorConfig,\n} from './registry';\n\nexport { setConsent, acceptAll, denyAll } from './consent';\n\nexport type { McConfig, McVendor, McCommand, ConfigCommand, VendorCommand } from './layer';\n\nexport { emitter, type ConsentEventMap } from './emitter';\nexport { generateUUID } from './utils/uuid';\nexport { initMcLayer } from './layer';\n\nimport { initMcLayer } from './layer';\n\nif (typeof window !== 'undefined') {\n initMcLayer();\n}\n"]}
|
|
@@ -1,37 +1,3 @@
|
|
|
1
|
-
type Subscriber<T> = (value: T) => void;
|
|
2
|
-
type Unsubscriber = () => void;
|
|
3
|
-
declare class Store<T> {
|
|
4
|
-
private value;
|
|
5
|
-
private subscribers;
|
|
6
|
-
constructor(initialValue: T);
|
|
7
|
-
get(): T;
|
|
8
|
-
set(newValue: T): void;
|
|
9
|
-
update(updater: (value: T) => T): void;
|
|
10
|
-
subscribe(callback: Subscriber<T>): Unsubscriber;
|
|
11
|
-
private notify;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface ConsentState {
|
|
15
|
-
[serviceId: string]: boolean;
|
|
16
|
-
}
|
|
17
|
-
interface ServiceMetadata {
|
|
18
|
-
id: string;
|
|
19
|
-
name: string;
|
|
20
|
-
description: string;
|
|
21
|
-
category: string;
|
|
22
|
-
/** Human-readable label for the purpose/category in 'purpose' displayMode. */
|
|
23
|
-
purposeLabel?: string | Record<string, string>;
|
|
24
|
-
/** Optional description for the purpose/category in 'purpose' displayMode. */
|
|
25
|
-
purposeDescription?: string | Record<string, string>;
|
|
26
|
-
loaded: boolean;
|
|
27
|
-
requireConsent: boolean;
|
|
28
|
-
}
|
|
29
|
-
declare const consentState: Store<ConsentState>;
|
|
30
|
-
declare const hasAnswered: Store<boolean>;
|
|
31
|
-
declare const servicesList: Store<ServiceMetadata[]>;
|
|
32
|
-
declare const isPanelOpen: Store<boolean>;
|
|
33
|
-
declare const openPanel: () => void;
|
|
34
|
-
|
|
35
1
|
type ConsentEventMap = {
|
|
36
2
|
'consent:update': {
|
|
37
3
|
vendor: string;
|
|
@@ -159,6 +125,40 @@ declare global {
|
|
|
159
125
|
*/
|
|
160
126
|
declare function initMcLayer(): void;
|
|
161
127
|
|
|
128
|
+
type Subscriber<T> = (value: T) => void;
|
|
129
|
+
type Unsubscriber = () => void;
|
|
130
|
+
declare class Store<T> {
|
|
131
|
+
private value;
|
|
132
|
+
private subscribers;
|
|
133
|
+
constructor(initialValue: T);
|
|
134
|
+
get(): T;
|
|
135
|
+
set(newValue: T): void;
|
|
136
|
+
update(updater: (value: T) => T): void;
|
|
137
|
+
subscribe(callback: Subscriber<T>): Unsubscriber;
|
|
138
|
+
private notify;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface ConsentState {
|
|
142
|
+
[serviceId: string]: boolean;
|
|
143
|
+
}
|
|
144
|
+
interface ServiceMetadata {
|
|
145
|
+
id: string;
|
|
146
|
+
name: string;
|
|
147
|
+
description: string;
|
|
148
|
+
category: string;
|
|
149
|
+
/** Human-readable label for the purpose/category in 'purpose' displayMode. */
|
|
150
|
+
purposeLabel?: string | Record<string, string>;
|
|
151
|
+
/** Optional description for the purpose/category in 'purpose' displayMode. */
|
|
152
|
+
purposeDescription?: string | Record<string, string>;
|
|
153
|
+
loaded: boolean;
|
|
154
|
+
requireConsent: boolean;
|
|
155
|
+
}
|
|
156
|
+
declare const consentState: Store<ConsentState>;
|
|
157
|
+
declare const hasAnswered: Store<boolean>;
|
|
158
|
+
declare const servicesList: Store<ServiceMetadata[]>;
|
|
159
|
+
declare const isPanelOpen: Store<boolean>;
|
|
160
|
+
declare const openPanel: () => void;
|
|
161
|
+
|
|
162
162
|
declare global {
|
|
163
163
|
interface Window {
|
|
164
164
|
_modernConsentConfig: McConfig;
|
|
@@ -215,7 +215,7 @@ declare function registerService(args: {
|
|
|
215
215
|
config: VendorConfig;
|
|
216
216
|
}): void;
|
|
217
217
|
/**
|
|
218
|
-
*
|
|
218
|
+
* Activate the service (script injection + DOM rendering).
|
|
219
219
|
*/
|
|
220
220
|
declare function activateService(id: string): Promise<void>;
|
|
221
221
|
|
package/dist/resolver.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { u as VendorResolver, _ as __resetResolvers, b as addResolver, r as resolveVendor } from './resolver-
|
|
1
|
+
export { u as VendorResolver, _ as __resetResolvers, b as addResolver, r as resolveVendor } from './resolver-CssVkauA.js';
|
package/dist/resolver.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-UZ3JLA4T.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// src/resolver.ts
|
|
2
|
-
var _resolvers = [];
|
|
3
|
-
function addResolver(resolver) {
|
|
4
|
-
_resolvers.push(resolver);
|
|
5
|
-
return () => {
|
|
6
|
-
const idx = _resolvers.indexOf(resolver);
|
|
7
|
-
if (idx !== -1) _resolvers.splice(idx, 1);
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
function resolveVendor(name) {
|
|
11
|
-
for (let i = _resolvers.length - 1; i >= 0; i--) {
|
|
12
|
-
const result = _resolvers[i](name);
|
|
13
|
-
if (result) return result;
|
|
14
|
-
}
|
|
15
|
-
return void 0;
|
|
16
|
-
}
|
|
17
|
-
function __resetResolvers() {
|
|
18
|
-
_resolvers.length = 0;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export { __resetResolvers, addResolver, resolveVendor };
|
|
22
|
-
//# sourceMappingURL=chunk-UZ3JLA4T.js.map
|
|
23
|
-
//# sourceMappingURL=chunk-UZ3JLA4T.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resolver.ts"],"names":[],"mappings":";AASA,IAAM,aAA+B,EAAC;AAS/B,SAAS,YAAY,QAAA,EAAsC;AAChE,EAAA,UAAA,CAAW,KAAK,QAAQ,CAAA;AACxB,EAAA,OAAO,MAAM;AACX,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,OAAA,CAAQ,QAAQ,CAAA;AACvC,IAAA,IAAI,GAAA,KAAQ,EAAA,EAAI,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC1C,CAAA;AACF;AAMO,SAAS,cAAc,IAAA,EAAwC;AACpE,EAAA,KAAA,IAAS,IAAI,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC/C,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,CAAC,CAAA,CAAE,IAAI,CAAA;AACjC,IAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,gBAAA,GAAyB;AACvC,EAAA,UAAA,CAAW,MAAA,GAAS,CAAA;AACtB","file":"chunk-UZ3JLA4T.js","sourcesContent":["// core/src/resolver.ts\nimport type { VendorLoader } from './registry';\n\n/**\n * A resolver maps a vendor name to a loader function.\n * Return `undefined` to pass resolution to the next resolver in the chain.\n */\nexport type VendorResolver = (name: string) => VendorLoader | undefined;\n\nconst _resolvers: VendorResolver[] = [];\n\n/**\n * Register a vendor resolver. Resolvers are tried in LIFO order\n * (last registered = highest priority), following the convention\n * from Vite/Rollup where later plugins override earlier ones.\n *\n * @returns A cleanup function that removes this resolver from the chain.\n */\nexport function addResolver(resolver: VendorResolver): () => void {\n _resolvers.push(resolver);\n return () => {\n const idx = _resolvers.indexOf(resolver);\n if (idx !== -1) _resolvers.splice(idx, 1);\n };\n}\n\n/**\n * Resolve a vendor name to a loader by walking the resolver chain (LIFO).\n * Returns `undefined` if no resolver can handle the name.\n */\nexport function resolveVendor(name: string): VendorLoader | undefined {\n for (let i = _resolvers.length - 1; i >= 0; i--) {\n const result = _resolvers[i](name);\n if (result) return result;\n }\n return undefined;\n}\n\n/** @internal — test helper only */\nexport function __resetResolvers(): void {\n _resolvers.length = 0;\n}\n"]}
|