@cookieyes/core 0.3.0 → 0.5.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 +55 -12
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +374 -20
- 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;
|
|
@@ -108,6 +239,20 @@ type TranslationMap = {
|
|
|
108
239
|
poweredBy: string;
|
|
109
240
|
preferencesTitle: string;
|
|
110
241
|
preferencesIntro: string;
|
|
242
|
+
/** Shown in place of a toggle on a category marked `required: true`. */
|
|
243
|
+
alwaysActive: string;
|
|
244
|
+
/** Accessible name of the preferences dialog. */
|
|
245
|
+
preferencesDialogLabel: string;
|
|
246
|
+
/** Accessible name of the opt-out dialog. */
|
|
247
|
+
optOutDialogLabel: string;
|
|
248
|
+
/** Accessible name of the floating recall button. */
|
|
249
|
+
recallButtonLabel: string;
|
|
250
|
+
/** Accessible name of the banner's close button (rendered under CCPA only). */
|
|
251
|
+
bannerCloseLabel: string;
|
|
252
|
+
/** Accessible name of the preferences dialog's close button. */
|
|
253
|
+
preferencesCloseLabel: string;
|
|
254
|
+
/** Accessible name of the opt-out dialog's close button. */
|
|
255
|
+
optOutCloseLabel: string;
|
|
111
256
|
categories: {
|
|
112
257
|
necessary: CategoryText;
|
|
113
258
|
functional: CategoryText;
|
|
@@ -122,6 +267,12 @@ type TranslationMap = {
|
|
|
122
267
|
successText: string;
|
|
123
268
|
successCountdown: string;
|
|
124
269
|
};
|
|
270
|
+
gatedFrame: {
|
|
271
|
+
/** Placeholder shown in place of blocked embedded content. `{category}` is substituted. */
|
|
272
|
+
placeholder: string;
|
|
273
|
+
/** Label of the placeholder's button, which opens the preferences dialog. */
|
|
274
|
+
action: string;
|
|
275
|
+
};
|
|
125
276
|
reloadNotice: {
|
|
126
277
|
message: string;
|
|
127
278
|
reloadButton: string;
|
|
@@ -141,6 +292,30 @@ type LanguageInfo = {
|
|
|
141
292
|
direction: TextDirection;
|
|
142
293
|
languages: string[];
|
|
143
294
|
};
|
|
295
|
+
/** Returns the visitor's region synchronously, e.g. "DE" or "US-CA" (or undefined). */
|
|
296
|
+
type RegionDetector = () => string | undefined;
|
|
297
|
+
/** Optional geo-detection: pick the banner's regulation from the visitor's region. */
|
|
298
|
+
type RegionConfig = {
|
|
299
|
+
/** Return the visitor's region synchronously — e.g. from a hosting header you read. */
|
|
300
|
+
detect?: RegionDetector | undefined;
|
|
301
|
+
/** Which regulation each region maps to (you own this). Matched most-specific first: "US-CA" then "US". */
|
|
302
|
+
map?: Record<string, Regulation> | undefined;
|
|
303
|
+
/** Honour the browser's GPC "do not sell/share" signal (a CCPA opt-out). Default `true`. */
|
|
304
|
+
honorGpc?: boolean | undefined;
|
|
305
|
+
/** Regulation to apply when the region is unknown or detection fails. Default `"GDPR"`. */
|
|
306
|
+
strictest?: Regulation | undefined;
|
|
307
|
+
/** Log the region decision to the console at setup (for local debugging). Default `false`. */
|
|
308
|
+
debug?: boolean | undefined;
|
|
309
|
+
};
|
|
310
|
+
/** How the active regulation was decided. */
|
|
311
|
+
type RegionSource = "manual" | "detected" | "strictest";
|
|
312
|
+
/** The outcome of geo-detection — the region seen and the regulation chosen. */
|
|
313
|
+
type RegionDecision = {
|
|
314
|
+
region: string | undefined;
|
|
315
|
+
regulation: Regulation;
|
|
316
|
+
source: RegionSource;
|
|
317
|
+
confidence: "high" | "low";
|
|
318
|
+
};
|
|
144
319
|
type ThemeConfig = {
|
|
145
320
|
primaryColor?: string | undefined;
|
|
146
321
|
backgroundColor?: string | undefined;
|
|
@@ -149,14 +324,25 @@ type ThemeConfig = {
|
|
|
149
324
|
borderColor?: string | undefined;
|
|
150
325
|
borderRadius?: string | undefined;
|
|
151
326
|
fontFamily?: string | undefined;
|
|
152
|
-
|
|
153
|
-
|
|
327
|
+
/**
|
|
328
|
+
* Focus-ring color for interactive elements. Falls back to
|
|
329
|
+
* `var(--cy-primary)` — the ring matches your brand color exactly like it
|
|
330
|
+
* did before this field existed.
|
|
331
|
+
*/
|
|
332
|
+
focusColor?: string | undefined;
|
|
333
|
+
/**
|
|
334
|
+
* Background color of the floating recall widget (the small circular
|
|
335
|
+
* re-open button). Falls back to `"#0056a7"` in light mode. In dark mode,
|
|
336
|
+
* this value is still respected if you set it; only when you don't set it
|
|
337
|
+
* does a dark-mode default apply, the same way
|
|
338
|
+
* backgroundColor/textColor/mutedTextColor/borderColor already work.
|
|
339
|
+
*/
|
|
340
|
+
widgetBackgroundColor?: string | undefined;
|
|
154
341
|
};
|
|
155
342
|
type ScriptEntry = {
|
|
156
343
|
id: string;
|
|
157
344
|
src: string;
|
|
158
345
|
category: ConsentCategory;
|
|
159
|
-
strategy?: "afterConsent" | "lazyOnce" | undefined;
|
|
160
346
|
onLoad?: (() => void) | undefined;
|
|
161
347
|
};
|
|
162
348
|
type I18nConfig = {
|
|
@@ -186,6 +372,12 @@ type ConsentConfig = {
|
|
|
186
372
|
theme?: ThemeConfig | undefined;
|
|
187
373
|
colorScheme?: ColorScheme | undefined;
|
|
188
374
|
reloadOnRevoke?: boolean | undefined;
|
|
375
|
+
/**
|
|
376
|
+
* How to combine multiple categories that map to the same Google Consent Mode
|
|
377
|
+
* signal: `"any"` (default) grants the signal if any maps-and-granted; `"all"`
|
|
378
|
+
* requires every mapping category. Only affects custom overlapping mappings.
|
|
379
|
+
*/
|
|
380
|
+
googleConsentMatch?: "all" | "any" | undefined;
|
|
189
381
|
/**
|
|
190
382
|
* Built-in, first-party integrations to stop cleanly (no reload) when their
|
|
191
383
|
* category is revoked — e.g. `{ vendor: "meta" }`. (Google Analytics/Tag
|
|
@@ -200,6 +392,14 @@ type ConsentConfig = {
|
|
|
200
392
|
* shows the reload notice rather than silently continuing to track.
|
|
201
393
|
*/
|
|
202
394
|
customStopHandlers?: StopHandler[] | undefined;
|
|
395
|
+
/** Detected region (e.g. "US-CA"), recorded on the consent-log payload. */
|
|
396
|
+
region?: string | undefined;
|
|
397
|
+
/**
|
|
398
|
+
* Internal — set by the runtime when a CCPA visitor arrives with the browser's
|
|
399
|
+
* GPC "do not sell" signal on. Starts them opted out (non-required categories
|
|
400
|
+
* off) until they explicitly choose otherwise, so nothing is shared first.
|
|
401
|
+
*/
|
|
402
|
+
gpcOptOut?: boolean | undefined;
|
|
203
403
|
onConsentReady?: ((state: ConsentSnapshot) => void) | undefined;
|
|
204
404
|
onConsentUpdate?: ((state: ConsentSnapshot) => void) | undefined;
|
|
205
405
|
};
|
|
@@ -261,6 +461,8 @@ type ConsentPayload = {
|
|
|
261
461
|
categories: Record<string, boolean>;
|
|
262
462
|
regulation: Regulation;
|
|
263
463
|
domain: string;
|
|
464
|
+
/** Detected region when geo-detection is on (e.g. "US-CA"); omitted otherwise. */
|
|
465
|
+
region?: string | undefined;
|
|
264
466
|
};
|
|
265
467
|
/**
|
|
266
468
|
* Customer-implemented adapter that decides how a consent decision
|
|
@@ -276,7 +478,7 @@ interface ConsentBackend {
|
|
|
276
478
|
}
|
|
277
479
|
/**
|
|
278
480
|
* @deprecated Use `"cookie-only"` instead — identical behavior, clearer name.
|
|
279
|
-
* `"offline"` still works but will be removed
|
|
481
|
+
* `"offline"` still works but will be removed after three release cycles.
|
|
280
482
|
*/
|
|
281
483
|
type DeprecatedOfflineMode = "offline";
|
|
282
484
|
type ConsentRuntimeMode = "self-hosted" | "cookie-only" | DeprecatedOfflineMode;
|
|
@@ -294,10 +496,15 @@ type CookieYesConfigCommon = {
|
|
|
294
496
|
* nested `overrides.regulation`).
|
|
295
497
|
*/
|
|
296
498
|
regulation?: Regulation | undefined;
|
|
499
|
+
/**
|
|
500
|
+
* Optional geo-detection: choose the regulation from the visitor's region.
|
|
501
|
+
* Fully optional — omit it and nothing changes. A manual `regulation` (above)
|
|
502
|
+
* always wins over detection. See {@link RegionConfig}.
|
|
503
|
+
*/
|
|
504
|
+
region?: RegionConfig | undefined;
|
|
297
505
|
colorScheme?: ColorScheme | undefined;
|
|
298
506
|
theme?: ThemeConfig | undefined;
|
|
299
507
|
i18n?: I18nConfig | undefined;
|
|
300
|
-
consentCategories?: ConsentCategory[] | undefined;
|
|
301
508
|
/**
|
|
302
509
|
* Define your own category taxonomy. Omit to get the built-in five
|
|
303
510
|
* (necessary, functional, analytics, performance, advertisement) unchanged.
|
|
@@ -308,12 +515,29 @@ type CookieYesConfigCommon = {
|
|
|
308
515
|
networkBlocker?: NetworkBlockerConfig | undefined;
|
|
309
516
|
reloadOnRevoke?: boolean | undefined;
|
|
310
517
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* needed.) Integrations with no clean runtime stop fall back to the reload notice.
|
|
518
|
+
* How to combine multiple categories that map to the same Google Consent Mode
|
|
519
|
+
* signal: `"any"` (default) or `"all"`. Only matters for a custom taxonomy
|
|
520
|
+
* where more than one category maps to the same signal.
|
|
315
521
|
*/
|
|
316
|
-
|
|
522
|
+
googleConsentMatch?: "all" | "any" | undefined;
|
|
523
|
+
/**
|
|
524
|
+
* Ready-made third-party integrations to gate behind consent — Segment, Meta,
|
|
525
|
+
* Google, and more — using a preset from `@cookieyes/scripts`. Each preset
|
|
526
|
+
* returns an {@link Integration}: it loads only once its category is granted
|
|
527
|
+
* (or, for Google Consent Mode, loads immediately and denies by default), and
|
|
528
|
+
* is removed or silenced on withdrawal.
|
|
529
|
+
*
|
|
530
|
+
* @example integrations: [segment({ writeKey: "..." })]
|
|
531
|
+
*/
|
|
532
|
+
integrations?: Integration[] | undefined;
|
|
533
|
+
/**
|
|
534
|
+
* @deprecated Renamed from `integrations`. Built-in stop-handlers for a few
|
|
535
|
+
* first-party vendors — e.g. `{ vendor: "meta" }` — stopped cleanly (no
|
|
536
|
+
* reload) when their category is revoked. Prefer the new `integrations` field
|
|
537
|
+
* with a preset from `@cookieyes/scripts`; this will be removed after three
|
|
538
|
+
* release cycles.
|
|
539
|
+
*/
|
|
540
|
+
builtInIntegrations?: BuiltInIntegration[] | undefined;
|
|
317
541
|
/**
|
|
318
542
|
* Your own scripts' stop instructions, for anything without a built-in
|
|
319
543
|
* integration. A handler that can stop cleanly provides `stop()`; one that
|
|
@@ -440,6 +664,8 @@ type ConsentStore = {
|
|
|
440
664
|
* so it follows whatever taxonomy is configured.
|
|
441
665
|
*/
|
|
442
666
|
categories: ResolvedCategories;
|
|
667
|
+
/** How the active regulation was decided (region, source, confidence). */
|
|
668
|
+
getRegion: () => RegionDecision;
|
|
443
669
|
/**
|
|
444
670
|
* React to consent decisions. `"save"` fires on every save (even an
|
|
445
671
|
* unchanged re-confirm); `"change"` fires only when a category actually
|
|
@@ -453,6 +679,8 @@ type ConsentStore = {
|
|
|
453
679
|
type ConsentRuntime = {
|
|
454
680
|
consentManager: ConsentManager;
|
|
455
681
|
consentStore: ConsentStore;
|
|
682
|
+
/** Config + live status for each script integration — data for a debug view. */
|
|
683
|
+
getIntegrations: () => IntegrationDebugInfo[];
|
|
456
684
|
};
|
|
457
685
|
|
|
458
686
|
/**
|
|
@@ -519,14 +747,17 @@ declare function resolveCategories(defs?: CategoryDef[]): ResolvedCategories;
|
|
|
519
747
|
type _NormalizedConfig = {
|
|
520
748
|
mode: ConsentRuntimeMode;
|
|
521
749
|
regulation?: Regulation | undefined;
|
|
750
|
+
region?: RegionConfig | undefined;
|
|
522
751
|
colorScheme?: ColorScheme | undefined;
|
|
523
752
|
theme?: ThemeConfig | undefined;
|
|
524
753
|
i18n?: I18nConfig | undefined;
|
|
525
|
-
consentCategories?: ConsentCategory[] | undefined;
|
|
526
754
|
categories?: CategoryDef[] | undefined;
|
|
527
755
|
networkBlocker?: NetworkBlockerConfig | undefined;
|
|
528
756
|
reloadOnRevoke?: boolean | undefined;
|
|
529
|
-
|
|
757
|
+
googleConsentMatch?: "all" | "any" | undefined;
|
|
758
|
+
integrations?: Integration[] | undefined;
|
|
759
|
+
/** @deprecated Renamed from `integrations`; use `integrations` with a `@cookieyes/scripts` preset. */
|
|
760
|
+
builtInIntegrations?: BuiltInIntegration[] | undefined;
|
|
530
761
|
customStopHandlers?: StopHandler[] | undefined;
|
|
531
762
|
onConsentReady?: ((state: ConsentSnapshot) => void) | undefined;
|
|
532
763
|
onConsentUpdate?: ((state: ConsentSnapshot) => void) | undefined;
|
|
@@ -560,6 +791,15 @@ type RawCookieFields = {
|
|
|
560
791
|
};
|
|
561
792
|
declare function parseCookie(raw: string): RawCookieFields;
|
|
562
793
|
declare function serializeCookie(snapshot: ConsentSnapshot): string;
|
|
794
|
+
/**
|
|
795
|
+
* Find and parse the consent cookie inside a `name=value; name2=value2` string.
|
|
796
|
+
*
|
|
797
|
+
* Shared by the browser (`document.cookie`) and the server (a request's `Cookie`
|
|
798
|
+
* header) — the two formats are identical, and one implementation means the
|
|
799
|
+
* server can never disagree with the client about what a visitor's cookie says.
|
|
800
|
+
* Returns `null` when the cookie is absent or its value cannot be decoded.
|
|
801
|
+
*/
|
|
802
|
+
declare function parseCookieHeader(header: string): RawCookieFields | null;
|
|
563
803
|
declare function generateConsentId(): string;
|
|
564
804
|
|
|
565
805
|
/**
|
|
@@ -570,6 +810,14 @@ declare function generateConsentId(): string;
|
|
|
570
810
|
declare function _warnOfflineModeDeprecated(): void;
|
|
571
811
|
/** @internal test-only — resets the one-time warning guard between test cases. */
|
|
572
812
|
declare function _resetOfflineModeWarning(): void;
|
|
813
|
+
/**
|
|
814
|
+
* One-time-per-page-load console warning for the deprecated `builtInIntegrations`
|
|
815
|
+
* config field (formerly `integrations`). Both packages call this so the wording
|
|
816
|
+
* and the "once" behavior stay identical.
|
|
817
|
+
*/
|
|
818
|
+
declare function _warnBuiltInIntegrationsDeprecated(): void;
|
|
819
|
+
/** @internal test-only — resets the one-time warning guard between test cases. */
|
|
820
|
+
declare function _resetBuiltInIntegrationsWarning(): void;
|
|
573
821
|
|
|
574
822
|
type ConsentEmitter = {
|
|
575
823
|
/**
|
|
@@ -596,12 +844,14 @@ type GcmValue = "granted" | "denied";
|
|
|
596
844
|
* Compute the granted/denied value for every GCM signal from the current
|
|
597
845
|
* category consent, using each category's `gcm` mapping.
|
|
598
846
|
*
|
|
599
|
-
* -
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
847
|
+
* - When several categories map to the same signal, `match` decides: `"any"`
|
|
848
|
+
* (default) grants it if *any* mapping category is granted; `"all"` requires
|
|
849
|
+
* *every* mapping category to be granted. For the built-in five (one category
|
|
850
|
+
* per signal) the two are identical — `match` only matters for custom overlaps.
|
|
851
|
+
* - `security_storage` is always `granted` (strictly necessary, not consentable).
|
|
852
|
+
* - A signal that no category maps to stays `denied`.
|
|
603
853
|
*/
|
|
604
|
-
declare function computeGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean
|
|
854
|
+
declare function computeGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean>, match?: "all" | "any"): Record<GoogleConsentSignal, GcmValue>;
|
|
605
855
|
/**
|
|
606
856
|
* Push a Consent Mode `update` for all seven signals onto the dataLayer, if one
|
|
607
857
|
* is present. Safe to call on load and on every consent change; a no-op when no
|
|
@@ -611,7 +861,7 @@ declare function computeGoogleConsent(resolved: ResolvedCategories, categories:
|
|
|
611
861
|
* that must run before their Google tags, typically denying everything). This
|
|
612
862
|
* function owns the *update* that reflects the visitor's actual choice.
|
|
613
863
|
*/
|
|
614
|
-
declare function broadcastGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean
|
|
864
|
+
declare function broadcastGoogleConsent(resolved: ResolvedCategories, categories: Record<string, boolean>, match?: "all" | "any"): void;
|
|
615
865
|
|
|
616
866
|
declare const en: TranslationMap;
|
|
617
867
|
|
|
@@ -655,6 +905,39 @@ declare function createLanguageController(i18n: I18nConfig | undefined, onChange
|
|
|
655
905
|
|
|
656
906
|
declare function createConsentManager(config: ConsentConfig): ConsentManager;
|
|
657
907
|
|
|
908
|
+
/** Anything with a header getter — a `Headers` object, Next's `headers()`, etc. */
|
|
909
|
+
type HeaderSource = {
|
|
910
|
+
get(name: string): string | null | undefined;
|
|
911
|
+
};
|
|
912
|
+
/**
|
|
913
|
+
* Read the visitor's region from request headers on the server (Next.js, or any
|
|
914
|
+
* framework). Pass the request's headers and get back a region like "US-CA" or
|
|
915
|
+
* "DE" (or undefined). By default it reads the well-known Vercel/Cloudflare
|
|
916
|
+
* headers; pass `{ header }` to read your own instead. Hand the result to
|
|
917
|
+
* `region.detect` in your client config.
|
|
918
|
+
*/
|
|
919
|
+
declare function regionFromHeaders(headers: HeaderSource, options?: {
|
|
920
|
+
header?: string;
|
|
921
|
+
}): string | undefined;
|
|
922
|
+
/** True when the browser is sending the GPC "do not sell/share" signal. */
|
|
923
|
+
declare function readGpc(): boolean;
|
|
924
|
+
/**
|
|
925
|
+
* Decide which regulation applies from the visitor's region alone. A manual
|
|
926
|
+
* regulation always wins; otherwise the detected region is mapped to a
|
|
927
|
+
* regulation, and anything unknown falls back to the strictest — never to the
|
|
928
|
+
* lightest, so a required banner is never skipped.
|
|
929
|
+
*
|
|
930
|
+
* GPC is deliberately *not* considered here: it never changes which banner
|
|
931
|
+
* shows (that is geo only), it only opts a CCPA visitor out client-side. Server
|
|
932
|
+
* and client therefore resolve the same regulation, with no hydration mismatch.
|
|
933
|
+
*/
|
|
934
|
+
declare function resolveRegion(config: RegionConfig, manual?: Regulation): RegionDecision;
|
|
935
|
+
/**
|
|
936
|
+
* @internal Dev aid for `region.debug`: print how the regulation was decided,
|
|
937
|
+
* plus whether GPC started the visitor opted out. Shared by both runtimes.
|
|
938
|
+
*/
|
|
939
|
+
declare function _logRegionDecision(decision: RegionDecision, gpcOptOut: boolean): void;
|
|
940
|
+
|
|
658
941
|
declare function getOrCreateConsentRuntime(config: CookieYesConfig): ConsentRuntime;
|
|
659
942
|
/**
|
|
660
943
|
* Canonical setup entry point. Alias of {@link getOrCreateConsentRuntime} that
|
|
@@ -665,5 +948,76 @@ declare function getOrCreateConsentRuntime(config: CookieYesConfig): ConsentRunt
|
|
|
665
948
|
declare function initCookieYes(config: CookieYesConfig): ConsentRuntime;
|
|
666
949
|
declare function resetConsentRuntime(): void;
|
|
667
950
|
|
|
668
|
-
|
|
669
|
-
|
|
951
|
+
/**
|
|
952
|
+
* @internal Test-only — empty the script registry and forget what was injected.
|
|
953
|
+
* Mirrors {@link _clearStopHandlers}. When a `document` is present the injected
|
|
954
|
+
* `<script>` elements are removed from it too, so one test can never leave a
|
|
955
|
+
* gated script behind for the next one. Safe to call with nothing registered.
|
|
956
|
+
*/
|
|
957
|
+
declare function _clearScriptRegistry(): void;
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* The subset of your consent config that affects reading a stored decision.
|
|
961
|
+
* `CookieYesConfig` satisfies this structurally, so you can pass the same object
|
|
962
|
+
* you give `initCookieYes`.
|
|
963
|
+
*/
|
|
964
|
+
type ServerConsentOptions = {
|
|
965
|
+
regulation?: Regulation | undefined;
|
|
966
|
+
categories?: CategoryDef[] | undefined;
|
|
967
|
+
};
|
|
968
|
+
/**
|
|
969
|
+
* Read a visitor's already-made consent decision from a request's `Cookie`
|
|
970
|
+
* header, on the server, with no `document` and no browser APIs.
|
|
971
|
+
*
|
|
972
|
+
* Use it to keep the banner out of the HTML entirely for a returning visitor.
|
|
973
|
+
* Without it the server has no idea whether the visitor has chosen, so it sends
|
|
974
|
+
* banner markup to everyone and the client removes it after hydration — the
|
|
975
|
+
* banner visibly appears and then vanishes, which reads as a bug.
|
|
976
|
+
*
|
|
977
|
+
* Returns `null` whenever the banner *should* be shown:
|
|
978
|
+
* - no consent cookie (a first-time visitor),
|
|
979
|
+
* - a cookie that records no decision yet (`action:no`, e.g. a CCPA visitor who
|
|
980
|
+
* has an implicit-consent cookie but has not acted),
|
|
981
|
+
* - a corrupt cookie,
|
|
982
|
+
* - a cookie written against a **different category taxonomy**, which the client
|
|
983
|
+
* also treats as stale and re-requests. The one exception mirrors the client
|
|
984
|
+
* exactly: a legacy cookie with no taxonomy stamp is still honoured when the
|
|
985
|
+
* built-in five categories are in effect, so existing visitors are not
|
|
986
|
+
* re-prompted by an upgrade.
|
|
987
|
+
*
|
|
988
|
+
* Otherwise returns the stored snapshot, ready to hand to `CookieYesProvider`'s
|
|
989
|
+
* `initialConsent`.
|
|
990
|
+
*
|
|
991
|
+
* ```ts
|
|
992
|
+
* // Any SSR framework — pass the request's Cookie header:
|
|
993
|
+
* const initialConsent = readServerConsent(request.headers.get("cookie") ?? "", config);
|
|
994
|
+
* ```
|
|
995
|
+
*
|
|
996
|
+
* In Next.js App Router, prefer `getServerConsent(config)` from
|
|
997
|
+
* `@cookieyes/nextjs`, which reads `cookies()` for you.
|
|
998
|
+
*
|
|
999
|
+
* **Never** put the result on `initCookieYes` or the runtime: the runtime is a
|
|
1000
|
+
* module-level singleton shared across concurrent requests, so per-visitor state
|
|
1001
|
+
* there would leak between them. It belongs in the component tree.
|
|
1002
|
+
*/
|
|
1003
|
+
declare function readServerConsent(cookieHeader: string, options?: ServerConsentOptions): ConsentSnapshot | null;
|
|
1004
|
+
|
|
1005
|
+
/**
|
|
1006
|
+
* The version of `@cookieyes/core` this build was produced from.
|
|
1007
|
+
*
|
|
1008
|
+
* The literal below is a **sentinel, replaced at build time** with the real
|
|
1009
|
+
* version from `package.json` (see the `injectPkgVersion` plugin in
|
|
1010
|
+
* `rollup.shared.mjs`). It is done that way rather than hand-maintained because
|
|
1011
|
+
* Changesets bumps `package.json` on the release PR — a constant someone has to
|
|
1012
|
+
* remember to update would go stale on exactly the commit that matters, and a
|
|
1013
|
+
* test guarding it would block an automated release PR instead.
|
|
1014
|
+
*
|
|
1015
|
+
* Reading this from source (this repo's own tests, or a `workspace:*` link)
|
|
1016
|
+
* leaves the sentinel in place. Treat `0.0.0-dev` as "unknown version", never as
|
|
1017
|
+
* a real one — `@cookieyes/test` does exactly that before deciding whether to
|
|
1018
|
+
* warn about a mismatched pair.
|
|
1019
|
+
*/
|
|
1020
|
+
declare const CORE_VERSION = "0.0.0-dev";
|
|
1021
|
+
|
|
1022
|
+
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 };
|
|
1023
|
+
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 };
|