Files
supabase/packages/common/consent-state.ts
T
Ivan Vasilov 1cd1ebfc7f chire: Sort imports in all packages, cms, design-system and ui-library apps (#41610)
Sorted all imports in all packages, `cms`, `design-system` and
`ui-library` apps by running `pnpm format` on them.

All changes in this PR are done by the script.
2026-02-05 13:54:10 +01:00

122 lines
3.6 KiB
TypeScript

import type Usercentrics from '@usercentrics/cmp-browser-sdk'
import type { BaseCategory, UserDecision } from '@usercentrics/cmp-browser-sdk'
import { proxy, snapshot, useSnapshot } from 'valtio'
import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from './constants'
export const consentState = proxy({
// Usercentrics state
UC: null as Usercentrics | null,
categories: null as BaseCategory[] | null,
// Our state
showConsentToast: false,
hasConsented: false,
acceptAll: () => {
if (!consentState.UC) return
const previousConsentValue = consentState.hasConsented
consentState.hasConsented = true
consentState.showConsentToast = false
consentState.UC.acceptAllServices()
.then(() => {
consentState.categories = consentState.UC?.getCategoriesBaseInfo() ?? null
})
.catch(() => {
consentState.hasConsented = previousConsentValue
consentState.showConsentToast = true
})
},
denyAll: () => {
if (!consentState.UC) return
const previousConsentValue = consentState.hasConsented
consentState.hasConsented = false
consentState.showConsentToast = false
consentState.UC.denyAllServices()
.then(() => {
consentState.categories = consentState.UC?.getCategoriesBaseInfo() ?? null
})
.catch(() => {
consentState.showConsentToast = previousConsentValue
})
},
updateServices: (decisions: UserDecision[]) => {
if (!consentState.UC) return
consentState.showConsentToast = false
consentState.UC.updateServices(decisions)
.then(() => {
consentState.hasConsented = consentState.UC?.areAllConsentsAccepted() ?? false
consentState.categories = consentState.UC?.getCategoriesBaseInfo() ?? null
})
.catch(() => {
consentState.showConsentToast = true
})
},
})
async function initUserCentrics() {
if (process.env.NODE_ENV === 'test' || !IS_PLATFORM) return
// [Alaister] For local development and staging, we accept all consent by default.
// If you need to test usercentrics in these environments, comment out this
// NEXT_PUBLIC_ENVIRONMENT check and add an ngrok domain to usercentrics
if (
process.env.NEXT_PUBLIC_ENVIRONMENT === 'local' ||
process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging'
) {
consentState.hasConsented = true
return
}
const { default: Usercentrics } = await import('@usercentrics/cmp-browser-sdk')
const UC = new Usercentrics(process.env.NEXT_PUBLIC_USERCENTRICS_RULESET_ID!, {
rulesetId: process.env.NEXT_PUBLIC_USERCENTRICS_RULESET_ID,
useRulesetId: true,
})
const initialUIValues = await UC.init()
consentState.UC = UC
const hasConsented = UC.areAllConsentsAccepted()
// 0 = first layer, aka show consent toast
consentState.showConsentToast = initialUIValues.initialLayer === 0
consentState.hasConsented = hasConsented
consentState.categories = UC.getCategoriesBaseInfo()
// If the user has previously consented (before usercentrics), accept all services
if (!hasConsented && localStorage?.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT) === 'true') {
consentState.acceptAll()
localStorage.removeItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
}
}
// Usercentrics is not available on the server
if (typeof window !== 'undefined') {
initUserCentrics()
}
// Public API for consent
export function hasConsented() {
return snapshot(consentState).hasConsented
}
export function useConsentState() {
const snap = useSnapshot(consentState)
return {
hasAccepted: snap.hasConsented,
categories: snap.categories as BaseCategory[] | null,
acceptAll: snap.acceptAll,
denyAll: snap.denyAll,
updateServices: snap.updateServices,
}
}