@cookieyes/core 0.3.0 → 0.4.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 +46 -5
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +339 -14
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The integration format — the shared contract between the consent engine and
|
|
3
|
+
* every vendor preset (Google, Segment, Meta, …). It carries no vendor
|
|
4
|
+
* knowledge; a preset in `@cookieyes/scripts` fills it in.
|
|
5
|
+
*
|
|
6
|
+
* Two plain axes describe every vendor:
|
|
7
|
+
* - `load`: when the vendor starts — right away, or only after consent.
|
|
8
|
+
* - `onRevoke`: what happens when consent is withdrawn — one of three modes.
|
|
9
|
+
*
|
|
10
|
+
* `onRevoke` is declarative (readable without running `setup`, so a debug view
|
|
11
|
+
* or a version check can inspect it), and it's a discriminated union so the
|
|
12
|
+
* compiler forces the matching handler — you can't declare `"silence"` with no
|
|
13
|
+
* way to actually silence.
|
|
14
|
+
*/
|
|
15
|
+
type Cleanup = () => void;
|
|
16
|
+
type SilenceControl = {
|
|
17
|
+
silence: () => void;
|
|
18
|
+
resume: () => void;
|
|
19
|
+
};
|
|
20
|
+
/** What a vendor's `setup` receives from the engine. */
|
|
21
|
+
type SetupCtx = {
|
|
22
|
+
/** Is this integration's category currently committed-granted? */
|
|
23
|
+
granted: () => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Subscribe to committed-consent changes; returns an unsubscribe function.
|
|
26
|
+
* `keep` vendors (e.g. Google Consent Mode) use this to emit their own
|
|
27
|
+
* updates on every change. The engine also releases these automatically when
|
|
28
|
+
* the integration is torn down, so a vendor listener never outlives it.
|
|
29
|
+
*/
|
|
30
|
+
onConsentChange: (fn: () => void) => () => void;
|
|
31
|
+
/** Resolved region/regulation — for a vendor's US-state privacy switch. */
|
|
32
|
+
region: RegionDecision;
|
|
33
|
+
};
|
|
34
|
+
type Base = {
|
|
35
|
+
id: string;
|
|
36
|
+
/**
|
|
37
|
+
* The consent category (or categories) that gate this integration. Pass an
|
|
38
|
+
* array to require more than one — combined with {@link Base.match}.
|
|
39
|
+
*/
|
|
40
|
+
category: ConsentCategory | ConsentCategory[];
|
|
41
|
+
/**
|
|
42
|
+
* How to combine multiple categories: `"all"` (default) needs every one
|
|
43
|
+
* granted; `"any"` needs at least one. Ignored for a single category.
|
|
44
|
+
*/
|
|
45
|
+
match?: "all" | "any";
|
|
46
|
+
/** Format version; an unknown version is refused (see {@link runIntegrations}). */
|
|
47
|
+
version: number;
|
|
48
|
+
/**
|
|
49
|
+
* When to start. Note: `setup` always runs on a microtask, so `immediately`
|
|
50
|
+
* is *very early* but not synchronous / same-tick. The truly-first-thing case
|
|
51
|
+
* (Consent Mode's deny-default before any tag fires) is the server `<head>`
|
|
52
|
+
* snippet's job, not the engine's.
|
|
53
|
+
*/
|
|
54
|
+
load: "immediately" | "afterConsent";
|
|
55
|
+
};
|
|
56
|
+
type Integration = Base & ({
|
|
57
|
+
onRevoke: "keep";
|
|
58
|
+
setup: (ctx: SetupCtx) => void | Promise<void>;
|
|
59
|
+
} | {
|
|
60
|
+
onRevoke: "remove";
|
|
61
|
+
setup: (ctx: SetupCtx) => Cleanup | Promise<Cleanup>;
|
|
62
|
+
} | {
|
|
63
|
+
onRevoke: "silence";
|
|
64
|
+
setup: (ctx: SetupCtx) => SilenceControl | Promise<SilenceControl>;
|
|
65
|
+
});
|
|
66
|
+
/** The format version this engine understands. Bump on a breaking format change. */
|
|
67
|
+
declare const INTEGRATION_FORMAT_VERSION = 1;
|
|
68
|
+
/**
|
|
69
|
+
* Warn when a vendor is configured on both sides — a new `integrations` preset
|
|
70
|
+
* whose id matches a deprecated `builtInIntegrations` vendor. Both would run,
|
|
71
|
+
* which for a tracker means double-counted events (the DEVP-38 double-pixel).
|
|
72
|
+
* Preset ids are the vendor's canonical name (`"segment"`, `"meta"`, …), which
|
|
73
|
+
* is exactly the built-in vendor name, so the match is a plain id === vendor.
|
|
74
|
+
*/
|
|
75
|
+
declare function warnOverlappingVendors(integrationIds: string[], builtInVendors: string[]): void;
|
|
76
|
+
/**
|
|
77
|
+
* Warn when an `afterConsent` integration is gated on a category that isn't in
|
|
78
|
+
* the configured taxonomy — otherwise it waits for consent that can never be
|
|
79
|
+
* granted and silently never loads. A common trap with a custom `categories`
|
|
80
|
+
* list plus a preset left on its default category (e.g. `segment()` → "analytics").
|
|
81
|
+
* `immediately` integrations aren't gated by category, so they're not checked.
|
|
82
|
+
*/
|
|
83
|
+
declare function warnUnknownCategories(integrations: Integration[], knownCategoryIds: string[]): void;
|
|
84
|
+
/** Live status of one integration — read by the debug/self-check view. */
|
|
85
|
+
type IntegrationStatus = "idle" | "loading" | "active" | "silenced" | "removed" | "error";
|
|
86
|
+
/** What the engine needs from the consent runtime — framework-agnostic. */
|
|
87
|
+
type IntegrationHost = {
|
|
88
|
+
/** Committed-granted state for a category (never the unsaved toggle). */
|
|
89
|
+
granted: (category: ConsentCategory) => boolean;
|
|
90
|
+
/** Subscribe to committed-consent changes; returns unsubscribe. */
|
|
91
|
+
subscribe: (fn: () => void) => () => void;
|
|
92
|
+
region: RegionDecision;
|
|
93
|
+
};
|
|
94
|
+
/** One row for a debug view: an integration's config plus its live status. */
|
|
95
|
+
type IntegrationDebugInfo = {
|
|
96
|
+
id: string;
|
|
97
|
+
category: ConsentCategory | ConsentCategory[];
|
|
98
|
+
load: "immediately" | "afterConsent";
|
|
99
|
+
onRevoke: "keep" | "remove" | "silence";
|
|
100
|
+
status: IntegrationStatus;
|
|
101
|
+
};
|
|
102
|
+
type IntegrationRunner = {
|
|
103
|
+
/** Current status per integration id — the debug/self-check view reads this. */
|
|
104
|
+
status: () => Record<string, IntegrationStatus>;
|
|
105
|
+
/**
|
|
106
|
+
* Config + live status for every registered integration, in order — the data
|
|
107
|
+
* for a debug view (e.g. `console.table(runner.list())`).
|
|
108
|
+
*/
|
|
109
|
+
list: () => IntegrationDebugInfo[];
|
|
110
|
+
/**
|
|
111
|
+
* Tear the runner down: stop reconciling, release every vendor's
|
|
112
|
+
* consent-change listener, and undo each loaded vendor — `remove` runs its
|
|
113
|
+
* cleanup, `silence` is silenced. `keep` vendors' scripts stay (that's the
|
|
114
|
+
* mode), but their listeners are still released. Safe to call more than once.
|
|
115
|
+
*/
|
|
116
|
+
stop: () => void;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Run a set of integrations against the consent runtime. Reconciles each one on
|
|
120
|
+
* load and on every committed-consent change:
|
|
121
|
+
* - not loaded → load it (immediately, or once its category is granted)
|
|
122
|
+
* - `keep` → nothing on revoke (the vendor manages its own update)
|
|
123
|
+
* - `remove` → run cleanup on revoke; re-load on re-grant
|
|
124
|
+
* - `silence` → call `silence()` on revoke; `resume()` on re-grant
|
|
125
|
+
*
|
|
126
|
+
* `setup` may be async and may fail; a failure marks the integration `error`
|
|
127
|
+
* and is retried on the next trigger (never loops on its own). Nothing here
|
|
128
|
+
* throws into the host.
|
|
129
|
+
*/
|
|
130
|
+
declare function runIntegrations(integrations: Integration[], host: IntegrationHost): IntegrationRunner;
|
|
131
|
+
|
|
1
132
|
type NetworkBlockerRule = {
|
|
2
133
|
id: string;
|
|
3
134
|
domain: string;
|
|
@@ -141,6 +272,30 @@ type LanguageInfo = {
|
|
|
141
272
|
direction: TextDirection;
|
|
142
273
|
languages: string[];
|
|
143
274
|
};
|
|
275
|
+
/** Returns the visitor's region synchronously, e.g. "DE" or "US-CA" (or undefined). */
|
|
276
|
+
type RegionDetector = () => string | undefined;
|
|
277
|
+
/** Optional geo-detection: pick the banner's regulation from the visitor's region. */
|
|
278
|
+
type RegionConfig = {
|
|
279
|
+
/** Return the visitor's region synchronously — e.g. from a hosting header you read. */
|
|
280
|
+
detect?: RegionDetector | undefined;
|
|
281
|
+
/** Which regulation each region maps to (you own this). Matched most-specific first: "US-CA" then "US". */
|
|
282
|
+
map?: Record<string, Regulation> | undefined;
|
|
283
|
+
/** Honour the browser's GPC "do not sell/share" signal (a CCPA opt-out). Default `true`. */
|
|
284
|
+
honorGpc?: boolean | undefined;
|
|
285
|
+
/** Regulation to apply when the region is unknown or detection fails. Default `"GDPR"`. */
|
|
286
|
+
strictest?: Regulation | undefined;
|
|
287
|
+
/** Log the region decision to the console at setup (for local debugging). Default `false`. */
|
|
288
|
+
debug?: boolean | undefined;
|
|
289
|
+
};
|
|
290
|
+
/** How the active regulation was decided. */
|
|
291
|
+
type RegionSource = "manual" | "detected" | "strictest";
|
|
292
|
+
/** The outcome of geo-detection — the region seen and the regulation chosen. */
|
|
293
|
+
type RegionDecision = {
|
|
294
|
+
region: string | undefined;
|
|
295
|
+
regulation: Regulation;
|
|
296
|
+
source: RegionSource;
|
|
297
|
+
confidence: "high" | "low";
|
|
298
|
+
};
|
|
144
299
|
type ThemeConfig = {
|
|
145
300
|
primaryColor?: string | undefined;
|
|
146
301
|
backgroundColor?: string | undefined;
|
|
@@ -186,6 +341,12 @@ type ConsentConfig = {
|
|
|
186
341
|
theme?: ThemeConfig | undefined;
|
|
187
342
|
colorScheme?: ColorScheme | undefined;
|
|
188
343
|
reloadOnRevoke?: boolean | undefined;
|
|
344
|
+
/**
|
|
345
|
+
* How to combine multiple categories that map to the same Google Consent Mode
|
|
346
|
+
* signal: `"any"` (default) grants the signal if any maps-and-granted; `"all"`
|
|
347
|
+
* requires every mapping category. Only affects custom overlapping mappings.
|
|
348
|
+
*/
|
|
349
|
+
googleConsentMatch?: "all" | "any" | undefined;
|
|
189
350
|
/**
|
|
190
351
|
* Built-in, first-party integrations to stop cleanly (no reload) when their
|
|
191
352
|
* category is revoked — e.g. `{ vendor: "meta" }`. (Google Analytics/Tag
|
|
@@ -200,6 +361,14 @@ type ConsentConfig = {
|
|
|
200
361
|
* shows the reload notice rather than silently continuing to track.
|
|
201
362
|
*/
|
|
202
363
|
customStopHandlers?: StopHandler[] | undefined;
|
|
364
|
+
/** Detected region (e.g. "US-CA"), recorded on the consent-log payload. */
|
|
365
|
+
region?: string | undefined;
|
|
366
|
+
/**
|
|
367
|
+
* Internal — set by the runtime when a CCPA visitor arrives with the browser's
|
|
368
|
+
* GPC "do not sell" signal on. Starts them opted out (non-required categories
|
|
369
|
+
* off) until they explicitly choose otherwise, so nothing is shared first.
|
|
370
|
+
*/
|
|
371
|
+
gpcOptOut?: boolean | undefined;
|
|
203
372
|
onConsentReady?: ((state: ConsentSnapshot) => void) | undefined;
|
|
204
373
|
onConsentUpdate?: ((state: ConsentSnapshot) => void) | undefined;
|
|
205
374
|
};
|
|
@@ -261,6 +430,8 @@ type ConsentPayload = {
|
|
|
261
430
|
categories: Record<string, boolean>;
|
|
262
431
|
regulation: Regulation;
|
|
263
432
|
domain: string;
|
|
433
|
+
/** Detected region when geo-detection is on (e.g. "US-CA"); omitted otherwise. */
|
|
434
|
+
region?: string | undefined;
|
|
264
435
|
};
|
|
265
436
|
/**
|
|
266
437
|
* Customer-implemented adapter that decides how a consent decision
|
|
@@ -294,6 +465,12 @@ type CookieYesConfigCommon = {
|
|
|
294
465
|
* nested `overrides.regulation`).
|
|
295
466
|
*/
|
|
296
467
|
regulation?: Regulation | undefined;
|
|
468
|
+
/**
|
|
469
|
+
* Optional geo-detection: choose the regulation from the visitor's region.
|
|
470
|
+
* Fully optional — omit it and nothing changes. A manual `regulation` (above)
|
|
471
|
+
* always wins over detection. See {@link RegionConfig}.
|
|
472
|
+
*/
|
|
473
|
+
region?: RegionConfig | undefined;
|
|
297
474
|
colorScheme?: ColorScheme | undefined;
|
|
298
475
|
theme?: ThemeConfig | undefined;
|
|
299
476
|
i18n?: I18nConfig | undefined;
|
|
@@ -308,12 +485,29 @@ type CookieYesConfigCommon = {
|
|
|
308
485
|
networkBlocker?: NetworkBlockerConfig | undefined;
|
|
309
486
|
reloadOnRevoke?: boolean | undefined;
|
|
310
487
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* needed.) Integrations with no clean runtime stop fall back to the reload notice.
|
|
488
|
+
* How to combine multiple categories that map to the same Google Consent Mode
|
|
489
|
+
* signal: `"any"` (default) or `"all"`. Only matters for a custom taxonomy
|
|
490
|
+
* where more than one category maps to the same signal.
|
|
315
491
|
*/
|
|
316
|
-
|
|
492
|
+
googleConsentMatch?: "all" | "any" | undefined;
|
|
493
|
+
/**
|
|
494
|
+
* Ready-made third-party integrations to gate behind consent — Segment, Meta,
|
|
495
|
+
* Google, and more — using a preset from `@cookieyes/scripts`. Each preset
|
|
496
|
+
* returns an {@link Integration}: it loads only once its category is granted
|
|
497
|
+
* (or, for Google Consent Mode, loads immediately and denies by default), and
|
|
498
|
+
* is removed or silenced on withdrawal.
|
|
499
|
+
*
|
|
500
|
+
* @example integrations: [segment({ writeKey: "..." })]
|
|
501
|
+
*/
|
|
502
|
+
integrations?: Integration[] | undefined;
|
|
503
|
+
/**
|
|
504
|
+
* @deprecated Renamed from `integrations`. Built-in stop-handlers for a few
|
|
505
|
+
* first-party vendors — e.g. `{ vendor: "meta" }` — stopped cleanly (no
|
|
506
|
+
* reload) when their category is revoked. Prefer the new `integrations` field
|
|
507
|
+
* with a preset from `@cookieyes/scripts`; this will be removed in a future
|
|
508
|
+
* release.
|
|
509
|
+
*/
|
|
510
|
+
builtInIntegrations?: BuiltInIntegration[] | undefined;
|
|
317
511
|
/**
|
|
318
512
|
* Your own scripts' stop instructions, for anything without a built-in
|
|
319
513
|
* integration. A handler that can stop cleanly provides `stop()`; one that
|
|
@@ -440,6 +634,8 @@ type ConsentStore = {
|
|
|
440
634
|
* so it follows whatever taxonomy is configured.
|
|
441
635
|
*/
|
|
442
636
|
categories: ResolvedCategories;
|
|
637
|
+
/** How the active regulation was decided (region, source, confidence). */
|
|
638
|
+
getRegion: () => RegionDecision;
|
|
443
639
|
/**
|
|
444
640
|
* React to consent decisions. `"save"` fires on every save (even an
|
|
445
641
|
* unchanged re-confirm); `"change"` fires only when a category actually
|
|
@@ -453,6 +649,8 @@ type ConsentStore = {
|
|
|
453
649
|
type ConsentRuntime = {
|
|
454
650
|
consentManager: ConsentManager;
|
|
455
651
|
consentStore: ConsentStore;
|
|
652
|
+
/** Config + live status for each script integration — data for a debug view. */
|
|
653
|
+
getIntegrations: () => IntegrationDebugInfo[];
|
|
456
654
|
};
|
|
457
655
|
|
|
458
656
|
/**
|
|
@@ -519,6 +717,7 @@ declare function resolveCategories(defs?: CategoryDef[]): ResolvedCategories;
|
|
|
519
717
|
type _NormalizedConfig = {
|
|
520
718
|
mode: ConsentRuntimeMode;
|
|
521
719
|
regulation?: Regulation | undefined;
|
|
720
|
+
region?: RegionConfig | undefined;
|
|
522
721
|
colorScheme?: ColorScheme | undefined;
|
|
523
722
|
theme?: ThemeConfig | undefined;
|
|
524
723
|
i18n?: I18nConfig | undefined;
|
|
@@ -526,7 +725,10 @@ type _NormalizedConfig = {
|
|
|
526
725
|
categories?: CategoryDef[] | undefined;
|
|
527
726
|
networkBlocker?: NetworkBlockerConfig | undefined;
|
|
528
727
|
reloadOnRevoke?: boolean | undefined;
|
|
529
|
-
|
|
728
|
+
googleConsentMatch?: "all" | "any" | undefined;
|
|
729
|
+
integrations?: Integration[] | undefined;
|
|
730
|
+
/** @deprecated Renamed from `integrations`; use `integrations` with a `@cookieyes/scripts` preset. */
|
|
731
|
+
builtInIntegrations?: BuiltInIntegration[] | undefined;
|
|
530
732
|
customStopHandlers?: StopHandler[] | undefined;
|
|
531
733
|
onConsentReady?: ((state: ConsentSnapshot) => void) | undefined;
|
|
532
734
|
onConsentUpdate?: ((state: ConsentSnapshot) => void) | undefined;
|
|
@@ -560,6 +762,15 @@ type RawCookieFields = {
|
|
|
560
762
|
};
|
|
561
763
|
declare function parseCookie(raw: string): RawCookieFields;
|
|
562
764
|
declare function serializeCookie(snapshot: ConsentSnapshot): string;
|
|
765
|
+
/**
|
|
766
|
+
* Find and parse the consent cookie inside a `name=value; name2=value2` string.
|
|
767
|
+
*
|
|
768
|
+
* Shared by the browser (`document.cookie`) and the server (a request's `Cookie`
|
|
769
|
+
* header) — the two formats are identical, and one implementation means the
|
|
770
|
+
* server can never disagree with the client about what a visitor's cookie says.
|
|
771
|
+
* Returns `null` when the cookie is absent or its value cannot be decoded.
|
|
772
|
+
*/
|
|
773
|
+
declare function parseCookieHeader(header: string): RawCookieFields | null;
|
|
563
774
|
declare function generateConsentId(): string;
|
|
564
775
|
|
|
565
776
|
/**
|
|
@@ -570,6 +781,14 @@ declare function generateConsentId(): string;
|
|
|
570
781
|
declare function _warnOfflineModeDeprecated(): void;
|
|
571
782
|
/** @internal test-only — resets the one-time warning guard between test cases. */
|
|
572
783
|
declare function _resetOfflineModeWarning(): void;
|
|
784
|
+
/**
|
|
785
|
+
* One-time-per-page-load console warning for the deprecated `builtInIntegrations`
|
|
786
|
+
* config field (formerly `integrations`). Both packages call this so the wording
|
|
787
|
+
* and the "once" behavior stay identical.
|
|
788
|
+
*/
|
|
789
|
+
declare function _warnBuiltInIntegrationsDeprecated(): void;
|
|
790
|
+
/** @internal test-only — resets the one-time warning guard between test cases. */
|
|
791
|
+
declare function _resetBuiltInIntegrationsWarning(): void;
|
|
573
792
|
|
|
574
793
|
type ConsentEmitter = {
|
|
575
794
|
/**
|
|
@@ -596,12 +815,14 @@ type GcmValue = "granted" | "denied";
|
|
|
596
815
|
* Compute the granted/denied value for every GCM signal from the current
|
|
597
816
|
* category consent, using each category's `gcm` mapping.
|
|
598
817
|
*
|
|
599
|
-
* -
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
818
|
+
* - When several categories map to the same signal, `match` decides: `"any"`
|
|
819
|
+
* (default) grants it if *any* mapping category is granted; `"all"` requires
|
|
820
|
+
* *every* mapping category to be granted. For the built-in five (one category
|
|
821
|
+
* per signal) the two are identical — `match` only matters for custom overlaps.
|
|
822
|
+
* - `security_storage` is always `granted` (strictly necessary, not consentable).
|
|
823
|
+
* - A signal that no category maps to stays `denied`.
|
|
603
824
|
*/
|
|
604
|
-
declare function computeGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean
|
|
825
|
+
declare function computeGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean>, match?: "all" | "any"): Record<GoogleConsentSignal, GcmValue>;
|
|
605
826
|
/**
|
|
606
827
|
* Push a Consent Mode `update` for all seven signals onto the dataLayer, if one
|
|
607
828
|
* is present. Safe to call on load and on every consent change; a no-op when no
|
|
@@ -611,7 +832,7 @@ declare function computeGoogleConsent(resolved: ResolvedCategories, categories:
|
|
|
611
832
|
* that must run before their Google tags, typically denying everything). This
|
|
612
833
|
* function owns the *update* that reflects the visitor's actual choice.
|
|
613
834
|
*/
|
|
614
|
-
declare function broadcastGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean
|
|
835
|
+
declare function broadcastGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean>, match?: "all" | "any"): void;
|
|
615
836
|
|
|
616
837
|
declare const en: TranslationMap;
|
|
617
838
|
|
|
@@ -655,6 +876,39 @@ declare function createLanguageController(i18n: I18nConfig | undefined, onChange
|
|
|
655
876
|
|
|
656
877
|
declare function createConsentManager(config: ConsentConfig): ConsentManager;
|
|
657
878
|
|
|
879
|
+
/** Anything with a header getter — a `Headers` object, Next's `headers()`, etc. */
|
|
880
|
+
type HeaderSource = {
|
|
881
|
+
get(name: string): string | null | undefined;
|
|
882
|
+
};
|
|
883
|
+
/**
|
|
884
|
+
* Read the visitor's region from request headers on the server (Next.js, or any
|
|
885
|
+
* framework). Pass the request's headers and get back a region like "US-CA" or
|
|
886
|
+
* "DE" (or undefined). By default it reads the well-known Vercel/Cloudflare
|
|
887
|
+
* headers; pass `{ header }` to read your own instead. Hand the result to
|
|
888
|
+
* `region.detect` in your client config.
|
|
889
|
+
*/
|
|
890
|
+
declare function regionFromHeaders(headers: HeaderSource, options?: {
|
|
891
|
+
header?: string;
|
|
892
|
+
}): string | undefined;
|
|
893
|
+
/** True when the browser is sending the GPC "do not sell/share" signal. */
|
|
894
|
+
declare function readGpc(): boolean;
|
|
895
|
+
/**
|
|
896
|
+
* Decide which regulation applies from the visitor's region alone. A manual
|
|
897
|
+
* regulation always wins; otherwise the detected region is mapped to a
|
|
898
|
+
* regulation, and anything unknown falls back to the strictest — never to the
|
|
899
|
+
* lightest, so a required banner is never skipped.
|
|
900
|
+
*
|
|
901
|
+
* GPC is deliberately *not* considered here: it never changes which banner
|
|
902
|
+
* shows (that is geo only), it only opts a CCPA visitor out client-side. Server
|
|
903
|
+
* and client therefore resolve the same regulation, with no hydration mismatch.
|
|
904
|
+
*/
|
|
905
|
+
declare function resolveRegion(config: RegionConfig, manual?: Regulation): RegionDecision;
|
|
906
|
+
/**
|
|
907
|
+
* @internal Dev aid for `region.debug`: print how the regulation was decided,
|
|
908
|
+
* plus whether GPC started the visitor opted out. Shared by both runtimes.
|
|
909
|
+
*/
|
|
910
|
+
declare function _logRegionDecision(decision: RegionDecision, gpcOptOut: boolean): void;
|
|
911
|
+
|
|
658
912
|
declare function getOrCreateConsentRuntime(config: CookieYesConfig): ConsentRuntime;
|
|
659
913
|
/**
|
|
660
914
|
* Canonical setup entry point. Alias of {@link getOrCreateConsentRuntime} that
|
|
@@ -665,5 +919,76 @@ declare function getOrCreateConsentRuntime(config: CookieYesConfig): ConsentRunt
|
|
|
665
919
|
declare function initCookieYes(config: CookieYesConfig): ConsentRuntime;
|
|
666
920
|
declare function resetConsentRuntime(): void;
|
|
667
921
|
|
|
668
|
-
|
|
669
|
-
|
|
922
|
+
/**
|
|
923
|
+
* @internal Test-only — empty the script registry and forget what was injected.
|
|
924
|
+
* Mirrors {@link _clearStopHandlers}. When a `document` is present the injected
|
|
925
|
+
* `<script>` elements are removed from it too, so one test can never leave a
|
|
926
|
+
* gated script behind for the next one. Safe to call with nothing registered.
|
|
927
|
+
*/
|
|
928
|
+
declare function _clearScriptRegistry(): void;
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* The subset of your consent config that affects reading a stored decision.
|
|
932
|
+
* `CookieYesConfig` satisfies this structurally, so you can pass the same object
|
|
933
|
+
* you give `initCookieYes`.
|
|
934
|
+
*/
|
|
935
|
+
type ServerConsentOptions = {
|
|
936
|
+
regulation?: Regulation | undefined;
|
|
937
|
+
categories?: CategoryDef[] | undefined;
|
|
938
|
+
};
|
|
939
|
+
/**
|
|
940
|
+
* Read a visitor's already-made consent decision from a request's `Cookie`
|
|
941
|
+
* header, on the server, with no `document` and no browser APIs.
|
|
942
|
+
*
|
|
943
|
+
* Use it to keep the banner out of the HTML entirely for a returning visitor.
|
|
944
|
+
* Without it the server has no idea whether the visitor has chosen, so it sends
|
|
945
|
+
* banner markup to everyone and the client removes it after hydration — the
|
|
946
|
+
* banner visibly appears and then vanishes, which reads as a bug.
|
|
947
|
+
*
|
|
948
|
+
* Returns `null` whenever the banner *should* be shown:
|
|
949
|
+
* - no consent cookie (a first-time visitor),
|
|
950
|
+
* - a cookie that records no decision yet (`action:no`, e.g. a CCPA visitor who
|
|
951
|
+
* has an implicit-consent cookie but has not acted),
|
|
952
|
+
* - a corrupt cookie,
|
|
953
|
+
* - a cookie written against a **different category taxonomy**, which the client
|
|
954
|
+
* also treats as stale and re-requests. The one exception mirrors the client
|
|
955
|
+
* exactly: a legacy cookie with no taxonomy stamp is still honoured when the
|
|
956
|
+
* built-in five categories are in effect, so existing visitors are not
|
|
957
|
+
* re-prompted by an upgrade.
|
|
958
|
+
*
|
|
959
|
+
* Otherwise returns the stored snapshot, ready to hand to `CookieYesProvider`'s
|
|
960
|
+
* `initialConsent`.
|
|
961
|
+
*
|
|
962
|
+
* ```ts
|
|
963
|
+
* // Any SSR framework — pass the request's Cookie header:
|
|
964
|
+
* const initialConsent = readServerConsent(request.headers.get("cookie") ?? "", config);
|
|
965
|
+
* ```
|
|
966
|
+
*
|
|
967
|
+
* In Next.js App Router, prefer `getServerConsent(config)` from
|
|
968
|
+
* `@cookieyes/nextjs`, which reads `cookies()` for you.
|
|
969
|
+
*
|
|
970
|
+
* **Never** put the result on `initCookieYes` or the runtime: the runtime is a
|
|
971
|
+
* module-level singleton shared across concurrent requests, so per-visitor state
|
|
972
|
+
* there would leak between them. It belongs in the component tree.
|
|
973
|
+
*/
|
|
974
|
+
declare function readServerConsent(cookieHeader: string, options?: ServerConsentOptions): ConsentSnapshot | null;
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* The version of `@cookieyes/core` this build was produced from.
|
|
978
|
+
*
|
|
979
|
+
* The literal below is a **sentinel, replaced at build time** with the real
|
|
980
|
+
* version from `package.json` (see the `injectPkgVersion` plugin in
|
|
981
|
+
* `rollup.shared.mjs`). It is done that way rather than hand-maintained because
|
|
982
|
+
* Changesets bumps `package.json` on the release PR — a constant someone has to
|
|
983
|
+
* remember to update would go stale on exactly the commit that matters, and a
|
|
984
|
+
* test guarding it would block an automated release PR instead.
|
|
985
|
+
*
|
|
986
|
+
* Reading this from source (this repo's own tests, or a `workspace:*` link)
|
|
987
|
+
* leaves the sentinel in place. Treat `0.0.0-dev` as "unknown version", never as
|
|
988
|
+
* a real one — `@cookieyes/test` does exactly that before deciding whether to
|
|
989
|
+
* warn about a mismatched pair.
|
|
990
|
+
*/
|
|
991
|
+
declare const CORE_VERSION = "0.0.0-dev";
|
|
992
|
+
|
|
993
|
+
export { CORE_VERSION, DEFAULT_CATEGORIES, INTEGRATION_FORMAT_VERSION, _clearScriptRegistry, _clearStopHandlers, _logRegionDecision, _normalizeConfig, _resetBuiltInIntegrationsWarning, _resetOfflineModeWarning, _warnBuiltInIntegrationsDeprecated, _warnOfflineModeDeprecated, broadcastGoogleConsent, computeGoogleConsent, createConsentEmitter, createConsentManager, createLanguageController, en as defaultTranslations, generateConsentId, getOrCreateConsentRuntime, getTextDirection, initCookieYes, installNetworkBlocker, mergeTranslations, parseCookie, parseCookieHeader, pickLanguage, primaryOf, readGpc, readServerConsent, regionFromHeaders, registerStopHandler, resetConsentRuntime, resolveBuiltInIntegration, resolveCategories, resolveRegion, resolveTranslations, runIntegrations, serializeCookie, uninstallNetworkBlocker, warnOverlappingVendors, warnUnknownCategories };
|
|
994
|
+
export type { ActiveUI, AnyStopHandler, BlockedRequestInfo, BuiltInIntegration, CategoryDef, CategoryText, Cleanup, ColorScheme, ConsentBackend, ConsentCategory, ConsentChangePayload, ConsentConfig, ConsentEmitter, ConsentEventListener, ConsentEventOptions, ConsentEventPayload, ConsentEventType, ConsentManager, ConsentPayload, ConsentRuntime, ConsentRuntimeMode, ConsentRuntimeOptions, ConsentSnapshot, ConsentStore, ConsentStoreState, CookieYesConfig, CookieYesOfflineConfig, CookieYesSelfHostedConfig, GoogleConsentSignal, HeaderSource, I18nConfig, Integration, IntegrationDebugInfo, IntegrationHost, IntegrationRunner, IntegrationStatus, LanguageController, LanguageInfo, NetworkBlockerConfig, NetworkBlockerRule, PartialTranslations, RegionConfig, RegionDecision, RegionDetector, RegionSource, Regulation, ReloadNoticeState, ReloadOnlyHandler, ResolvedCategories, ScriptEntry, ServerConsentOptions, SetupCtx, SilenceControl, StopHandler, TextDirection, ThemeConfig, TranslationMap, _NormalizedConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e="cookieyes-consent",t=new Set(["consentid","consent","action","tax","lastRenewedDate"]);function n(e){const n={categories:{}};for(const o of e.split(",")){const e=o.indexOf(":");if(-1===e)continue;const r=o.slice(0,e).trim(),a=o.slice(e+1).trim();t.has(r)?n[r]=a:r.length>0&&(n.categories[r]=a)}return n}function o(e){const t=[`consentid:${e.consentId}`,"consent:"+(e.hasActed?"yes":"no"),"action:"+(e.hasActed?"yes":"no")];e.taxonomyHash&&t.push(`tax:${e.taxonomyHash}`);for(const[n,o]of Object.entries(e.categories))t.push(`${n}:${o?"yes":"no"}`);return t.push(`lastRenewedDate:${e.lastRenewed??Date.now()}`),t.join(",")}function r(t){if("undefined"==typeof document)return;const n=encodeURIComponent(o(t));document.cookie=`${e}=${n}; max-age=31536000; path=/; SameSite=Lax`}function a(){"undefined"!=typeof document&&(document.cookie=`${e}=; max-age=0; path=/`)}function s(){const e=new Uint8Array(32);if("undefined"!=typeof crypto&&crypto.getRandomValues)crypto.getRandomValues(e);else for(let t=0;t<e.length;t++)e[t]=Math.floor(256*Math.random());return btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"").slice(0,44)}function i(e,t,n){const o="CCPA"===t,r={};for(const e of n.ids)r[e]=!!n.requiredIds.has(e)||o;return{consentId:e,hasActed:!1,categories:r,regulation:t,taxonomyHash:n.taxonomyHash}}const c=[{id:"necessary",required:!0},{id:"functional",gcm:["functionality_storage","personalization_storage"]},{id:"analytics",gcm:["analytics_storage"]},{id:"performance"},{id:"advertisement",gcm:["ad_storage","ad_user_data","ad_personalization"]}];function d(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return(t>>>0).toString(36)}function l(e,t){const n=e.map(e=>e.id),o=new Set(e.filter(e=>e.required).map(e=>e.id)),r=e.map(e=>`${e.id}:${e.required?1:0}:${(e.gcm??[]).join("+")}`).join("|");return{list:e,ids:n,requiredIds:o,taxonomyHash:d(r),isDefault:t}}function u(e){if(!e||0===e.length)return l(c,!0);const n=function(e){const n=e.map(e=>e.id);return n.some(e=>"string"!=typeof e||0===e.length)?"every category needs a non-empty string id":n.some(e=>e.includes(",")||e.includes(":"))?"category ids must not contain ',' or ':'":new Set(n).size!==n.length?"category ids must be unique":n.some(e=>t.has(e))?`category ids must not be one of the reserved keys: ${[...t].join(", ")}`:e.some(e=>!0===e.required)?null:"at least one category must be marked { required: true }"}(e);return n?("undefined"!=typeof console&&console.warn(`[cookieyes] Invalid categories config (${n}). Falling back to the default five (necessary, functional, analytics, performance, advertisement).`),l(c,!0)):l(e,!1)}function g(e){"undefined"!=typeof console&&console.warn(e)}function f(e){const t={mode:e.mode},n=e.overrides?.regulation;return void 0!==e.regulation?(t.regulation=e.regulation,void 0!==n&&g("[CookieYes] Received both `regulation` and the deprecated `overrides.regulation`. Using the top-level `regulation` and ignoring `overrides`. Drop the `overrides` object — it is deprecated and will be removed after three release cycles.")):void 0!==n&&(t.regulation=n),void 0!==e.colorScheme&&(t.colorScheme=e.colorScheme),void 0!==e.theme&&(t.theme=e.theme),void 0!==e.i18n&&(t.i18n=e.i18n),void 0!==e.consentCategories&&(t.consentCategories=e.consentCategories),void 0!==e.categories&&(t.categories=e.categories),void 0!==e.networkBlocker&&(t.networkBlocker=e.networkBlocker),void 0!==e.reloadOnRevoke&&(t.reloadOnRevoke=e.reloadOnRevoke),void 0!==e.integrations&&(t.integrations=e.integrations),void 0!==e.customStopHandlers&&(t.customStopHandlers=e.customStopHandlers),void 0!==e.onConsentReady&&(t.onConsentReady=e.onConsentReady),void 0!==e.onConsentUpdate&&(t.onConsentUpdate=e.onConsentUpdate),"self-hosted"===e.mode&&(void 0!==e.apiKey&&(t.apiKey=e.apiKey),void 0!==e.backend&&(t.backend=e.backend),void 0!==e.apiUrl?(t.apiUrl=e.apiUrl,void 0!==e.backendURL&&g("[CookieYes] Received both `apiUrl` and the deprecated `backendURL`. Using `apiUrl` and ignoring `backendURL`. Rename `backendURL` to `apiUrl` — the alias is deprecated and will be removed after three release cycles.")):void 0!==e.backendURL&&(t.apiUrl=e.backendURL)),t}let h=!1;function p(){h||(h=!0,"undefined"!=typeof console&&console.warn('[cookieyes] mode: "offline" has been renamed to "cookie-only". Both do exactly the same thing, but "offline" is deprecated and will be removed in 3 releases. Update to .mode("cookie-only") (or { mode: "cookie-only" }).'))}function y(){h=!1}function m(e){const t={save:new Set,change:new Set};let n={...e()};function o(e,t,n){try{e.listener(n)}catch(e){"undefined"!=typeof console&&console.error(`[cookieyes] a consent "${t}" listener threw; others are unaffected:`,e)}}function r(e,n){for(const r of[...t[e]])r.category&&!n.changedCategories.includes(r.category)||o(r,e,n)}return{on(n,r,a){const s=a?.category?{listener:r,category:a.category}:{listener:r};return t[n].add(s),o(s,n,{categories:{...e()},changedCategories:[],isInitial:!0}),()=>{t[n].delete(s)}},push(e){const t={...e},o=[];for(const e of Object.keys(t))n[e]!==t[e]&&o.push(e);n=t,r("save",{categories:t,changedCategories:o,isInitial:!1}),o.length>0&&r("change",{categories:t,changedCategories:o,isInitial:!1})}}}const w=["ad_storage","ad_user_data","ad_personalization","analytics_storage","functionality_storage","personalization_storage","security_storage"];function v(e,t){const n={};for(const e of w)n[e]="denied";n.security_storage="granted";for(const o of e.list)if(o.gcm&&0!==o.gcm.length&&t[o.id])for(const e of o.gcm)n[e]="granted";return n}function k(e,t){if("undefined"==typeof window||!Array.isArray(window.dataLayer))return;const n=v(e,t),o=window.dataLayer;if(!o)return;!function(){o.push(arguments)}("consent","update",n)}const b={bannerTitle:"We value your privacy",bannerDescription:"We use cookies to enhance your browsing experience, serve personalised ads or content, and analyse our traffic. By clicking “Accept All”, you consent to our use of cookies.",acceptAll:"Accept All",rejectAll:"Reject All",managePreferences:"Customise",savePreferences:"Save My Preferences",doNotSell:"Do Not Sell or Share My Personal Information",ccpaDescription:"This website or its third-party tools process personal data. You can opt out of the sale of your personal information by clicking on the “Do Not Sell or Share My Personal Information” link.",accept:"Accept",poweredBy:"Powered by CookieYes",preferencesTitle:"Customise Consent Preferences",preferencesIntro:"We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.",categories:{necessary:{label:"Necessary",description:"Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data."},functional:{label:"Functional",description:"Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features."},analytics:{label:"Analytics",description:"Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc."},performance:{label:"Performance",description:"Performance cookies are used to understand and analyse the key performance indexes of the website which helps in delivering a better user experience for the visitors."},advertisement:{label:"Advertisement",description:"Advertisement cookies are used to provide visitors with customised advertisements based on the pages you visited previously and to analyse the effectiveness of the ad campaigns."}},optOut:{title:"Opt-out Preferences",description:'We use third-party cookies that help us analyse how you use this website, store your preferences, and provide the content and advertisements that are relevant to you. However, you can opt out of these cookies by checking "Do Not Sell or Share My Personal Information" and clicking the "Save My Preferences" button. Once you opt out, you can opt in again at any time by unchecking "Do Not Sell or Share My Personal Information" and clicking the "Save My Preferences" button.',cancel:"Cancel",successText:"Your opt-out preference has been honored.",successCountdown:"Banner closes automatically in {seconds} s..."},reloadNotice:{message:"Some tracking on this page can only be fully stopped by reloading. Reload to apply your change, or dismiss to keep browsing.",reloadButton:"Reload page",dismissButton:"Dismiss"}},S=new Set(["ar","he","fa","ur","ps","sd","yi","dv"]);function C(e){return e.split("-")[0]?.toLowerCase()??""}function R(e){return S.has(C(e))?"rtl":"ltr"}function A(e,t){if(!t)return e;const n={...e};for(const[o,r]of Object.entries(t)){if(null==r)continue;const t=e[o],a="object"==typeof r&&!Array.isArray(r)&&"object"==typeof t&&null!=t;n[o]=a?A(t,r):r}return n}function U(e){const t=e?.messages??{},n=[];e?.locale&&n.push(e.locale),(e?.detectBrowserLanguage??1)&&"undefined"!=typeof navigator&&navigator.language&&n.push(navigator.language);for(const e of n){if(t[e])return e;const n=C(e);if(n&&t[n])return n}return"en"}function I(e){const t=e?.messages??{},n=U(e);return A(b,t[n]??t[C(n)])}function x(e,t){const n={...e?.messages},o=e?.loadLanguage,r=new Set;let a=U(e),s=l(a),i=u();function c(e){return n[e]??n[C(e)]}function d(e){return"en"===C(e)||void 0!==c(e)}function l(e){return A(b,c(e))}function u(){return{language:a,direction:R(a),languages:Array.from(new Set(["en",...Object.keys(n)]))}}function g(e){a=e,s=l(e),i=u(),t()}function f(e,t){r.has(e)||"undefined"==typeof console||(r.add(e),console.warn(`[cookieyes] no translations for language "${e}"; staying on "${a}". Add it to i18n.messages or provide i18n.loadLanguage.`,t??""))}function h(e){return d(e)?(g(e),Promise.resolve()):o?Promise.resolve().then(()=>o(e)).then(t=>{n[e]=t,g(e)}).catch(t=>f(e,t)):(f(e),Promise.resolve())}return o&&e?.locale&&!d(e.locale)&&"undefined"!=typeof window&&h(e.locale),{getTranslations:()=>s,getLanguageInfo:()=>i,setLanguage:h,getCategoryText:function(e){return c(a)?.categories?.[e]}}}const L=new Map,P=new Map;function B(e,t){if(document.getElementById(e))return;const n=document.createElement("script");n.id=e,n.src=t.src,n.async=!0,t.onLoad&&n.addEventListener("load",t.onLoad,{once:!0}),document.head.appendChild(n),P.set(e,n)}function H(e){return"needsReload"in e&&!0===e.needsReload}function O(e){switch(e.vendor){case"meta":return{id:"meta",category:e.category??"advertisement",stop:()=>window.fbq?.("consent","revoke"),resume:()=>window.fbq?.("consent","grant")};case"tiktok":return{id:"tiktok",category:e.category??"advertisement",needsReload:!0};case"linkedin":return{id:"linkedin",category:e.category??"advertisement",needsReload:!0};case"hotjar":return{id:"hotjar",category:e.category??"analytics",needsReload:!0};case"segment":return{id:"segment",category:e.category??"analytics",needsReload:!0}}}const q=new Map,$=new Set,M=new Set;function j(e){q.set(e.id,e)}function T(){q.clear(),$.clear(),M.clear()}function _(e){const t=[];for(const n of q.values()){const o=!0!==e[n.category];if(H(n))o?M.has(n.id)&&(t.push(n.id),M.delete(n.id)):M.add(n.id);else if(o){if(!$.has(n.id))try{n.stop(),$.add(n.id)}catch{t.push(n.id)}}else if($.has(n.id)){$.delete(n.id);try{n.resume?.()}catch{}}}return{reloadRequiredBy:t}}function D(e){return{consentId:e.consentId,categories:e.categories,regulation:e.regulation,domain:"undefined"!=typeof window?window.location.hostname:"unknown"}}function N(t){const o=new Set,c=u(t.categories);let d,l,g,f=!1;function h(e){const t={};for(const n of c.ids)t[n]=!!c.requiredIds.has(n)||e(n);return t}let p=[],y=!1;for(const e of t.integrations??[])j(O(e));for(const e of t.customStopHandlers??[])j(e);const m=function(){if("undefined"==typeof document)return null;const t=document.cookie.split(";");for(const o of t){const t=o.trim(),r=t.indexOf("=");if(-1!==r&&t.slice(0,r).trim()===e){const e=t.slice(r+1).trim();return n(decodeURIComponent(e))}}return null}(),w=t.regulation??"DEFAULT",v=m?.tax,b=v===c.taxonomyHash,S=null!=m&&(b||void 0===v&&c.isDefault);if(null!=m&&S)d=function(e,t,n){const o={};for(const t of n.ids)o[t]=!!n.requiredIds.has(t)||"yes"===e.categories[t];return{consentId:e.consentid??s(),hasActed:"yes"===e.action,categories:o,regulation:t,lastRenewed:e.lastRenewedDate?Number(e.lastRenewedDate):void 0,taxonomyHash:e.tax}}(m,w,c);else{const e=m?.consentid??s();d=i(e,w,c),null!=m&&a(),"CCPA"===d.regulation&&r(d)}function C(){const e={consentId:d.consentId,hasActed:d.hasActed,categories:{...d.categories},regulation:d.regulation,lastRenewed:d.lastRenewed,taxonomyHash:d.taxonomyHash};for(const t of o)t(e)}function R(){!function(e){if("undefined"!=typeof document)for(const[t,n]of L)!0===e[n.category]&&(P.has(t)||B(t,n))}(g)}function A(){if(d={...d,hasActed:!0,lastRenewed:Date.now()},r(d),t.backend)try{Promise.resolve(t.backend.persist(D(d))).catch(()=>{})}catch{}else t.apiUrl&&async function(e,t,n){const o=D(n),r={"Content-Type":"application/json"};t&&(r.Authorization=`Bearer ${t}`);try{await fetch(e,{method:"POST",headers:r,body:JSON.stringify(o),keepalive:!0})}catch{}}(t.apiUrl,t.apiKey,d);let e=!1;for(const t of c.ids)if(l[t]&&!d.categories[t]){e=!0;break}l={...d.categories},g={...d.categories},R();const{reloadRequiredBy:n}=_(g);var o;((o=n).length!==p.length||o.some((e,t)=>e!==p[t]))&&(p=o,y=!1),k(c,g),C(),t.onConsentUpdate?.(d),e&&t.reloadOnRevoke&&"undefined"!=typeof window&&window.location.reload()}d={...d,taxonomyHash:c.taxonomyHash},l={...d.categories},g={...d.categories},Promise.resolve().then(()=>t.onConsentReady?.(d));const U={get consentId(){return d.consentId},get hasActed(){return d.hasActed},get categories(){return{...d.categories}},get committedCategories(){return{...g}},get regulation(){return d.regulation},get lastRenewed(){return d.lastRenewed},get taxonomyHash(){return d.taxonomyHash},get isPreferencesOpen(){return f},acceptAll(){d={...d,categories:h(()=>!0)},f=!1,A()},rejectAll(){d={...d,categories:h(()=>!1)},f=!1,A()},acceptSelected(e){d={...d,categories:h(t=>e.includes(t))},f=!1,A()},updateCategory(e,t){c.requiredIds.has(e)||c.ids.includes(e)&&(d={...d,categories:{...d.categories,[e]:t}},C())},savePreferences(){f=!1,A()},resetConsent(){a();const e=s();d=i(e,d.regulation,c),g={...d.categories},l={...d.categories},f=!1,_(g),k(c,g),p=[],y=!1,C()},showPreferences(){f=!0,C()},hidePreferences(){f=!1,C()},subscribe:e=>(o.add(e),()=>o.delete(e)),registerScript(e){!function(e){L.set(e.id,e)}(e),R()},get reloadNotice(){return{required:p.length>0&&!y,reasons:[...p]}},dismissReloadNotice(){y||(y=!0,C())}};return R(),function(e){for(const t of q.values()){const n=!0!==e[t.category];if(H(t))n?M.delete(t.id):M.add(t.id);else try{n?(t.stop(),$.add(t.id)):($.delete(t.id),t.resume?.())}catch{}}}(d.categories),k(c,d.categories),U}function X(e,t,n,o){let r;try{const e="undefined"!=typeof window?window.location.href:"http://localhost";r=new URL(t,e)}catch{return null}const a=r.hostname.toLowerCase(),s=r.pathname+r.search,i=n.toUpperCase();for(const t of e){const e=t.domain.toLowerCase();if((a===e||a.endsWith("."+e))&&((!t.pathIncludes||s.includes(t.pathIncludes))&&(!t.methods||t.methods.map(e=>e.toUpperCase()).includes(i))&&!o(t.category)))return t}return null}let E=null;function F(e,t){if("undefined"==typeof window)return()=>{};if(E)return()=>{};if(!e.rules.length)return()=>{};const n={originalFetch:window.fetch,originalXhrOpen:XMLHttpRequest.prototype.open,originalXhrSend:XMLHttpRequest.prototype.send,originalSendBeacon:"undefined"!=typeof navigator&&"function"==typeof navigator.sendBeacon?navigator.sendBeacon:void 0};E=n;const o=!1!==e.logBlockedRequests;function r(t){o&&console.warn(`[cookieyes] blocked ${t.method} ${t.url} (rule "${t.rule.id}", category: ${t.rule.category})`),e.onRequestBlocked?.(t)}if(window.fetch=function(o,a){let s="",i=a?.method??"GET";"string"==typeof o?s=o:o instanceof URL?s=o.toString():(s=o.url,i=a?.method??o.method);const c=X(e.rules,s,i,t);return c?(r({rule:c,url:s,method:i}),Promise.reject(new TypeError(`Blocked by consent (rule: ${c.id}, category: ${c.category})`))):n.originalFetch.call(window,o,a)},XMLHttpRequest.prototype.open=function(e,t,...o){return this._cyUrl=t.toString(),this._cyMethod=e,n.originalXhrOpen.apply(this,[e,t,...o])},XMLHttpRequest.prototype.send=function(o){const a=this._cyUrl??"",s=this._cyMethod??"GET",i=X(e.rules,a,s,t);return i?(r({rule:i,url:a,method:s}),void this.abort()):n.originalXhrSend.call(this,o)},n.originalSendBeacon){const o=n.originalSendBeacon;navigator.sendBeacon=function(n,a){const s=X(e.rules,n.toString(),"POST",t);return s?(r({rule:s,url:n.toString(),method:"POST"}),!0):o.call(navigator,n,a)}}return K}function K(){E&&("undefined"!=typeof window&&(window.fetch=E.originalFetch,XMLHttpRequest.prototype.open=E.originalXhrOpen,XMLHttpRequest.prototype.send=E.originalXhrSend,E.originalSendBeacon&&(navigator.sendBeacon=E.originalSendBeacon)),E=null)}let z=null;function Y(e){if(z)return z;"offline"===e.mode&&p();const t=f(e),n=new Set,o=t.onConsentUpdate;let r;const a={};"self-hosted"===t.mode&&(t.backend?a.backend=t.backend:t.apiUrl&&(a.apiUrl=t.apiUrl)),t.apiKey&&(a.apiKey=t.apiKey),t.regulation&&(a.regulation=t.regulation),t.colorScheme&&(a.colorScheme=t.colorScheme),t.theme&&(a.theme=t.theme),t.reloadOnRevoke&&(a.reloadOnRevoke=t.reloadOnRevoke),t.integrations&&(a.integrations=t.integrations),t.customStopHandlers&&(a.customStopHandlers=t.customStopHandlers),t.categories&&(a.categories=t.categories),t.onConsentReady&&(a.onConsentReady=t.onConsentReady),a.onConsentUpdate=e=>{o?.(e),r.push(e.categories);const t=function(e){const t=[],n=[];for(const o of Object.keys(e))e[o]?t.push(o):n.push(o);return{allowedCategories:t,deniedCategories:n}}(e.categories);for(const e of n)e(t)};const s=N(a);r=m(()=>s.committedCategories);const i=u(t.categories),c=new Set;function d(){const e=g();for(const t of c)t(e)}s.subscribe(d);const l=x(t.i18n,d);function g(){const e=s.categories;return{consentId:s.consentId,hasActed:s.hasActed,categories:e,consents:e,committedConsents:s.committedCategories,regulation:s.regulation,lastRenewed:s.lastRenewed,taxonomyHash:s.taxonomyHash,activeUI:s.isPreferencesOpen?"dialog":s.hasActed?null:"banner",has:e=>!0===s.committedCategories[e],saveConsents:async e=>{"all"===e?s.acceptAll():"necessary"===e?s.rejectAll():s.acceptSelected(e)},setConsent:(e,t)=>s.updateCategory(e,t),subscribeToConsentChanges:e=>(n.add(e),()=>{n.delete(e)})}}const h={subscribe:e=>(c.add(e),()=>{c.delete(e)}),getState:g,on:(e,t,n)=>r.on(e,t,n),get translations(){return l.getTranslations()},getLanguageInfo:l.getLanguageInfo,setLanguage:l.setLanguage,getCategoryText:l.getCategoryText,categories:i};return t.networkBlocker&&t.networkBlocker.rules.length>0&&F(t.networkBlocker,e=>!0===s.committedCategories[e]),z={consentManager:s,consentStore:h},z}function W(e){return Y(e)}function G(){z=null}export{c as DEFAULT_CATEGORIES,T as _clearStopHandlers,f as _normalizeConfig,y as _resetOfflineModeWarning,p as _warnOfflineModeDeprecated,k as broadcastGoogleConsent,v as computeGoogleConsent,m as createConsentEmitter,N as createConsentManager,x as createLanguageController,b as defaultTranslations,s as generateConsentId,Y as getOrCreateConsentRuntime,R as getTextDirection,W as initCookieYes,F as installNetworkBlocker,A as mergeTranslations,n as parseCookie,U as pickLanguage,C as primaryOf,j as registerStopHandler,G as resetConsentRuntime,O as resolveBuiltInIntegration,u as resolveCategories,I as resolveTranslations,o as serializeCookie,K as uninstallNetworkBlocker};
|
|
1
|
+
const e="cookieyes-consent",t=new Set(["consentid","consent","action","tax","lastRenewedDate"]);function n(e){const n={categories:{}};for(const o of e.split(",")){const e=o.indexOf(":");if(-1===e)continue;const i=o.slice(0,e).trim(),r=o.slice(e+1).trim();t.has(i)?n[i]=r:i.length>0&&(n.categories[i]=r)}return n}function o(e){const t=[`consentid:${e.consentId}`,"consent:"+(e.hasActed?"yes":"no"),"action:"+(e.hasActed?"yes":"no")];e.taxonomyHash&&t.push(`tax:${e.taxonomyHash}`);for(const[n,o]of Object.entries(e.categories))t.push(`${n}:${o?"yes":"no"}`);return t.push(`lastRenewedDate:${e.lastRenewed??Date.now()}`),t.join(",")}function i(t){for(const o of t.split(";")){const t=o.trim(),i=t.indexOf("=");if(-1===i)continue;if(t.slice(0,i).trim()!==e)continue;const r=t.slice(i+1).trim();try{return n(decodeURIComponent(r))}catch{return null}}return null}function r(t){if("undefined"==typeof document)return;const n=encodeURIComponent(o(t));document.cookie=`${e}=${n}; max-age=31536000; path=/; SameSite=Lax`}function a(){"undefined"!=typeof document&&(document.cookie=`${e}=; max-age=0; path=/`)}function s(){const e=new Uint8Array(32);if("undefined"!=typeof crypto&&crypto.getRandomValues)crypto.getRandomValues(e);else for(let t=0;t<e.length;t++)e[t]=Math.floor(256*Math.random());return btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"").slice(0,44)}function c(e,t,n){const o={};for(const t of n.ids)o[t]=!!n.requiredIds.has(t)||"yes"===e.categories[t];return{consentId:e.consentid??s(),hasActed:"yes"===e.action,categories:o,regulation:t,lastRenewed:e.lastRenewedDate?Number(e.lastRenewedDate):void 0,taxonomyHash:e.tax}}function d(e,t,n){const o="CCPA"===t,i={};for(const e of n.ids)i[e]=!!n.requiredIds.has(e)||o;return{consentId:e,hasActed:!1,categories:i,regulation:t,taxonomyHash:n.taxonomyHash}}const l=[{id:"necessary",required:!0},{id:"functional",gcm:["functionality_storage","personalization_storage"]},{id:"analytics",gcm:["analytics_storage"]},{id:"performance"},{id:"advertisement",gcm:["ad_storage","ad_user_data","ad_personalization"]}];function u(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return(t>>>0).toString(36)}function g(e,t){const n=e.map(e=>e.id),o=new Set(e.filter(e=>e.required).map(e=>e.id)),i=e.map(e=>`${e.id}:${e.required?1:0}:${(e.gcm??[]).join("+")}`).join("|");return{list:e,ids:n,requiredIds:o,taxonomyHash:u(i),isDefault:t}}function f(e){if(!e||0===e.length)return g(l,!0);const n=function(e){const n=e.map(e=>e.id);return n.some(e=>"string"!=typeof e||0===e.length)?"every category needs a non-empty string id":n.some(e=>e.includes(",")||e.includes(":"))?"category ids must not contain ',' or ':'":new Set(n).size!==n.length?"category ids must be unique":n.some(e=>t.has(e))?`category ids must not be one of the reserved keys: ${[...t].join(", ")}`:e.some(e=>!0===e.required)?null:"at least one category must be marked { required: true }"}(e);return n?("undefined"!=typeof console&&console.warn(`[cookieyes] Invalid categories config (${n}). Falling back to the default five (necessary, functional, analytics, performance, advertisement).`),g(l,!0)):g(e,!1)}function h(e){"undefined"!=typeof console&&console.warn(e)}function y(e){const t={mode:e.mode},n=e.overrides?.regulation;return void 0!==e.regulation?(t.regulation=e.regulation,void 0!==n&&h("[CookieYes] Received both `regulation` and the deprecated `overrides.regulation`. Using the top-level `regulation` and ignoring `overrides`. Drop the `overrides` object — it is deprecated and will be removed after three release cycles.")):void 0!==n&&(t.regulation=n),void 0!==e.region&&(t.region=e.region),void 0!==e.colorScheme&&(t.colorScheme=e.colorScheme),void 0!==e.theme&&(t.theme=e.theme),void 0!==e.i18n&&(t.i18n=e.i18n),void 0!==e.consentCategories&&(t.consentCategories=e.consentCategories),void 0!==e.categories&&(t.categories=e.categories),void 0!==e.networkBlocker&&(t.networkBlocker=e.networkBlocker),void 0!==e.reloadOnRevoke&&(t.reloadOnRevoke=e.reloadOnRevoke),void 0!==e.googleConsentMatch&&(t.googleConsentMatch=e.googleConsentMatch),void 0!==e.integrations&&(t.integrations=e.integrations),void 0!==e.builtInIntegrations&&(t.builtInIntegrations=e.builtInIntegrations),void 0!==e.customStopHandlers&&(t.customStopHandlers=e.customStopHandlers),void 0!==e.onConsentReady&&(t.onConsentReady=e.onConsentReady),void 0!==e.onConsentUpdate&&(t.onConsentUpdate=e.onConsentUpdate),"self-hosted"===e.mode&&(void 0!==e.apiKey&&(t.apiKey=e.apiKey),void 0!==e.backend&&(t.backend=e.backend),void 0!==e.apiUrl?(t.apiUrl=e.apiUrl,void 0!==e.backendURL&&h("[CookieYes] Received both `apiUrl` and the deprecated `backendURL`. Using `apiUrl` and ignoring `backendURL`. Rename `backendURL` to `apiUrl` — the alias is deprecated and will be removed after three release cycles.")):void 0!==e.backendURL&&(t.apiUrl=e.backendURL)),t}let p=!1;function m(){p||(p=!0,"undefined"!=typeof console&&console.warn('[cookieyes] mode: "offline" has been renamed to "cookie-only". Both do exactly the same thing, but "offline" is deprecated and will be removed in 3 releases. Update to .mode("cookie-only") (or { mode: "cookie-only" }).'))}function v(){p=!1}let w=!1;function b(){w||(w=!0,"undefined"!=typeof console&&console.warn("[cookieyes] `builtInIntegrations` (formerly the `integrations` field) is deprecated and will be removed in a future release. Use the `integrations` field with a preset from `@cookieyes/scripts` instead."))}function k(){w=!1}function C(e){const t={save:new Set,change:new Set};let n={...e()};function o(e,t,n){try{e.listener(n)}catch(e){"undefined"!=typeof console&&console.error(`[cookieyes] a consent "${t}" listener threw; others are unaffected:`,e)}}function i(e,n){for(const i of[...t[e]])i.category&&!n.changedCategories.includes(i.category)||o(i,e,n)}return{on(n,i,r){const a=r?.category?{listener:i,category:r.category}:{listener:i};return t[n].add(a),o(a,n,{categories:{...e()},changedCategories:[],isInitial:!0}),()=>{t[n].delete(a)}},push(e){const t={...e},o=[];for(const e of Object.keys(t))n[e]!==t[e]&&o.push(e);n=t,i("save",{categories:t,changedCategories:o,isInitial:!1}),o.length>0&&i("change",{categories:t,changedCategories:o,isInitial:!1})}}}function R(e){"undefined"!=typeof console&&console.warn(`[cookieyes] ${e}`)}const S=["ad_storage","ad_user_data","ad_personalization","analytics_storage","functionality_storage","personalization_storage","security_storage"];function I(e,t,n="any"){const o={};for(const i of S){if("security_storage"===i){o[i]="granted";continue}const r=e.list.filter(e=>e.gcm?.includes(i));if(0===r.length){o[i]="denied";continue}const a="all"===n?r.every(e=>!0===t[e.id]):r.some(e=>!0===t[e.id]);o[i]=a?"granted":"denied"}return o}function A(e,t,n="any"){if("undefined"==typeof window||!Array.isArray(window.dataLayer))return;const o=I(e,t,n),i=window.dataLayer;if(!i)return;!function(){i.push(arguments)}("consent","update",o)}const x={bannerTitle:"We value your privacy",bannerDescription:"We use cookies to enhance your browsing experience, serve personalised ads or content, and analyse our traffic. By clicking “Accept All”, you consent to our use of cookies.",acceptAll:"Accept All",rejectAll:"Reject All",managePreferences:"Customise",savePreferences:"Save My Preferences",doNotSell:"Do Not Sell or Share My Personal Information",ccpaDescription:"This website or its third-party tools process personal data. You can opt out of the sale of your personal information by clicking on the “Do Not Sell or Share My Personal Information” link.",accept:"Accept",poweredBy:"Powered by CookieYes",preferencesTitle:"Customise Consent Preferences",preferencesIntro:"We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.",categories:{necessary:{label:"Necessary",description:"Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data."},functional:{label:"Functional",description:"Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features."},analytics:{label:"Analytics",description:"Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc."},performance:{label:"Performance",description:"Performance cookies are used to understand and analyse the key performance indexes of the website which helps in delivering a better user experience for the visitors."},advertisement:{label:"Advertisement",description:"Advertisement cookies are used to provide visitors with customised advertisements based on the pages you visited previously and to analyse the effectiveness of the ad campaigns."}},optOut:{title:"Opt-out Preferences",description:'We use third-party cookies that help us analyse how you use this website, store your preferences, and provide the content and advertisements that are relevant to you. However, you can opt out of these cookies by checking "Do Not Sell or Share My Personal Information" and clicking the "Save My Preferences" button. Once you opt out, you can opt in again at any time by unchecking "Do Not Sell or Share My Personal Information" and clicking the "Save My Preferences" button.',cancel:"Cancel",successText:"Your opt-out preference has been honored.",successCountdown:"Banner closes automatically in {seconds} s..."},reloadNotice:{message:"Some tracking on this page can only be fully stopped by reloading. Reload to apply your change, or dismiss to keep browsing.",reloadButton:"Reload page",dismissButton:"Dismiss"}},$=new Set(["ar","he","fa","ur","ps","sd","yi","dv"]);function U(e){return e.split("-")[0]?.toLowerCase()??""}function L(e){return $.has(U(e))?"rtl":"ltr"}function P(e,t){if(!t)return e;const n={...e};for(const[o,i]of Object.entries(t)){if(null==i)continue;const t=e[o],r="object"==typeof i&&!Array.isArray(i)&&"object"==typeof t&&null!=t;n[o]=r?P(t,i):i}return n}function O(e){const t=e?.messages??{},n=[];e?.locale&&n.push(e.locale),(e?.detectBrowserLanguage??1)&&"undefined"!=typeof navigator&&navigator.language&&n.push(navigator.language);for(const e of n){if(t[e])return e;const n=U(e);if(n&&t[n])return n}return"en"}function H(e){const t=e?.messages??{},n=O(e);return P(x,t[n]??t[U(n)])}const M=1;function B(e,t){const n=new Set(e);for(const e of t)n.has(e)&&T(`"${e}" is configured as both a script integration and a built-in integration — remove one to avoid loading it twice (e.g. double-counted events).`)}function q(e,t){const n=new Set(t);for(const t of e){if("afterConsent"!==t.load)continue;const e=t.category,o=Array.isArray(e)?e:[e];if(0!==o.length)for(const e of o)n.has(e)||T(`integration "${t.id}" is gated on category "${e}", which isn't in your configured categories — it will never load. Pass a category that exists (e.g. segment({ category: "…" })), or add it to your taxonomy.`);else T(`integration "${t.id}" has an empty category list — it will never load. Give it at least one category that exists in your taxonomy.`)}}function T(e,t){"undefined"!=typeof console&&(void 0!==t?console.error(`[cookieyes] ${e}`,t):console.warn(`[cookieyes] ${e}`))}function j(e,t){const n=Array.isArray(e.category)?e.category:[e.category];return 0!==n.length&&("any"===e.match?n.some(e=>t.granted(e)):n.every(e=>t.granted(e)))}function D(e,t){const n=[],o=new Set;let i=!1;for(const t of e){const e=t;"string"!=typeof e.vendor||"function"==typeof e.setup?1===t.version?o.has(t.id)?T(`integration "${t.id}" is registered more than once; skipping the duplicate.`):(o.add(t.id),n.push({integration:t,status:"idle",everLoaded:!1,loading:!1,control:void 0,subs:new Set,wasGranted:!1})):T(`integration "${t.id}" uses format version ${t.version}, but this build understands 1. Skipping it.`):T(`an entry in "integrations" looks like the old built-in format ({ vendor: "${e.vendor}" }). That moved to "builtInIntegrations" — move it there, or use a preset from "@cookieyes/scripts" in "integrations". Skipping it.`)}function r(e){for(const t of e.subs)try{t()}catch{}e.subs.clear()}function a(e){r(e),"active"===e.status&&(!function(e){const{integration:t,control:n}=e;try{"remove"===t.onRevoke?n?.():"silence"===t.onRevoke&&n?.silence()}catch(e){T(`integration "${t.id}" threw while being torn down.`,e)}e.control=void 0}(e),"remove"===e.integration.onRevoke?e.status="removed":"silence"===e.integration.onRevoke&&(e.status="silenced"))}function s(e){e.loading=!0,e.status="loading",Promise.resolve().then(()=>e.integration.setup(function(e){return{granted:()=>j(e.integration,t),onConsentChange:n=>{const o=t.subscribe(n);return e.subs.add(o),()=>{e.subs.delete(o)&&o()}},region:t.region}}(e))).then(t=>{e.loading=!1,e.control=t??void 0,e.everLoaded=!0,e.status="active",i?a(e):c(e)}).catch(t=>{e.loading=!1,e.status="error",r(e),T(`integration "${e.integration.id}" failed to load; will retry on the next change.`,t)})}function c(e){const{integration:n}=e,o=j(n,t);if(o&&(e.wasGranted=!0),i||e.loading)return;if("idle"===e.status||"removed"===e.status||"error"===e.status){return void((e.everLoaded?o:"immediately"===n.load||o)&&s(e))}if("keep"===n.onRevoke)return;if("remove"===n.onRevoke){if(!o&&"active"===e.status&&e.wasGranted){r(e);try{e.control?.()}catch(e){T(`integration "${n.id}" cleanup threw on revoke.`,e)}e.control=void 0,e.status="removed"}return}const a=e.control;if(o||"active"!==e.status){if(o&&"silenced"===e.status){try{a?.resume()}catch(e){T(`integration "${n.id}" resume() threw.`,e)}e.status="active"}}else{try{a?.silence()}catch(e){T(`integration "${n.id}" silence() threw.`,e)}e.status="silenced"}}function d(){for(const e of n)c(e)}const l=t.subscribe(d);return d(),{status:()=>{const e={};for(const t of n)e[t.integration.id]=t.status;return e},list:()=>n.map(e=>({id:e.integration.id,category:e.integration.category,load:e.integration.load,onRevoke:e.integration.onRevoke,status:e.status})),stop:()=>{if(!i){i=!0,l();for(const e of n)a(e)}}}}function _(e,t){const n={...e?.messages},o=e?.loadLanguage,i=new Set;let r=O(e),a=l(r),s=u();function c(e){return n[e]??n[U(e)]}function d(e){return"en"===U(e)||void 0!==c(e)}function l(e){return P(x,c(e))}function u(){return{language:r,direction:L(r),languages:Array.from(new Set(["en",...Object.keys(n)]))}}function g(e){r=e,a=l(e),s=u(),t()}function f(e,t){i.has(e)||"undefined"==typeof console||(i.add(e),console.warn(`[cookieyes] no translations for language "${e}"; staying on "${r}". Add it to i18n.messages or provide i18n.loadLanguage.`,t??""))}function h(e){return d(e)?(g(e),Promise.resolve()):o?Promise.resolve().then(()=>o(e)).then(t=>{n[e]=t,g(e)}).catch(t=>f(e,t)):(f(e),Promise.resolve())}return o&&e?.locale&&!d(e.locale)&&"undefined"!=typeof window&&h(e.locale),{getTranslations:()=>a,getLanguageInfo:()=>s,setLanguage:h,getCategoryText:function(e){return c(r)?.categories?.[e]}}}const N=new Map,X=new Map;function E(){if("undefined"!=typeof document)for(const e of X.values())e.remove();N.clear(),X.clear()}function F(e,t){if(document.getElementById(e))return;const n=document.createElement("script");n.id=e,n.src=t.src,n.async=!0,t.onLoad&&n.addEventListener("load",t.onLoad,{once:!0}),document.head.appendChild(n),X.set(e,n)}function G(e){return"needsReload"in e&&!0===e.needsReload}function z(e){switch(e.vendor){case"meta":return{id:"meta",category:e.category??"advertisement",stop:()=>window.fbq?.("consent","revoke"),resume:()=>window.fbq?.("consent","grant")};case"tiktok":return{id:"tiktok",category:e.category??"advertisement",needsReload:!0};case"linkedin":return{id:"linkedin",category:e.category??"advertisement",needsReload:!0};case"hotjar":return{id:"hotjar",category:e.category??"analytics",needsReload:!0};case"segment":return{id:"segment",category:e.category??"analytics",needsReload:!0}}}const K=new Map,Y=new Set,W=new Set;function J(e){K.set(e.id,e)}function V(){K.clear(),Y.clear(),W.clear()}function Q(e){const t=[];for(const n of K.values()){const o=!0!==e[n.category];if(G(n))o?W.has(n.id)&&(t.push(n.id),W.delete(n.id)):W.add(n.id);else if(o){if(!Y.has(n.id))try{n.stop(),Y.add(n.id)}catch{t.push(n.id)}}else if(Y.has(n.id)){Y.delete(n.id);try{n.resume?.()}catch{}}}return{reloadRequiredBy:t}}function Z(e,t){const n={consentId:e.consentId,categories:e.categories,regulation:e.regulation,domain:"undefined"!=typeof window?window.location.hostname:"unknown"};return t&&(n.region=t),n}function ee(e){const t=new Set,n=f(e.categories),o=e.googleConsentMatch??"any";let l;void 0===e.googleConsentMatch&&function(e){const t=new Map;for(const n of e.list)for(const e of n.gcm??[]){let o=t.get(e);o||(o=new Set,t.set(e,o)),o.add(n.id)}for(const[e,n]of t)n.size<=1||R(`categories ${[...n].map(e=>JSON.stringify(e)).join(", ")} all map to the Google signal "${e}", which is a single on/off — this mapping is lossy. Set \`googleConsentMatch: "all"\` to grant it only when all are granted, or "any" (default) to grant it when any is.`)}(n);let u,g,h=!1;function y(e){const t={};for(const o of n.ids)t[o]=!!n.requiredIds.has(o)||e(o);return t}let p=[],m=!1;for(const t of e.integrations??[])J(z(t));for(const t of e.customStopHandlers??[])J(t);const v="undefined"==typeof document?null:i(document.cookie),w=e.regulation??"DEFAULT",b=v?.tax,k=b===n.taxonomyHash,C=null!=v&&(k||void 0===b&&n.isDefault);if(null!=v&&C)l=c(v,w,n);else{const e=v?.consentid??s();l=d(e,w,n),null!=v&&a(),"CCPA"===l.regulation&&r(l)}function S(){const e={consentId:l.consentId,hasActed:l.hasActed,categories:{...l.categories},regulation:l.regulation,lastRenewed:l.lastRenewed,taxonomyHash:l.taxonomyHash};for(const n of t)n(e)}function I(){!function(e){if("undefined"!=typeof document)for(const[t,n]of N)!0===e[n.category]&&(X.has(t)||F(t,n))}(g)}function x(){l={...l,hasActed:!0,lastRenewed:Date.now()},r(l);let t=!1;for(const e of n.ids)if(u[e]&&!l.categories[e]){t=!0;break}if(u={...l.categories},g={...l.categories},S(),e.onConsentUpdate?.(l),e.backend)try{Promise.resolve(e.backend.persist(Z(l,e.region))).catch(()=>{})}catch{}else e.apiUrl&&async function(e,t,n,o){const i=Z(n,o),r={"Content-Type":"application/json"};t&&(r.Authorization=`Bearer ${t}`);try{await fetch(e,{method:"POST",headers:r,body:JSON.stringify(i),keepalive:!0})}catch{}}(e.apiUrl,e.apiKey,l,e.region);try{I()}catch{}let i=!1;try{const{reloadRequiredBy:e}=Q(g);i=function(e){const t=e.length!==p.length||e.some((e,t)=>e!==p[t]);return t&&(p=e,m=!1),t}(e)}catch{}try{A(n,g,o)}catch{}i&&S(),t&&e.reloadOnRevoke&&"undefined"!=typeof window&&window.location.reload()}l={...l,taxonomyHash:n.taxonomyHash},e.gpcOptOut&&!l.hasActed&&(l={...l,categories:y(()=>!1)},r(l)),u={...l.categories},g={...l.categories},Promise.resolve().then(()=>e.onConsentReady?.(l));const $={get consentId(){return l.consentId},get hasActed(){return l.hasActed},get categories(){return{...l.categories}},get committedCategories(){return{...g}},get regulation(){return l.regulation},get lastRenewed(){return l.lastRenewed},get taxonomyHash(){return l.taxonomyHash},get isPreferencesOpen(){return h},acceptAll(){l={...l,categories:y(()=>!0)},h=!1,x()},rejectAll(){l={...l,categories:y(()=>!1)},h=!1,x()},acceptSelected(e){l={...l,categories:y(t=>e.includes(t))},h=!1,x()},updateCategory(e,t){n.requiredIds.has(e)||n.ids.includes(e)&&(l={...l,categories:{...l.categories,[e]:t}},S())},savePreferences(){h=!1,x()},resetConsent(){a();const e=s();l=d(e,l.regulation,n),g={...l.categories},u={...l.categories},h=!1,Q(g),A(n,g,o),p=[],m=!1,S()},showPreferences(){h=!0,S()},hidePreferences(){h=!1,S()},subscribe:e=>(t.add(e),()=>t.delete(e)),registerScript(e){!function(e){N.set(e.id,e)}(e),I()},get reloadNotice(){return{required:p.length>0&&!m,reasons:[...p]}},dismissReloadNotice(){m||(m=!0,S())}};I();try{!function(e){for(const t of K.values()){const n=!0!==e[t.category];if(G(t))n?W.delete(t.id):W.add(t.id);else try{n?(t.stop(),Y.add(t.id)):(Y.delete(t.id),t.resume?.())}catch{}}}(l.categories)}catch{}try{A(n,l.categories,o)}catch{}return $}function te(e,t,n,o){let i;try{const e="undefined"!=typeof window?window.location.href:"http://localhost";i=new URL(t,e)}catch{return null}const r=i.hostname.toLowerCase(),a=i.pathname+i.search,s=n.toUpperCase();for(const t of e){const e=t.domain.toLowerCase();if((r===e||r.endsWith("."+e))&&((!t.pathIncludes||a.includes(t.pathIncludes))&&(!t.methods||t.methods.map(e=>e.toUpperCase()).includes(s))&&!o(t.category)))return t}return null}let ne=null;function oe(e,t){if("undefined"==typeof window)return()=>{};if(ne)return()=>{};if(!e.rules.length)return()=>{};const n={originalFetch:window.fetch,originalXhrOpen:XMLHttpRequest.prototype.open,originalXhrSend:XMLHttpRequest.prototype.send,originalSendBeacon:"undefined"!=typeof navigator&&"function"==typeof navigator.sendBeacon?navigator.sendBeacon:void 0};ne=n;const o=!1!==e.logBlockedRequests;function i(t){o&&console.warn(`[cookieyes] blocked ${t.method} ${t.url} (rule "${t.rule.id}", category: ${t.rule.category})`),e.onRequestBlocked?.(t)}if(window.fetch=function(o,r){let a="",s=r?.method??"GET";"string"==typeof o?a=o:o instanceof URL?a=o.toString():(a=o.url,s=r?.method??o.method);const c=te(e.rules,a,s,t);return c?(i({rule:c,url:a,method:s}),Promise.reject(new TypeError(`Blocked by consent (rule: ${c.id}, category: ${c.category})`))):n.originalFetch.call(window,o,r)},XMLHttpRequest.prototype.open=function(e,t,...o){return this._cyUrl=t.toString(),this._cyMethod=e,n.originalXhrOpen.apply(this,[e,t,...o])},XMLHttpRequest.prototype.send=function(o){const r=this._cyUrl??"",a=this._cyMethod??"GET",s=te(e.rules,r,a,t);return s?(i({rule:s,url:r,method:a}),void this.abort()):n.originalXhrSend.call(this,o)},n.originalSendBeacon){const o=n.originalSendBeacon;navigator.sendBeacon=function(n,r){const a=te(e.rules,n.toString(),"POST",t);return a?(i({rule:a,url:n.toString(),method:"POST"}),!0):o.call(navigator,n,r)}}return ie}function ie(){ne&&("undefined"!=typeof window&&(window.fetch=ne.originalFetch,XMLHttpRequest.prototype.open=ne.originalXhrOpen,XMLHttpRequest.prototype.send=ne.originalXhrSend,ne.originalSendBeacon&&(navigator.sendBeacon=ne.originalSendBeacon)),ne=null)}const re=[{country:"x-vercel-ip-country",region:"x-vercel-ip-country-region"},{country:"cf-ipcountry"}];function ae(e,t){if(t?.header)return e.get(t.header)||void 0;for(const{country:t,region:n}of re){const o=e.get(t);if(!o)continue;const i=n?e.get(n):void 0;return i?`${o}-${i}`:o}}function se(){return"undefined"!=typeof navigator&&!0===navigator.globalPrivacyControl}function ce(e,t){const n=e.strictest??"GDPR";if(t)return e.detect&&"undefined"!=typeof console&&console.warn("[cookieyes] `regulation` is set manually, so region detection is ignored. Remove one of them to clear the conflict."),{region:void 0,regulation:t,source:"manual",confidence:"high"};const o=e.detect?.(),i=o?function(e,t){if(e)return e[t]??e[t.split("-")[0]??""]}(e.map,o):void 0;return{region:o,regulation:i??n,source:i?"detected":"strictest",confidence:i?"high":"low"}}function de(e,t){"undefined"!=typeof console&&console.info("[cookieyes] region detection",{region:e.region,regulation:e.regulation,source:e.source,confidence:e.confidence,gpcOptOut:t})}let le=null,ue=null;function ge(e){if(le)return le;"offline"===e.mode&&m();const t=y(e),n=new Set,o=t.onConsentUpdate;let i;const r=t.region?ce(t.region,t.regulation):{region:void 0,regulation:t.regulation??"DEFAULT",source:"manual",confidence:"high"},a={};"self-hosted"===t.mode&&(t.backend?a.backend=t.backend:t.apiUrl&&(a.apiUrl=t.apiUrl)),t.apiKey&&(a.apiKey=t.apiKey),a.regulation=r.regulation,r.region&&(a.region=r.region);const s=(c=r.regulation,d=t.region,"CCPA"===c&&(d?.honorGpc??!0)&&se());var c,d;s&&(a.gpcOptOut=!0),t.region?.debug&&de(r,s),t.colorScheme&&(a.colorScheme=t.colorScheme),t.theme&&(a.theme=t.theme),t.reloadOnRevoke&&(a.reloadOnRevoke=t.reloadOnRevoke),t.googleConsentMatch&&(a.googleConsentMatch=t.googleConsentMatch),t.builtInIntegrations&&t.builtInIntegrations.length>0&&(b(),a.integrations=t.builtInIntegrations),t.customStopHandlers&&(a.customStopHandlers=t.customStopHandlers),t.categories&&(a.categories=t.categories),t.onConsentReady&&(a.onConsentReady=t.onConsentReady),a.onConsentUpdate=e=>{o?.(e),i.push(e.categories);const t=function(e){const t=[],n=[];for(const o of Object.keys(e))e[o]?t.push(o):n.push(o);return{allowedCategories:t,deniedCategories:n}}(e.categories);for(const e of n)e(t)};const l=ee(a);i=C(()=>l.committedCategories);const u=f(t.categories),g=new Set;function h(){const e=v();for(const t of g)t(e)}l.subscribe(h);const p=_(t.i18n,h);function v(){const e=l.categories;return{consentId:l.consentId,hasActed:l.hasActed,categories:e,consents:e,committedConsents:l.committedCategories,regulation:l.regulation,lastRenewed:l.lastRenewed,taxonomyHash:l.taxonomyHash,activeUI:l.isPreferencesOpen?"dialog":l.hasActed?null:"banner",has:e=>!0===l.committedCategories[e],saveConsents:async e=>{"all"===e?l.acceptAll():"necessary"===e?l.rejectAll():l.acceptSelected(e)},setConsent:(e,t)=>l.updateCategory(e,t),subscribeToConsentChanges:e=>(n.add(e),()=>{n.delete(e)})}}const w={subscribe:e=>(g.add(e),()=>{g.delete(e)}),getState:v,on:(e,t,n)=>i.on(e,t,n),get translations(){return p.getTranslations()},getLanguageInfo:p.getLanguageInfo,setLanguage:p.setLanguage,getCategoryText:p.getCategoryText,categories:u,getRegion:()=>r};return t.networkBlocker&&t.networkBlocker.rules.length>0&&oe(t.networkBlocker,e=>!0===l.committedCategories[e]),t.integrations&&t.integrations.length>0&&(B(t.integrations.map(e=>e.id),(t.builtInIntegrations??[]).map(e=>e.vendor)),q(t.integrations,u.ids),ue=D(t.integrations,{granted:e=>!0===l.committedCategories[e],subscribe:e=>l.subscribe(()=>e()),region:r})),le={consentManager:l,consentStore:w,getIntegrations:()=>ue?.list()??[]},le}function fe(e){return ge(e)}function he(){ue?.stop(),ue=null,le=null}function ye(e,t={}){if("string"!=typeof e||0===e.length)return null;const n=i(e);if(null==n)return null;const o=f(t.categories),r=n.tax;if(!(r===o.taxonomyHash||void 0===r&&o.isDefault))return null;const a=c(n,t.regulation??"DEFAULT",o);return a.hasActed?{...a,taxonomyHash:o.taxonomyHash}:null}const pe="0.4.0";export{pe as CORE_VERSION,l as DEFAULT_CATEGORIES,M as INTEGRATION_FORMAT_VERSION,E as _clearScriptRegistry,V as _clearStopHandlers,de as _logRegionDecision,y as _normalizeConfig,k as _resetBuiltInIntegrationsWarning,v as _resetOfflineModeWarning,b as _warnBuiltInIntegrationsDeprecated,m as _warnOfflineModeDeprecated,A as broadcastGoogleConsent,I as computeGoogleConsent,C as createConsentEmitter,ee as createConsentManager,_ as createLanguageController,x as defaultTranslations,s as generateConsentId,ge as getOrCreateConsentRuntime,L as getTextDirection,fe as initCookieYes,oe as installNetworkBlocker,P as mergeTranslations,n as parseCookie,i as parseCookieHeader,O as pickLanguage,U as primaryOf,se as readGpc,ye as readServerConsent,ae as regionFromHeaders,J as registerStopHandler,he as resetConsentRuntime,z as resolveBuiltInIntegration,f as resolveCategories,ce as resolveRegion,H as resolveTranslations,D as runIntegrations,o as serializeCookie,ie as uninstallNetworkBlocker,B as warnOverlappingVendors,q as warnUnknownCategories};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|