@owlmeans/consent 0.1.18-rc.9 → 0.1.18
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 +229 -0
- package/build/consts.d.ts +78 -3
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +104 -0
- package/build/consts.js.map +1 -1
- package/build/consts.local.d.ts +12 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +12 -0
- package/build/consts.local.js.map +1 -0
- package/build/geo/types.d.ts +47 -0
- package/build/geo/types.d.ts.map +1 -0
- package/build/geo/types.js +2 -0
- package/build/geo/types.js.map +1 -0
- package/build/geo.d.ts +4 -0
- package/build/geo.d.ts.map +1 -0
- package/build/geo.js +96 -0
- package/build/geo.js.map +1 -0
- package/build/gtobserver/types.d.ts +75 -0
- package/build/gtobserver/types.d.ts.map +1 -0
- package/build/gtobserver/types.js +2 -0
- package/build/gtobserver/types.js.map +1 -0
- package/build/gtobserver.d.ts +7 -0
- package/build/gtobserver.d.ts.map +1 -0
- package/build/gtobserver.js +142 -0
- package/build/gtobserver.js.map +1 -0
- package/build/i18n/be.json +8 -1
- package/build/i18n/de.json +8 -1
- package/build/i18n/en.json +8 -1
- package/build/i18n/es.json +8 -1
- package/build/i18n/fr.json +8 -1
- package/build/i18n/pl.json +8 -1
- package/build/i18n/ru.json +8 -1
- package/build/i18n/types.d.ts +11 -0
- package/build/i18n/types.d.ts.map +1 -0
- package/build/i18n/types.js +2 -0
- package/build/i18n/types.js.map +1 -0
- package/build/i18n/uk.json +8 -1
- package/build/i18n.d.ts +4 -14
- package/build/i18n.d.ts.map +1 -1
- package/build/i18n.js +12 -27
- package/build/i18n.js.map +1 -1
- package/build/index.d.ts +13 -5
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -3
- package/build/index.js.map +1 -1
- package/build/linker/types.d.ts +59 -0
- package/build/linker/types.d.ts.map +1 -0
- package/build/linker/types.js +2 -0
- package/build/linker/types.js.map +1 -0
- package/build/linker.d.ts +5 -74
- package/build/linker.d.ts.map +1 -1
- package/build/linker.js +290 -324
- package/build/linker.js.map +1 -1
- package/build/plugins/types.d.ts +42 -0
- package/build/plugins/types.d.ts.map +1 -0
- package/build/plugins/types.js +2 -0
- package/build/plugins/types.js.map +1 -0
- package/build/plugins.d.ts +4 -68
- package/build/plugins.d.ts.map +1 -1
- package/build/plugins.js +73 -61
- package/build/plugins.js.map +1 -1
- package/build/storage/types.d.ts +31 -0
- package/build/storage/types.d.ts.map +1 -0
- package/build/storage/types.js +2 -0
- package/build/storage/types.js.map +1 -0
- package/build/storage.d.ts +6 -22
- package/build/storage.d.ts.map +1 -1
- package/build/storage.js +72 -81
- package/build/storage.js.map +1 -1
- package/build/store.d.ts +2 -2
- package/build/store.d.ts.map +1 -1
- package/build/store.js +115 -31
- package/build/store.js.map +1 -1
- package/build/types.d.ts +141 -5
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +9 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/package.json +3 -3
- package/src/consts.local.ts +16 -0
- package/src/consts.ts +120 -3
- package/src/geo/types.ts +49 -0
- package/src/geo.ts +122 -0
- package/src/gtobserver/types.ts +73 -0
- package/src/gtobserver.ts +182 -0
- package/src/i18n/be.json +8 -1
- package/src/i18n/de.json +8 -1
- package/src/i18n/en.json +8 -1
- package/src/i18n/es.json +8 -1
- package/src/i18n/fr.json +8 -1
- package/src/i18n/pl.json +8 -1
- package/src/i18n/ru.json +8 -1
- package/src/i18n/types.ts +11 -0
- package/src/i18n/uk.json +8 -1
- package/src/i18n.ts +20 -32
- package/src/index.ts +13 -12
- package/src/linker/types.ts +59 -0
- package/src/linker.ts +301 -349
- package/src/plugins/types.ts +42 -0
- package/src/plugins.ts +82 -105
- package/src/storage/types.ts +31 -0
- package/src/storage.ts +75 -77
- package/src/store.ts +125 -31
- package/src/types.local.ts +9 -0
- package/src/types.ts +148 -5
- package/tests/consent.spec.ts +26 -28
- package/tests/geo.spec.ts +474 -0
- package/tests/linker.spec.ts +68 -74
- package/tests/tracking.spec.ts +14 -14
- package/build/gtm.d.ts +0 -72
- package/build/gtm.d.ts.map +0 -1
- package/build/gtm.js +0 -182
- package/build/gtm.js.map +0 -1
- package/src/gtm.ts +0 -220
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# @owlmeans/consent
|
|
2
|
+
|
|
3
|
+
The framework-free core of OwlMeans cookie consent: the category model, dual localStorage/cookie
|
|
4
|
+
storage with in-place migration, the observable document-level `consentStore`, Google Consent Mode
|
|
5
|
+
v2 signalling with the inline head scripts that must run before a tag manager loads, the built-in
|
|
6
|
+
dialog copy in eight languages, and cross-domain consent through decorated links. It has **zero
|
|
7
|
+
runtime dependencies**, so an Astro island or a plain script can load it. An app uses it directly
|
|
8
|
+
to stamp the head snippet, read a decision outside React, or gate a loader. It renders nothing — the
|
|
9
|
+
dialog, the re-open button and the cookie-policy page are `@owlmeans/web-consent` (or
|
|
10
|
+
`@owlmeans/web-panel/consent` bound to OwlMeans i18n), and the Google tag snippet itself is
|
|
11
|
+
`@owlmeans/web-gtm`. Per-person marketing preferences on the server are `@owlmeans/marketing-consent`,
|
|
12
|
+
not this package.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bun add @owlmeans/consent@^0.1.18
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Concepts
|
|
21
|
+
|
|
22
|
+
- **Category** — a `ConsentCategory`: a stable `key`, label/description keys, an optional
|
|
23
|
+
`globalVar` written on `window`, the Consent Mode `signals` it drives and an optional `dataLayer`
|
|
24
|
+
`event`. The defaults are `essential` (required), `analytics` and `marketing`.
|
|
25
|
+
- **Required category** — always granted and rendered locked: disclosure, not a question.
|
|
26
|
+
- **Record** — a `ConsentRecord` `{ v?, [categoryKey]: boolean }`, stored under
|
|
27
|
+
`site_cookie_consent` in both localStorage and a 365-day `SameSite=Lax` cookie, localStorage read
|
|
28
|
+
first. A record without `v` is migrated in place (`essential: true`, `v: 2`), never discarded.
|
|
29
|
+
- **Store** — `consentStore`, a module singleton: consent belongs to the document, not to a
|
|
30
|
+
component tree, and is reachable from click handlers and non-React code.
|
|
31
|
+
- **Ordering rule** — `consent/default` must be on `window.dataLayer` before the tag manager loads,
|
|
32
|
+
so it is pushed by an inline script stamped above the snippet, not by a bundle.
|
|
33
|
+
- **Plugin** — a `ConsentPlugin` that can `adopt` a decision or a language from outside storage,
|
|
34
|
+
`decorate` outgoing URLs and disclose `domains`. `consentLinkHelper.consentLinker()` is the one
|
|
35
|
+
built-in plugin.
|
|
36
|
+
- **Interface language** — strictly necessary storage (`owlmeans-lng`); no category governs it.
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### Start the store and read the decision
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { consentStore, CONSENT_ANALYTICS } from '@owlmeans/consent'
|
|
44
|
+
|
|
45
|
+
consentStore.init() // push defaults, read + migrate, apply, open when nothing is stored
|
|
46
|
+
|
|
47
|
+
const unsubscribe = consentStore.subscribe(state => {
|
|
48
|
+
if (state.open) {
|
|
49
|
+
showDialog(state.reason) // 'initial' | 'reopen' | 'login' | custom
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
if (consentStore.granted(CONSENT_ANALYTICS)) {
|
|
54
|
+
startAnalytics()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
consentStore.save({ essential: true, analytics: true, marketing: false })
|
|
58
|
+
consentStore.acceptAll()
|
|
59
|
+
consentStore.open('reopen') // e.g. from a footer link
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`useConsent()` in `@owlmeans/web-consent` calls `init` on mount; a host that mounts neither the
|
|
63
|
+
dialog nor a tag loader calls it once itself, with the same options everything else receives.
|
|
64
|
+
|
|
65
|
+
### Stamp the head snippet above the tag manager
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { consentModeHelper } from '@owlmeans/consent'
|
|
69
|
+
|
|
70
|
+
const bootstrap = consentModeHelper.consentBootstrapScript() // defaults + the stored record
|
|
71
|
+
|
|
72
|
+
// Withhold a loader until tracking is granted (now or by a later CONSENT_EVENT)
|
|
73
|
+
const gated = consentModeHelper.consentGateScript(loaderIife)
|
|
74
|
+
|
|
75
|
+
// Escaping `</script` / `<!--` in the composed inline script is the caller's job
|
|
76
|
+
const head = `<script>${bootstrap};${gated}</script>`
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Custom categories
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { DEFAULT_CONSENT_CATEGORIES, consentStore } from '@owlmeans/consent'
|
|
83
|
+
import type { ConsentCategory } from '@owlmeans/consent'
|
|
84
|
+
|
|
85
|
+
const categories: ConsentCategory[] = [
|
|
86
|
+
...DEFAULT_CONSENT_CATEGORIES.filter(category => category.key !== 'marketing'),
|
|
87
|
+
{ key: 'chat', labelKey: 'chat', descriptionKey: 'chatDesc', globalVar: 'owlConsentChat' },
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
consentStore.init({ categories })
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Share a decision across first-party domains
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { consentLinkHelper, consentStore } from '@owlmeans/consent'
|
|
97
|
+
|
|
98
|
+
const linker = {
|
|
99
|
+
domains: ['owlmeans.com', 'app.example.com'],
|
|
100
|
+
language: { supported: ['en', 'pl', 'de'] }, // omit `supported` on a send-only site
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
consentStore.init({ linker }) // registers consentLinker, adopts, writes the language, strips `owlcc`
|
|
104
|
+
|
|
105
|
+
// For a page that must adopt before any bundle (and before its i18n reads storage)
|
|
106
|
+
const fragment = consentLinkHelper.consentLinkerScript({ linker })
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Ask only where the law requires it
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { consentPluginHelper, consentStore } from '@owlmeans/consent'
|
|
113
|
+
|
|
114
|
+
// Cloudflare mode: a same-origin GET of /cdn-cgi/trace, `loc=` decides
|
|
115
|
+
consentStore.init({ geo: { cloudflare: true } })
|
|
116
|
+
|
|
117
|
+
// …or a locator of your own — one async method that resolves the country or throws
|
|
118
|
+
consentPluginHelper.registerConsentPlugin({
|
|
119
|
+
alias: 'my-geo', locate: async () => ({ country: await myCountryLookup() }),
|
|
120
|
+
})
|
|
121
|
+
consentStore.init({ geo: {} })
|
|
122
|
+
|
|
123
|
+
await consentStore.settled() // the state once the lookup is over
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
A visitor located in `CONSENT_REQUIRED_COUNTRIES` (or `geo.countries`) is asked; anyone else gets an
|
|
127
|
+
automatic decision (`auto: <unix s>` on the record) — every category, or only the required ones
|
|
128
|
+
under Global Privacy Control; a visitor nobody can locate is asked. An automatic decision is trusted
|
|
129
|
+
for `CONSENT_AUTO_MAX_AGE` (one hour) and then re-checked silently; an explicit decision always wins.
|
|
130
|
+
|
|
131
|
+
### Built-in copy
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { consentI18nHelper } from '@owlmeans/consent'
|
|
135
|
+
|
|
136
|
+
const t = consentI18nHelper.defaultConsentTranslate('pl-PL') // falls back to 'en'
|
|
137
|
+
t('analytics', 'Analytics')
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API
|
|
141
|
+
|
|
142
|
+
### Store and helpers
|
|
143
|
+
|
|
144
|
+
| Symbol | Kind | Purpose |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `consentStore`, `makeConsentStore()` | store | `get`, `subscribe`, `init(opts?)`, `save(record)`, `acceptAll`, `open(reason?)`, `close`, `granted(key)`, `options()`, `settled()` |
|
|
147
|
+
| `consentStorageHelper`, `createConsentStorageHelper()` | helper | `migrateConsent`, `readConsent`, `writeConsent`, `clearConsent` |
|
|
148
|
+
| `consentModeHelper`, `createConsentModeHelper()` | helper | `gtagConsent`, `consentDefaults`, `consentUpdate`, `pushConsentDefaults`, `applyConsent`, `trackingGranted`, `consentBootstrapScript`, `consentGateScript` |
|
|
149
|
+
| `consentLinkHelper`, `createConsentLinkHelper()` | helper | `encodeConsentLink`, `decodeConsentLink`, `writeConsentLanguage`, `consentLinker`, `stripConsentLinkParam`, `consentLinkerScript` |
|
|
150
|
+
| `consentPluginHelper`, `createConsentPluginHelper()` | helper | `registerConsentPlugin`, `unregisterConsentPlugin`, `consentPlugins`, `decorateConsentUrl`, `consentDomains`, `adoptConsent`, `adoptConsentLanguage`, `startConsentPlugins`, `locateConsent` |
|
|
151
|
+
| `consentGeoHelper`, `createConsentGeoHelper()` | helper | `enabled`, `parseTrace`, `cloudflareLocator`, `requiresConsent`, `decide`, `privacySignal`, `automaticRecord`, `autoState` |
|
|
152
|
+
| `consentI18nHelper`, `createConsentI18nHelper()` | helper | `normalizeLocale`, `defaultConsentTranslate`, `interpolate` |
|
|
153
|
+
|
|
154
|
+
Deprecated top-level wrappers (`compat:factory-refactor`) remain exported: `readConsent`,
|
|
155
|
+
`writeConsent`, `clearConsent`, `openConsent`, `isConsented`, `consentBootstrapScript`,
|
|
156
|
+
`defaultConsentTranslate`, `decorateConsentUrl`, `encodeConsentLink`, `consentLinkerScript`. New code
|
|
157
|
+
calls the helper members.
|
|
158
|
+
|
|
159
|
+
### Constants
|
|
160
|
+
|
|
161
|
+
| Symbol | Value / purpose |
|
|
162
|
+
|---|---|
|
|
163
|
+
| `CONSENT_KEY` | `'site_cookie_consent'` — storage key, must not change |
|
|
164
|
+
| `CONSENT_COOKIE_DAYS` | `365` |
|
|
165
|
+
| `CONSENT_SCHEMA_VERSION` | `2` — stored record shape |
|
|
166
|
+
| `CONSENT_SETUP_FLAG` | `'cookieConsentSetup'` — window flag making `pushConsentDefaults` idempotent |
|
|
167
|
+
| `CONSENT_EVENT` | `'owlmeans:consent'` — dispatched by `applyConsent`, `detail.record` |
|
|
168
|
+
| `CONSENT_ESSENTIAL`, `CONSENT_ANALYTICS`, `CONSENT_MARKETING` | default category keys |
|
|
169
|
+
| `CONSENT_LANGUAGE_KEY` | `'owlmeans-lng'` — the interface-language storage key |
|
|
170
|
+
| `CONSENT_LOCALES` | `en pl ru be uk es de fr` |
|
|
171
|
+
| `DEFAULT_CONSENT_MESSAGES` | built-in dialog copy per locale |
|
|
172
|
+
| `DEFAULT_CONSENT_CATEGORIES` | `essential` (required), `analytics`, `marketing` |
|
|
173
|
+
| `CONSENT_SIGNAL_DEFAULTS` | every Consent Mode v2 signal `denied`, except `security_storage` `granted` |
|
|
174
|
+
| `CONSENT_LINK_PARAM`, `CONSENT_LINK_MAX_AGE`, `CONSENT_LINK_SKEW` | `'owlcc'`, `300` s, `60` s |
|
|
175
|
+
| `CONSENT_REQUIRED_COUNTRIES` | where a located visitor is asked — the union of `CONSENT_COUNTRIES_GDPR`, `CONSENT_COUNTRIES_ALIGNED`, `CONSENT_COUNTRIES_OPT_IN` |
|
|
176
|
+
| `CONSENT_GEO_UNKNOWN` | codes that name no country (`XX`, `T1`, …) — asked |
|
|
177
|
+
| `CONSENT_TRACE_PATH`, `CONSENT_GEO_TIMEOUT` | `'/cdn-cgi/trace'`, `2500` ms |
|
|
178
|
+
| `CONSENT_AUTO_MAX_AGE` | `3600` s — how long an automatic decision is trusted |
|
|
179
|
+
| `CONSENT_IDLE_STATE` | the frozen pre-init state and server snapshot |
|
|
180
|
+
| `CONSENT_STATE_ATTRIBUTE` | `'data-consent'` on `<html>`: `locating`, `open`, `decided`, `idle` |
|
|
181
|
+
|
|
182
|
+
### Types
|
|
183
|
+
|
|
184
|
+
| Symbol | Purpose |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `ConsentSignal` | the Consent Mode v2 signal names |
|
|
187
|
+
| `ConsentCategory`, `ConsentRecord`, `ConsentService` | category, stored decision, disclosed third-party service |
|
|
188
|
+
| `ConsentOptions` | `categories?`, `storageKey?`, `cookieDays?`, `cookieDomain?`, `silent?`, `linker?`, `geo?` |
|
|
189
|
+
| `ConsentGeoOptions`, `ConsentCloudflareOptions`, `ConsentGeoPlugin`, `ConsentGeoLocation`, `ConsentLocating` | the geo gate: `cloudflare?`, `countries?`, `timeout?`; a locator plugin; its answer; the lookup phase |
|
|
190
|
+
| `ConsentGeoHelper`, `ConsentGeoVerdict`, `ConsentAutoState` | the geo helper's interface, `'ask' \| 'auto'`, `'fresh' \| 'stale'` |
|
|
191
|
+
| `ConsentLinkerOptions`, `ConsentLinkerLanguage` | `domains`, `param?`, `maxAge?`, `language?`; `supported?`, `storageKey?` |
|
|
192
|
+
| `ConsentState`, `ConsentReason`, `ConsentListener`, `ConsentStore` | store state and contract |
|
|
193
|
+
| `ConsentLocale`, `ConsentLinkPayload`, `ConsentPlugin` | locale union, decoded `owlcc` payload, plugin seam |
|
|
194
|
+
| `ConsentModeHelper`, `ConsentStorageHelper`, `ConsentLinkHelper`, `ConsentPluginHelper`, `ConsentI18nHelper` | helper interfaces |
|
|
195
|
+
|
|
196
|
+
## Cross-domain linking rules
|
|
197
|
+
|
|
198
|
+
`consentLinker().adopt` accepts a decorated link only when the payload decodes with the current
|
|
199
|
+
version, the referrer host is a listed domain, the timestamp is within `maxAge` (and at most 60 s in
|
|
200
|
+
the future), and every local optional category is present. It runs only when the document has no
|
|
201
|
+
stored record. The parameter is stripped from the visible URL whether or not it was adopted. Links
|
|
202
|
+
with `rel="noreferrer"` are never decorated.
|
|
203
|
+
|
|
204
|
+
## Common pitfalls
|
|
205
|
+
|
|
206
|
+
- Stamp `consentBootstrapScript()` inline above the tag-manager snippet; pushing defaults from a
|
|
207
|
+
React bundle is too late.
|
|
208
|
+
- `silent: true` suppresses runtime pushes only — the stamped bootstrap string still pushes.
|
|
209
|
+
- Do not set `cookieDomain` on an existing site: it orphans the host-only cookie and re-asks every
|
|
210
|
+
visitor. Do not change `CONSENT_KEY` for the same reason.
|
|
211
|
+
- Never present the required category as a choice, and never word a login gate as consent to
|
|
212
|
+
essential cookies.
|
|
213
|
+
- Consent Mode speaks on `window.dataLayer` only; a tag on another queue never hears it.
|
|
214
|
+
- Neither `consentBootstrapScript`, `consentGateScript` nor the composed result is HTML-escaped by
|
|
215
|
+
this package beyond JSON-encoding its own values.
|
|
216
|
+
- Release both ends of a linked domain pair together: a receiver that asks about a category the
|
|
217
|
+
sender dropped refuses the link.
|
|
218
|
+
|
|
219
|
+
The `consent` skill covers the category model, storage migration, the ordering rule, gated loading,
|
|
220
|
+
the plugin seam and language linking in depth.
|
|
221
|
+
|
|
222
|
+
## Related packages
|
|
223
|
+
|
|
224
|
+
- [`@owlmeans/web-consent`](../web-consent) — the React dialog, re-open button, `CookiePolicy` and `useConsent`
|
|
225
|
+
- [`@owlmeans/web-gtm`](../web-gtm) — Google tag head snippet, CSP hosts and Google service disclosure
|
|
226
|
+
- [`@owlmeans/web-panel`](../web-panel) — `/consent` subpath bound to OwlMeans i18n and the panel menu
|
|
227
|
+
- [`@owlmeans/astro`](../astro) — `owlHeadScripts` for Astro sites, legal-page suppression
|
|
228
|
+
- [`@owlmeans/web-marketing-consent`](../web-marketing-consent) — bridges marketing preferences into `consentStore.save`
|
|
229
|
+
- [`@owlmeans/client-i18n`](../client-i18n) — reads the `owlmeans-lng` language choice this package may write
|
package/build/consts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConsentCategory } from './types.js';
|
|
1
|
+
import type { ConsentCategory, ConsentLocale, ConsentState } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Where a visitor's choice is stored.
|
|
4
4
|
*
|
|
@@ -38,8 +38,16 @@ export declare const CONSENT_MARKETING = "marketing";
|
|
|
38
38
|
* language part has to run in an inline `<head>` script, before any bundle exists.
|
|
39
39
|
*/
|
|
40
40
|
export declare const CONSENT_LANGUAGE_KEY = "owlmeans-lng";
|
|
41
|
-
export declare const CONSENT_LOCALES: readonly [
|
|
42
|
-
|
|
41
|
+
export declare const CONSENT_LOCALES: readonly ["en", "pl", "ru", "be", "uk", "es", "de", "fr"];
|
|
42
|
+
/**
|
|
43
|
+
* The dialog's copy, in the box.
|
|
44
|
+
*
|
|
45
|
+
* Carried here rather than registered into an i18n framework because one of the three consumers is
|
|
46
|
+
* an Astro site with React islands and no OwlMeans i18n at all — and a consent dialog that renders
|
|
47
|
+
* raw keys is worse than no dialog. An application that HAS translations passes `translate` and
|
|
48
|
+
* overrides every one of these.
|
|
49
|
+
*/
|
|
50
|
+
export declare const DEFAULT_CONSENT_MESSAGES: Record<ConsentLocale, Record<string, string>>;
|
|
43
51
|
/**
|
|
44
52
|
* The categories every OwlMeans surface starts with.
|
|
45
53
|
*
|
|
@@ -56,4 +64,71 @@ export declare const DEFAULT_CONSENT_CATEGORIES: ConsentCategory[];
|
|
|
56
64
|
* fraud prevention, which are strictly necessary. Everything else starts denied.
|
|
57
65
|
*/
|
|
58
66
|
export declare const CONSENT_SIGNAL_DEFAULTS: Record<string, 'granted' | 'denied'>;
|
|
67
|
+
/** The URL parameter a decorated link carries the decision in, absent an override. */
|
|
68
|
+
export declare const CONSENT_LINK_PARAM = "owlcc";
|
|
69
|
+
/** How old a decorated link's timestamp may be and still be trusted, in seconds, absent an override. */
|
|
70
|
+
export declare const CONSENT_LINK_MAX_AGE = 300;
|
|
71
|
+
/** Clock skew allowed the OTHER way — a timestamp up to this far in the future is still trusted. */
|
|
72
|
+
export declare const CONSENT_LINK_SKEW = 60;
|
|
73
|
+
/**
|
|
74
|
+
* Where prior consent for non-essential cookies is the law: the EU and EEA (ePrivacy Art. 5(3) with
|
|
75
|
+
* the GDPR), including the parts of member states that carry an ISO code of their own — Åland and
|
|
76
|
+
* the French outermost regions (French Guiana, Guadeloupe, Martinique, Réunion, Mayotte,
|
|
77
|
+
* Saint-Martin). The Canary Islands, Azores, Madeira, Ceuta and Melilla report their state's code.
|
|
78
|
+
* Greece is `GR`, as Cloudflare and every ISO feed spell it.
|
|
79
|
+
*/
|
|
80
|
+
export declare const CONSENT_COUNTRIES_GDPR: readonly string[];
|
|
81
|
+
/**
|
|
82
|
+
* Jurisdictions outside the EEA whose rule for cookies is the same prior opt-in, by statute or by
|
|
83
|
+
* the regulator's guidance (2026):
|
|
84
|
+
*
|
|
85
|
+
* - the United Kingdom (PECR — the 2025 Data (Use and Access) Act exempts some first-party
|
|
86
|
+
* analytics, advertising still needs consent), the Crown Dependencies and Gibraltar;
|
|
87
|
+
* - Switzerland (FDPIC guidelines, 2025: explicit consent for tracking and profiling);
|
|
88
|
+
* - Andorra, Monaco, San Marino and the Vatican; Türkiye (KVKK cookie guide); Serbia (ZZPL and the
|
|
89
|
+
* electronic-communications law); Albania, Bosnia and Herzegovina, Montenegro, North Macedonia,
|
|
90
|
+
* Kosovo, Moldova, Georgia and Ukraine (GDPR-modelled laws);
|
|
91
|
+
* - territories under a member state's regulator but outside the EU: the Faroe Islands and
|
|
92
|
+
* Greenland (Denmark); Saint-Barthélemy, Saint-Pierre-et-Miquelon, New Caledonia, French
|
|
93
|
+
* Polynesia, Wallis and Futuna (France); the Caribbean Netherlands.
|
|
94
|
+
*/
|
|
95
|
+
export declare const CONSENT_COUNTRIES_ALIGNED: readonly string[];
|
|
96
|
+
/**
|
|
97
|
+
* Prior opt-in regimes elsewhere (2026): Brazil (LGPD, ANPD cookie guide), Canada (Québec's Law 25
|
|
98
|
+
* — the country is the finest grain a CDN reports, so all of Canada), China (PIPL), South Korea
|
|
99
|
+
* (PIPA), Nigeria (NDPA), Saudi Arabia (PDPL), Thailand (PDPA), Vietnam (PDPL 2026).
|
|
100
|
+
*
|
|
101
|
+
* Deliberately absent: India (the DPDP Act's consent rules apply from mid-2027 — add `IN` then),
|
|
102
|
+
* and the notice-or-opt-out regimes — the United States, Japan, Australia, Singapore. South
|
|
103
|
+
* Africa's POPIA is read both ways by the guides and is left out until its regulator says more.
|
|
104
|
+
*/
|
|
105
|
+
export declare const CONSENT_COUNTRIES_OPT_IN: readonly string[];
|
|
106
|
+
/**
|
|
107
|
+
* Every country where a located visitor is ASKED (`ConsentGeoOptions.countries` replaces it). A
|
|
108
|
+
* visitor located anywhere else gets an automatic decision; one who cannot be located is asked.
|
|
109
|
+
*/
|
|
110
|
+
export declare const CONSENT_REQUIRED_COUNTRIES: readonly string[];
|
|
111
|
+
/**
|
|
112
|
+
* Codes that name no country: Cloudflare's `XX` (no data) and `T1` (Tor), the retired MaxMind
|
|
113
|
+
* pseudo-codes (`A1` anonymous proxy, `A2` satellite, `O1` other) and the continent buckets some
|
|
114
|
+
* feeds fall back to (`EU`, `AP`), plus `ZZ` (unknown). A visitor reported with one is asked.
|
|
115
|
+
*/
|
|
116
|
+
export declare const CONSENT_GEO_UNKNOWN: readonly string[];
|
|
117
|
+
/** Cloudflare's trace endpoint — served by the edge on every proxied host, `loc=` among its lines. */
|
|
118
|
+
export declare const CONSENT_TRACE_PATH = "/cdn-cgi/trace";
|
|
119
|
+
/** How long locating may take before the visitor is asked anyway, in ms. */
|
|
120
|
+
export declare const CONSENT_GEO_TIMEOUT = 2500;
|
|
121
|
+
/**
|
|
122
|
+
* How long an automatic decision is trusted, in seconds. Older, it counts as undecided — in the
|
|
123
|
+
* head scripts as much as in the store — until the visitor is located again, so a grant derived in
|
|
124
|
+
* one country never reaches a page opened an hour later in another.
|
|
125
|
+
*/
|
|
126
|
+
export declare const CONSENT_AUTO_MAX_AGE = 3600;
|
|
127
|
+
/** The state of a store nobody has initialised — and the only server-side snapshot. */
|
|
128
|
+
export declare const CONSENT_IDLE_STATE: ConsentState;
|
|
129
|
+
/**
|
|
130
|
+
* The attribute on `<html>` that mirrors the consent phase: `locating`, `open`, `decided` or `idle`.
|
|
131
|
+
* Absent until the store first runs. A test waits on it, and a stylesheet may key on it.
|
|
132
|
+
*/
|
|
133
|
+
export declare const CONSENT_STATE_ATTRIBUTE = "data-consent";
|
|
59
134
|
//# sourceMappingURL=consts.d.ts.map
|
package/build/consts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAW9E;;;;;GAKG;AACH,eAAO,MAAM,WAAW,wBAAwB,CAAA;AAEhD,eAAO,MAAM,mBAAmB,MAAM,CAAA;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAA;AAEvC,2FAA2F;AAC3F,eAAO,MAAM,kBAAkB,uBAAuB,CAAA;AAEtD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,qBAAqB,CAAA;AAE/C,eAAO,MAAM,iBAAiB,cAAc,CAAA;AAC5C,eAAO,MAAM,iBAAiB,cAAc,CAAA;AAC5C,eAAO,MAAM,iBAAiB,cAAc,CAAA;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,iBAAiB,CAAA;AAElD,eAAO,MAAM,eAAe,2DAA+F,CAAA;AAE3H;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAElF,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,EAAE,eAAe,EAmBvD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,QAAQ,CAQxE,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC,wGAAwG;AACxG,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC,oGAAoG;AACpG,eAAO,MAAM,iBAAiB,KAAK,CAAA;AAEnC;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAKlD,CAAA;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAKrD,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAEpD,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAEtD,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAE/C,CAAA;AAEF,sGAAsG;AACtG,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAExC,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,EAAE,YAE/B,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAA"}
|
package/build/consts.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import en from './i18n/en.json' with { type: 'json' };
|
|
2
|
+
import pl from './i18n/pl.json' with { type: 'json' };
|
|
3
|
+
import ru from './i18n/ru.json' with { type: 'json' };
|
|
4
|
+
import be from './i18n/be.json' with { type: 'json' };
|
|
5
|
+
import uk from './i18n/uk.json' with { type: 'json' };
|
|
6
|
+
import es from './i18n/es.json' with { type: 'json' };
|
|
7
|
+
import de from './i18n/de.json' with { type: 'json' };
|
|
8
|
+
import fr from './i18n/fr.json' with { type: 'json' };
|
|
1
9
|
/**
|
|
2
10
|
* Where a visitor's choice is stored.
|
|
3
11
|
*
|
|
@@ -38,6 +46,17 @@ export const CONSENT_MARKETING = 'marketing';
|
|
|
38
46
|
*/
|
|
39
47
|
export const CONSENT_LANGUAGE_KEY = 'owlmeans-lng';
|
|
40
48
|
export const CONSENT_LOCALES = ['en', 'pl', 'ru', 'be', 'uk', 'es', 'de', 'fr'];
|
|
49
|
+
/**
|
|
50
|
+
* The dialog's copy, in the box.
|
|
51
|
+
*
|
|
52
|
+
* Carried here rather than registered into an i18n framework because one of the three consumers is
|
|
53
|
+
* an Astro site with React islands and no OwlMeans i18n at all — and a consent dialog that renders
|
|
54
|
+
* raw keys is worse than no dialog. An application that HAS translations passes `translate` and
|
|
55
|
+
* overrides every one of these.
|
|
56
|
+
*/
|
|
57
|
+
export const DEFAULT_CONSENT_MESSAGES = {
|
|
58
|
+
en, pl, ru, be, uk, es, de, fr,
|
|
59
|
+
};
|
|
41
60
|
/**
|
|
42
61
|
* The categories every OwlMeans surface starts with.
|
|
43
62
|
*
|
|
@@ -81,4 +100,89 @@ export const CONSENT_SIGNAL_DEFAULTS = {
|
|
|
81
100
|
personalization_storage: 'denied',
|
|
82
101
|
security_storage: 'granted',
|
|
83
102
|
};
|
|
103
|
+
/** The URL parameter a decorated link carries the decision in, absent an override. */
|
|
104
|
+
export const CONSENT_LINK_PARAM = 'owlcc';
|
|
105
|
+
/** How old a decorated link's timestamp may be and still be trusted, in seconds, absent an override. */
|
|
106
|
+
export const CONSENT_LINK_MAX_AGE = 300;
|
|
107
|
+
/** Clock skew allowed the OTHER way — a timestamp up to this far in the future is still trusted. */
|
|
108
|
+
export const CONSENT_LINK_SKEW = 60;
|
|
109
|
+
/**
|
|
110
|
+
* Where prior consent for non-essential cookies is the law: the EU and EEA (ePrivacy Art. 5(3) with
|
|
111
|
+
* the GDPR), including the parts of member states that carry an ISO code of their own — Åland and
|
|
112
|
+
* the French outermost regions (French Guiana, Guadeloupe, Martinique, Réunion, Mayotte,
|
|
113
|
+
* Saint-Martin). The Canary Islands, Azores, Madeira, Ceuta and Melilla report their state's code.
|
|
114
|
+
* Greece is `GR`, as Cloudflare and every ISO feed spell it.
|
|
115
|
+
*/
|
|
116
|
+
export const CONSENT_COUNTRIES_GDPR = Object.freeze([
|
|
117
|
+
'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU',
|
|
118
|
+
'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK',
|
|
119
|
+
'AX', 'GF', 'GP', 'MQ', 'RE', 'YT', 'MF',
|
|
120
|
+
'IS', 'LI', 'NO',
|
|
121
|
+
]);
|
|
122
|
+
/**
|
|
123
|
+
* Jurisdictions outside the EEA whose rule for cookies is the same prior opt-in, by statute or by
|
|
124
|
+
* the regulator's guidance (2026):
|
|
125
|
+
*
|
|
126
|
+
* - the United Kingdom (PECR — the 2025 Data (Use and Access) Act exempts some first-party
|
|
127
|
+
* analytics, advertising still needs consent), the Crown Dependencies and Gibraltar;
|
|
128
|
+
* - Switzerland (FDPIC guidelines, 2025: explicit consent for tracking and profiling);
|
|
129
|
+
* - Andorra, Monaco, San Marino and the Vatican; Türkiye (KVKK cookie guide); Serbia (ZZPL and the
|
|
130
|
+
* electronic-communications law); Albania, Bosnia and Herzegovina, Montenegro, North Macedonia,
|
|
131
|
+
* Kosovo, Moldova, Georgia and Ukraine (GDPR-modelled laws);
|
|
132
|
+
* - territories under a member state's regulator but outside the EU: the Faroe Islands and
|
|
133
|
+
* Greenland (Denmark); Saint-Barthélemy, Saint-Pierre-et-Miquelon, New Caledonia, French
|
|
134
|
+
* Polynesia, Wallis and Futuna (France); the Caribbean Netherlands.
|
|
135
|
+
*/
|
|
136
|
+
export const CONSENT_COUNTRIES_ALIGNED = Object.freeze([
|
|
137
|
+
'GB', 'GG', 'JE', 'IM', 'GI',
|
|
138
|
+
'CH',
|
|
139
|
+
'AD', 'MC', 'SM', 'VA', 'TR', 'RS', 'AL', 'BA', 'ME', 'MK', 'XK', 'MD', 'GE', 'UA',
|
|
140
|
+
'FO', 'GL', 'BL', 'PM', 'NC', 'PF', 'WF', 'BQ',
|
|
141
|
+
]);
|
|
142
|
+
/**
|
|
143
|
+
* Prior opt-in regimes elsewhere (2026): Brazil (LGPD, ANPD cookie guide), Canada (Québec's Law 25
|
|
144
|
+
* — the country is the finest grain a CDN reports, so all of Canada), China (PIPL), South Korea
|
|
145
|
+
* (PIPA), Nigeria (NDPA), Saudi Arabia (PDPL), Thailand (PDPA), Vietnam (PDPL 2026).
|
|
146
|
+
*
|
|
147
|
+
* Deliberately absent: India (the DPDP Act's consent rules apply from mid-2027 — add `IN` then),
|
|
148
|
+
* and the notice-or-opt-out regimes — the United States, Japan, Australia, Singapore. South
|
|
149
|
+
* Africa's POPIA is read both ways by the guides and is left out until its regulator says more.
|
|
150
|
+
*/
|
|
151
|
+
export const CONSENT_COUNTRIES_OPT_IN = Object.freeze([
|
|
152
|
+
'BR', 'CA', 'CN', 'KR', 'NG', 'SA', 'TH', 'VN',
|
|
153
|
+
]);
|
|
154
|
+
/**
|
|
155
|
+
* Every country where a located visitor is ASKED (`ConsentGeoOptions.countries` replaces it). A
|
|
156
|
+
* visitor located anywhere else gets an automatic decision; one who cannot be located is asked.
|
|
157
|
+
*/
|
|
158
|
+
export const CONSENT_REQUIRED_COUNTRIES = Object.freeze([
|
|
159
|
+
...CONSENT_COUNTRIES_GDPR, ...CONSENT_COUNTRIES_ALIGNED, ...CONSENT_COUNTRIES_OPT_IN,
|
|
160
|
+
]);
|
|
161
|
+
/**
|
|
162
|
+
* Codes that name no country: Cloudflare's `XX` (no data) and `T1` (Tor), the retired MaxMind
|
|
163
|
+
* pseudo-codes (`A1` anonymous proxy, `A2` satellite, `O1` other) and the continent buckets some
|
|
164
|
+
* feeds fall back to (`EU`, `AP`), plus `ZZ` (unknown). A visitor reported with one is asked.
|
|
165
|
+
*/
|
|
166
|
+
export const CONSENT_GEO_UNKNOWN = Object.freeze([
|
|
167
|
+
'XX', 'T1', 'A1', 'A2', 'O1', 'EU', 'AP', 'ZZ',
|
|
168
|
+
]);
|
|
169
|
+
/** Cloudflare's trace endpoint — served by the edge on every proxied host, `loc=` among its lines. */
|
|
170
|
+
export const CONSENT_TRACE_PATH = '/cdn-cgi/trace';
|
|
171
|
+
/** How long locating may take before the visitor is asked anyway, in ms. */
|
|
172
|
+
export const CONSENT_GEO_TIMEOUT = 2500;
|
|
173
|
+
/**
|
|
174
|
+
* How long an automatic decision is trusted, in seconds. Older, it counts as undecided — in the
|
|
175
|
+
* head scripts as much as in the store — until the visitor is located again, so a grant derived in
|
|
176
|
+
* one country never reaches a page opened an hour later in another.
|
|
177
|
+
*/
|
|
178
|
+
export const CONSENT_AUTO_MAX_AGE = 3600;
|
|
179
|
+
/** The state of a store nobody has initialised — and the only server-side snapshot. */
|
|
180
|
+
export const CONSENT_IDLE_STATE = Object.freeze({
|
|
181
|
+
record: null, open: false, reason: null, locating: null,
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* The attribute on `<html>` that mirrors the consent phase: `locating`, `open`, `decided` or `idle`.
|
|
185
|
+
* Absent until the store first runs. A test waits on it, and a stylesheet may key on it.
|
|
186
|
+
*/
|
|
187
|
+
export const CONSENT_STATE_ATTRIBUTE = 'data-consent';
|
|
84
188
|
//# sourceMappingURL=consts.js.map
|
package/build/consts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAA;AAEhD,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEvC,2FAA2F;AAC3F,MAAM,CAAC,MAAM,kBAAkB,GAAG,oBAAoB,CAAA;AAEtD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAA;AAE/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAA;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAA;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAA;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAAA;AAElD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const CONSENT_LINK_VERSION = 2;
|
|
2
|
+
/** A BCP 47-shaped tag: a 2–3 letter language and up to three subtags (`pl`, `pt-BR`, `zh-Hant-TW`). */
|
|
3
|
+
export declare const LANGUAGE_TAG: RegExp;
|
|
4
|
+
/** The built-in Cloudflare locator's registry alias. */
|
|
5
|
+
export declare const CLOUDFLARE_LOCATOR_ALIAS = "cloudflare";
|
|
6
|
+
/** Below anything an application registers: an application's own locator always asks first. */
|
|
7
|
+
export declare const CLOUDFLARE_LOCATOR_PRIORITY = -100;
|
|
8
|
+
/** An ISO 3166-1 alpha-2 code, upper case. */
|
|
9
|
+
export declare const COUNTRY_CODE: RegExp;
|
|
10
|
+
/** Clock skew tolerated on an automatic decision's timestamp, in seconds. */
|
|
11
|
+
export declare const AUTO_SKEW = 60;
|
|
12
|
+
//# sourceMappingURL=consts.local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.local.d.ts","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,wGAAwG;AACxG,eAAO,MAAM,YAAY,QAA4C,CAAA;AAErE,wDAAwD;AACxD,eAAO,MAAM,wBAAwB,eAAe,CAAA;AAEpD,+FAA+F;AAC/F,eAAO,MAAM,2BAA2B,OAAO,CAAA;AAE/C,8CAA8C;AAC9C,eAAO,MAAM,YAAY,QAAe,CAAA;AAExC,6EAA6E;AAC7E,eAAO,MAAM,SAAS,KAAK,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const CONSENT_LINK_VERSION = 2;
|
|
2
|
+
/** A BCP 47-shaped tag: a 2–3 letter language and up to three subtags (`pl`, `pt-BR`, `zh-Hant-TW`). */
|
|
3
|
+
export const LANGUAGE_TAG = /^[a-z]{2,3}(?:[-_][a-z0-9]{1,8}){0,3}$/i;
|
|
4
|
+
/** The built-in Cloudflare locator's registry alias. */
|
|
5
|
+
export const CLOUDFLARE_LOCATOR_ALIAS = 'cloudflare';
|
|
6
|
+
/** Below anything an application registers: an application's own locator always asks first. */
|
|
7
|
+
export const CLOUDFLARE_LOCATOR_PRIORITY = -100;
|
|
8
|
+
/** An ISO 3166-1 alpha-2 code, upper case. */
|
|
9
|
+
export const COUNTRY_CODE = /^[A-Z]{2}$/;
|
|
10
|
+
/** Clock skew tolerated on an automatic decision's timestamp, in seconds. */
|
|
11
|
+
export const AUTO_SKEW = 60;
|
|
12
|
+
//# sourceMappingURL=consts.local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.local.js","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAA;AAErC,wGAAwG;AACxG,MAAM,CAAC,MAAM,YAAY,GAAG,yCAAyC,CAAA;AAErE,wDAAwD;AACxD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAA;AAEpD,+FAA+F;AAC/F,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,GAAG,CAAA;AAE/C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,YAAY,GAAG,YAAY,CAAA;AAExC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ConsentGeoPlugin, ConsentOptions, ConsentRecord } from '../types.js';
|
|
2
|
+
/** What locating the visitor decided: ask them, or decide for them automatically. */
|
|
3
|
+
export type ConsentGeoVerdict = 'ask' | 'auto';
|
|
4
|
+
/** Whether a record is an automatic decision, and whether it is still trusted. */
|
|
5
|
+
export type ConsentAutoState = 'fresh' | 'stale';
|
|
6
|
+
/**
|
|
7
|
+
* Asking only where the law requires it: locating the visitor, the decision that follows, and the
|
|
8
|
+
* automatic record written where nobody needs to be asked.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConsentGeoHelper {
|
|
11
|
+
/** Whether `opts.geo` turns the gate on AND something can answer — the Cloudflare locator or a plugin. */
|
|
12
|
+
enabled: (opts?: ConsentOptions) => boolean;
|
|
13
|
+
/** Every `key=value` line of a Cloudflare trace body. Never throws; anything else parses to `{}`. */
|
|
14
|
+
parseTrace: (text: string) => Record<string, string>;
|
|
15
|
+
/**
|
|
16
|
+
* The built-in locator: a same-origin GET of the trace endpoint, cookies left out, never cached.
|
|
17
|
+
* Rejects when `opts.geo.cloudflare` is off, the request fails or answers non-2xx, or the body is
|
|
18
|
+
* not a trace (an SPA serving its `index.html` for every path answers 200 here).
|
|
19
|
+
*/
|
|
20
|
+
cloudflareLocator: () => ConsentGeoPlugin;
|
|
21
|
+
/**
|
|
22
|
+
* Whether a visitor located in `country` must be asked: yes inside `opts.geo.countries`
|
|
23
|
+
* (`CONSENT_REQUIRED_COUNTRIES`), and yes for anything that names no country.
|
|
24
|
+
*/
|
|
25
|
+
requiresConsent: (country: string | null, opts?: ConsentOptions) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Locate and decide, bounded by `opts.geo.timeout`. Never rejects: a visitor nobody could locate
|
|
28
|
+
* resolves `'ask'`.
|
|
29
|
+
*/
|
|
30
|
+
decide: (opts: ConsentOptions) => Promise<ConsentGeoVerdict>;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the browser sends Global Privacy Control — a legally binding opt-out in several US
|
|
33
|
+
* states, so an automatic decision honours it.
|
|
34
|
+
*/
|
|
35
|
+
privacySignal: () => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The automatic decision for a visitor nobody needs to ask: every category on — or, under Global
|
|
38
|
+
* Privacy Control, only the required ones — stamped `auto` with the current time.
|
|
39
|
+
*/
|
|
40
|
+
automaticRecord: (opts?: ConsentOptions) => ConsentRecord;
|
|
41
|
+
/**
|
|
42
|
+
* `fresh` for an automatic decision younger than `CONSENT_AUTO_MAX_AGE`, `stale` for an older one
|
|
43
|
+
* (or one stamped in the future beyond the skew), `null` for an explicit record or none.
|
|
44
|
+
*/
|
|
45
|
+
autoState: (record: ConsentRecord | null) => ConsentAutoState | null;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/geo/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAElF,qFAAqF;AACrF,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,CAAA;AAE9C,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAA;AAEhD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0GAA0G;IAC1G,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,cAAc,KAAK,OAAO,CAAA;IAC3C,qGAAqG;IACrG,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpD;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;IACzC;;;OAGG;IACH,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,cAAc,KAAK,OAAO,CAAA;IAC3E;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC5D;;;OAGG;IACH,aAAa,EAAE,MAAM,OAAO,CAAA;IAC5B;;;OAGG;IACH,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,cAAc,KAAK,aAAa,CAAA;IACzD;;;OAGG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,KAAK,gBAAgB,GAAG,IAAI,CAAA;CACrE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/geo/types.ts"],"names":[],"mappings":""}
|
package/build/geo.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../src/geo.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAoB,gBAAgB,EAAqB,MAAM,gBAAgB,CAAA;AAE3F,eAAO,MAAM,sBAAsB,QAAO,gBA2GzC,CAAA;AAED,eAAO,MAAM,gBAAgB,kBAA2B,CAAA"}
|