refactor(consent-sdk,dsms-gateway): split ConsentManager, types, and main.py

- consent-sdk/src/types/index.ts: extracted 438 LOC into core.ts, config.ts,
  vendor.ts, api.ts, events.ts, storage.ts, translations.ts; index.ts is now
  a 21-LOC barrel re-exporter
- consent-sdk/src/core/ConsentManager.ts: extracted normalizeConsentInput,
  isConsentExpired, needsConsent, ALL_CATEGORIES, MINIMAL_CATEGORIES into
  consent-manager-helpers.ts; reduced from 467 to 345 LOC
- dsms-gateway/main.py: extracted models → models.py, config → config.py,
  IPFS helpers + verify_token → dependencies.py, route handlers →
  routers/documents.py and routers/node.py; main.py is now a 41-LOC app
  factory; test mock paths updated accordingly (27/27 tests pass)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-18 08:42:32 +02:00
parent 9ecd3b2d84
commit a7fe32fb82
18 changed files with 1115 additions and 1042 deletions

View File

@@ -1,14 +1,9 @@
/**
* ConsentManager - Hauptklasse fuer das Consent Management
*
* DSGVO/TTDSG-konformes Consent Management fuer Web, PWA und Mobile.
*/
/** ConsentManager - DSGVO/TTDSG-konformes Consent Management fuer Web, PWA und Mobile. */
import type {
ConsentConfig,
ConsentState,
ConsentCategory,
ConsentCategories,
ConsentInput,
ConsentEventType,
ConsentEventCallback,
@@ -20,15 +15,16 @@ import { ConsentAPI } from './ConsentAPI';
import { EventEmitter } from '../utils/EventEmitter';
import { generateFingerprint } from '../utils/fingerprint';
import { SDK_VERSION } from '../version';
import {
DEFAULT_CONSENT,
mergeConsentConfig,
} from './consent-manager-config';
import { mergeConsentConfig } from './consent-manager-config';
import { updateGoogleConsentMode as applyGoogleConsent } from './consent-manager-google';
import {
normalizeConsentInput,
isConsentExpired,
needsConsent,
ALL_CATEGORIES,
MINIMAL_CATEGORIES,
} from './consent-manager-helpers';
/**
* ConsentManager - Zentrale Klasse fuer Consent-Verwaltung
*/
export class ConsentManager {
private config: ConsentConfig;
private storage: ConsentStorage;
@@ -41,7 +37,7 @@ export class ConsentManager {
private deviceFingerprint: string = '';
constructor(config: ConsentConfig) {
this.config = this.mergeConfig(config);
this.config = mergeConsentConfig(config);
this.storage = new ConsentStorage(this.config);
this.scriptBlocker = new ScriptBlocker(this.config);
this.api = new ConsentAPI(this.config);
@@ -72,7 +68,7 @@ export class ConsentManager {
this.log('Loaded consent from storage:', this.currentConsent);
// Pruefen ob Consent abgelaufen
if (this.isConsentExpired()) {
if (isConsentExpired(this.currentConsent, this.config)) {
this.log('Consent expired, clearing');
this.storage.clear();
this.currentConsent = null;
@@ -89,7 +85,7 @@ export class ConsentManager {
this.emit('init', this.currentConsent);
// Banner anzeigen falls noetig
if (this.needsConsent()) {
if (needsConsent(this.currentConsent, this.config)) {
this.showBanner();
}
@@ -100,9 +96,7 @@ export class ConsentManager {
}
}
// ===========================================================================
// Public API
// ===========================================================================
// --- Public API ---
/**
* Pruefen ob Consent fuer Kategorie vorhanden
@@ -135,7 +129,7 @@ export class ConsentManager {
* Consent setzen
*/
async setConsent(input: ConsentInput): Promise<void> {
const categories = this.normalizeConsentInput(input);
const categories = normalizeConsentInput(input);
// Essential ist immer aktiv
categories.essential = true;
@@ -184,15 +178,7 @@ export class ConsentManager {
* Alle Kategorien akzeptieren
*/
async acceptAll(): Promise<void> {
const allCategories: ConsentCategories = {
essential: true,
functional: true,
analytics: true,
marketing: true,
social: true,
};
await this.setConsent(allCategories);
await this.setConsent(ALL_CATEGORIES);
this.emit('accept_all', this.currentConsent!);
this.hideBanner();
}
@@ -201,15 +187,7 @@ export class ConsentManager {
* Alle nicht-essentiellen Kategorien ablehnen
*/
async rejectAll(): Promise<void> {
const minimalCategories: ConsentCategories = {
essential: true,
functional: false,
analytics: false,
marketing: false,
social: false,
};
await this.setConsent(minimalCategories);
await this.setConsent(MINIMAL_CATEGORIES);
this.emit('reject_all', this.currentConsent!);
this.hideBanner();
}
@@ -247,52 +225,23 @@ export class ConsentManager {
return JSON.stringify(exportData, null, 2);
}
// ===========================================================================
// Banner Control
// ===========================================================================
// --- Banner Control ---
/**
* Pruefen ob Consent-Abfrage noetig
*/
needsConsent(): boolean {
if (!this.currentConsent) {
return true;
}
if (this.isConsentExpired()) {
return true;
}
// Recheck nach X Tagen
if (this.config.consent?.recheckAfterDays) {
const consentDate = new Date(this.currentConsent.timestamp);
const recheckDate = new Date(consentDate);
recheckDate.setDate(
recheckDate.getDate() + this.config.consent.recheckAfterDays
);
if (new Date() > recheckDate) {
return true;
}
}
return false;
return needsConsent(this.currentConsent, this.config);
}
/**
* Banner anzeigen
*/
showBanner(): void {
if (this.bannerVisible) {
return;
}
if (this.bannerVisible) return;
this.bannerVisible = true;
this.emit('banner_show', undefined);
this.config.onBannerShow?.();
// Banner wird von UI-Komponente gerendert
// Hier nur Status setzen
this.log('Banner shown');
}
@@ -300,14 +249,10 @@ export class ConsentManager {
* Banner verstecken
*/
hideBanner(): void {
if (!this.bannerVisible) {
return;
}
if (!this.bannerVisible) return;
this.bannerVisible = false;
this.emit('banner_hide', undefined);
this.config.onBannerHide?.();
this.log('Banner hidden');
}
@@ -326,9 +271,7 @@ export class ConsentManager {
return this.bannerVisible;
}
// ===========================================================================
// Event Handling
// ===========================================================================
// --- Event Handling ---
/**
* Event-Listener registrieren
@@ -350,35 +293,13 @@ export class ConsentManager {
this.events.off(event, callback);
}
// ===========================================================================
// Internal Methods
// ===========================================================================
/**
* Konfiguration zusammenfuehren — delegates to the extracted helper.
*/
private mergeConfig(config: ConsentConfig): ConsentConfig {
return mergeConsentConfig(config);
}
/**
* Consent-Input normalisieren
*/
private normalizeConsentInput(input: ConsentInput): ConsentCategories {
if ('categories' in input && input.categories) {
return { ...DEFAULT_CONSENT, ...input.categories };
}
return { ...DEFAULT_CONSENT, ...(input as Partial<ConsentCategories>) };
}
// --- Internal Methods ---
/**
* Consent anwenden (Skripte aktivieren/blockieren)
*/
private applyConsent(): void {
if (!this.currentConsent) {
return;
}
if (!this.currentConsent) return;
for (const [category, allowed] of Object.entries(
this.currentConsent.categories
@@ -391,69 +312,26 @@ export class ConsentManager {
}
// Google Consent Mode aktualisieren
this.updateGoogleConsentMode();
}
/**
* Google Consent Mode v2 aktualisieren — delegates to the extracted helper.
*/
private updateGoogleConsentMode(): void {
if (applyGoogleConsent(this.currentConsent)) {
this.log('Google Consent Mode updated');
}
}
/**
* Pruefen ob Consent abgelaufen
*/
private isConsentExpired(): boolean {
if (!this.currentConsent?.expiresAt) {
// Fallback: Nach rememberDays ablaufen
if (this.currentConsent?.timestamp && this.config.consent?.rememberDays) {
const consentDate = new Date(this.currentConsent.timestamp);
const expiryDate = new Date(consentDate);
expiryDate.setDate(
expiryDate.getDate() + this.config.consent.rememberDays
);
return new Date() > expiryDate;
}
return false;
}
return new Date() > new Date(this.currentConsent.expiresAt);
}
/**
* Event emittieren
*/
private emit<T extends ConsentEventType>(
event: T,
data: ConsentEventData[T]
): void {
private emit<T extends ConsentEventType>(event: T, data: ConsentEventData[T]): void {
this.events.emit(event, data);
}
/**
* Fehler behandeln
*/
private handleError(error: Error): void {
this.log('Error:', error);
this.emit('error', error);
this.config.onError?.(error);
}
/**
* Debug-Logging
*/
private log(...args: unknown[]): void {
if (this.config.debug) {
console.log('[ConsentSDK]', ...args);
}
if (this.config.debug) console.log('[ConsentSDK]', ...args);
}
// ===========================================================================
// Static Methods
// ===========================================================================
// --- Static Methods ---
/**
* SDK-Version abrufen

View File

@@ -0,0 +1,88 @@
/**
* consent-manager-helpers.ts
*
* Pure helper functions used by ConsentManager that have no dependency on
* class instance state. Extracted to keep ConsentManager.ts under the
* 350 LOC soft target.
*/
import type {
ConsentState,
ConsentCategories,
ConsentInput,
ConsentConfig,
} from '../types';
import { DEFAULT_CONSENT } from './consent-manager-config';
/** All categories accepted (used by acceptAll). */
export const ALL_CATEGORIES: ConsentCategories = {
essential: true,
functional: true,
analytics: true,
marketing: true,
social: true,
};
/** Only essential consent (used by rejectAll). */
export const MINIMAL_CATEGORIES: ConsentCategories = {
essential: true,
functional: false,
analytics: false,
marketing: false,
social: false,
};
/**
* Normalise a ConsentInput into a full ConsentCategories map.
* Always returns a shallow copy — never mutates the input.
*/
export function normalizeConsentInput(input: ConsentInput): ConsentCategories {
if ('categories' in input && input.categories) {
return { ...DEFAULT_CONSENT, ...input.categories };
}
return { ...DEFAULT_CONSENT, ...(input as Partial<ConsentCategories>) };
}
/**
* Return true when the stored consent record has passed its expiry date.
* Falls back to `rememberDays` from config when `expiresAt` is absent.
*/
export function isConsentExpired(
consent: ConsentState | null,
config: ConsentConfig
): boolean {
if (!consent) return false;
if (!consent.expiresAt) {
if (consent.timestamp && config.consent?.rememberDays) {
const consentDate = new Date(consent.timestamp);
const expiryDate = new Date(consentDate);
expiryDate.setDate(expiryDate.getDate() + config.consent.rememberDays);
return new Date() > expiryDate;
}
return false;
}
return new Date() > new Date(consent.expiresAt);
}
/**
* Return true when the user needs to be shown the consent banner.
*/
export function needsConsent(
consent: ConsentState | null,
config: ConsentConfig
): boolean {
if (!consent) return true;
if (isConsentExpired(consent, config)) return true;
if (config.consent?.recheckAfterDays) {
const consentDate = new Date(consent.timestamp);
const recheckDate = new Date(consentDate);
recheckDate.setDate(recheckDate.getDate() + config.consent.recheckAfterDays);
if (new Date() > recheckDate) return true;
}
return false;
}

View File

@@ -0,0 +1,56 @@
/**
* Consent SDK Types — API request/response shapes
*/
import type { ConsentCategory, ConsentState } from './core';
import type { ConsentUIConfig, TCFConfig } from './config';
import type { ConsentVendor } from './vendor';
// =============================================================================
// API Types
// =============================================================================
/**
* API-Antwort fuer Consent-Erstellung
*/
export interface ConsentAPIResponse {
consentId: string;
timestamp: string;
expiresAt: string;
version: string;
}
/**
* API-Antwort fuer Site-Konfiguration
*/
export interface SiteConfigResponse {
siteId: string;
siteName: string;
categories: CategoryConfig[];
ui: ConsentUIConfig;
legal: LegalConfig;
tcf?: TCFConfig;
}
/**
* Kategorie-Konfiguration vom Server
*/
export interface CategoryConfig {
id: ConsentCategory;
name: Record<string, string>;
description: Record<string, string>;
required: boolean;
vendors: ConsentVendor[];
}
/**
* Rechtliche Konfiguration
*/
export interface LegalConfig {
privacyPolicyUrl: string;
imprintUrl: string;
dpo?: {
name: string;
email: string;
};
}

View File

@@ -0,0 +1,166 @@
/**
* Consent SDK Types — Configuration
*/
import type { ConsentCategory, ConsentState } from './core';
// =============================================================================
// Configuration
// =============================================================================
/**
* UI-Position des Banners
*/
export type BannerPosition = 'bottom' | 'top' | 'center';
/**
* Banner-Layout
*/
export type BannerLayout = 'bar' | 'modal' | 'floating';
/**
* Farbschema
*/
export type BannerTheme = 'light' | 'dark' | 'auto';
/**
* UI-Konfiguration
*/
export interface ConsentUIConfig {
/** Position des Banners */
position?: BannerPosition;
/** Layout-Typ */
layout?: BannerLayout;
/** Farbschema */
theme?: BannerTheme;
/** Pfad zu Custom CSS */
customCss?: string;
/** z-index fuer Banner */
zIndex?: number;
/** Scroll blockieren bei Modal */
blockScrollOnModal?: boolean;
/** Custom Container-ID */
containerId?: string;
}
/**
* Consent-Verhaltens-Konfiguration
*/
export interface ConsentBehaviorConfig {
/** Muss Nutzer interagieren? */
required?: boolean;
/** "Alle ablehnen" Button sichtbar */
rejectAllVisible?: boolean;
/** "Alle akzeptieren" Button sichtbar */
acceptAllVisible?: boolean;
/** Einzelne Kategorien waehlbar */
granularControl?: boolean;
/** Einzelne Vendors waehlbar */
vendorControl?: boolean;
/** Auswahl speichern */
rememberChoice?: boolean;
/** Speicherdauer in Tagen */
rememberDays?: number;
/** Nur in EU anzeigen (Geo-Targeting) */
geoTargeting?: boolean;
/** Erneut nachfragen nach X Tagen */
recheckAfterDays?: number;
}
/**
* TCF 2.2 Konfiguration
*/
export interface TCFConfig {
/** TCF aktivieren */
enabled?: boolean;
/** CMP ID */
cmpId?: number;
/** CMP Version */
cmpVersion?: number;
}
/**
* PWA-spezifische Konfiguration
*/
export interface PWAConfig {
/** Offline-Unterstuetzung aktivieren */
offlineSupport?: boolean;
/** Bei Reconnect synchronisieren */
syncOnReconnect?: boolean;
/** Cache-Strategie */
cacheStrategy?: 'stale-while-revalidate' | 'network-first' | 'cache-first';
}
/**
* Haupt-Konfiguration fuer ConsentManager
*/
export interface ConsentConfig {
// Pflichtfelder
/** API-Endpunkt fuer Consent-Backend */
apiEndpoint: string;
/** Site-ID */
siteId: string;
// Sprache
/** Sprache (ISO 639-1) */
language?: string;
/** Fallback-Sprache */
fallbackLanguage?: string;
// UI
/** UI-Konfiguration */
ui?: ConsentUIConfig;
// Verhalten
/** Consent-Verhaltens-Konfiguration */
consent?: ConsentBehaviorConfig;
// Kategorien
/** Aktive Kategorien */
categories?: ConsentCategory[];
// TCF
/** TCF 2.2 Konfiguration */
tcf?: TCFConfig;
// PWA
/** PWA-Konfiguration */
pwa?: PWAConfig;
// Callbacks
/** Callback bei Consent-Aenderung */
onConsentChange?: (consent: ConsentState) => void;
/** Callback wenn Banner angezeigt wird */
onBannerShow?: () => void;
/** Callback wenn Banner geschlossen wird */
onBannerHide?: () => void;
/** Callback bei Fehler */
onError?: (error: Error) => void;
// Debug
/** Debug-Modus aktivieren */
debug?: boolean;
}

View File

@@ -0,0 +1,65 @@
/**
* Consent SDK Types — Core: categories, state, input
*/
// =============================================================================
// Consent Categories
// =============================================================================
/**
* Standard-Consent-Kategorien nach IAB TCF 2.2
*/
export type ConsentCategory =
| 'essential' // Technisch notwendig (TTDSG § 25 Abs. 2)
| 'functional' // Personalisierung, Komfortfunktionen
| 'analytics' // Anonyme Nutzungsanalyse
| 'marketing' // Werbung, Retargeting
| 'social'; // Social Media Plugins
/**
* Consent-Status pro Kategorie
*/
export type ConsentCategories = Record<ConsentCategory, boolean>;
/**
* Consent-Status pro Vendor
*/
export type ConsentVendors = Record<string, boolean>;
// =============================================================================
// Consent State
// =============================================================================
/**
* Aktueller Consent-Zustand
*/
export interface ConsentState {
/** Consent pro Kategorie */
categories: ConsentCategories;
/** Consent pro Vendor (optional, für granulare Kontrolle) */
vendors: ConsentVendors;
/** Zeitstempel der letzten Aenderung */
timestamp: string;
/** SDK-Version bei Erstellung */
version: string;
/** Eindeutige Consent-ID vom Backend */
consentId?: string;
/** Ablaufdatum */
expiresAt?: string;
/** IAB TCF String (falls aktiviert) */
tcfString?: string;
}
/**
* Minimaler Consent-Input fuer setConsent()
*/
export type ConsentInput = Partial<ConsentCategories> | {
categories?: Partial<ConsentCategories>;
vendors?: ConsentVendors;
};

View File

@@ -0,0 +1,49 @@
/**
* Consent SDK Types — Event system
*/
import type { ConsentState } from './core';
// =============================================================================
// Events
// =============================================================================
/**
* Event-Typen
*/
export type ConsentEventType =
| 'init'
| 'change'
| 'accept_all'
| 'reject_all'
| 'save_selection'
| 'banner_show'
| 'banner_hide'
| 'settings_open'
| 'settings_close'
| 'vendor_enable'
| 'vendor_disable'
| 'error';
/**
* Event-Listener Callback
*/
export type ConsentEventCallback<T = unknown> = (data: T) => void;
/**
* Event-Daten fuer verschiedene Events
*/
export type ConsentEventData = {
init: ConsentState | null;
change: ConsentState;
accept_all: ConsentState;
reject_all: ConsentState;
save_selection: ConsentState;
banner_show: undefined;
banner_hide: undefined;
settings_open: undefined;
settings_close: undefined;
vendor_enable: string;
vendor_disable: string;
error: Error;
};

View File

@@ -1,438 +1,21 @@
/**
* Consent SDK Types
* Consent SDK Types — barrel re-export
*
* DSGVO/TTDSG-konforme Typdefinitionen für das Consent Management System.
* Domain files:
* core.ts — ConsentCategory, ConsentCategories, ConsentVendors, ConsentState, ConsentInput
* config.ts — BannerPosition, BannerLayout, BannerTheme, ConsentUIConfig,
* ConsentBehaviorConfig, TCFConfig, PWAConfig, ConsentConfig
* vendor.ts — CookieInfo, ConsentVendor
* api.ts — ConsentAPIResponse, SiteConfigResponse, CategoryConfig, LegalConfig
* events.ts — ConsentEventType, ConsentEventCallback, ConsentEventData
* storage.ts — ConsentStorageAdapter
* translations.ts — ConsentTranslations, SupportedLanguage
*/
// =============================================================================
// Consent Categories
// =============================================================================
/**
* Standard-Consent-Kategorien nach IAB TCF 2.2
*/
export type ConsentCategory =
| 'essential' // Technisch notwendig (TTDSG § 25 Abs. 2)
| 'functional' // Personalisierung, Komfortfunktionen
| 'analytics' // Anonyme Nutzungsanalyse
| 'marketing' // Werbung, Retargeting
| 'social'; // Social Media Plugins
/**
* Consent-Status pro Kategorie
*/
export type ConsentCategories = Record<ConsentCategory, boolean>;
/**
* Consent-Status pro Vendor
*/
export type ConsentVendors = Record<string, boolean>;
// =============================================================================
// Consent State
// =============================================================================
/**
* Aktueller Consent-Zustand
*/
export interface ConsentState {
/** Consent pro Kategorie */
categories: ConsentCategories;
/** Consent pro Vendor (optional, für granulare Kontrolle) */
vendors: ConsentVendors;
/** Zeitstempel der letzten Aenderung */
timestamp: string;
/** SDK-Version bei Erstellung */
version: string;
/** Eindeutige Consent-ID vom Backend */
consentId?: string;
/** Ablaufdatum */
expiresAt?: string;
/** IAB TCF String (falls aktiviert) */
tcfString?: string;
}
/**
* Minimaler Consent-Input fuer setConsent()
*/
export type ConsentInput = Partial<ConsentCategories> | {
categories?: Partial<ConsentCategories>;
vendors?: ConsentVendors;
};
// =============================================================================
// Configuration
// =============================================================================
/**
* UI-Position des Banners
*/
export type BannerPosition = 'bottom' | 'top' | 'center';
/**
* Banner-Layout
*/
export type BannerLayout = 'bar' | 'modal' | 'floating';
/**
* Farbschema
*/
export type BannerTheme = 'light' | 'dark' | 'auto';
/**
* UI-Konfiguration
*/
export interface ConsentUIConfig {
/** Position des Banners */
position?: BannerPosition;
/** Layout-Typ */
layout?: BannerLayout;
/** Farbschema */
theme?: BannerTheme;
/** Pfad zu Custom CSS */
customCss?: string;
/** z-index fuer Banner */
zIndex?: number;
/** Scroll blockieren bei Modal */
blockScrollOnModal?: boolean;
/** Custom Container-ID */
containerId?: string;
}
/**
* Consent-Verhaltens-Konfiguration
*/
export interface ConsentBehaviorConfig {
/** Muss Nutzer interagieren? */
required?: boolean;
/** "Alle ablehnen" Button sichtbar */
rejectAllVisible?: boolean;
/** "Alle akzeptieren" Button sichtbar */
acceptAllVisible?: boolean;
/** Einzelne Kategorien waehlbar */
granularControl?: boolean;
/** Einzelne Vendors waehlbar */
vendorControl?: boolean;
/** Auswahl speichern */
rememberChoice?: boolean;
/** Speicherdauer in Tagen */
rememberDays?: number;
/** Nur in EU anzeigen (Geo-Targeting) */
geoTargeting?: boolean;
/** Erneut nachfragen nach X Tagen */
recheckAfterDays?: number;
}
/**
* TCF 2.2 Konfiguration
*/
export interface TCFConfig {
/** TCF aktivieren */
enabled?: boolean;
/** CMP ID */
cmpId?: number;
/** CMP Version */
cmpVersion?: number;
}
/**
* PWA-spezifische Konfiguration
*/
export interface PWAConfig {
/** Offline-Unterstuetzung aktivieren */
offlineSupport?: boolean;
/** Bei Reconnect synchronisieren */
syncOnReconnect?: boolean;
/** Cache-Strategie */
cacheStrategy?: 'stale-while-revalidate' | 'network-first' | 'cache-first';
}
/**
* Haupt-Konfiguration fuer ConsentManager
*/
export interface ConsentConfig {
// Pflichtfelder
/** API-Endpunkt fuer Consent-Backend */
apiEndpoint: string;
/** Site-ID */
siteId: string;
// Sprache
/** Sprache (ISO 639-1) */
language?: string;
/** Fallback-Sprache */
fallbackLanguage?: string;
// UI
/** UI-Konfiguration */
ui?: ConsentUIConfig;
// Verhalten
/** Consent-Verhaltens-Konfiguration */
consent?: ConsentBehaviorConfig;
// Kategorien
/** Aktive Kategorien */
categories?: ConsentCategory[];
// TCF
/** TCF 2.2 Konfiguration */
tcf?: TCFConfig;
// PWA
/** PWA-Konfiguration */
pwa?: PWAConfig;
// Callbacks
/** Callback bei Consent-Aenderung */
onConsentChange?: (consent: ConsentState) => void;
/** Callback wenn Banner angezeigt wird */
onBannerShow?: () => void;
/** Callback wenn Banner geschlossen wird */
onBannerHide?: () => void;
/** Callback bei Fehler */
onError?: (error: Error) => void;
// Debug
/** Debug-Modus aktivieren */
debug?: boolean;
}
// =============================================================================
// Vendor Configuration
// =============================================================================
/**
* Cookie-Information
*/
export interface CookieInfo {
/** Cookie-Name */
name: string;
/** Cookie-Domain */
domain: string;
/** Ablaufzeit (z.B. "2 Jahre", "Session") */
expiration: string;
/** Speichertyp */
type: 'http' | 'localStorage' | 'sessionStorage' | 'indexedDB';
/** Beschreibung */
description: string;
}
/**
* Vendor-Definition
*/
export interface ConsentVendor {
/** Eindeutige Vendor-ID */
id: string;
/** Anzeigename */
name: string;
/** Kategorie */
category: ConsentCategory;
/** IAB TCF Purposes (falls relevant) */
purposes?: number[];
/** Legitimate Interests */
legitimateInterests?: number[];
/** Cookie-Liste */
cookies: CookieInfo[];
/** Link zur Datenschutzerklaerung */
privacyPolicyUrl: string;
/** Datenaufbewahrung */
dataRetention?: string;
/** Datentransfer (z.B. "USA (EU-US DPF)", "EU") */
dataTransfer?: string;
}
// =============================================================================
// API Types
// =============================================================================
/**
* API-Antwort fuer Consent-Erstellung
*/
export interface ConsentAPIResponse {
consentId: string;
timestamp: string;
expiresAt: string;
version: string;
}
/**
* API-Antwort fuer Site-Konfiguration
*/
export interface SiteConfigResponse {
siteId: string;
siteName: string;
categories: CategoryConfig[];
ui: ConsentUIConfig;
legal: LegalConfig;
tcf?: TCFConfig;
}
/**
* Kategorie-Konfiguration vom Server
*/
export interface CategoryConfig {
id: ConsentCategory;
name: Record<string, string>;
description: Record<string, string>;
required: boolean;
vendors: ConsentVendor[];
}
/**
* Rechtliche Konfiguration
*/
export interface LegalConfig {
privacyPolicyUrl: string;
imprintUrl: string;
dpo?: {
name: string;
email: string;
};
}
// =============================================================================
// Events
// =============================================================================
/**
* Event-Typen
*/
export type ConsentEventType =
| 'init'
| 'change'
| 'accept_all'
| 'reject_all'
| 'save_selection'
| 'banner_show'
| 'banner_hide'
| 'settings_open'
| 'settings_close'
| 'vendor_enable'
| 'vendor_disable'
| 'error';
/**
* Event-Listener Callback
*/
export type ConsentEventCallback<T = unknown> = (data: T) => void;
/**
* Event-Daten fuer verschiedene Events
*/
export type ConsentEventData = {
init: ConsentState | null;
change: ConsentState;
accept_all: ConsentState;
reject_all: ConsentState;
save_selection: ConsentState;
banner_show: undefined;
banner_hide: undefined;
settings_open: undefined;
settings_close: undefined;
vendor_enable: string;
vendor_disable: string;
error: Error;
};
// =============================================================================
// Storage
// =============================================================================
/**
* Storage-Adapter Interface
*/
export interface ConsentStorageAdapter {
/** Consent laden */
get(): ConsentState | null;
/** Consent speichern */
set(consent: ConsentState): void;
/** Consent loeschen */
clear(): void;
/** Pruefen ob Consent existiert */
exists(): boolean;
}
// =============================================================================
// Translations
// =============================================================================
/**
* Uebersetzungsstruktur
*/
export interface ConsentTranslations {
title: string;
description: string;
acceptAll: string;
rejectAll: string;
settings: string;
saveSelection: string;
close: string;
categories: {
[K in ConsentCategory]: {
name: string;
description: string;
};
};
footer: {
privacyPolicy: string;
imprint: string;
cookieDetails: string;
};
accessibility: {
closeButton: string;
categoryToggle: string;
requiredCategory: string;
};
}
/**
* Alle unterstuetzten Sprachen
*/
export type SupportedLanguage =
| 'de' | 'en' | 'fr' | 'es' | 'it' | 'nl' | 'pl' | 'pt'
| 'cs' | 'da' | 'el' | 'fi' | 'hu' | 'ro' | 'sk' | 'sl' | 'sv';
export * from './core';
export * from './config';
export * from './vendor';
export * from './api';
export * from './events';
export * from './storage';
export * from './translations';

View File

@@ -0,0 +1,26 @@
/**
* Consent SDK Types — Storage adapter interface
*/
import type { ConsentState } from './core';
// =============================================================================
// Storage
// =============================================================================
/**
* Storage-Adapter Interface
*/
export interface ConsentStorageAdapter {
/** Consent laden */
get(): ConsentState | null;
/** Consent speichern */
set(consent: ConsentState): void;
/** Consent loeschen */
clear(): void;
/** Pruefen ob Consent existiert */
exists(): boolean;
}

View File

@@ -0,0 +1,45 @@
/**
* Consent SDK Types — Translations and i18n
*/
import type { ConsentCategory } from './core';
// =============================================================================
// Translations
// =============================================================================
/**
* Uebersetzungsstruktur
*/
export interface ConsentTranslations {
title: string;
description: string;
acceptAll: string;
rejectAll: string;
settings: string;
saveSelection: string;
close: string;
categories: {
[K in ConsentCategory]: {
name: string;
description: string;
};
};
footer: {
privacyPolicy: string;
imprint: string;
cookieDetails: string;
};
accessibility: {
closeButton: string;
categoryToggle: string;
requiredCategory: string;
};
}
/**
* Alle unterstuetzten Sprachen
*/
export type SupportedLanguage =
| 'de' | 'en' | 'fr' | 'es' | 'it' | 'nl' | 'pl' | 'pt'
| 'cs' | 'da' | 'el' | 'fi' | 'hu' | 'ro' | 'sk' | 'sl' | 'sv';

View File

@@ -0,0 +1,61 @@
/**
* Consent SDK Types — Vendor definitions
*/
import type { ConsentCategory } from './core';
// =============================================================================
// Vendor Configuration
// =============================================================================
/**
* Cookie-Information
*/
export interface CookieInfo {
/** Cookie-Name */
name: string;
/** Cookie-Domain */
domain: string;
/** Ablaufzeit (z.B. "2 Jahre", "Session") */
expiration: string;
/** Speichertyp */
type: 'http' | 'localStorage' | 'sessionStorage' | 'indexedDB';
/** Beschreibung */
description: string;
}
/**
* Vendor-Definition
*/
export interface ConsentVendor {
/** Eindeutige Vendor-ID */
id: string;
/** Anzeigename */
name: string;
/** Kategorie */
category: ConsentCategory;
/** IAB TCF Purposes (falls relevant) */
purposes?: number[];
/** Legitimate Interests */
legitimateInterests?: number[];
/** Cookie-Liste */
cookies: CookieInfo[];
/** Link zur Datenschutzerklaerung */
privacyPolicyUrl: string;
/** Datenaufbewahrung */
dataRetention?: string;
/** Datentransfer (z.B. "USA (EU-US DPF)", "EU") */
dataTransfer?: string;
}