@cookiemunch/consent-shim 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Every published release, newest first. Dates are the day the version was cut.
4
4
 
5
+ ## 0.2.0 (2026-10-25)
6
+
7
+ - Added: the shim also sets `window.__consent`, the shared API's name from now on; `window.__fdConsent` stays, the same object. Calls queued on either are replayed, and a `__consent` another tool owns is left alone.
8
+
5
9
  ## 0.1.0 (2026-10-24)
6
10
 
7
11
  - Added: `import '@cookiemunch/consent-shim'` sets `window.__fdConsent` over Cookiebot, OneTrust or no consent tool; `dist/fd-consent-shim.js` is the same script as the CDN's.
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # @cookiemunch/consent-shim
2
2
 
3
- `window.__fdConsent` on any page: one small consent API that a chat widget, a referral snippet or an
3
+ `window.__consent` (also `window.__fdConsent`, the same object) on any page: one small consent API that a chat widget, a referral snippet or an
4
4
  analytics tag can code against, whatever consent tool the page runs. Cookie Munch sets it natively;
5
5
  on a page running Cookiebot, OneTrust or no consent tool, this shim sets the same object.
6
6
 
7
7
  ```ts
8
8
  import '@cookiemunch/consent-shim';
9
9
 
10
- const fd = window.__fdConsent;
10
+ const fd = window.__consent;
11
11
  fd.has('referrals'); // true, false, or null before the visitor decides
12
12
  fd.on('change', (state) => { /* … */ });
13
13
  await fd.request('support_chat'); // the mapped category's state (the shim cannot prompt)
@@ -1,2 +1,2 @@
1
- "use strict";(()=>{(s=>{let c=s.__fdConsent;if(c&&c.version)return;let b=c&&c.q||[],d={support_chat:"preferences",referrals:"marketing",product_analytics:"statistics",...s.fdConsentShim&&s.fdConsentShim.map},k=["preferences","statistics","marketing"],y=()=>!!s.navigator.globalPrivacyControl,a=()=>{let e=s.Cookiebot;if(e&&e.consent&&typeof e.hasResponse=="boolean"){let t=e.consent;return["cookiebot",e.hasResponse,!0,{preferences:!!t.preferences,statistics:!!t.statistics,marketing:!!t.marketing}]}let n=s.OnetrustActiveGroups;if(typeof n=="string"){let t=r=>n.indexOf(`,${r},`)>=0;return["onetrust",/(^|; )OptanonAlertBoxClosed=/.test(document.cookie),!0,{preferences:t("C0003"),statistics:t("C0002"),marketing:t("C0004")}]}return["none",!1,!1,{preferences:!0,statistics:!0,marketing:!y()}]},u=()=>{let[,e,n,t]=a(),o={necessary:!0,...t};for(let r in d)o[r]=!!t[d[r]];return{decided:e,required:n,categories:o,stamp:null,region:"",gpc:y(),decidedAt:null}},f=()=>{let e=a();return e[1]||!e[2]},h={},m=e=>{if(e=="necessary")return!0;let n=k.indexOf(e)>=0?e:d[e];return n?f()?!!a()[3][n]:null:(h[e]||(h[e]=1,console.warn(`[fd-consent-shim] unknown category "${e}"; answering false`)),!1)},i=[],l=e=>{let n=u();i.slice().forEach(t=>{try{t(n,e)}catch(o){console.error(o)}})};s.addEventListener("CookiebotOnAccept",()=>l("accept")),s.addEventListener("CookiebotOnDecline",()=>l("decline")),s.addEventListener("OneTrustGroupsUpdated",()=>l("selection"));let g=(e,n)=>e!="change"||typeof n!="function"?()=>{}:(i.push(n),f()&&Promise.resolve().then(()=>i.indexOf(n)>=0&&n(u(),"replay")),()=>{let t=i.indexOf(n);t>=0&&i.splice(t,1)}),C=()=>new Promise(e=>{if(f())return e(u());let n=g("change",t=>(n(),e(t)))}),p={version:1,get provider(){return`shim:${a()[0]}`},has:m,on:g,ready:C,request:e=>Promise.resolve(m(e)===!0),identify:()=>{},layout:{bottomInset:()=>0,on:()=>()=>{}}},v=e=>{let[n,t,o,r]=e;n=="on"?g(t,o):n=="ready"?C().then(t):n=="request"&&p.request(t).then(r)};p.q={push:(...e)=>(e.forEach(v),0)},s.__fdConsent=p,b.forEach(v)})(window);})();
1
+ "use strict";(()=>{(s=>{let _=n=>!!n&&typeof n=="object"&&("q"in n||"version"in n),a=s.__fdConsent,r=_(s.__consent)?s.__consent:void 0;if(a&&a.version||r&&r.version)return;let h=n=>n&&Array.isArray(n.q)?n.q:[],q=[...h(a),...r&&r!==a?h(r):[]],f={support_chat:"preferences",referrals:"marketing",product_analytics:"statistics",...s.fdConsentShim&&s.fdConsentShim.map},O=["preferences","statistics","marketing"],m=()=>!!s.navigator.globalPrivacyControl,d=()=>{let n=s.Cookiebot;if(n&&n.consent&&typeof n.hasResponse=="boolean"){let t=n.consent;return["cookiebot",n.hasResponse,!0,{preferences:!!t.preferences,statistics:!!t.statistics,marketing:!!t.marketing}]}let e=s.OnetrustActiveGroups;if(typeof e=="string"){let t=i=>e.indexOf(`,${i},`)>=0;return["onetrust",/(^|; )OptanonAlertBoxClosed=/.test(document.cookie),!0,{preferences:t("C0003"),statistics:t("C0002"),marketing:t("C0004")}]}return["none",!1,!1,{preferences:!0,statistics:!0,marketing:!m()}]},l=()=>{let[,n,e,t]=d(),o={necessary:!0,...t};for(let i in f)o[i]=!!t[f[i]];return{decided:n,required:e,categories:o,stamp:null,region:"",gpc:m(),decidedAt:null}},p=()=>{let n=d();return n[1]||!n[2]},v={},b=n=>{if(n=="necessary")return!0;let e=O.indexOf(n)>=0?n:f[n];return e?p()?!!d()[3][e]:null:(v[n]||(v[n]=1,console.warn(`[fd-consent-shim] unknown category "${n}"; answering false`)),!1)},c=[],g=n=>{let e=l();c.slice().forEach(t=>{try{t(e,n)}catch(o){console.error(o)}})};s.addEventListener("CookiebotOnAccept",()=>g("accept")),s.addEventListener("CookiebotOnDecline",()=>g("decline")),s.addEventListener("OneTrustGroupsUpdated",()=>g("selection"));let y=(n,e)=>n!="change"||typeof e!="function"?()=>{}:(c.push(e),p()&&Promise.resolve().then(()=>c.indexOf(e)>=0&&e(l(),"replay")),()=>{let t=c.indexOf(e);t>=0&&c.splice(t,1)}),C=()=>new Promise(n=>{if(p())return n(l());let e=y("change",t=>(e(),n(t)))}),u={version:1,get provider(){return`shim:${d()[0]}`},has:b,on:y,ready:C,request:n=>Promise.resolve(b(n)===!0),identify:()=>{},layout:{bottomInset:()=>0,on:()=>()=>{}}},k=n=>{let[e,t,o,i]=n;e=="on"?y(t,o):e=="ready"?C().then(t):e=="request"&&u.request(t).then(i)};u.q={push:(...n)=>(n.forEach(k),0)},s.__fdConsent=u,(s.__consent===void 0||r)&&(s.__consent=u),q.forEach(k)})(window);})();
2
2
  //# sourceMappingURL=fd-consent-shim.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shim.ts"],"sourcesContent":["/**\n * fd-consent-shim.js (CMU-X18): `window.__fdConsent` on a site that does NOT run Cookie Munch —\n * Cookiebot, OneTrust, or no CMP at all (GPC only) — so a chat widget or a referral snippet\n * codes against one API wherever it is embedded.\n *\n * <script src=\"https://cdn.cookiemunch.net/fd-consent-shim.js\" async></script>\n *\n * It maps the CMP's categories onto the standard ids, and the reserved ids onto those:\n * `support_chat` → preferences, `referrals` → marketing, `product_analytics` → statistics (change with\n * `window.fdConsentShim = { map: { referrals: 'statistics' } }` before it loads). It cannot\n * prompt, so `request()` answers with the mapped category's state; `layout` answers 0;\n * `identify` does nothing. With no CMP there is nothing to decide: every category is allowed\n * except where Global Privacy Control says no (marketing, and what maps to it).\n *\n * Do not load it on a Cookie Munch site: Cookie Munch sets the native object itself.\n * Standalone and tiny (size-gated): it imports nothing.\n */\n\ntype Cats = Record<string, boolean>;\ntype Cb = (s: unknown, cause: string) => void;\n\n((w: Window & Record<string, any>) => {\n const fd = w.__fdConsent;\n if (fd && fd.version) return; // a CMP already set the real one\n const queued: unknown[][] = (fd && fd.q) || [];\n const map: Record<string, string> = { support_chat: 'preferences', referrals: 'marketing', product_analytics: 'statistics', ...(w.fdConsentShim && w.fdConsentShim.map) };\n const std = ['preferences', 'statistics', 'marketing'];\n const gpc = (): boolean => !!(w.navigator as Navigator & { globalPrivacyControl?: boolean }).globalPrivacyControl;\n\n /** What the CMP on the page says now: [provider, decided, required, categories]. */\n const read = (): [string, boolean, boolean, Cats] => {\n const cb = w.Cookiebot;\n if (cb && cb.consent && typeof cb.hasResponse == 'boolean') {\n const c = cb.consent;\n return ['cookiebot', cb.hasResponse, true, { preferences: !!c.preferences, statistics: !!c.statistics, marketing: !!c.marketing }];\n }\n const groups: unknown = w.OnetrustActiveGroups;\n if (typeof groups == 'string') {\n const on = (g: string): boolean => groups.indexOf(`,${g},`) >= 0;\n const closed = /(^|; )OptanonAlertBoxClosed=/.test(document.cookie);\n return ['onetrust', closed, true, { preferences: on('C0003'), statistics: on('C0002'), marketing: on('C0004') }];\n }\n return ['none', false, false, { preferences: true, statistics: true, marketing: !gpc() }];\n };\n\n const snapshot = () => {\n const [, decided, required, c] = read();\n const categories: Cats = { necessary: true, ...c };\n for (const id in map) categories[id] = !!c[map[id]!];\n return { decided, required, categories, stamp: null, region: '', gpc: gpc(), decidedAt: null };\n };\n const settled = (): boolean => {\n const r = read();\n return r[1] || !r[2];\n };\n const warned: Record<string, 1> = {};\n const has = (cat: string): boolean | null => {\n if (cat == 'necessary') return true;\n const id = std.indexOf(cat) >= 0 ? cat : map[cat];\n if (!id) {\n if (!warned[cat]) (warned[cat] = 1), console.warn(`[fd-consent-shim] unknown category \"${cat}\"; answering false`);\n return false;\n }\n return settled() ? !!read()[3][id] : null;\n };\n\n const listeners: Cb[] = [];\n const emit = (cause: string): void => {\n const s = snapshot();\n listeners.slice().forEach((cb) => {\n try {\n cb(s, cause);\n } catch (e) {\n console.error(e);\n }\n });\n };\n // Cookiebot's events, and OneTrust's; whichever CMP the page runs fires its own.\n w.addEventListener('CookiebotOnAccept', () => emit('accept'));\n w.addEventListener('CookiebotOnDecline', () => emit('decline'));\n w.addEventListener('OneTrustGroupsUpdated', () => emit('selection'));\n\n const on = (ev: string, cb: Cb): (() => void) => {\n if (ev != 'change' || typeof cb != 'function') return () => undefined;\n listeners.push(cb);\n if (settled()) Promise.resolve().then(() => listeners.indexOf(cb) >= 0 && cb(snapshot(), 'replay'));\n return () => {\n const i = listeners.indexOf(cb);\n if (i >= 0) listeners.splice(i, 1);\n };\n };\n const ready = () =>\n new Promise((done) => {\n if (settled()) return done(snapshot());\n const off = on('change', (s) => (off(), done(s)));\n });\n\n const api: Record<string, any> = {\n version: 1,\n get provider() {\n return `shim:${read()[0]}`;\n },\n has,\n on,\n ready,\n // It cannot ask: the answer is the mapped category's state (false while undecided).\n request: (cat: string) => Promise.resolve(has(cat) === true),\n identify: () => undefined,\n layout: { bottomInset: () => 0, on: () => () => undefined },\n };\n const run = (c: unknown[]): void => {\n const [m, a, b, d] = c as [string, any, any, any];\n if (m == 'on') on(a, b);\n else if (m == 'ready') ready().then(a);\n else if (m == 'request') api.request(a).then(d);\n };\n api.q = { push: (...calls: unknown[][]) => (calls.forEach(run), 0) };\n w.__fdConsent = api;\n queued.forEach(run);\n})(window as never);\n"],"mappings":"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","names":["w","fd","queued","map","std","gpc","read","cb","c","groups","on","g","snapshot","decided","required","categories","id","settled","r","warned","has","cat","listeners","emit","cause","s","e","ev","i","ready","done","off","api","run","m","a","b","d","calls"]}
1
+ {"version":3,"sources":["../src/shim.ts"],"sourcesContent":["/**\n * fd-consent-shim.js (CMU-X18): `window.__fdConsent` on a site that does NOT run Cookie Munch —\n * Cookiebot, OneTrust, or no CMP at all (GPC only) — so a chat widget or a referral snippet\n * codes against one API wherever it is embedded.\n *\n * <script src=\"https://cdn.cookiemunch.net/fd-consent-shim.js\" async></script>\n *\n * It maps the CMP's categories onto the standard ids, and the reserved ids onto those:\n * `support_chat` → preferences, `referrals` → marketing, `product_analytics` → statistics (change with\n * `window.fdConsentShim = { map: { referrals: 'statistics' } }` before it loads). It cannot\n * prompt, so `request()` answers with the mapped category's state; `layout` answers 0;\n * `identify` does nothing. With no CMP there is nothing to decide: every category is allowed\n * except where Global Privacy Control says no (marketing, and what maps to it).\n *\n * Do not load it on a Cookie Munch site: Cookie Munch sets the native object itself.\n * Standalone and tiny (size-gated): it imports nothing.\n */\n\ntype Cats = Record<string, boolean>;\ntype Cb = (s: unknown, cause: string) => void;\n\n((w: Window & Record<string, any>) => {\n // window.__consent is the name; __fdConsent is an alias of the same object. An embed may have queued on either.\n const ours = (o: any): boolean => !!o && typeof o == 'object' && ('q' in o || 'version' in o);\n const fd = w.__fdConsent;\n const alt = ours(w.__consent) ? w.__consent : undefined;\n if ((fd && fd.version) || (alt && alt.version)) return; // a CMP already set the real one\n const qOf = (o: any): unknown[][] => (o && Array.isArray(o.q) ? o.q : []);\n const queued: unknown[][] = [...qOf(fd), ...(alt && alt !== fd ? qOf(alt) : [])];\n const map: Record<string, string> = { support_chat: 'preferences', referrals: 'marketing', product_analytics: 'statistics', ...(w.fdConsentShim && w.fdConsentShim.map) };\n const std = ['preferences', 'statistics', 'marketing'];\n const gpc = (): boolean => !!(w.navigator as Navigator & { globalPrivacyControl?: boolean }).globalPrivacyControl;\n\n /** What the CMP on the page says now: [provider, decided, required, categories]. */\n const read = (): [string, boolean, boolean, Cats] => {\n const cb = w.Cookiebot;\n if (cb && cb.consent && typeof cb.hasResponse == 'boolean') {\n const c = cb.consent;\n return ['cookiebot', cb.hasResponse, true, { preferences: !!c.preferences, statistics: !!c.statistics, marketing: !!c.marketing }];\n }\n const groups: unknown = w.OnetrustActiveGroups;\n if (typeof groups == 'string') {\n const on = (g: string): boolean => groups.indexOf(`,${g},`) >= 0;\n const closed = /(^|; )OptanonAlertBoxClosed=/.test(document.cookie);\n return ['onetrust', closed, true, { preferences: on('C0003'), statistics: on('C0002'), marketing: on('C0004') }];\n }\n return ['none', false, false, { preferences: true, statistics: true, marketing: !gpc() }];\n };\n\n const snapshot = () => {\n const [, decided, required, c] = read();\n const categories: Cats = { necessary: true, ...c };\n for (const id in map) categories[id] = !!c[map[id]!];\n return { decided, required, categories, stamp: null, region: '', gpc: gpc(), decidedAt: null };\n };\n const settled = (): boolean => {\n const r = read();\n return r[1] || !r[2];\n };\n const warned: Record<string, 1> = {};\n const has = (cat: string): boolean | null => {\n if (cat == 'necessary') return true;\n const id = std.indexOf(cat) >= 0 ? cat : map[cat];\n if (!id) {\n if (!warned[cat]) (warned[cat] = 1), console.warn(`[fd-consent-shim] unknown category \"${cat}\"; answering false`);\n return false;\n }\n return settled() ? !!read()[3][id] : null;\n };\n\n const listeners: Cb[] = [];\n const emit = (cause: string): void => {\n const s = snapshot();\n listeners.slice().forEach((cb) => {\n try {\n cb(s, cause);\n } catch (e) {\n console.error(e);\n }\n });\n };\n // Cookiebot's events, and OneTrust's; whichever CMP the page runs fires its own.\n w.addEventListener('CookiebotOnAccept', () => emit('accept'));\n w.addEventListener('CookiebotOnDecline', () => emit('decline'));\n w.addEventListener('OneTrustGroupsUpdated', () => emit('selection'));\n\n const on = (ev: string, cb: Cb): (() => void) => {\n if (ev != 'change' || typeof cb != 'function') return () => undefined;\n listeners.push(cb);\n if (settled()) Promise.resolve().then(() => listeners.indexOf(cb) >= 0 && cb(snapshot(), 'replay'));\n return () => {\n const i = listeners.indexOf(cb);\n if (i >= 0) listeners.splice(i, 1);\n };\n };\n const ready = () =>\n new Promise((done) => {\n if (settled()) return done(snapshot());\n const off = on('change', (s) => (off(), done(s)));\n });\n\n const api: Record<string, any> = {\n version: 1,\n get provider() {\n return `shim:${read()[0]}`;\n },\n has,\n on,\n ready,\n // It cannot ask: the answer is the mapped category's state (false while undecided).\n request: (cat: string) => Promise.resolve(has(cat) === true),\n identify: () => undefined,\n layout: { bottomInset: () => 0, on: () => () => undefined },\n };\n const run = (c: unknown[]): void => {\n const [m, a, b, d] = c as [string, any, any, any];\n if (m == 'on') on(a, b);\n else if (m == 'ready') ready().then(a);\n else if (m == 'request') api.request(a).then(d);\n };\n api.q = { push: (...calls: unknown[][]) => (calls.forEach(run), 0) };\n w.__fdConsent = api;\n if (w.__consent === undefined || alt) w.__consent = api;\n queued.forEach(run);\n})(window as never);\n"],"mappings":"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","names":["w","ours","o","fd","alt","qOf","queued","map","std","gpc","read","cb","c","groups","on","g","snapshot","decided","required","categories","id","settled","r","warned","has","cat","listeners","emit","cause","s","e","ev","i","ready","done","off","api","run","m","a","b","d","calls"]}
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
1
  // src/shim.ts
2
2
  ((w) => {
3
+ const ours = (o) => !!o && typeof o == "object" && ("q" in o || "version" in o);
3
4
  const fd = w.__fdConsent;
4
- if (fd && fd.version) return;
5
- const queued = fd && fd.q || [];
5
+ const alt = ours(w.__consent) ? w.__consent : void 0;
6
+ if (fd && fd.version || alt && alt.version) return;
7
+ const qOf = (o) => o && Array.isArray(o.q) ? o.q : [];
8
+ const queued = [...qOf(fd), ...alt && alt !== fd ? qOf(alt) : []];
6
9
  const map = { support_chat: "preferences", referrals: "marketing", product_analytics: "statistics", ...w.fdConsentShim && w.fdConsentShim.map };
7
10
  const std = ["preferences", "statistics", "marketing"];
8
11
  const gpc = () => !!w.navigator.globalPrivacyControl;
@@ -88,6 +91,7 @@
88
91
  };
89
92
  api.q = { push: (...calls) => (calls.forEach(run), 0) };
90
93
  w.__fdConsent = api;
94
+ if (w.__consent === void 0 || alt) w.__consent = api;
91
95
  queued.forEach(run);
92
96
  })(window);
93
97
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shim.ts"],"sourcesContent":["/**\n * fd-consent-shim.js (CMU-X18): `window.__fdConsent` on a site that does NOT run Cookie Munch —\n * Cookiebot, OneTrust, or no CMP at all (GPC only) — so a chat widget or a referral snippet\n * codes against one API wherever it is embedded.\n *\n * <script src=\"https://cdn.cookiemunch.net/fd-consent-shim.js\" async></script>\n *\n * It maps the CMP's categories onto the standard ids, and the reserved ids onto those:\n * `support_chat` → preferences, `referrals` → marketing, `product_analytics` → statistics (change with\n * `window.fdConsentShim = { map: { referrals: 'statistics' } }` before it loads). It cannot\n * prompt, so `request()` answers with the mapped category's state; `layout` answers 0;\n * `identify` does nothing. With no CMP there is nothing to decide: every category is allowed\n * except where Global Privacy Control says no (marketing, and what maps to it).\n *\n * Do not load it on a Cookie Munch site: Cookie Munch sets the native object itself.\n * Standalone and tiny (size-gated): it imports nothing.\n */\n\ntype Cats = Record<string, boolean>;\ntype Cb = (s: unknown, cause: string) => void;\n\n((w: Window & Record<string, any>) => {\n const fd = w.__fdConsent;\n if (fd && fd.version) return; // a CMP already set the real one\n const queued: unknown[][] = (fd && fd.q) || [];\n const map: Record<string, string> = { support_chat: 'preferences', referrals: 'marketing', product_analytics: 'statistics', ...(w.fdConsentShim && w.fdConsentShim.map) };\n const std = ['preferences', 'statistics', 'marketing'];\n const gpc = (): boolean => !!(w.navigator as Navigator & { globalPrivacyControl?: boolean }).globalPrivacyControl;\n\n /** What the CMP on the page says now: [provider, decided, required, categories]. */\n const read = (): [string, boolean, boolean, Cats] => {\n const cb = w.Cookiebot;\n if (cb && cb.consent && typeof cb.hasResponse == 'boolean') {\n const c = cb.consent;\n return ['cookiebot', cb.hasResponse, true, { preferences: !!c.preferences, statistics: !!c.statistics, marketing: !!c.marketing }];\n }\n const groups: unknown = w.OnetrustActiveGroups;\n if (typeof groups == 'string') {\n const on = (g: string): boolean => groups.indexOf(`,${g},`) >= 0;\n const closed = /(^|; )OptanonAlertBoxClosed=/.test(document.cookie);\n return ['onetrust', closed, true, { preferences: on('C0003'), statistics: on('C0002'), marketing: on('C0004') }];\n }\n return ['none', false, false, { preferences: true, statistics: true, marketing: !gpc() }];\n };\n\n const snapshot = () => {\n const [, decided, required, c] = read();\n const categories: Cats = { necessary: true, ...c };\n for (const id in map) categories[id] = !!c[map[id]!];\n return { decided, required, categories, stamp: null, region: '', gpc: gpc(), decidedAt: null };\n };\n const settled = (): boolean => {\n const r = read();\n return r[1] || !r[2];\n };\n const warned: Record<string, 1> = {};\n const has = (cat: string): boolean | null => {\n if (cat == 'necessary') return true;\n const id = std.indexOf(cat) >= 0 ? cat : map[cat];\n if (!id) {\n if (!warned[cat]) (warned[cat] = 1), console.warn(`[fd-consent-shim] unknown category \"${cat}\"; answering false`);\n return false;\n }\n return settled() ? !!read()[3][id] : null;\n };\n\n const listeners: Cb[] = [];\n const emit = (cause: string): void => {\n const s = snapshot();\n listeners.slice().forEach((cb) => {\n try {\n cb(s, cause);\n } catch (e) {\n console.error(e);\n }\n });\n };\n // Cookiebot's events, and OneTrust's; whichever CMP the page runs fires its own.\n w.addEventListener('CookiebotOnAccept', () => emit('accept'));\n w.addEventListener('CookiebotOnDecline', () => emit('decline'));\n w.addEventListener('OneTrustGroupsUpdated', () => emit('selection'));\n\n const on = (ev: string, cb: Cb): (() => void) => {\n if (ev != 'change' || typeof cb != 'function') return () => undefined;\n listeners.push(cb);\n if (settled()) Promise.resolve().then(() => listeners.indexOf(cb) >= 0 && cb(snapshot(), 'replay'));\n return () => {\n const i = listeners.indexOf(cb);\n if (i >= 0) listeners.splice(i, 1);\n };\n };\n const ready = () =>\n new Promise((done) => {\n if (settled()) return done(snapshot());\n const off = on('change', (s) => (off(), done(s)));\n });\n\n const api: Record<string, any> = {\n version: 1,\n get provider() {\n return `shim:${read()[0]}`;\n },\n has,\n on,\n ready,\n // It cannot ask: the answer is the mapped category's state (false while undecided).\n request: (cat: string) => Promise.resolve(has(cat) === true),\n identify: () => undefined,\n layout: { bottomInset: () => 0, on: () => () => undefined },\n };\n const run = (c: unknown[]): void => {\n const [m, a, b, d] = c as [string, any, any, any];\n if (m == 'on') on(a, b);\n else if (m == 'ready') ready().then(a);\n else if (m == 'request') api.request(a).then(d);\n };\n api.q = { push: (...calls: unknown[][]) => (calls.forEach(run), 0) };\n w.__fdConsent = api;\n queued.forEach(run);\n})(window as never);\n"],"mappings":"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","names":["on"]}
1
+ {"version":3,"sources":["../src/shim.ts"],"sourcesContent":["/**\n * fd-consent-shim.js (CMU-X18): `window.__fdConsent` on a site that does NOT run Cookie Munch —\n * Cookiebot, OneTrust, or no CMP at all (GPC only) — so a chat widget or a referral snippet\n * codes against one API wherever it is embedded.\n *\n * <script src=\"https://cdn.cookiemunch.net/fd-consent-shim.js\" async></script>\n *\n * It maps the CMP's categories onto the standard ids, and the reserved ids onto those:\n * `support_chat` → preferences, `referrals` → marketing, `product_analytics` → statistics (change with\n * `window.fdConsentShim = { map: { referrals: 'statistics' } }` before it loads). It cannot\n * prompt, so `request()` answers with the mapped category's state; `layout` answers 0;\n * `identify` does nothing. With no CMP there is nothing to decide: every category is allowed\n * except where Global Privacy Control says no (marketing, and what maps to it).\n *\n * Do not load it on a Cookie Munch site: Cookie Munch sets the native object itself.\n * Standalone and tiny (size-gated): it imports nothing.\n */\n\ntype Cats = Record<string, boolean>;\ntype Cb = (s: unknown, cause: string) => void;\n\n((w: Window & Record<string, any>) => {\n // window.__consent is the name; __fdConsent is an alias of the same object. An embed may have queued on either.\n const ours = (o: any): boolean => !!o && typeof o == 'object' && ('q' in o || 'version' in o);\n const fd = w.__fdConsent;\n const alt = ours(w.__consent) ? w.__consent : undefined;\n if ((fd && fd.version) || (alt && alt.version)) return; // a CMP already set the real one\n const qOf = (o: any): unknown[][] => (o && Array.isArray(o.q) ? o.q : []);\n const queued: unknown[][] = [...qOf(fd), ...(alt && alt !== fd ? qOf(alt) : [])];\n const map: Record<string, string> = { support_chat: 'preferences', referrals: 'marketing', product_analytics: 'statistics', ...(w.fdConsentShim && w.fdConsentShim.map) };\n const std = ['preferences', 'statistics', 'marketing'];\n const gpc = (): boolean => !!(w.navigator as Navigator & { globalPrivacyControl?: boolean }).globalPrivacyControl;\n\n /** What the CMP on the page says now: [provider, decided, required, categories]. */\n const read = (): [string, boolean, boolean, Cats] => {\n const cb = w.Cookiebot;\n if (cb && cb.consent && typeof cb.hasResponse == 'boolean') {\n const c = cb.consent;\n return ['cookiebot', cb.hasResponse, true, { preferences: !!c.preferences, statistics: !!c.statistics, marketing: !!c.marketing }];\n }\n const groups: unknown = w.OnetrustActiveGroups;\n if (typeof groups == 'string') {\n const on = (g: string): boolean => groups.indexOf(`,${g},`) >= 0;\n const closed = /(^|; )OptanonAlertBoxClosed=/.test(document.cookie);\n return ['onetrust', closed, true, { preferences: on('C0003'), statistics: on('C0002'), marketing: on('C0004') }];\n }\n return ['none', false, false, { preferences: true, statistics: true, marketing: !gpc() }];\n };\n\n const snapshot = () => {\n const [, decided, required, c] = read();\n const categories: Cats = { necessary: true, ...c };\n for (const id in map) categories[id] = !!c[map[id]!];\n return { decided, required, categories, stamp: null, region: '', gpc: gpc(), decidedAt: null };\n };\n const settled = (): boolean => {\n const r = read();\n return r[1] || !r[2];\n };\n const warned: Record<string, 1> = {};\n const has = (cat: string): boolean | null => {\n if (cat == 'necessary') return true;\n const id = std.indexOf(cat) >= 0 ? cat : map[cat];\n if (!id) {\n if (!warned[cat]) (warned[cat] = 1), console.warn(`[fd-consent-shim] unknown category \"${cat}\"; answering false`);\n return false;\n }\n return settled() ? !!read()[3][id] : null;\n };\n\n const listeners: Cb[] = [];\n const emit = (cause: string): void => {\n const s = snapshot();\n listeners.slice().forEach((cb) => {\n try {\n cb(s, cause);\n } catch (e) {\n console.error(e);\n }\n });\n };\n // Cookiebot's events, and OneTrust's; whichever CMP the page runs fires its own.\n w.addEventListener('CookiebotOnAccept', () => emit('accept'));\n w.addEventListener('CookiebotOnDecline', () => emit('decline'));\n w.addEventListener('OneTrustGroupsUpdated', () => emit('selection'));\n\n const on = (ev: string, cb: Cb): (() => void) => {\n if (ev != 'change' || typeof cb != 'function') return () => undefined;\n listeners.push(cb);\n if (settled()) Promise.resolve().then(() => listeners.indexOf(cb) >= 0 && cb(snapshot(), 'replay'));\n return () => {\n const i = listeners.indexOf(cb);\n if (i >= 0) listeners.splice(i, 1);\n };\n };\n const ready = () =>\n new Promise((done) => {\n if (settled()) return done(snapshot());\n const off = on('change', (s) => (off(), done(s)));\n });\n\n const api: Record<string, any> = {\n version: 1,\n get provider() {\n return `shim:${read()[0]}`;\n },\n has,\n on,\n ready,\n // It cannot ask: the answer is the mapped category's state (false while undecided).\n request: (cat: string) => Promise.resolve(has(cat) === true),\n identify: () => undefined,\n layout: { bottomInset: () => 0, on: () => () => undefined },\n };\n const run = (c: unknown[]): void => {\n const [m, a, b, d] = c as [string, any, any, any];\n if (m == 'on') on(a, b);\n else if (m == 'ready') ready().then(a);\n else if (m == 'request') api.request(a).then(d);\n };\n api.q = { push: (...calls: unknown[][]) => (calls.forEach(run), 0) };\n w.__fdConsent = api;\n if (w.__consent === undefined || alt) w.__consent = api;\n queued.forEach(run);\n})(window as never);\n"],"mappings":"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","names":["on"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cookiemunch/consent-shim",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "window.__fdConsent on any page: one consent API for embeds over Cookiebot, OneTrust or no consent tool",
5
5
  "license": "MIT",
6
6
  "type": "module",