lynkow 3.0.2 → 3.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/errors.ts","../src/utils/fetch.ts","../src/utils/query.ts","../src/services/base.ts","../src/services/contents.ts","../src/services/categories.ts","../src/services/tags.ts","../src/services/pages.ts","../src/services/blocks.ts","../src/utils/spam.ts","../src/services/forms.ts","../src/services/reviews.ts","../src/services/site.ts","../src/services/legal.ts","../src/services/cookies.ts","../src/services/seo.ts","../src/services/paths.ts","../src/core/environment.ts","../src/services/analytics.ts","../src/services/consent.ts","../src/services/branding.ts","../src/core/cache.ts","../src/core/logger.ts","../src/utils/events.ts","../src/utils/locale.ts","../src/client.ts","../src/types/index.ts"],"names":["LynkowError","_LynkowError","message","code","status","details","cause","response","body","error","isLynkowError","getErrorCode","fetchWithError","url","options","errorData","errors","buildQueryString","params","searchParams","key","value","CACHE_TTL","BaseService","config","path","query","baseUrl","queryString","locale","queryWithLocale","fetchOptions","cacheKey","ttl","pattern","localOptions","CACHE_PREFIX","ContentsService","filters","slug","CategoriesService","TagsService","PagesService","BlocksService","generateSpamFields","sessionStartTime","FormsService","data","spamFields","ReviewsService","slugOrId","result","SiteService","LegalService","CookiesService","preferences","SeoService","PathsService","isBrowser","isServer","browserOnly","fn","fallback","browserOnlyAsync","TRACKER_SCRIPT_ID","AnalyticsService","resolve","reject","checkLoaded","script","event","STORAGE_KEY","DEFAULT_CATEGORIES","ConsentService","events","stored","categories","wrapper","newCategories","position","theme","layout","primaryColor","borderRadius","bannerStyles","floatingStyles","modalStyles","layoutStyles","positionStyle","isDark","bgColor","textColor","texts","currentCategories","categoriesHTML","cat","acceptBtn","rejectBtn","prefsBtn","_config","form","closeBtn","modal","e","formData","BADGE_ID","STYLES_ID","BADGE_STYLES","BrandingService","styleElement","badge","DEFAULT_TTL","STORAGE_PREFIX","memoryCache","createCache","defaultTtl","prefix","getKey","isExpired","entry","get","fullKey","set","remove","invalidate","keysToRemove","i","getOrSet","factory","cached","createLogger","args","level","createEventEmitter","listeners","on","listener","off","eventListeners","emit","once","wrappedListener","removeAllListeners","detectLocale","enabledLocales","defaultLocale","getStoredLocale","pathLocale","getLocaleFromPath","htmlLang","normalized","setStoredLocale","segments","firstSegment","isValidLocale","DEFAULT_BASE_URL","createClient","cache","logger","normalizedBaseUrl","internalConfig","state","services","updateServicesLocale","initialize","siteConfig","detected","createLynkowClient","isContentResolve","isCategoryResolve"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error handling utilities for Lynkow SDK\n */\n\n/**\n * Error codes for Lynkow SDK errors\n */\nexport type ErrorCode =\n | 'BAD_REQUEST'\n | 'VALIDATION_ERROR'\n | 'UNAUTHORIZED'\n | 'FORBIDDEN'\n | 'NOT_FOUND'\n | 'RATE_LIMITED'\n | 'TOO_MANY_REQUESTS'\n | 'TIMEOUT'\n | 'NETWORK_ERROR'\n | 'INTERNAL_ERROR'\n | 'SERVICE_UNAVAILABLE'\n | 'UNKNOWN'\n\n/**\n * API error detail from server response\n */\nexport interface ApiErrorDetail {\n message: string\n field?: string\n code?: string\n}\n\n/**\n * Custom error class for Lynkow SDK\n * Provides structured error information including HTTP status codes and error details\n */\nexport class LynkowError extends Error {\n /**\n * Error name (always 'LynkowError')\n */\n override readonly name = 'LynkowError'\n\n /**\n * Error code for categorization\n */\n readonly code: ErrorCode\n\n /**\n * HTTP status code (if applicable)\n */\n readonly status?: number\n\n /**\n * Additional error details from the API\n */\n readonly details?: ApiErrorDetail[]\n\n /**\n * Original error that caused this error (if any)\n */\n override readonly cause?: Error\n\n constructor(\n message: string,\n code: ErrorCode,\n status?: number,\n details?: ApiErrorDetail[],\n cause?: Error\n ) {\n super(message)\n this.code = code\n this.status = status\n this.details = details\n this.cause = cause\n\n // Maintain proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, LynkowError)\n }\n }\n\n /**\n * Create a LynkowError from an HTTP response\n */\n static async fromResponse(response: Response): Promise<LynkowError> {\n const status = response.status\n let message = `HTTP ${status}`\n let details: ApiErrorDetail[] | undefined\n\n try {\n const body = await response.json()\n if (body.errors && Array.isArray(body.errors)) {\n details = body.errors\n message = body.errors[0]?.message || message\n } else if (body.error) {\n message = body.error\n } else if (body.message) {\n message = body.message\n }\n } catch {\n // Response body is not JSON, use status text\n message = response.statusText || message\n }\n\n const code = LynkowError.statusToCode(status)\n return new LynkowError(message, code, status, details)\n }\n\n /**\n * Create a LynkowError from a network error\n */\n static fromNetworkError(error: Error): LynkowError {\n if (error.name === 'AbortError') {\n return new LynkowError('Request timed out', 'TIMEOUT', undefined, undefined, error)\n }\n\n if (error.name === 'TypeError') {\n return new LynkowError(\n 'Network error - please check your connection',\n 'NETWORK_ERROR',\n undefined,\n undefined,\n error\n )\n }\n\n return new LynkowError(error.message || 'Unknown error', 'UNKNOWN', undefined, undefined, error)\n }\n\n /**\n * Map HTTP status code to error code\n */\n private static statusToCode(status: number): ErrorCode {\n switch (status) {\n case 400:\n return 'VALIDATION_ERROR'\n case 401:\n return 'UNAUTHORIZED'\n case 403:\n return 'FORBIDDEN'\n case 404:\n return 'NOT_FOUND'\n case 429:\n return 'RATE_LIMITED'\n default:\n return 'UNKNOWN'\n }\n }\n\n /**\n * Convert error to a plain object for serialization\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n details: this.details,\n }\n }\n}\n\n/**\n * Type guard to check if an error is a LynkowError\n *\n * @example\n * ```typescript\n * try {\n * await lynkow.contents.getBySlug('not-found')\n * } catch (error) {\n * if (isLynkowError(error) && error.code === 'NOT_FOUND') {\n * // Handle 404\n * }\n * }\n * ```\n */\nexport function isLynkowError(error: unknown): error is LynkowError {\n return error instanceof LynkowError\n}\n","import { LynkowError, type ErrorCode, type ApiErrorDetail } from '../core/errors'\n\n/**\n * Converts an HTTP status code to an error code\n */\nfunction getErrorCode(status: number): ErrorCode {\n switch (status) {\n case 400:\n return 'BAD_REQUEST'\n case 401:\n return 'UNAUTHORIZED'\n case 403:\n return 'FORBIDDEN'\n case 404:\n return 'NOT_FOUND'\n case 422:\n return 'VALIDATION_ERROR'\n case 429:\n return 'TOO_MANY_REQUESTS'\n case 503:\n return 'SERVICE_UNAVAILABLE'\n default:\n return 'INTERNAL_ERROR'\n }\n}\n\n/**\n * Performs a fetch request with error handling\n */\nexport async function fetchWithError<T>(\n url: string,\n options: RequestInit\n): Promise<T> {\n let response: Response\n\n try {\n response = await fetch(url, options)\n } catch (error) {\n // Network error\n throw new LynkowError(\n 'Network error: Unable to reach the server',\n 'NETWORK_ERROR',\n 0,\n [{ message: error instanceof Error ? error.message : 'Unknown error' }]\n )\n }\n\n // OK response\n if (response.ok) {\n return response.json()\n }\n\n // HTTP error\n let errorData: Record<string, unknown> = {}\n try {\n errorData = await response.json()\n } catch {\n // No JSON body\n }\n\n const code = getErrorCode(response.status)\n const message =\n (errorData['error'] as string) ||\n (errorData['message'] as string) ||\n `HTTP error: ${response.status}`\n const errors: ApiErrorDetail[] =\n (errorData['errors'] as ApiErrorDetail[]) || [{ message }]\n\n throw new LynkowError(message, code, response.status, errors)\n}\n","/**\n * Builds a query string from an object\n */\nexport function buildQueryString(params: Record<string, unknown>): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null && value !== '') {\n searchParams.append(key, String(value))\n }\n }\n\n return searchParams.toString()\n}\n","import type { BaseRequestOptions } from '../types'\nimport type { Cache } from '../core/cache'\nimport { fetchWithError } from '../utils/fetch'\nimport { buildQueryString } from '../utils/query'\n\n/**\n * Normalized internal configuration\n */\nexport interface InternalConfig {\n siteId: string\n baseUrl: string\n locale?: string\n fetchOptions: RequestInit\n /** Optional cache manager for caching responses */\n cache?: Cache\n}\n\n/** Cache TTL constants (in milliseconds) */\nexport const CACHE_TTL = {\n /** Short TTL for frequently changing data (5 minutes) */\n SHORT: 5 * 60 * 1000,\n /** Medium TTL for moderately changing data (10 minutes) */\n MEDIUM: 10 * 60 * 1000,\n /** Long TTL for rarely changing data (30 minutes) */\n LONG: 30 * 60 * 1000,\n} as const\n\n/**\n * Base service that all specific services inherit from\n */\nexport abstract class BaseService {\n protected config: InternalConfig\n protected cache?: Cache\n\n constructor(config: InternalConfig) {\n this.config = config\n this.cache = config.cache\n }\n\n /**\n * Builds the full URL for an endpoint\n */\n protected buildEndpointUrl(\n path: string,\n query?: Record<string, unknown>\n ): string {\n const baseUrl = `${this.config.baseUrl}/public/${this.config.siteId}${path}`\n\n if (query && Object.keys(query).length > 0) {\n const queryString = buildQueryString(query)\n return `${baseUrl}?${queryString}`\n }\n\n return baseUrl\n }\n\n /**\n * Performs a GET request\n */\n protected async get<T>(\n path: string,\n query?: Record<string, unknown>,\n options?: BaseRequestOptions\n ): Promise<T> {\n // Add locale if configured\n const locale = options?.locale || this.config.locale\n const queryWithLocale = locale ? { ...query, locale } : query\n\n const url = this.buildEndpointUrl(path, queryWithLocale)\n const fetchOptions = this.mergeFetchOptions(options?.fetchOptions)\n\n return fetchWithError<T>(url, {\n method: 'GET',\n ...fetchOptions,\n })\n }\n\n /**\n * Performs a cached GET request\n * If cache is available and data exists, returns cached data\n * Otherwise fetches from API and caches the result\n *\n * @param cacheKey - Unique cache key\n * @param path - API endpoint path\n * @param query - Query parameters\n * @param options - Request options\n * @param ttl - Cache TTL in milliseconds (default: SHORT)\n */\n protected async getWithCache<T>(\n cacheKey: string,\n path: string,\n query?: Record<string, unknown>,\n options?: BaseRequestOptions,\n ttl: number = CACHE_TTL.SHORT\n ): Promise<T> {\n // If cache is available, use getOrSet\n if (this.cache) {\n return this.cache.getOrSet<T>(\n cacheKey,\n () => this.get<T>(path, query, options),\n ttl\n )\n }\n\n // No cache, just fetch\n return this.get<T>(path, query, options)\n }\n\n /**\n * Invalidates cache entries matching a pattern\n * @param pattern - Pattern to match cache keys\n */\n protected invalidateCache(pattern?: string): void {\n this.cache?.invalidate(pattern)\n }\n\n /**\n * Performs a POST request\n */\n protected async post<T>(\n path: string,\n body: Record<string, unknown>,\n options?: BaseRequestOptions\n ): Promise<T> {\n const url = this.buildEndpointUrl(path)\n const fetchOptions = this.mergeFetchOptions(options?.fetchOptions)\n\n return fetchWithError<T>(url, {\n method: 'POST',\n ...fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...fetchOptions.headers,\n },\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Performs a GET request that returns plain text (XML, txt)\n */\n protected async getText(\n path: string,\n options?: BaseRequestOptions\n ): Promise<string> {\n const url = this.buildEndpointUrl(path)\n const fetchOptions = this.mergeFetchOptions(options?.fetchOptions)\n\n const response = await fetch(url, {\n method: 'GET',\n ...fetchOptions,\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error: ${response.status}`)\n }\n\n return response.text()\n }\n\n /**\n * Merges local fetch options with global ones\n */\n private mergeFetchOptions(localOptions?: RequestInit): RequestInit {\n return {\n ...this.config.fetchOptions,\n ...localOptions,\n headers: {\n ...this.config.fetchOptions.headers,\n ...localOptions?.headers,\n },\n }\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n Content,\n ContentsFilters,\n ContentsListResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'contents_'\n\n/**\n * Service for contents (blog articles)\n */\nexport class ContentsService extends BaseService {\n /**\n * Retrieves a paginated list of published contents\n *\n * @param filters - Optional filters (pagination, category, tag, search)\n * @param options - Request options\n * @returns Paginated list of contents\n *\n * @example\n * ```typescript\n * const { data, meta } = await lynkow.contents.list({\n * page: 1,\n * perPage: 10,\n * category: 'tech'\n * })\n * ```\n */\n async list(\n filters?: ContentsFilters,\n options?: BaseRequestOptions\n ): Promise<ContentsListResponse> {\n const query: Record<string, unknown> = {}\n\n if (filters?.page) query['page'] = filters.page\n if (filters?.perPage) query['perPage'] = filters.perPage\n if (filters?.category) query['category'] = filters.category\n if (filters?.tag) query['tag'] = filters.tag\n if (filters?.search) query['search'] = filters.search\n if (filters?.sort) query['sort'] = filters.sort\n if (filters?.order) query['order'] = filters.order\n if (filters?.locale) query['locale'] = filters.locale\n\n const cacheKey = `${CACHE_PREFIX}list_${JSON.stringify(filters || {})}`\n return this.getWithCache<ContentsListResponse>(\n cacheKey,\n '/contents',\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a content by its slug\n *\n * @param slug - Content slug\n * @param options - Request options (locale)\n * @returns Full content\n *\n * @example\n * ```typescript\n * const content = await lynkow.contents.getBySlug('my-article')\n * ```\n */\n async getBySlug(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<Content> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${locale || 'default'}`\n return this.getWithCache<Content>(\n cacheKey,\n `/contents/slug/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Clear contents cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n CategoriesListResponse,\n CategoryTreeResponse,\n CategoryDetailResponse,\n CategoryOptions,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'categories_'\n\n/**\n * Service for categories\n */\nexport class CategoriesService extends BaseService {\n /**\n * Retrieves the list of categories\n *\n * @param options - Request options (locale)\n * @returns List of categories with counters\n *\n * @example\n * ```typescript\n * const { data, blogUrlMode } = await lynkow.categories.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<CategoriesListResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}`\n return this.getWithCache<CategoriesListResponse>(\n cacheKey,\n '/categories',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves the category tree\n *\n * @param options - Request options (locale)\n * @returns Complete tree structure\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.categories.tree()\n * // data[0].children contient les sous-categories\n * ```\n */\n async tree(options?: BaseRequestOptions): Promise<CategoryTreeResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}tree_${locale || 'default'}`\n return this.getWithCache<CategoryTreeResponse>(\n cacheKey,\n '/categories/tree',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a category with its paginated contents\n *\n * @param slug - Category slug\n * @param options - Options (locale, pagination)\n * @returns Category with contents\n *\n * @example\n * ```typescript\n * const { category, contents } = await lynkow.categories.getBySlug('tech', {\n * page: 1,\n * perPage: 10\n * })\n * ```\n */\n async getBySlug(\n slug: string,\n options?: CategoryOptions & BaseRequestOptions\n ): Promise<CategoryDetailResponse> {\n const query: Record<string, unknown> = {}\n\n if (options?.page) query['page'] = options.page\n if (options?.perPage) query['limit'] = options.perPage\n\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${JSON.stringify(options || {})}`\n return this.getWithCache<CategoryDetailResponse>(\n cacheKey,\n `/categories/${encodeURIComponent(slug)}`,\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Clear categories cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type { TagsListResponse, BaseRequestOptions } from '../types'\n\nconst CACHE_PREFIX = 'tags_'\n\n/**\n * Service for tags\n */\nexport class TagsService extends BaseService {\n /**\n * Retrieves the list of tags\n *\n * @param options - Request options (locale)\n * @returns List of tags\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.tags.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<TagsListResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}`\n return this.getWithCache<TagsListResponse>(\n cacheKey,\n '/tags',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Clear tags cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type { Page, PagesListResponse, BaseRequestOptions } from '../types'\n\nconst CACHE_PREFIX = 'pages_'\n\n/**\n * Options for listing pages\n */\nexport interface PagesListOptions extends BaseRequestOptions {\n /** Filter pages by tag (e.g., 'legal' for legal documents) */\n tag?: string\n}\n\n/**\n * Service for pages (Site Blocks of type \"page\")\n */\nexport class PagesService extends BaseService {\n /**\n * Retrieves the list of published pages\n *\n * @param options - Request options (locale, tag filter)\n * @returns List of pages\n *\n * @example\n * ```typescript\n * // List all pages\n * const { data } = await lynkow.pages.list()\n *\n * // List legal documents\n * const { data } = await lynkow.pages.list({ tag: 'legal' })\n * ```\n */\n async list(options?: PagesListOptions): Promise<PagesListResponse> {\n const locale = options?.locale || this.config.locale\n const query: Record<string, unknown> = {}\n if (options?.tag) query['tag'] = options.tag\n\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}_${options?.tag || 'all'}`\n return this.getWithCache<PagesListResponse>(\n cacheKey,\n '/pages',\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a page by its slug\n *\n * @param slug - Page slug\n * @param options - Request options (locale)\n * @returns Full page with resolved data\n *\n * @example\n * ```typescript\n * const page = await lynkow.pages.getBySlug('about')\n * ```\n */\n async getBySlug(slug: string, options?: BaseRequestOptions): Promise<Page> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${locale || 'default'}`\n\n const response = await this.getWithCache<{ data: Page }>(\n cacheKey,\n `/pages/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Retrieves a page by its path\n *\n * @param path - Page path (e.g.: /services/consulting)\n * @param options - Request options (locale)\n * @returns Full page with resolved data\n *\n * @example\n * ```typescript\n * const page = await lynkow.pages.getByPath('/services/consulting')\n * ```\n */\n async getByPath(path: string, options?: BaseRequestOptions): Promise<Page> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}path_${path}_${locale || 'default'}`\n\n const response = await this.getWithCache<{ data: Page }>(\n cacheKey,\n '/page-by-path',\n { path },\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Retrieves JSON-LD data for a page\n *\n * @param slug - Page slug\n * @param options - Request options (locale)\n * @returns JSON-LD data (Schema.org)\n *\n * @example\n * ```typescript\n * const jsonLd = await lynkow.pages.getJsonLd('about')\n * // Utiliser dans <script type=\"application/ld+json\">\n * ```\n */\n async getJsonLd(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<Record<string, unknown>> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}jsonld_${slug}_${locale || 'default'}`\n\n const response = await this.getWithCache<{ data: Record<string, unknown> }>(\n cacheKey,\n `/pages/${encodeURIComponent(slug)}/json-ld`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Clear pages cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n SiteConfigResponse,\n GlobalBlockResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'globals_'\n\n/**\n * Service for global blocks (header, footer, etc.)\n * Also aliased as `globals` in the client\n */\nexport class BlocksService extends BaseService {\n /**\n * Retrieves the site configuration with all global blocks\n *\n * @param options - Request options (locale)\n * @returns Configuration and global blocks\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.globals.siteConfig()\n * const header = data.globals['header']\n * const footer = data.globals['footer']\n * ```\n */\n async siteConfig(options?: BaseRequestOptions): Promise<SiteConfigResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}siteconfig_${locale || 'default'}`\n return this.getWithCache<SiteConfigResponse>(\n cacheKey,\n '/site-config',\n undefined,\n options,\n CACHE_TTL.MEDIUM\n )\n }\n\n /**\n * Retrieves a specific global block by its slug\n *\n * @param slug - Block slug (e.g.: 'header', 'footer')\n * @param options - Request options (locale)\n * @returns Global block with resolved data\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.globals.getBySlug('header')\n * // data.data contient les donnees du bloc\n * ```\n */\n async getBySlug(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<GlobalBlockResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}${slug}_${locale || 'default'}`\n return this.getWithCache<GlobalBlockResponse>(\n cacheKey,\n `/global/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.MEDIUM\n )\n }\n\n /**\n * @deprecated Use `getBySlug()` instead\n */\n async global(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<GlobalBlockResponse> {\n return this.getBySlug(slug, options)\n }\n\n /**\n * Clear globals cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","/**\n * Anti-spam fields for public submissions\n */\nexport interface SpamFields {\n /** Honeypot field (must be empty) */\n _hp: string\n\n /** Session start timestamp */\n _ts: number\n}\n\n/**\n * Generates anti-spam fields for a submission\n *\n * @param sessionStartTime - Client creation timestamp\n * @returns Anti-spam fields\n */\nexport function generateSpamFields(sessionStartTime: number): SpamFields {\n return {\n _hp: '', // Honeypot - always empty\n _ts: sessionStartTime, // Session timestamp\n }\n}\n","import { BaseService, CACHE_TTL, type InternalConfig } from './base'\nimport type {\n Form,\n FormSubmitData,\n FormSubmitResponse,\n SubmitOptions,\n BaseRequestOptions,\n} from '../types'\nimport { generateSpamFields } from '../utils/spam'\n\nconst CACHE_PREFIX = 'forms_'\n\n/**\n * Service for forms\n */\nexport class FormsService extends BaseService {\n /**\n * Client creation timestamp (for anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Retrieves a form by its slug\n *\n * @param slug - Form slug\n * @returns Form schema\n *\n * @example\n * ```typescript\n * const form = await lynkow.forms.getBySlug('contact')\n * // Use form.schema to generate the form\n * ```\n */\n async getBySlug(slug: string): Promise<Form> {\n const cacheKey = `${CACHE_PREFIX}${slug}`\n const response = await this.getWithCache<{ data: Form }>(\n cacheKey,\n `/forms/${encodeURIComponent(slug)}`,\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n return response.data\n }\n\n /**\n * Submits a form\n *\n * Anti-spam fields (_hp, _ts) are added automatically.\n *\n * @param slug - Form slug\n * @param data - Form data\n * @param options - Options (reCAPTCHA token if enabled)\n * @returns Submission response\n *\n * @example\n * ```typescript\n * const result = await lynkow.forms.submit('contact', {\n * name: 'John Doe',\n * email: 'john@example.com',\n * message: 'Hello!'\n * })\n * ```\n */\n async submit(\n slug: string,\n data: FormSubmitData,\n options?: SubmitOptions & BaseRequestOptions\n ): Promise<FormSubmitResponse> {\n // Add anti-spam fields\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Build the body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Add reCAPTCHA token if provided\n if (options?.recaptchaToken) {\n body['_recaptcha_token'] = options.recaptchaToken\n }\n\n return this.post<FormSubmitResponse>(\n `/forms/${encodeURIComponent(slug)}/submit`,\n body,\n options\n )\n }\n\n /**\n * Clear forms cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL, type InternalConfig } from './base'\nimport type {\n Review,\n ReviewSettings,\n ReviewSubmitData,\n ReviewSubmitResponse,\n ReviewsListResponse,\n ReviewsFilters,\n SubmitOptions,\n BaseRequestOptions,\n} from '../types'\nimport { generateSpamFields } from '../utils/spam'\n\nconst CACHE_PREFIX = 'reviews_'\n\n/**\n * Service for customer reviews\n */\nexport class ReviewsService extends BaseService {\n /**\n * Client creation timestamp (for anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Retrieves the list of approved reviews\n *\n * @param filters - Filters (pagination, rating)\n * @param options - Request options\n * @returns Paginated list of reviews\n *\n * @example\n * ```typescript\n * const { data, meta } = await lynkow.reviews.list({\n * minRating: 4,\n * perPage: 10\n * })\n * ```\n */\n async list(\n filters?: ReviewsFilters,\n options?: BaseRequestOptions\n ): Promise<ReviewsListResponse> {\n const query: Record<string, unknown> = {}\n\n if (filters?.page) query['page'] = filters.page\n if (filters?.perPage) query['perPage'] = filters.perPage\n if (filters?.minRating) query['minRating'] = filters.minRating\n if (filters?.maxRating) query['maxRating'] = filters.maxRating\n if (filters?.sort) query['sort'] = filters.sort\n if (filters?.order) query['order'] = filters.order\n\n const cacheKey = `${CACHE_PREFIX}list_${JSON.stringify(filters || {})}`\n return this.getWithCache<ReviewsListResponse>(\n cacheKey,\n '/reviews',\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a review by its slug or ID\n *\n * @param slugOrId - Review slug or ID\n * @returns Full review\n *\n * @example\n * ```typescript\n * const review = await lynkow.reviews.getBySlug('excellent-service')\n * ```\n */\n async getBySlug(slugOrId: string): Promise<Review> {\n const cacheKey = `${CACHE_PREFIX}slug_${slugOrId}`\n const response = await this.getWithCache<{ data: Review }>(\n cacheKey,\n `/reviews/${encodeURIComponent(slugOrId)}`,\n undefined,\n undefined,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Retrieves public review settings\n *\n * @returns Settings (required fields, rating scale, etc.)\n *\n * @example\n * ```typescript\n * const settings = await lynkow.reviews.settings()\n * if (settings.fields.email.required) {\n * // Afficher le champ email comme requis\n * }\n * ```\n */\n async settings(): Promise<ReviewSettings> {\n const cacheKey = `${CACHE_PREFIX}settings`\n return this.getWithCache<ReviewSettings>(\n cacheKey,\n '/reviews/settings',\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n }\n\n /**\n * Submits a new review\n *\n * Anti-spam fields (_hp, _ts) are added automatically.\n *\n * @param data - Review data\n * @param options - Options (reCAPTCHA token if enabled)\n * @returns Submission response\n *\n * @example\n * ```typescript\n * const result = await lynkow.reviews.submit({\n * authorName: 'Alice',\n * rating: 5,\n * content: 'Excellent service !'\n * })\n * ```\n */\n async submit(\n data: ReviewSubmitData,\n options?: SubmitOptions & BaseRequestOptions\n ): Promise<ReviewSubmitResponse> {\n // Add anti-spam fields\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Build the body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Add reCAPTCHA token if provided\n if (options?.recaptchaToken) {\n body['_recaptcha_token'] = options.recaptchaToken\n }\n\n const result = await this.post<ReviewSubmitResponse>('/reviews', body, options)\n\n // Invalidate cache after submission\n this.invalidateCache(CACHE_PREFIX)\n\n return result\n }\n\n /**\n * Clear reviews cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type { SiteConfig } from '../types'\n\nconst CACHE_PREFIX = 'site_'\n\n/**\n * Service for site configuration\n */\nexport class SiteService extends BaseService {\n /**\n * Retrieves the public site configuration\n *\n * @returns Site configuration\n *\n * @example\n * ```typescript\n * const config = await lynkow.site.getConfig()\n * console.log(config.enabledLocales) // ['fr', 'en']\n * ```\n */\n async getConfig(): Promise<SiteConfig> {\n const cacheKey = `${CACHE_PREFIX}config`\n const response = await this.getWithCache<{ data: SiteConfig }>(\n cacheKey,\n '/site',\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n return response.data\n }\n\n /**\n * Clear site configuration cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n LegalDocument,\n LegalListResponse,\n LegalDocumentResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'legal_'\n\n/**\n * Service for accessing legal documents (pages tagged with 'legal')\n *\n * @deprecated Use `pages.list({ tag: 'legal' })` and `pages.getBySlug(slug)` instead.\n * This service will be removed in the next major version.\n *\n * @remarks\n * Legal documents are now regular pages with the 'legal' tag.\n * This service provides convenience methods to access them.\n *\n * @example\n * ```typescript\n * // Deprecated:\n * const docs = await sdk.legal.list()\n * const privacy = await sdk.legal.getBySlug('privacy-policy')\n *\n * // Recommended:\n * const docs = await sdk.pages.list({ tag: 'legal' })\n * const privacy = await sdk.pages.getBySlug('privacy-policy')\n * ```\n */\nexport class LegalService extends BaseService {\n /**\n * List all legal pages\n *\n * @deprecated Use `pages.list({ tag: 'legal' })` instead\n *\n * Returns all published pages that have the 'legal' tag.\n *\n * @param options - Request options (locale)\n * @returns Array of legal documents\n */\n async list(options?: BaseRequestOptions): Promise<LegalDocument[]> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}`\n const response = await this.getWithCache<LegalListResponse>(\n cacheKey,\n '/pages',\n { tag: 'legal' },\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Get a specific legal page by slug\n *\n * @deprecated Use `pages.getBySlug(slug)` instead\n *\n * @param slug - The page slug (e.g., 'privacy-policy', 'terms-of-service')\n * @param options - Request options (locale)\n * @returns The legal document\n * @throws {LynkowError} If the document doesn't exist (404)\n */\n async getBySlug(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<LegalDocument> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${locale || 'default'}`\n const response = await this.getWithCache<LegalDocumentResponse>(\n cacheKey,\n `/pages/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Clear legal documents cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n CookieConfig,\n CookiePreferences,\n ConsentLogResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'cookies_'\n\n/**\n * Service for cookie consent\n *\n * @remarks\n * This service will be expanded into the `consent` module in v3\n * with banner UI and preferences modal support.\n */\nexport class CookiesService extends BaseService {\n /**\n * Retrieves the cookie banner configuration\n *\n * @returns Banner configuration\n *\n * @example\n * ```typescript\n * const config = await lynkow.cookies.getConfig()\n * if (config.enabled) {\n * // Afficher le bandeau\n * }\n * ```\n */\n async getConfig(): Promise<CookieConfig> {\n const cacheKey = `${CACHE_PREFIX}config`\n const response = await this.getWithCache<{ data: CookieConfig }>(\n cacheKey,\n '/cookie-consent/config',\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n return response.data\n }\n\n /**\n * Records user consent\n *\n * @param preferences - Preferences by category\n * @returns Confirmation with consent ID\n *\n * @example\n * ```typescript\n * await lynkow.cookies.logConsent({\n * necessary: true,\n * analytics: true,\n * marketing: false\n * })\n * ```\n */\n async logConsent(\n preferences: CookiePreferences,\n options?: BaseRequestOptions\n ): Promise<ConsentLogResponse> {\n return this.post<ConsentLogResponse>(\n '/cookie-consent/log',\n { preferences },\n options\n )\n }\n\n /**\n * Clear cookies configuration cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService } from './base'\nimport type { BaseRequestOptions } from '../types'\n\n/**\n * Service for SEO files\n */\nexport class SeoService extends BaseService {\n /**\n * Retrieves the XML sitemap\n *\n * @returns Sitemap XML content\n *\n * @example\n * ```typescript\n * // In a Next.js API route\n * export async function GET() {\n * const xml = await lynkow.seo.sitemap()\n * return new Response(xml, {\n * headers: { 'Content-Type': 'application/xml' }\n * })\n * }\n * ```\n */\n async sitemap(options?: BaseRequestOptions): Promise<string> {\n return this.getText('/sitemap.xml', options)\n }\n\n /**\n * Retrieves the robots.txt file\n *\n * @returns robots.txt content\n *\n * @example\n * ```typescript\n * // In a Next.js API route\n * export async function GET() {\n * const txt = await lynkow.seo.robots()\n * return new Response(txt, {\n * headers: { 'Content-Type': 'text/plain' }\n * })\n * }\n * ```\n */\n async robots(options?: BaseRequestOptions): Promise<string> {\n return this.getText('/robots.txt', options)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n PathsListResponse,\n ResolveResponse,\n Redirect,\n BaseRequestOptions,\n} from '../types'\nimport { LynkowError } from '../core/errors'\n\nconst CACHE_PREFIX = 'paths_'\n\n/**\n * Service for paths (SSG, resolution)\n */\nexport class PathsService extends BaseService {\n /**\n * Retrieves all paths for static generation\n *\n * @param options - Request options (locale)\n * @returns List of paths\n *\n * @example\n * ```typescript\n * // In Next.js generateStaticParams()\n * export async function generateStaticParams() {\n * const { paths } = await lynkow.paths.list()\n * return paths.map(p => ({\n * slug: p.segments\n * }))\n * }\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<PathsListResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'all'}`\n return this.getWithCache<PathsListResponse>(\n cacheKey,\n '/paths',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Resolves a path to its content or category\n *\n * @param path - Path to resolve\n * @param options - Request options\n * @returns Corresponding content or category\n *\n * @example\n * ```typescript\n * const result = await lynkow.paths.resolve('/blog/tech/my-article')\n *\n * if (result.type === 'content') {\n * // Afficher l'article\n * } else {\n * // Afficher la categorie avec ses articles\n * }\n * ```\n */\n async resolve(\n path: string,\n options?: BaseRequestOptions\n ): Promise<ResolveResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}resolve_${path}_${locale || 'default'}`\n return this.getWithCache<ResolveResponse>(\n cacheKey,\n '/resolve',\n { path },\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Checks if a path has a configured redirect\n *\n * @param path - Path to check\n * @returns Redirect or null\n *\n * @example\n * ```typescript\n * // In a Next.js middleware\n * const redirect = await lynkow.paths.matchRedirect(pathname)\n * if (redirect) {\n * return NextResponse.redirect(redirect.target, redirect.statusCode)\n * }\n * ```\n */\n async matchRedirect(\n path: string,\n options?: BaseRequestOptions\n ): Promise<Redirect | null> {\n try {\n const response = await this.get<{ data: Redirect }>(\n '/redirects/match',\n { path },\n options\n )\n return response.data\n } catch (error: unknown) {\n // 404 = no redirect found\n if (error instanceof LynkowError && error.status === 404) {\n return null\n }\n throw error\n }\n }\n\n /**\n * Clear paths cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","/**\n * Environment detection utilities\n * Determines if code is running in browser or server environment\n */\n\n/**\n * Check if running in a browser environment\n */\nexport const isBrowser: boolean =\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.document.createElement !== 'undefined'\n\n/**\n * Check if running in a server environment (Node.js, Deno, etc.)\n */\nexport const isServer: boolean = !isBrowser\n\n/**\n * Execute a function only in browser environment\n * Returns the fallback value in server environment\n *\n * @param fn - Function to execute in browser\n * @param fallback - Value to return in server environment\n * @returns Result of fn() in browser, fallback in server\n *\n * @example\n * ```typescript\n * const visitorId = browserOnly(\n * () => localStorage.getItem('visitor_id'),\n * null\n * )\n * ```\n */\nexport function browserOnly<T>(fn: () => T, fallback: T): T {\n if (isBrowser) {\n return fn()\n }\n return fallback\n}\n\n/**\n * Execute an async function only in browser environment\n * Returns the fallback value in server environment\n *\n * @param fn - Async function to execute in browser\n * @param fallback - Value to return in server environment\n * @returns Promise resolving to result of fn() in browser, fallback in server\n *\n * @example\n * ```typescript\n * const config = await browserOnlyAsync(\n * () => fetchConfig(),\n * defaultConfig\n * )\n * ```\n */\nexport async function browserOnlyAsync<T>(fn: () => Promise<T>, fallback: T): Promise<T> {\n if (isBrowser) {\n return fn()\n }\n return fallback\n}\n\n/**\n * No-op function for browser-only features in server environment\n * Useful for methods that should silently do nothing on server\n */\nexport function noop(): void {\n // Intentionally empty\n}\n\n/**\n * Create a no-op version of a function for server environment\n *\n * @param fn - Function to wrap\n * @returns Original function in browser, no-op in server\n */\nexport function browserOnlyFn<T extends (...args: any[]) => any>(fn: T): T {\n if (isBrowser) {\n return fn\n }\n return noop as T\n}\n","/**\n * Analytics module for Lynkow SDK\n *\n * Browser-only module that loads and wraps the Lynkow tracker.js\n * All methods are no-op on server.\n */\n\nimport { isBrowser } from '../core/environment'\nimport type { InternalConfig } from './base'\n\n/**\n * Data for tracking pageviews\n */\nexport interface PageviewData {\n /** Page path (default: window.location.pathname) */\n path?: string\n /** Page title (default: document.title) */\n title?: string\n /** Referrer URL */\n referrer?: string\n}\n\n/**\n * Data for tracking custom events\n */\nexport interface EventData {\n /** Event type */\n type: string\n /** Additional event data */\n [key: string]: unknown\n}\n\n/**\n * Funnel step data\n */\nexport interface FunnelStepData {\n /** Funnel identifier */\n funnelId: string\n /** Step number (1-based) */\n stepNumber: number\n /** Step name */\n stepName: string\n /** Funnel name (optional) */\n funnelName?: string\n}\n\n/**\n * LynkowAnalytics global interface (from tracker.js)\n */\ninterface LynkowAnalyticsGlobal {\n init: (siteId: string, options?: { endpoint?: string }) => void\n track: (event: Record<string, unknown>) => void\n trackFunnel: (funnelId: string, stepNumber: number, stepName: string, funnelName?: string) => void\n}\n\ndeclare global {\n interface Window {\n LynkowAnalytics?: LynkowAnalyticsGlobal\n }\n}\n\nconst TRACKER_SCRIPT_ID = 'lynkow-tracker'\n\n/**\n * Analytics service that loads and wraps the Lynkow tracker.js\n *\n * Browser-only. All methods are no-op on server.\n */\nexport class AnalyticsService {\n private config: InternalConfig\n private enabled = true\n private initialized = false\n private loading = false\n private loadPromise: Promise<void> | null = null\n\n constructor(config: InternalConfig) {\n this.config = config\n }\n\n /**\n * Get the tracker script URL\n */\n private getTrackerUrl(): string {\n return `${this.config.baseUrl}/analytics/tracker.js`\n }\n\n /**\n * Load the tracker.js script\n */\n private loadTracker(): Promise<void> {\n if (!isBrowser) return Promise.resolve()\n\n // Already loaded\n if (window.LynkowAnalytics) {\n return Promise.resolve()\n }\n\n // Already loading\n if (this.loadPromise) {\n return this.loadPromise\n }\n\n this.loading = true\n this.loadPromise = new Promise((resolve, reject) => {\n // Check if script tag already exists\n if (document.getElementById(TRACKER_SCRIPT_ID)) {\n // Wait for it to load\n const checkLoaded = setInterval(() => {\n if (window.LynkowAnalytics) {\n clearInterval(checkLoaded)\n this.loading = false\n resolve()\n }\n }, 50)\n\n // Timeout after 10 seconds\n setTimeout(() => {\n clearInterval(checkLoaded)\n this.loading = false\n reject(new Error('Tracker script load timeout'))\n }, 10000)\n\n return\n }\n\n // Create and inject script\n const script = document.createElement('script')\n script.id = TRACKER_SCRIPT_ID\n script.src = this.getTrackerUrl()\n script.async = true\n script.setAttribute('data-site-id', this.config.siteId)\n if (this.config.baseUrl) {\n script.setAttribute('data-api-url', this.config.baseUrl)\n }\n\n script.onload = () => {\n this.loading = false\n // Wait a tick for the tracker to auto-initialize\n setTimeout(() => {\n if (window.LynkowAnalytics) {\n resolve()\n } else {\n reject(new Error('Tracker script loaded but LynkowAnalytics not found'))\n }\n }, 0)\n }\n\n script.onerror = () => {\n this.loading = false\n reject(new Error('Failed to load tracker script'))\n }\n\n document.head.appendChild(script)\n })\n\n return this.loadPromise\n }\n\n /**\n * Initialize analytics tracking\n * Loads the tracker.js script and initializes it\n */\n async init(): Promise<void> {\n if (!isBrowser || this.initialized) return\n\n try {\n await this.loadTracker()\n\n // The tracker auto-initializes via data-site-id attribute\n // But we can also manually init if needed\n if (window.LynkowAnalytics && !this.initialized) {\n // Tracker already auto-initialized via data-site-id\n this.initialized = true\n }\n } catch (error) {\n console.error('[Lynkow] Failed to initialize analytics:', error)\n }\n }\n\n /**\n * Track a custom event\n *\n * @example\n * ```typescript\n * lynkow.analytics.trackEvent({\n * type: 'purchase',\n * productId: 'abc123',\n * amount: 99.99\n * })\n * ```\n */\n async trackEvent(event: EventData): Promise<void> {\n if (!isBrowser || !this.enabled) return\n\n await this.init()\n\n if (window.LynkowAnalytics) {\n window.LynkowAnalytics.track(event)\n }\n }\n\n /**\n * Track a funnel step\n *\n * @example\n * ```typescript\n * lynkow.analytics.trackFunnelStep({\n * funnelId: 'checkout',\n * stepNumber: 2,\n * stepName: 'payment',\n * funnelName: 'Checkout Flow'\n * })\n * ```\n */\n async trackFunnelStep(data: FunnelStepData): Promise<void> {\n if (!isBrowser || !this.enabled) return\n\n await this.init()\n\n if (window.LynkowAnalytics) {\n window.LynkowAnalytics.trackFunnel(\n data.funnelId,\n data.stepNumber,\n data.stepName,\n data.funnelName\n )\n }\n }\n\n /**\n * Track a pageview manually\n * Note: The tracker automatically tracks pageviews, this is for SPA navigation\n *\n * @example\n * ```typescript\n * // After SPA navigation\n * lynkow.analytics.trackPageview({ path: '/new-page' })\n * ```\n */\n async trackPageview(data?: PageviewData): Promise<void> {\n if (!isBrowser || !this.enabled) return\n\n await this.init()\n\n if (window.LynkowAnalytics) {\n window.LynkowAnalytics.track({\n type: 'pageview',\n path: data?.path || window.location.pathname,\n title: data?.title || document.title,\n referrer: data?.referrer || document.referrer,\n })\n }\n }\n\n /**\n * Enable analytics tracking\n */\n enable(): void {\n this.enabled = true\n }\n\n /**\n * Disable analytics tracking\n */\n disable(): void {\n this.enabled = false\n }\n\n /**\n * Check if analytics is enabled\n */\n isEnabled(): boolean {\n return this.enabled\n }\n\n /**\n * Check if tracker is loaded and initialized\n */\n isInitialized(): boolean {\n return this.initialized && !!window.LynkowAnalytics\n }\n\n /**\n * Get the underlying LynkowAnalytics global object\n * For advanced usage when you need direct access to the tracker\n */\n getTracker(): LynkowAnalyticsGlobal | undefined {\n if (!isBrowser) return undefined\n return window.LynkowAnalytics\n }\n\n /**\n * Clean up resources (removes the tracker script)\n */\n destroy(): void {\n if (!isBrowser) return\n\n const script = document.getElementById(TRACKER_SCRIPT_ID)\n script?.remove()\n\n this.initialized = false\n this.loadPromise = null\n }\n}\n","/**\n * Consent module for Lynkow SDK\n *\n * Hybrid module: API everywhere + UI browser-only\n */\n\nimport { isBrowser } from '../core/environment'\nimport type { InternalConfig } from './base'\nimport type { CookieConfig, CookiePreferences } from '../types'\nimport type { EventEmitter } from '../utils/events'\n\n// Use same key as tracker.js for consistency\nconst STORAGE_KEY = '_lkw_consent'\n\n/**\n * Consent categories\n */\nexport interface ConsentCategories {\n /** Always true, not modifiable */\n necessary: boolean\n /** Analytics cookies */\n analytics: boolean\n /** Marketing cookies */\n marketing: boolean\n /** Preference cookies */\n preferences: boolean\n}\n\n/**\n * Default consent categories (no consent given)\n */\nconst DEFAULT_CATEGORIES: ConsentCategories = {\n necessary: true,\n analytics: false,\n marketing: false,\n preferences: false,\n}\n\n/**\n * Consent service for cookie consent management\n *\n * Provides:\n * - API methods that work everywhere (getConfig, logConsent)\n * - UI methods that work only in browser (show, hide, acceptAll, etc.)\n */\nexport class ConsentService {\n private config: InternalConfig\n private events: EventEmitter\n private bannerElement: HTMLElement | null = null\n private preferencesElement: HTMLElement | null = null\n private configCache: CookieConfig | null = null\n\n constructor(config: InternalConfig, events: EventEmitter) {\n this.config = config\n this.events = events\n }\n\n // === API Methods (work everywhere) ===\n\n /**\n * Get cookie consent configuration from API\n */\n async getConfig(): Promise<CookieConfig> {\n if (this.configCache) return this.configCache\n\n const url = `${this.config.baseUrl}/public/${this.config.siteId}/cookie-consent/config`\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n ...this.config.fetchOptions,\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch consent config: ${response.status}`)\n }\n\n const data = await response.json()\n this.configCache = data.data as CookieConfig\n return this.configCache\n }\n\n /**\n * Log consent to server\n */\n async logConsent(preferences: CookiePreferences): Promise<void> {\n const url = `${this.config.baseUrl}/public/${this.config.siteId}/cookie-consent/log`\n\n await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ preferences }),\n ...this.config.fetchOptions,\n }).catch(() => {\n // Silently ignore errors\n })\n }\n\n // === Storage Methods ===\n // Format: { choices: { necessary, analytics, marketing, preferences } }\n // This format is compatible with tracker.js\n\n private getStoredConsent(): ConsentCategories | null {\n if (!isBrowser) return null\n\n try {\n const stored = localStorage.getItem(STORAGE_KEY)\n if (stored) {\n const data = JSON.parse(stored)\n // Handle both old format and new { choices: {...} } format\n if (data.choices) {\n return data.choices as ConsentCategories\n }\n return data as ConsentCategories\n }\n } catch {\n // localStorage unavailable\n }\n\n return null\n }\n\n private saveConsent(categories: ConsentCategories): void {\n if (!isBrowser) return\n\n try {\n // Save in { choices: {...} } format for tracker.js compatibility\n localStorage.setItem(STORAGE_KEY, JSON.stringify({ choices: categories }))\n } catch {\n // localStorage unavailable\n }\n\n this.events.emit('consent-changed', categories as unknown as Record<string, boolean>)\n\n // Dispatch custom event for tracker.js\n document.dispatchEvent(new CustomEvent('lynkow:consent:update', {\n detail: categories\n }))\n }\n\n // === UI Methods (browser-only) ===\n\n /**\n * Show the consent banner\n */\n show(): void {\n if (!isBrowser) return\n if (this.bannerElement) return\n\n this.getConfig().then((config) => {\n if (!config.enabled) return\n\n const wrapper = document.createElement('div')\n wrapper.innerHTML = this.createBannerHTML(config)\n this.bannerElement = wrapper.firstElementChild as HTMLElement\n document.body.appendChild(this.bannerElement)\n this.attachBannerEvents()\n })\n }\n\n /**\n * Hide the consent banner\n */\n hide(): void {\n if (!isBrowser) return\n\n this.bannerElement?.remove()\n this.bannerElement = null\n }\n\n /**\n * Show the preferences modal\n */\n showPreferences(): void {\n if (!isBrowser) return\n if (this.preferencesElement) return\n\n this.getConfig().then((config) => {\n const categories = this.getCategories()\n\n const wrapper = document.createElement('div')\n wrapper.innerHTML = this.createPreferencesHTML(config, categories)\n this.preferencesElement = wrapper.firstElementChild as HTMLElement\n document.body.appendChild(this.preferencesElement)\n this.attachPreferencesEvents(config)\n })\n }\n\n /**\n * Get current consent categories\n */\n getCategories(): ConsentCategories {\n if (!isBrowser) return { ...DEFAULT_CATEGORIES }\n return this.getStoredConsent() || { ...DEFAULT_CATEGORIES }\n }\n\n /**\n * Check if user has already consented\n */\n hasConsented(): boolean {\n if (!isBrowser) return false\n return this.getStoredConsent() !== null\n }\n\n /**\n * Accept all cookies\n */\n acceptAll(): void {\n if (!isBrowser) return\n\n const categories: ConsentCategories = {\n necessary: true,\n analytics: true,\n marketing: true,\n preferences: true,\n }\n this.saveConsent(categories)\n this.logConsent(categories as unknown as CookiePreferences)\n this.hide()\n }\n\n /**\n * Reject all optional cookies\n */\n rejectAll(): void {\n if (!isBrowser) return\n\n const categories: ConsentCategories = {\n necessary: true,\n analytics: false,\n marketing: false,\n preferences: false,\n }\n this.saveConsent(categories)\n this.logConsent(categories as unknown as CookiePreferences)\n this.hide()\n }\n\n /**\n * Set specific consent categories\n */\n setCategories(categories: Partial<ConsentCategories>): void {\n if (!isBrowser) return\n\n const current = this.getCategories()\n const newCategories: ConsentCategories = {\n ...current,\n ...categories,\n necessary: true, // Always required\n }\n this.saveConsent(newCategories)\n this.logConsent(newCategories as unknown as CookiePreferences)\n }\n\n /**\n * Reset consent and show banner again\n */\n reset(): void {\n if (!isBrowser) return\n\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Silently ignore\n }\n\n this.events.emit('consent-changed', { ...DEFAULT_CATEGORIES } as unknown as Record<string, boolean>)\n this.show()\n }\n\n // === Private UI Helpers ===\n\n private createBannerHTML(config: CookieConfig): string {\n const position = config.position || 'bottom'\n const theme = config.theme || 'light'\n const layout = config.layout || 'banner'\n const primaryColor = config.primaryColor || '#0066cc'\n const borderRadius = config.borderRadius ?? 8\n\n // Position styles based on layout type\n const bannerStyles: Record<string, string> = {\n bottom: 'bottom: 0; left: 0; right: 0;',\n top: 'top: 0; left: 0; right: 0;',\n 'bottom-left': 'bottom: 0; left: 0; right: 0;',\n 'bottom-right': 'bottom: 0; left: 0; right: 0;',\n center: 'top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px);',\n }\n\n const floatingStyles: Record<string, string> = {\n bottom: `bottom: 20px; left: 50%; transform: translateX(-50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n top: `top: 20px; left: 50%; transform: translateX(-50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n 'bottom-left': `bottom: 20px; left: 20px; max-width: 400px; border-radius: ${borderRadius}px;`,\n 'bottom-right': `bottom: 20px; right: 20px; max-width: 400px; border-radius: ${borderRadius}px;`,\n center: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n }\n\n const modalStyles: Record<string, string> = {\n center: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n bottom: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n top: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n 'bottom-left': `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n 'bottom-right': `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n }\n\n let layoutStyles: Record<string, string>\n if (layout === 'floating') {\n layoutStyles = floatingStyles\n } else if (layout === 'modal') {\n layoutStyles = modalStyles\n } else {\n layoutStyles = bannerStyles\n }\n const positionStyle = layoutStyles[position] || layoutStyles['bottom'] || ''\n\n const isDark = theme === 'dark'\n const bgColor = isDark ? '#1a1a1a' : '#ffffff'\n const textColor = isDark ? '#ffffff' : '#1a1a1a'\n\n const texts = config.texts || {\n title: 'Nous utilisons des cookies',\n description:\n 'Ce site utilise des cookies pour ameliorer votre experience.',\n acceptAll: 'Accepter tout',\n rejectAll: 'Refuser',\n customize: 'Personnaliser',\n save: 'Enregistrer',\n }\n\n // Modal needs a backdrop\n const modalBackdrop = layout === 'modal' ? `\n <div id=\"lynkow-consent-backdrop\" style=\"\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0,0,0,0.5);\n z-index: 99998;\n \"></div>\n ` : ''\n\n return `\n ${modalBackdrop}\n <div id=\"lynkow-consent-banner\" style=\"\n position: fixed;\n ${positionStyle}\n z-index: 99999;\n padding: 20px;\n background: ${bgColor};\n color: ${textColor};\n box-shadow: 0 4px 20px rgba(0,0,0,0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 14px;\n \">\n <div style=\"max-width: 1200px; margin: 0 auto;\">\n <h3 style=\"margin: 0 0 10px 0; font-size: 16px;\">${texts.title}</h3>\n <p style=\"margin: 0 0 15px 0; line-height: 1.5;\">\n ${texts.description}\n </p>\n <div style=\"display: flex; gap: 10px; flex-wrap: wrap;\">\n <button id=\"lynkow-consent-accept\" style=\"\n padding: 10px 20px;\n background: ${primaryColor};\n color: white;\n border: none;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">${texts.acceptAll}</button>\n <button id=\"lynkow-consent-reject\" style=\"\n padding: 10px 20px;\n background: transparent;\n color: inherit;\n border: 1px solid currentColor;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">${texts.rejectAll}</button>\n <button id=\"lynkow-consent-preferences\" style=\"\n padding: 10px 20px;\n background: transparent;\n color: inherit;\n border: none;\n cursor: pointer;\n font-size: 14px;\n text-decoration: underline;\n \">${texts.customize}</button>\n </div>\n </div>\n </div>\n `\n }\n\n private createPreferencesHTML(\n config: CookieConfig,\n currentCategories: ConsentCategories\n ): string {\n const theme = config.theme || 'light'\n const primaryColor = config.primaryColor || '#0066cc'\n const borderRadius = config.borderRadius ?? 8\n const isDark = theme === 'dark'\n const bgColor = isDark ? '#1a1a1a' : '#ffffff'\n const textColor = isDark ? '#ffffff' : '#1a1a1a'\n\n const texts = config.texts || {\n title: 'Preferences de cookies',\n save: 'Enregistrer',\n acceptAll: 'Accepter tout',\n rejectAll: 'Refuser',\n customize: 'Personnaliser',\n description: '',\n }\n\n const categories = config.categories || []\n const categoriesHTML = categories\n .map(\n (cat) => `\n <label style=\"display: flex; align-items: flex-start; gap: 10px; margin: 15px 0; cursor: ${cat.required ? 'not-allowed' : 'pointer'};\">\n <input\n type=\"checkbox\"\n name=\"${cat.id}\"\n ${currentCategories[cat.id as keyof ConsentCategories] ? 'checked' : ''}\n ${cat.required ? 'disabled checked' : ''}\n style=\"width: 18px; height: 18px; margin-top: 2px; accent-color: ${primaryColor};\"\n />\n <div style=\"flex: 1;\">\n <strong style=\"opacity: ${cat.required ? '0.6' : '1'};\">\n ${cat.name}${cat.required ? ' (requis)' : ''}\n </strong>\n <p style=\"margin: 5px 0 0 0; font-size: 13px; opacity: 0.8;\">\n ${cat.description}\n </p>\n </div>\n </label>\n `\n )\n .join('')\n\n return `\n <div id=\"lynkow-consent-preferences-modal\" style=\"\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 100000;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n \">\n <div style=\"\n background: ${bgColor};\n color: ${textColor};\n padding: 30px;\n border-radius: ${borderRadius}px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow-y: auto;\n \">\n <h2 style=\"margin: 0 0 20px 0; font-size: 20px;\">${texts.title || 'Preferences de cookies'}</h2>\n\n <form id=\"lynkow-consent-form\">\n ${categoriesHTML}\n\n <div style=\"display: flex; gap: 10px; margin-top: 25px; padding-top: 20px; border-top: 1px solid rgba(128,128,128,0.3);\">\n <button type=\"submit\" style=\"\n padding: 10px 20px;\n background: ${primaryColor};\n color: white;\n border: none;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">${texts.save || 'Enregistrer'}</button>\n <button type=\"button\" id=\"lynkow-consent-close\" style=\"\n padding: 10px 20px;\n background: transparent;\n color: inherit;\n border: 1px solid currentColor;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">Annuler</button>\n </div>\n </form>\n </div>\n </div>\n `\n }\n\n private attachBannerEvents(): void {\n const acceptBtn = document.getElementById('lynkow-consent-accept')\n const rejectBtn = document.getElementById('lynkow-consent-reject')\n const prefsBtn = document.getElementById('lynkow-consent-preferences')\n\n acceptBtn?.addEventListener('click', () => {\n this.acceptAll()\n })\n\n rejectBtn?.addEventListener('click', () => {\n this.rejectAll()\n })\n\n prefsBtn?.addEventListener('click', () => {\n this.showPreferences()\n })\n }\n\n private attachPreferencesEvents(_config: CookieConfig): void {\n const form = document.getElementById(\n 'lynkow-consent-form'\n ) as HTMLFormElement\n const closeBtn = document.getElementById('lynkow-consent-close')\n const modal = document.getElementById('lynkow-consent-preferences-modal')\n\n form?.addEventListener('submit', (e) => {\n e.preventDefault()\n const formData = new FormData(form)\n\n const newCategories: ConsentCategories = {\n necessary: true,\n analytics: formData.has('analytics'),\n marketing: formData.has('marketing'),\n preferences: formData.has('preferences'),\n }\n\n this.setCategories(newCategories)\n this.hide()\n\n this.preferencesElement?.remove()\n this.preferencesElement = null\n })\n\n closeBtn?.addEventListener('click', () => {\n this.preferencesElement?.remove()\n this.preferencesElement = null\n })\n\n modal?.addEventListener('click', (e) => {\n if (e.target === modal) {\n this.preferencesElement?.remove()\n this.preferencesElement = null\n }\n })\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.hide()\n this.preferencesElement?.remove()\n this.preferencesElement = null\n }\n}\n","/**\n * Branding module for Lynkow SDK\n *\n * Browser-only module. Displays \"Powered by Lynkow\" badge for free plan users.\n */\n\nimport { isBrowser } from '../core/environment'\n\nconst BADGE_ID = 'lynkow-badge'\nconst STYLES_ID = 'lynkow-badge-styles'\n\nconst BADGE_STYLES = `\n #${BADGE_ID} {\n position: fixed;\n bottom: 16px;\n right: 16px;\n background: #1a1a1a;\n color: #888;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 11px;\n padding: 6px 10px;\n border-radius: 4px;\n text-decoration: none;\n opacity: 0.7;\n transition: opacity 0.2s, color 0.2s;\n z-index: 9999;\n line-height: 1;\n }\n\n #${BADGE_ID}:hover {\n opacity: 1;\n color: #fff;\n }\n\n @media (max-width: 480px) {\n #${BADGE_ID} {\n bottom: 10px;\n right: 10px;\n font-size: 10px;\n padding: 5px 8px;\n }\n }\n\n @media (prefers-color-scheme: light) {\n #${BADGE_ID} {\n background: #f5f5f5;\n color: #666;\n }\n\n #${BADGE_ID}:hover {\n color: #1a1a1a;\n }\n }\n`\n\n/**\n * Branding service for \"Powered by Lynkow\" badge\n *\n * Browser-only. All methods are no-op on server.\n */\nexport class BrandingService {\n private badgeElement: HTMLElement | null = null\n\n /**\n * Inject styles into document head\n */\n private injectStyles(): void {\n if (document.getElementById(STYLES_ID)) return\n\n const styleElement = document.createElement('style')\n styleElement.id = STYLES_ID\n styleElement.textContent = BADGE_STYLES\n document.head.appendChild(styleElement)\n }\n\n /**\n * Inject the branding badge into the page\n */\n inject(): void {\n if (!isBrowser) return\n if (document.getElementById(BADGE_ID)) return\n\n // Inject styles\n this.injectStyles()\n\n // Create badge element\n const badge = document.createElement('a')\n badge.id = BADGE_ID\n badge.href = 'https://lynkow.com?ref=badge'\n badge.target = '_blank'\n badge.rel = 'noopener noreferrer'\n badge.textContent = 'Powered by Lynkow'\n badge.setAttribute('aria-label', 'Powered by Lynkow - Visit lynkow.com')\n\n document.body.appendChild(badge)\n this.badgeElement = badge\n }\n\n /**\n * Remove the branding badge from the page\n */\n remove(): void {\n if (!isBrowser) return\n\n this.badgeElement?.remove()\n this.badgeElement = null\n\n // Also remove styles\n document.getElementById(STYLES_ID)?.remove()\n }\n\n /**\n * Check if the badge is currently visible\n */\n isVisible(): boolean {\n if (!isBrowser) return false\n return document.getElementById(BADGE_ID) !== null\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.remove()\n }\n}\n","/**\n * Cache manager for Lynkow SDK\n * Uses memory cache on server, localStorage on browser\n */\n\nimport { isBrowser } from './environment'\n\n/**\n * Cache entry with TTL\n */\ninterface CacheEntry<T> {\n value: T\n expiresAt: number\n}\n\n/**\n * Cache configuration\n */\nexport interface CacheConfig {\n /** Default TTL in milliseconds (default: 5 minutes) */\n defaultTtl?: number\n /** Storage key prefix */\n prefix?: string\n}\n\nconst DEFAULT_TTL = 5 * 60 * 1000 // 5 minutes\nconst STORAGE_PREFIX = 'lynkow_cache_'\n\n/**\n * In-memory cache for server environment\n */\nconst memoryCache = new Map<string, CacheEntry<unknown>>()\n\n/**\n * Create a cache manager\n */\nexport function createCache(config: CacheConfig = {}) {\n const defaultTtl = config.defaultTtl ?? DEFAULT_TTL\n const prefix = config.prefix ?? STORAGE_PREFIX\n\n /**\n * Get full cache key with prefix\n */\n function getKey(key: string): string {\n return `${prefix}${key}`\n }\n\n /**\n * Check if an entry is expired\n */\n function isExpired(entry: CacheEntry<unknown>): boolean {\n return Date.now() > entry.expiresAt\n }\n\n /**\n * Get value from cache\n */\n function get<T>(key: string): T | null {\n const fullKey = getKey(key)\n\n if (isBrowser) {\n try {\n const stored = localStorage.getItem(fullKey)\n if (!stored) return null\n\n const entry = JSON.parse(stored) as CacheEntry<T>\n if (isExpired(entry)) {\n localStorage.removeItem(fullKey)\n return null\n }\n return entry.value\n } catch {\n return null\n }\n }\n\n // Server: use memory cache\n const entry = memoryCache.get(fullKey) as CacheEntry<T> | undefined\n if (!entry) return null\n\n if (isExpired(entry)) {\n memoryCache.delete(fullKey)\n return null\n }\n return entry.value\n }\n\n /**\n * Set value in cache\n */\n function set<T>(key: string, value: T, ttl: number = defaultTtl): void {\n const fullKey = getKey(key)\n const entry: CacheEntry<T> = {\n value,\n expiresAt: Date.now() + ttl,\n }\n\n if (isBrowser) {\n try {\n localStorage.setItem(fullKey, JSON.stringify(entry))\n } catch {\n // localStorage full or unavailable, silently fail\n }\n return\n }\n\n // Server: use memory cache\n memoryCache.set(fullKey, entry)\n }\n\n /**\n * Remove value from cache\n */\n function remove(key: string): void {\n const fullKey = getKey(key)\n\n if (isBrowser) {\n try {\n localStorage.removeItem(fullKey)\n } catch {\n // Silently fail\n }\n return\n }\n\n memoryCache.delete(fullKey)\n }\n\n /**\n * Invalidate cache entries matching a pattern\n * If no pattern is provided, clears all cache entries\n */\n function invalidate(pattern?: string): void {\n if (isBrowser) {\n try {\n const keysToRemove: string[] = []\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i)\n if (key && key.startsWith(prefix)) {\n if (!pattern || key.includes(pattern)) {\n keysToRemove.push(key)\n }\n }\n }\n keysToRemove.forEach((key) => localStorage.removeItem(key))\n } catch {\n // Silently fail\n }\n return\n }\n\n // Server: clear memory cache\n if (!pattern) {\n // Clear all entries with our prefix\n for (const key of memoryCache.keys()) {\n if (key.startsWith(prefix)) {\n memoryCache.delete(key)\n }\n }\n } else {\n // Clear entries matching pattern\n for (const key of memoryCache.keys()) {\n if (key.startsWith(prefix) && key.includes(pattern)) {\n memoryCache.delete(key)\n }\n }\n }\n }\n\n /**\n * Get or set value in cache\n * If value exists and is not expired, returns cached value\n * Otherwise, calls factory function and caches the result\n */\n async function getOrSet<T>(\n key: string,\n factory: () => Promise<T>,\n ttl: number = defaultTtl\n ): Promise<T> {\n const cached = get<T>(key)\n if (cached !== null) {\n return cached\n }\n\n const value = await factory()\n set(key, value, ttl)\n return value\n }\n\n return {\n get,\n set,\n remove,\n invalidate,\n getOrSet,\n }\n}\n\nexport type Cache = ReturnType<typeof createCache>\n","/**\n * Conditional logging utility for Lynkow SDK\n * Only logs when debug mode is enabled\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/**\n * Logger configuration\n */\nexport interface LoggerConfig {\n debug: boolean\n prefix?: string\n}\n\n/**\n * Create a logger instance with the given configuration\n *\n * @param config - Logger configuration\n * @returns Logger instance\n */\nexport function createLogger(config: LoggerConfig) {\n const prefix = config.prefix || '[Lynkow]'\n\n return {\n /**\n * Log a debug message (only when debug mode is enabled)\n */\n debug(...args: unknown[]): void {\n if (config.debug) {\n console.debug(prefix, ...args)\n }\n },\n\n /**\n * Log an info message\n */\n info(...args: unknown[]): void {\n console.info(prefix, ...args)\n },\n\n /**\n * Log a warning message\n */\n warn(...args: unknown[]): void {\n console.warn(prefix, ...args)\n },\n\n /**\n * Log an error message\n */\n error(...args: unknown[]): void {\n console.error(prefix, ...args)\n },\n\n /**\n * Log a message at the specified level\n */\n log(level: LogLevel, ...args: unknown[]): void {\n switch (level) {\n case 'debug':\n this.debug(...args)\n break\n case 'info':\n this.info(...args)\n break\n case 'warn':\n this.warn(...args)\n break\n case 'error':\n this.error(...args)\n break\n }\n },\n }\n}\n\nexport type Logger = ReturnType<typeof createLogger>\n","/**\n * Simple event emitter for Lynkow SDK\n */\n\n/**\n * Event types for the SDK\n */\nexport interface LynkowEvents {\n ready: void\n 'locale-changed': string\n 'consent-changed': Record<string, boolean>\n error: Error\n}\n\nexport type EventName = keyof LynkowEvents\n\n/**\n * Event listener function type\n */\nexport type EventListener<T> = (data: T) => void\n\n/**\n * Create an event emitter\n */\nexport function createEventEmitter() {\n const listeners = new Map<string, Set<EventListener<unknown>>>()\n\n /**\n * Subscribe to an event\n * @returns Unsubscribe function\n */\n function on<K extends EventName>(\n event: K,\n listener: EventListener<LynkowEvents[K]>\n ): () => void {\n if (!listeners.has(event)) {\n listeners.set(event, new Set())\n }\n listeners.get(event)!.add(listener as EventListener<unknown>)\n\n // Return unsubscribe function\n return () => off(event, listener)\n }\n\n /**\n * Unsubscribe from an event\n */\n function off<K extends EventName>(\n event: K,\n listener: EventListener<LynkowEvents[K]>\n ): void {\n const eventListeners = listeners.get(event)\n if (eventListeners) {\n eventListeners.delete(listener as EventListener<unknown>)\n }\n }\n\n /**\n * Emit an event to all listeners\n */\n function emit<K extends EventName>(event: K, data: LynkowEvents[K]): void {\n const eventListeners = listeners.get(event)\n if (!eventListeners) return\n\n for (const listener of eventListeners) {\n try {\n listener(data)\n } catch (error) {\n // Don't let one listener's error affect others\n console.error(`[Lynkow] Error in event listener for \"${event}\":`, error)\n }\n }\n }\n\n /**\n * Subscribe to an event, automatically unsubscribe after first emission\n */\n function once<K extends EventName>(\n event: K,\n listener: EventListener<LynkowEvents[K]>\n ): () => void {\n const wrappedListener = ((data: LynkowEvents[K]) => {\n off(event, wrappedListener as EventListener<LynkowEvents[K]>)\n listener(data)\n }) as EventListener<LynkowEvents[K]>\n\n return on(event, wrappedListener)\n }\n\n /**\n * Remove all listeners for an event or all events\n */\n function removeAllListeners(event?: EventName): void {\n if (event) {\n listeners.delete(event)\n } else {\n listeners.clear()\n }\n }\n\n return {\n on,\n off,\n emit,\n once,\n removeAllListeners,\n }\n}\n\nexport type EventEmitter = ReturnType<typeof createEventEmitter>\n","/**\n * Locale detection and management utilities\n */\n\nimport { isBrowser } from '../core/environment'\n\nconst STORAGE_KEY = 'lynkow_locale'\n\n/**\n * Detect the locale based on priority order:\n * 1. localStorage (previous user choice)\n * 2. URL path prefix (/en/, /fr/)\n * 3. HTML lang attribute\n * 4. Default locale\n *\n * @param enabledLocales - List of enabled locales for the site\n * @param defaultLocale - Default locale to use as fallback\n * @returns Detected locale\n */\nexport function detectLocale(enabledLocales: string[], defaultLocale: string): string {\n if (!isBrowser) {\n return defaultLocale\n }\n\n // 1. localStorage (previous user choice)\n const stored = getStoredLocale()\n if (stored && enabledLocales.includes(stored)) {\n return stored\n }\n\n // 2. URL path prefix\n const pathLocale = getLocaleFromPath(enabledLocales)\n if (pathLocale) {\n return pathLocale\n }\n\n // 3. HTML lang attribute\n const htmlLang = document.documentElement.lang\n if (htmlLang) {\n // Normalize (fr-FR → fr)\n const normalized = htmlLang.split('-')[0]?.toLowerCase()\n if (normalized && enabledLocales.includes(normalized)) {\n return normalized\n }\n }\n\n // 4. Default\n return defaultLocale\n}\n\n/**\n * Get locale from localStorage\n */\nexport function getStoredLocale(): string | null {\n if (!isBrowser) return null\n\n try {\n return localStorage.getItem(STORAGE_KEY)\n } catch {\n return null\n }\n}\n\n/**\n * Save locale to localStorage\n */\nexport function setStoredLocale(locale: string): void {\n if (!isBrowser) return\n\n try {\n localStorage.setItem(STORAGE_KEY, locale)\n } catch {\n // localStorage unavailable, silently fail\n }\n}\n\n/**\n * Remove locale from localStorage\n */\nexport function removeStoredLocale(): void {\n if (!isBrowser) return\n\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Silently fail\n }\n}\n\n/**\n * Extract locale from URL path\n * /en/about → en\n * /fr/services → fr\n * /about → null\n *\n * @param enabledLocales - List of enabled locales to check against\n * @returns Locale from path or null\n */\nexport function getLocaleFromPath(enabledLocales: string[]): string | null {\n if (!isBrowser) return null\n\n const path = window.location.pathname\n const segments = path.split('/').filter(Boolean)\n\n if (segments.length > 0) {\n const firstSegment = segments[0]?.toLowerCase()\n if (firstSegment && enabledLocales.includes(firstSegment)) {\n return firstSegment\n }\n }\n\n return null\n}\n\n/**\n * Check if a locale is valid (exists in enabled locales)\n */\nexport function isValidLocale(locale: string, enabledLocales: string[]): boolean {\n return enabledLocales.includes(locale)\n}\n","/**\n * Lynkow SDK Client\n * Main entry point for the SDK\n */\n\nimport type { LynkowConfig, LynkowClient, SiteConfig } from './types'\nimport type { InternalConfig } from './services/base'\nimport { ContentsService } from './services/contents'\nimport { CategoriesService } from './services/categories'\nimport { TagsService } from './services/tags'\nimport { PagesService } from './services/pages'\nimport { BlocksService } from './services/blocks'\nimport { FormsService } from './services/forms'\nimport { ReviewsService } from './services/reviews'\nimport { SiteService } from './services/site'\nimport { LegalService } from './services/legal'\nimport { CookiesService } from './services/cookies'\nimport { SeoService } from './services/seo'\nimport { PathsService } from './services/paths'\nimport { AnalyticsService } from './services/analytics'\nimport { ConsentService } from './services/consent'\nimport { BrandingService } from './services/branding'\n\n// Core modules\nimport { createCache, type Cache } from './core/cache'\nimport { createLogger, type Logger } from './core/logger'\nimport { createEventEmitter, type EventEmitter, type EventName, type LynkowEvents } from './utils/events'\nimport { isBrowser } from './core/environment'\nimport { detectLocale, setStoredLocale, isValidLocale } from './utils/locale'\n\n/**\n * Default Lynkow API base URL\n */\nconst DEFAULT_BASE_URL = 'https://api.lynkow.com'\n\n/**\n * Extended configuration for SDK v3\n */\nexport interface ClientConfig extends LynkowConfig {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean\n}\n\n/**\n * Extended client interface for SDK v3\n */\nexport interface Client extends LynkowClient {\n /**\n * Current locale\n */\n readonly locale: string\n\n /**\n * Available locales from site configuration\n */\n readonly availableLocales: string[]\n\n /**\n * Client configuration (readonly)\n */\n readonly config: Readonly<{\n siteId: string\n baseUrl: string\n debug: boolean\n }>\n\n /**\n * Set the current locale\n * @param locale - New locale to use\n */\n setLocale(locale: string): void\n\n /**\n * Clear all cached data\n */\n clearCache(): void\n\n /**\n * Destroy the client and clean up resources\n */\n destroy(): void\n\n /**\n * Subscribe to an event\n * @param event - Event name\n * @param listener - Event listener\n * @returns Unsubscribe function\n */\n on<K extends EventName>(event: K, listener: (data: LynkowEvents[K]) => void): () => void\n\n /**\n * Alias for blocks (v3 naming)\n * @deprecated Use `globals` instead in v3\n */\n blocks: BlocksService\n\n /**\n * Global blocks service (v3 naming)\n */\n globals: BlocksService\n\n /**\n * Analytics service (browser-only)\n */\n analytics: AnalyticsService\n\n /**\n * Consent service (cookie consent management)\n */\n consent: ConsentService\n\n /**\n * Branding service (badge for free plan)\n */\n branding: BrandingService\n}\n\n/**\n * Internal state for the client\n */\ninterface ClientState {\n locale: string\n availableLocales: string[]\n siteConfig: SiteConfig | null\n initialized: boolean\n}\n\n/**\n * Creates a Lynkow client instance (SDK v3)\n *\n * @param config - Client configuration\n * @returns Client instance with all services\n *\n * @example\n * ```typescript\n * const lynkow = createClient({\n * siteId: 'your-site-uuid',\n * locale: 'fr',\n * debug: true\n * })\n *\n * const posts = await lynkow.contents.list()\n * ```\n */\nexport function createClient(config: ClientConfig): Client {\n // Validation\n if (!config.siteId) {\n throw new Error('Lynkow SDK: siteId is required')\n }\n\n // Create core utilities\n const cache = createCache()\n const logger = createLogger({ debug: config.debug ?? false })\n const events = createEventEmitter()\n\n // Normalize configuration\n const normalizedBaseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, '')\n\n const internalConfig: InternalConfig = {\n siteId: config.siteId,\n baseUrl: normalizedBaseUrl,\n locale: config.locale,\n fetchOptions: config.fetchOptions || {},\n cache,\n }\n\n // Client state\n const state: ClientState = {\n locale: config.locale || 'fr',\n availableLocales: ['fr'],\n siteConfig: null,\n initialized: false,\n }\n\n // Create services\n const services = {\n contents: new ContentsService(internalConfig),\n categories: new CategoriesService(internalConfig),\n tags: new TagsService(internalConfig),\n pages: new PagesService(internalConfig),\n blocks: new BlocksService(internalConfig),\n forms: new FormsService(internalConfig),\n reviews: new ReviewsService(internalConfig),\n site: new SiteService(internalConfig),\n legal: new LegalService(internalConfig),\n cookies: new CookiesService(internalConfig),\n seo: new SeoService(internalConfig),\n paths: new PathsService(internalConfig),\n analytics: new AnalyticsService(internalConfig),\n consent: new ConsentService(internalConfig, events),\n branding: new BrandingService(),\n }\n\n /**\n * Update internal config locale for all services\n */\n function updateServicesLocale(locale: string): void {\n internalConfig.locale = locale\n }\n\n /**\n * Initialize client (fetch site config, detect locale)\n */\n async function initialize(): Promise<void> {\n if (state.initialized) return\n\n try {\n // Fetch site configuration\n const siteConfig = await services.site.getConfig()\n state.siteConfig = siteConfig\n const defaultLocale = siteConfig.defaultLocale || 'fr'\n state.availableLocales = siteConfig.enabledLocales || [defaultLocale]\n\n // Detect locale (browser only)\n if (isBrowser && !config.locale) {\n const detected = detectLocale(state.availableLocales, defaultLocale)\n state.locale = detected\n updateServicesLocale(detected)\n }\n\n state.initialized = true\n logger.debug('Client initialized', { locale: state.locale, availableLocales: state.availableLocales })\n\n // Initialize browser-only features\n if (isBrowser) {\n // Load and initialize the analytics tracker\n // The tracker handles consent checking internally via localStorage\n services.analytics.init()\n\n // Show consent banner if user hasn't made a choice yet\n if (!services.consent.hasConsented()) {\n services.consent.show()\n }\n\n // Inject branding badge if required (free plan)\n if (siteConfig.showBranding) {\n services.branding.inject()\n }\n }\n\n events.emit('ready', undefined as void)\n } catch (error) {\n logger.error('Failed to initialize client', error)\n events.emit('error', error as Error)\n }\n }\n\n // Auto-initialize in browser\n if (isBrowser) {\n // Defer initialization to next tick to allow event listeners to be set up\n setTimeout(() => initialize(), 0)\n }\n\n // Build the client object\n const client: Client = {\n // Services\n ...services,\n\n // v3 alias: globals = blocks\n globals: services.blocks,\n\n // Readonly config\n config: Object.freeze({\n siteId: config.siteId,\n baseUrl: normalizedBaseUrl,\n debug: config.debug ?? false,\n }),\n\n // Locale getter\n get locale(): string {\n return state.locale\n },\n\n // Available locales getter\n get availableLocales(): string[] {\n return [...state.availableLocales]\n },\n\n // Set locale\n setLocale(locale: string): void {\n if (!isValidLocale(locale, state.availableLocales)) {\n logger.warn(`Locale \"${locale}\" is not available. Available: ${state.availableLocales.join(', ')}`)\n return\n }\n\n if (locale === state.locale) return\n\n state.locale = locale\n updateServicesLocale(locale)\n\n // Save to localStorage (browser)\n if (isBrowser) {\n setStoredLocale(locale)\n }\n\n // Invalidate cache (content changes with locale)\n cache.invalidate()\n\n // Emit event\n events.emit('locale-changed', locale)\n logger.debug('Locale changed to', locale)\n },\n\n // Clear cache\n clearCache(): void {\n cache.invalidate()\n logger.debug('Cache cleared')\n },\n\n // Destroy client\n destroy(): void {\n services.analytics.destroy()\n services.consent.destroy()\n services.branding.destroy()\n cache.invalidate()\n events.removeAllListeners()\n logger.debug('Client destroyed')\n },\n\n // Event subscription\n on<K extends EventName>(event: K, listener: (data: LynkowEvents[K]) => void): () => void {\n return events.on(event, listener)\n },\n }\n\n return client\n}\n\n/**\n * Creates a Lynkow client instance (legacy naming)\n *\n * @deprecated Use `createClient` instead\n * @param config - Client configuration\n * @returns Client instance with all services\n */\nexport function createLynkowClient(config: LynkowConfig): LynkowClient {\n // For backward compatibility, return the basic client without v3 features\n if (!config.siteId) {\n throw new Error('Lynkow SDK: siteId is required')\n }\n\n const internalConfig: InternalConfig = {\n siteId: config.siteId,\n baseUrl: (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, ''),\n locale: config.locale,\n fetchOptions: config.fetchOptions || {},\n }\n\n return {\n contents: new ContentsService(internalConfig),\n categories: new CategoriesService(internalConfig),\n tags: new TagsService(internalConfig),\n pages: new PagesService(internalConfig),\n blocks: new BlocksService(internalConfig),\n forms: new FormsService(internalConfig),\n reviews: new ReviewsService(internalConfig),\n site: new SiteService(internalConfig),\n legal: new LegalService(internalConfig),\n cookies: new CookiesService(internalConfig),\n seo: new SeoService(internalConfig),\n paths: new PathsService(internalConfig),\n }\n}\n","// Config\nexport type { LynkowConfig, LynkowClient } from './config'\n\n// Entities\nexport type {\n Content,\n ContentSummary,\n ContentBody,\n ContentBlock,\n Author,\n} from './content'\n\nexport type {\n Category,\n CategoryWithCount,\n CategoryDetail,\n CategoryTreeNode,\n} from './category'\n\nexport type { Tag } from './tag'\n\nexport type { Page, PageSummary, PageSeo, Alternate } from './page'\n\nexport type { GlobalBlock } from './block'\n\nexport type {\n Form,\n FormField,\n FormFieldType,\n FormFieldOption,\n FormFieldValidation,\n FormSettings,\n FormSubmitData,\n} from './form'\n\nexport type {\n Review,\n ReviewResponse,\n ReviewSettings,\n ReviewSubmitData,\n} from './review'\n\nexport type { SiteConfig } from './site'\n\nexport type {\n LegalDocument,\n LegalListResponse,\n LegalDocumentResponse,\n} from './legal'\n\nexport type {\n CookieConfig,\n CookieCategory,\n CookieTexts,\n CookiePreferences,\n} from './cookie'\n\nexport type { Path, Redirect } from './path'\n\n// Responses\nexport type {\n PaginationMeta,\n PaginatedResponse,\n ContentsListResponse,\n CategoriesListResponse,\n CategoryTreeResponse,\n CategoryDetailResponse,\n TagsListResponse,\n PagesListResponse,\n SiteConfigResponse,\n GlobalBlockResponse,\n ReviewsListResponse,\n FormSubmitResponse,\n ReviewSubmitResponse,\n ConsentLogResponse,\n PathsListResponse,\n ContentResolveResponse,\n CategoryResolveResponse,\n ResolveResponse,\n} from './response'\n\n// Filters\nexport type {\n BaseRequestOptions,\n PaginationOptions,\n SortOptions,\n ContentsFilters,\n CategoryOptions,\n ReviewsFilters,\n SubmitOptions,\n} from './filters'\n\n// Errors\nexport type { ErrorCode, ApiErrorDetail } from './error'\n\n// Type guards\nimport type { ResolveResponse, ContentResolveResponse, CategoryResolveResponse } from './response'\n\n/**\n * Checks if a resolution response is a content\n */\nexport function isContentResolve(\n response: ResolveResponse\n): response is ContentResolveResponse {\n return response.type === 'content'\n}\n\n/**\n * Checks if a resolution response is a category\n */\nexport function isCategoryResolve(\n response: ResolveResponse\n): response is CategoryResolveResponse {\n return response.type === 'category'\n}\n"]}
1
+ {"version":3,"sources":["../src/core/errors.ts","../src/utils/fetch.ts","../src/utils/query.ts","../src/services/base.ts","../src/services/contents.ts","../src/services/categories.ts","../src/services/tags.ts","../src/services/pages.ts","../src/services/blocks.ts","../src/utils/spam.ts","../src/services/forms.ts","../src/services/reviews.ts","../src/services/site.ts","../src/services/legal.ts","../src/services/cookies.ts","../src/services/seo.ts","../src/services/paths.ts","../src/core/environment.ts","../src/services/analytics.ts","../src/services/consent.ts","../src/services/branding.ts","../src/core/cache.ts","../src/core/logger.ts","../src/utils/events.ts","../src/utils/locale.ts","../src/client.ts","../src/types/index.ts"],"names":["LynkowError","_LynkowError","message","code","status","details","cause","response","body","error","isLynkowError","getErrorCode","fetchWithError","url","options","errorData","errors","buildQueryString","params","searchParams","key","value","CACHE_TTL","BaseService","config","path","query","baseUrl","queryString","locale","queryWithLocale","fetchOptions","cacheKey","ttl","pattern","localOptions","CACHE_PREFIX","ContentsService","filters","slug","CategoriesService","TagsService","PagesService","BlocksService","generateSpamFields","sessionStartTime","FormsService","data","spamFields","ReviewsService","slugOrId","result","SiteService","LegalService","CookiesService","preferences","SeoService","PathsService","isBrowser","isServer","browserOnly","fn","fallback","browserOnlyAsync","TRACKER_SCRIPT_ID","AnalyticsService","resolve","reject","checkLoaded","script","event","STORAGE_KEY","DEFAULT_CATEGORIES","ConsentService","events","stored","categories","wrapper","newCategories","position","theme","layout","primaryColor","borderRadius","bannerStyles","floatingStyles","modalStyles","layoutStyles","positionStyle","isDark","bgColor","textColor","texts","currentCategories","categoriesHTML","cat","acceptBtn","rejectBtn","prefsBtn","_config","form","closeBtn","modal","e","formData","BADGE_ID","STYLES_ID","BADGE_STYLES","BrandingService","styleElement","badge","DEFAULT_TTL","STORAGE_PREFIX","memoryCache","createCache","defaultTtl","prefix","getKey","isExpired","entry","get","fullKey","set","remove","invalidate","keysToRemove","i","getOrSet","factory","cached","createLogger","args","level","createEventEmitter","listeners","on","listener","off","eventListeners","emit","once","wrappedListener","removeAllListeners","detectLocale","enabledLocales","defaultLocale","getStoredLocale","pathLocale","getLocaleFromPath","htmlLang","normalized","setStoredLocale","segments","firstSegment","isValidLocale","DEFAULT_BASE_URL","createClient","cache","logger","normalizedBaseUrl","internalConfig","state","services","updateServicesLocale","initialize","siteConfig","detected","createLynkowClient","isContentResolve","isCategoryResolve"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error handling utilities for Lynkow SDK\n */\n\n/**\n * Error codes for Lynkow SDK errors\n */\nexport type ErrorCode =\n | 'BAD_REQUEST'\n | 'VALIDATION_ERROR'\n | 'UNAUTHORIZED'\n | 'FORBIDDEN'\n | 'NOT_FOUND'\n | 'RATE_LIMITED'\n | 'TOO_MANY_REQUESTS'\n | 'TIMEOUT'\n | 'NETWORK_ERROR'\n | 'INTERNAL_ERROR'\n | 'SERVICE_UNAVAILABLE'\n | 'UNKNOWN'\n\n/**\n * API error detail from server response\n */\nexport interface ApiErrorDetail {\n message: string\n field?: string\n code?: string\n}\n\n/**\n * Custom error class for Lynkow SDK\n * Provides structured error information including HTTP status codes and error details\n */\nexport class LynkowError extends Error {\n /**\n * Error name (always 'LynkowError')\n */\n override readonly name = 'LynkowError'\n\n /**\n * Error code for categorization\n */\n readonly code: ErrorCode\n\n /**\n * HTTP status code (if applicable)\n */\n readonly status?: number\n\n /**\n * Additional error details from the API\n */\n readonly details?: ApiErrorDetail[]\n\n /**\n * Original error that caused this error (if any)\n */\n override readonly cause?: Error\n\n constructor(\n message: string,\n code: ErrorCode,\n status?: number,\n details?: ApiErrorDetail[],\n cause?: Error\n ) {\n super(message)\n this.code = code\n this.status = status\n this.details = details\n this.cause = cause\n\n // Maintain proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, LynkowError)\n }\n }\n\n /**\n * Create a LynkowError from an HTTP response\n */\n static async fromResponse(response: Response): Promise<LynkowError> {\n const status = response.status\n let message = `HTTP ${status}`\n let details: ApiErrorDetail[] | undefined\n\n try {\n const body = await response.json()\n if (body.errors && Array.isArray(body.errors)) {\n details = body.errors\n message = body.errors[0]?.message || message\n } else if (body.error) {\n message = body.error\n } else if (body.message) {\n message = body.message\n }\n } catch {\n // Response body is not JSON, use status text\n message = response.statusText || message\n }\n\n const code = LynkowError.statusToCode(status)\n return new LynkowError(message, code, status, details)\n }\n\n /**\n * Create a LynkowError from a network error\n */\n static fromNetworkError(error: Error): LynkowError {\n if (error.name === 'AbortError') {\n return new LynkowError('Request timed out', 'TIMEOUT', undefined, undefined, error)\n }\n\n if (error.name === 'TypeError') {\n return new LynkowError(\n 'Network error - please check your connection',\n 'NETWORK_ERROR',\n undefined,\n undefined,\n error\n )\n }\n\n return new LynkowError(error.message || 'Unknown error', 'UNKNOWN', undefined, undefined, error)\n }\n\n /**\n * Map HTTP status code to error code\n */\n private static statusToCode(status: number): ErrorCode {\n switch (status) {\n case 400:\n return 'VALIDATION_ERROR'\n case 401:\n return 'UNAUTHORIZED'\n case 403:\n return 'FORBIDDEN'\n case 404:\n return 'NOT_FOUND'\n case 429:\n return 'RATE_LIMITED'\n default:\n return 'UNKNOWN'\n }\n }\n\n /**\n * Convert error to a plain object for serialization\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n details: this.details,\n }\n }\n}\n\n/**\n * Type guard to check if an error is a LynkowError\n *\n * @example\n * ```typescript\n * try {\n * await lynkow.contents.getBySlug('not-found')\n * } catch (error) {\n * if (isLynkowError(error) && error.code === 'NOT_FOUND') {\n * // Handle 404\n * }\n * }\n * ```\n */\nexport function isLynkowError(error: unknown): error is LynkowError {\n return error instanceof LynkowError\n}\n","import { LynkowError, type ErrorCode, type ApiErrorDetail } from '../core/errors'\n\n/**\n * Converts an HTTP status code to an error code\n */\nfunction getErrorCode(status: number): ErrorCode {\n switch (status) {\n case 400:\n return 'BAD_REQUEST'\n case 401:\n return 'UNAUTHORIZED'\n case 403:\n return 'FORBIDDEN'\n case 404:\n return 'NOT_FOUND'\n case 422:\n return 'VALIDATION_ERROR'\n case 429:\n return 'TOO_MANY_REQUESTS'\n case 503:\n return 'SERVICE_UNAVAILABLE'\n default:\n return 'INTERNAL_ERROR'\n }\n}\n\n/**\n * Performs a fetch request with error handling\n */\nexport async function fetchWithError<T>(\n url: string,\n options: RequestInit\n): Promise<T> {\n let response: Response\n\n try {\n response = await fetch(url, options)\n } catch (error) {\n // Network error\n throw new LynkowError(\n 'Network error: Unable to reach the server',\n 'NETWORK_ERROR',\n 0,\n [{ message: error instanceof Error ? error.message : 'Unknown error' }]\n )\n }\n\n // OK response\n if (response.ok) {\n return response.json()\n }\n\n // HTTP error\n let errorData: Record<string, unknown> = {}\n try {\n errorData = await response.json()\n } catch {\n // No JSON body\n }\n\n const code = getErrorCode(response.status)\n const message =\n (errorData['error'] as string) ||\n (errorData['message'] as string) ||\n `HTTP error: ${response.status}`\n const errors: ApiErrorDetail[] =\n (errorData['errors'] as ApiErrorDetail[]) || [{ message }]\n\n throw new LynkowError(message, code, response.status, errors)\n}\n","/**\n * Builds a query string from an object\n */\nexport function buildQueryString(params: Record<string, unknown>): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null && value !== '') {\n searchParams.append(key, String(value))\n }\n }\n\n return searchParams.toString()\n}\n","import type { BaseRequestOptions } from '../types'\nimport type { Cache } from '../core/cache'\nimport { fetchWithError } from '../utils/fetch'\nimport { buildQueryString } from '../utils/query'\n\n/**\n * Normalized internal configuration\n */\nexport interface InternalConfig {\n siteId: string\n baseUrl: string\n locale?: string\n fetchOptions: RequestInit\n /** Optional cache manager for caching responses */\n cache?: Cache\n}\n\n/** Cache TTL constants (in milliseconds) */\nexport const CACHE_TTL = {\n /** Short TTL for frequently changing data (5 minutes) */\n SHORT: 5 * 60 * 1000,\n /** Medium TTL for moderately changing data (10 minutes) */\n MEDIUM: 10 * 60 * 1000,\n /** Long TTL for rarely changing data (30 minutes) */\n LONG: 30 * 60 * 1000,\n} as const\n\n/**\n * Base service that all specific services inherit from\n */\nexport abstract class BaseService {\n protected config: InternalConfig\n protected cache?: Cache\n\n constructor(config: InternalConfig) {\n this.config = config\n this.cache = config.cache\n }\n\n /**\n * Builds the full URL for an endpoint\n */\n protected buildEndpointUrl(\n path: string,\n query?: Record<string, unknown>\n ): string {\n const baseUrl = `${this.config.baseUrl}/public/${this.config.siteId}${path}`\n\n if (query && Object.keys(query).length > 0) {\n const queryString = buildQueryString(query)\n return `${baseUrl}?${queryString}`\n }\n\n return baseUrl\n }\n\n /**\n * Performs a GET request\n */\n protected async get<T>(\n path: string,\n query?: Record<string, unknown>,\n options?: BaseRequestOptions\n ): Promise<T> {\n // Add locale if configured\n const locale = options?.locale || this.config.locale\n const queryWithLocale = locale ? { ...query, locale } : query\n\n const url = this.buildEndpointUrl(path, queryWithLocale)\n const fetchOptions = this.mergeFetchOptions(options?.fetchOptions)\n\n return fetchWithError<T>(url, {\n method: 'GET',\n ...fetchOptions,\n })\n }\n\n /**\n * Performs a cached GET request\n * If cache is available and data exists, returns cached data\n * Otherwise fetches from API and caches the result\n *\n * @param cacheKey - Unique cache key\n * @param path - API endpoint path\n * @param query - Query parameters\n * @param options - Request options\n * @param ttl - Cache TTL in milliseconds (default: SHORT)\n */\n protected async getWithCache<T>(\n cacheKey: string,\n path: string,\n query?: Record<string, unknown>,\n options?: BaseRequestOptions,\n ttl: number = CACHE_TTL.SHORT\n ): Promise<T> {\n // If cache is available, use getOrSet\n if (this.cache) {\n return this.cache.getOrSet<T>(\n cacheKey,\n () => this.get<T>(path, query, options),\n ttl\n )\n }\n\n // No cache, just fetch\n return this.get<T>(path, query, options)\n }\n\n /**\n * Invalidates cache entries matching a pattern\n * @param pattern - Pattern to match cache keys\n */\n protected invalidateCache(pattern?: string): void {\n this.cache?.invalidate(pattern)\n }\n\n /**\n * Performs a POST request\n */\n protected async post<T>(\n path: string,\n body: Record<string, unknown>,\n options?: BaseRequestOptions\n ): Promise<T> {\n const url = this.buildEndpointUrl(path)\n const fetchOptions = this.mergeFetchOptions(options?.fetchOptions)\n\n return fetchWithError<T>(url, {\n method: 'POST',\n ...fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...fetchOptions.headers,\n },\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Performs a GET request that returns plain text (XML, txt)\n */\n protected async getText(\n path: string,\n options?: BaseRequestOptions\n ): Promise<string> {\n const url = this.buildEndpointUrl(path)\n const fetchOptions = this.mergeFetchOptions(options?.fetchOptions)\n\n const response = await fetch(url, {\n method: 'GET',\n ...fetchOptions,\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error: ${response.status}`)\n }\n\n return response.text()\n }\n\n /**\n * Merges local fetch options with global ones\n */\n private mergeFetchOptions(localOptions?: RequestInit): RequestInit {\n return {\n ...this.config.fetchOptions,\n ...localOptions,\n headers: {\n ...this.config.fetchOptions.headers,\n ...localOptions?.headers,\n },\n }\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n Content,\n ContentsFilters,\n ContentsListResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'contents_'\n\n/**\n * Service for contents (blog articles)\n */\nexport class ContentsService extends BaseService {\n /**\n * Retrieves a paginated list of published contents\n *\n * @param filters - Optional filters (pagination, category, tag, search)\n * @param options - Request options\n * @returns Paginated list of contents\n *\n * @example\n * ```typescript\n * const { data, meta } = await lynkow.contents.list({\n * page: 1,\n * perPage: 10,\n * category: 'tech'\n * })\n * ```\n */\n async list(\n filters?: ContentsFilters,\n options?: BaseRequestOptions\n ): Promise<ContentsListResponse> {\n const query: Record<string, unknown> = {}\n\n if (filters?.page) query['page'] = filters.page\n if (filters?.perPage) query['perPage'] = filters.perPage\n if (filters?.category) query['category'] = filters.category\n if (filters?.tag) query['tag'] = filters.tag\n if (filters?.search) query['search'] = filters.search\n if (filters?.sort) query['sort'] = filters.sort\n if (filters?.order) query['order'] = filters.order\n if (filters?.locale) query['locale'] = filters.locale\n\n const cacheKey = `${CACHE_PREFIX}list_${JSON.stringify(filters || {})}`\n return this.getWithCache<ContentsListResponse>(\n cacheKey,\n '/contents',\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a content by its slug\n *\n * @param slug - Content slug\n * @param options - Request options (locale)\n * @returns Full content\n *\n * @example\n * ```typescript\n * const content = await lynkow.contents.getBySlug('my-article')\n * ```\n */\n async getBySlug(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<Content> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${locale || 'default'}`\n return this.getWithCache<Content>(\n cacheKey,\n `/contents/slug/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Clear contents cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n CategoriesListResponse,\n CategoryTreeResponse,\n CategoryDetailResponse,\n CategoryOptions,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'categories_'\n\n/**\n * Service for categories\n */\nexport class CategoriesService extends BaseService {\n /**\n * Retrieves the list of categories\n *\n * @param options - Request options (locale)\n * @returns List of categories with counters\n *\n * @example\n * ```typescript\n * const { data, blogUrlMode } = await lynkow.categories.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<CategoriesListResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}`\n return this.getWithCache<CategoriesListResponse>(\n cacheKey,\n '/categories',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves the category tree\n *\n * @param options - Request options (locale)\n * @returns Complete tree structure\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.categories.tree()\n * // data[0].children contient les sous-categories\n * ```\n */\n async tree(options?: BaseRequestOptions): Promise<CategoryTreeResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}tree_${locale || 'default'}`\n return this.getWithCache<CategoryTreeResponse>(\n cacheKey,\n '/categories/tree',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a category with its paginated contents\n *\n * @param slug - Category slug\n * @param options - Options (locale, pagination)\n * @returns Category with contents\n *\n * @example\n * ```typescript\n * const { category, contents } = await lynkow.categories.getBySlug('tech', {\n * page: 1,\n * perPage: 10\n * })\n * ```\n */\n async getBySlug(\n slug: string,\n options?: CategoryOptions & BaseRequestOptions\n ): Promise<CategoryDetailResponse> {\n const query: Record<string, unknown> = {}\n\n if (options?.page) query['page'] = options.page\n if (options?.perPage) query['limit'] = options.perPage\n\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${JSON.stringify(options || {})}`\n return this.getWithCache<CategoryDetailResponse>(\n cacheKey,\n `/categories/${encodeURIComponent(slug)}`,\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Clear categories cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type { TagsListResponse, BaseRequestOptions } from '../types'\n\nconst CACHE_PREFIX = 'tags_'\n\n/**\n * Service for tags\n */\nexport class TagsService extends BaseService {\n /**\n * Retrieves the list of tags\n *\n * @param options - Request options (locale)\n * @returns List of tags\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.tags.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<TagsListResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}`\n return this.getWithCache<TagsListResponse>(\n cacheKey,\n '/tags',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Clear tags cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type { Page, PagesListResponse, BaseRequestOptions } from '../types'\n\nconst CACHE_PREFIX = 'pages_'\n\n/**\n * Options for listing pages\n */\nexport interface PagesListOptions extends BaseRequestOptions {\n /** Filter pages by tag (e.g., 'legal' for legal documents) */\n tag?: string\n}\n\n/**\n * Service for pages (Site Blocks of type \"page\")\n */\nexport class PagesService extends BaseService {\n /**\n * Retrieves the list of published pages\n *\n * @param options - Request options (locale, tag filter)\n * @returns List of pages\n *\n * @example\n * ```typescript\n * // List all pages\n * const { data } = await lynkow.pages.list()\n *\n * // List legal documents\n * const { data } = await lynkow.pages.list({ tag: 'legal' })\n * ```\n */\n async list(options?: PagesListOptions): Promise<PagesListResponse> {\n const locale = options?.locale || this.config.locale\n const query: Record<string, unknown> = {}\n if (options?.tag) query['tag'] = options.tag\n\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}_${options?.tag || 'all'}`\n return this.getWithCache<PagesListResponse>(\n cacheKey,\n '/pages',\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a page by its slug\n *\n * @param slug - Page slug\n * @param options - Request options (locale)\n * @returns Full page with resolved data\n *\n * @example\n * ```typescript\n * const page = await lynkow.pages.getBySlug('about')\n * ```\n */\n async getBySlug(slug: string, options?: BaseRequestOptions): Promise<Page> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${locale || 'default'}`\n\n const response = await this.getWithCache<{ data: Page }>(\n cacheKey,\n `/pages/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Retrieves a page by its path\n *\n * @param path - Page path (e.g.: /services/consulting)\n * @param options - Request options (locale)\n * @returns Full page with resolved data\n *\n * @example\n * ```typescript\n * const page = await lynkow.pages.getByPath('/services/consulting')\n * ```\n */\n async getByPath(path: string, options?: BaseRequestOptions): Promise<Page> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}path_${path}_${locale || 'default'}`\n\n const response = await this.getWithCache<{ data: Page }>(\n cacheKey,\n '/page-by-path',\n { path },\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Retrieves JSON-LD data for a page\n *\n * @param slug - Page slug\n * @param options - Request options (locale)\n * @returns JSON-LD data (Schema.org)\n *\n * @example\n * ```typescript\n * const jsonLd = await lynkow.pages.getJsonLd('about')\n * // Utiliser dans <script type=\"application/ld+json\">\n * ```\n */\n async getJsonLd(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<Record<string, unknown>> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}jsonld_${slug}_${locale || 'default'}`\n\n const response = await this.getWithCache<{ data: Record<string, unknown> }>(\n cacheKey,\n `/pages/${encodeURIComponent(slug)}/json-ld`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Clear pages cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n SiteConfigResponse,\n GlobalBlockResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'globals_'\n\n/**\n * Service for global blocks (header, footer, etc.)\n * Also aliased as `globals` in the client\n */\nexport class BlocksService extends BaseService {\n /**\n * Retrieves the site configuration with all global blocks\n *\n * @param options - Request options (locale)\n * @returns Configuration and global blocks\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.globals.siteConfig()\n * const header = data.globals['header']\n * const footer = data.globals['footer']\n * ```\n */\n async siteConfig(options?: BaseRequestOptions): Promise<SiteConfigResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}siteconfig_${locale || 'default'}`\n return this.getWithCache<SiteConfigResponse>(\n cacheKey,\n '/site-config',\n undefined,\n options,\n CACHE_TTL.MEDIUM\n )\n }\n\n /**\n * Retrieves a specific global block by its slug\n *\n * @param slug - Block slug (e.g.: 'header', 'footer')\n * @param options - Request options (locale)\n * @returns Global block with resolved data\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.globals.getBySlug('header')\n * // data.data contient les donnees du bloc\n * ```\n */\n async getBySlug(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<GlobalBlockResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}${slug}_${locale || 'default'}`\n return this.getWithCache<GlobalBlockResponse>(\n cacheKey,\n `/global/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.MEDIUM\n )\n }\n\n /**\n * @deprecated Use `getBySlug()` instead\n */\n async global(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<GlobalBlockResponse> {\n return this.getBySlug(slug, options)\n }\n\n /**\n * Clear globals cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","/**\n * Anti-spam fields for public submissions\n */\nexport interface SpamFields {\n /** Honeypot field (must be empty) */\n _hp: string\n\n /** Session start timestamp */\n _ts: number\n}\n\n/**\n * Generates anti-spam fields for a submission\n *\n * @param sessionStartTime - Client creation timestamp\n * @returns Anti-spam fields\n */\nexport function generateSpamFields(sessionStartTime: number): SpamFields {\n return {\n _hp: '', // Honeypot - always empty\n _ts: sessionStartTime, // Session timestamp\n }\n}\n","import { BaseService, CACHE_TTL, type InternalConfig } from './base'\nimport type {\n Form,\n FormSubmitData,\n FormSubmitResponse,\n SubmitOptions,\n BaseRequestOptions,\n} from '../types'\nimport { generateSpamFields } from '../utils/spam'\n\nconst CACHE_PREFIX = 'forms_'\n\n/**\n * Service for forms\n */\nexport class FormsService extends BaseService {\n /**\n * Client creation timestamp (for anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Retrieves a form by its slug\n *\n * @param slug - Form slug\n * @returns Form schema\n *\n * @example\n * ```typescript\n * const form = await lynkow.forms.getBySlug('contact')\n * // Use form.schema to generate the form\n * ```\n */\n async getBySlug(slug: string): Promise<Form> {\n const cacheKey = `${CACHE_PREFIX}${slug}`\n const response = await this.getWithCache<{ data: Form }>(\n cacheKey,\n `/forms/${encodeURIComponent(slug)}`,\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n return response.data\n }\n\n /**\n * Submits a form\n *\n * Anti-spam fields (_hp, _ts) are added automatically.\n *\n * @param slug - Form slug\n * @param data - Form data\n * @param options - Options (reCAPTCHA token if enabled)\n * @returns Submission response\n *\n * @example\n * ```typescript\n * const result = await lynkow.forms.submit('contact', {\n * name: 'John Doe',\n * email: 'john@example.com',\n * message: 'Hello!'\n * })\n * ```\n */\n async submit(\n slug: string,\n data: FormSubmitData,\n options?: SubmitOptions & BaseRequestOptions\n ): Promise<FormSubmitResponse> {\n // Add anti-spam fields\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Build the body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Add reCAPTCHA token if provided\n if (options?.recaptchaToken) {\n body['_recaptcha_token'] = options.recaptchaToken\n }\n\n return this.post<FormSubmitResponse>(\n `/forms/${encodeURIComponent(slug)}/submit`,\n body,\n options\n )\n }\n\n /**\n * Clear forms cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL, type InternalConfig } from './base'\nimport type {\n Review,\n ReviewSettings,\n ReviewSubmitData,\n ReviewSubmitResponse,\n ReviewsListResponse,\n ReviewsFilters,\n SubmitOptions,\n BaseRequestOptions,\n} from '../types'\nimport { generateSpamFields } from '../utils/spam'\n\nconst CACHE_PREFIX = 'reviews_'\n\n/**\n * Service for customer reviews\n */\nexport class ReviewsService extends BaseService {\n /**\n * Client creation timestamp (for anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Retrieves the list of approved reviews\n *\n * @param filters - Filters (pagination, rating)\n * @param options - Request options\n * @returns Paginated list of reviews\n *\n * @example\n * ```typescript\n * const { data, meta } = await lynkow.reviews.list({\n * minRating: 4,\n * perPage: 10\n * })\n * ```\n */\n async list(\n filters?: ReviewsFilters,\n options?: BaseRequestOptions\n ): Promise<ReviewsListResponse> {\n const query: Record<string, unknown> = {}\n\n if (filters?.page) query['page'] = filters.page\n if (filters?.perPage) query['perPage'] = filters.perPage\n if (filters?.minRating) query['minRating'] = filters.minRating\n if (filters?.maxRating) query['maxRating'] = filters.maxRating\n if (filters?.sort) query['sort'] = filters.sort\n if (filters?.order) query['order'] = filters.order\n\n const cacheKey = `${CACHE_PREFIX}list_${JSON.stringify(filters || {})}`\n return this.getWithCache<ReviewsListResponse>(\n cacheKey,\n '/reviews',\n query,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Retrieves a review by its slug or ID\n *\n * @param slugOrId - Review slug or ID\n * @returns Full review\n *\n * @example\n * ```typescript\n * const review = await lynkow.reviews.getBySlug('excellent-service')\n * ```\n */\n async getBySlug(slugOrId: string): Promise<Review> {\n const cacheKey = `${CACHE_PREFIX}slug_${slugOrId}`\n const response = await this.getWithCache<{ data: Review }>(\n cacheKey,\n `/reviews/${encodeURIComponent(slugOrId)}`,\n undefined,\n undefined,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Retrieves public review settings\n *\n * @returns Settings (required fields, rating scale, etc.)\n *\n * @example\n * ```typescript\n * const settings = await lynkow.reviews.settings()\n * if (settings.fields.email.required) {\n * // Afficher le champ email comme requis\n * }\n * ```\n */\n async settings(): Promise<ReviewSettings> {\n const cacheKey = `${CACHE_PREFIX}settings`\n return this.getWithCache<ReviewSettings>(\n cacheKey,\n '/reviews/settings',\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n }\n\n /**\n * Submits a new review\n *\n * Anti-spam fields (_hp, _ts) are added automatically.\n *\n * @param data - Review data\n * @param options - Options (reCAPTCHA token if enabled)\n * @returns Submission response\n *\n * @example\n * ```typescript\n * const result = await lynkow.reviews.submit({\n * authorName: 'Alice',\n * rating: 5,\n * content: 'Excellent service !'\n * })\n * ```\n */\n async submit(\n data: ReviewSubmitData,\n options?: SubmitOptions & BaseRequestOptions\n ): Promise<ReviewSubmitResponse> {\n // Add anti-spam fields\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Build the body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Add reCAPTCHA token if provided\n if (options?.recaptchaToken) {\n body['_recaptcha_token'] = options.recaptchaToken\n }\n\n const result = await this.post<ReviewSubmitResponse>('/reviews', body, options)\n\n // Invalidate cache after submission\n this.invalidateCache(CACHE_PREFIX)\n\n return result\n }\n\n /**\n * Clear reviews cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type { SiteConfig } from '../types'\n\nconst CACHE_PREFIX = 'site_'\n\n/**\n * Service for site configuration\n */\nexport class SiteService extends BaseService {\n /**\n * Retrieves the public site configuration\n *\n * @returns Site configuration\n *\n * @example\n * ```typescript\n * const config = await lynkow.site.getConfig()\n * console.log(config.enabledLocales) // ['fr', 'en']\n * ```\n */\n async getConfig(): Promise<SiteConfig> {\n const cacheKey = `${CACHE_PREFIX}config`\n const response = await this.getWithCache<{ data: SiteConfig }>(\n cacheKey,\n '/site',\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n return response.data\n }\n\n /**\n * Clear site configuration cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n LegalDocument,\n LegalListResponse,\n LegalDocumentResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'legal_'\n\n/**\n * Service for accessing legal documents (pages tagged with 'legal')\n *\n * @deprecated Use `pages.list({ tag: 'legal' })` and `pages.getBySlug(slug)` instead.\n * This service will be removed in the next major version.\n *\n * @remarks\n * Legal documents are now regular pages with the 'legal' tag.\n * This service provides convenience methods to access them.\n *\n * @example\n * ```typescript\n * // Deprecated:\n * const docs = await sdk.legal.list()\n * const privacy = await sdk.legal.getBySlug('privacy-policy')\n *\n * // Recommended:\n * const docs = await sdk.pages.list({ tag: 'legal' })\n * const privacy = await sdk.pages.getBySlug('privacy-policy')\n * ```\n */\nexport class LegalService extends BaseService {\n /**\n * List all legal pages\n *\n * @deprecated Use `pages.list({ tag: 'legal' })` instead\n *\n * Returns all published pages that have the 'legal' tag.\n *\n * @param options - Request options (locale)\n * @returns Array of legal documents\n */\n async list(options?: BaseRequestOptions): Promise<LegalDocument[]> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'default'}`\n const response = await this.getWithCache<LegalListResponse>(\n cacheKey,\n '/pages',\n { tag: 'legal' },\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Get a specific legal page by slug\n *\n * @deprecated Use `pages.getBySlug(slug)` instead\n *\n * @param slug - The page slug (e.g., 'privacy-policy', 'terms-of-service')\n * @param options - Request options (locale)\n * @returns The legal document\n * @throws {LynkowError} If the document doesn't exist (404)\n */\n async getBySlug(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<LegalDocument> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}slug_${slug}_${locale || 'default'}`\n const response = await this.getWithCache<LegalDocumentResponse>(\n cacheKey,\n `/pages/${encodeURIComponent(slug)}`,\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n return response.data\n }\n\n /**\n * Clear legal documents cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n CookieConfig,\n CookiePreferences,\n ConsentLogResponse,\n BaseRequestOptions,\n} from '../types'\n\nconst CACHE_PREFIX = 'cookies_'\n\n/**\n * Service for cookie consent\n *\n * @remarks\n * This service will be expanded into the `consent` module in v3\n * with banner UI and preferences modal support.\n */\nexport class CookiesService extends BaseService {\n /**\n * Retrieves the cookie banner configuration\n *\n * @returns Banner configuration\n *\n * @example\n * ```typescript\n * const config = await lynkow.cookies.getConfig()\n * if (config.enabled) {\n * // Afficher le bandeau\n * }\n * ```\n */\n async getConfig(): Promise<CookieConfig> {\n const cacheKey = `${CACHE_PREFIX}config`\n const response = await this.getWithCache<{ data: CookieConfig }>(\n cacheKey,\n '/cookie-consent/config',\n undefined,\n undefined,\n CACHE_TTL.MEDIUM\n )\n return response.data\n }\n\n /**\n * Records user consent\n *\n * @param preferences - Preferences by category\n * @returns Confirmation with consent ID\n *\n * @example\n * ```typescript\n * await lynkow.cookies.logConsent({\n * necessary: true,\n * analytics: true,\n * marketing: false\n * })\n * ```\n */\n async logConsent(\n preferences: CookiePreferences,\n options?: BaseRequestOptions\n ): Promise<ConsentLogResponse> {\n return this.post<ConsentLogResponse>(\n '/cookie-consent/log',\n { preferences },\n options\n )\n }\n\n /**\n * Clear cookies configuration cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","import { BaseService } from './base'\nimport type { BaseRequestOptions } from '../types'\n\n/**\n * Service for SEO files\n */\nexport class SeoService extends BaseService {\n /**\n * Retrieves the XML sitemap\n *\n * @returns Sitemap XML content\n *\n * @example\n * ```typescript\n * // In a Next.js API route\n * export async function GET() {\n * const xml = await lynkow.seo.sitemap()\n * return new Response(xml, {\n * headers: { 'Content-Type': 'application/xml' }\n * })\n * }\n * ```\n */\n async sitemap(options?: BaseRequestOptions): Promise<string> {\n return this.getText('/sitemap.xml', options)\n }\n\n /**\n * Retrieves the robots.txt file\n *\n * @returns robots.txt content\n *\n * @example\n * ```typescript\n * // In a Next.js API route\n * export async function GET() {\n * const txt = await lynkow.seo.robots()\n * return new Response(txt, {\n * headers: { 'Content-Type': 'text/plain' }\n * })\n * }\n * ```\n */\n async robots(options?: BaseRequestOptions): Promise<string> {\n return this.getText('/robots.txt', options)\n }\n}\n","import { BaseService, CACHE_TTL } from './base'\nimport type {\n PathsListResponse,\n ResolveResponse,\n Redirect,\n BaseRequestOptions,\n} from '../types'\nimport { LynkowError } from '../core/errors'\n\nconst CACHE_PREFIX = 'paths_'\n\n/**\n * Service for paths (SSG, resolution)\n */\nexport class PathsService extends BaseService {\n /**\n * Retrieves all paths for static generation\n *\n * @param options - Request options (locale)\n * @returns List of paths\n *\n * @example\n * ```typescript\n * // In Next.js generateStaticParams()\n * export async function generateStaticParams() {\n * const { paths } = await lynkow.paths.list()\n * return paths.map(p => ({\n * slug: p.segments\n * }))\n * }\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<PathsListResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}list_${locale || 'all'}`\n return this.getWithCache<PathsListResponse>(\n cacheKey,\n '/paths',\n undefined,\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Resolves a path to its content or category\n *\n * @param path - Path to resolve\n * @param options - Request options\n * @returns Corresponding content or category\n *\n * @example\n * ```typescript\n * const result = await lynkow.paths.resolve('/blog/tech/my-article')\n *\n * if (result.type === 'content') {\n * // Afficher l'article\n * } else {\n * // Afficher la categorie avec ses articles\n * }\n * ```\n */\n async resolve(\n path: string,\n options?: BaseRequestOptions\n ): Promise<ResolveResponse> {\n const locale = options?.locale || this.config.locale\n const cacheKey = `${CACHE_PREFIX}resolve_${path}_${locale || 'default'}`\n return this.getWithCache<ResolveResponse>(\n cacheKey,\n '/resolve',\n { path },\n options,\n CACHE_TTL.SHORT\n )\n }\n\n /**\n * Checks if a path has a configured redirect\n *\n * @param path - Path to check\n * @returns Redirect or null\n *\n * @example\n * ```typescript\n * // In a Next.js middleware\n * const redirect = await lynkow.paths.matchRedirect(pathname)\n * if (redirect) {\n * return NextResponse.redirect(redirect.target, redirect.statusCode)\n * }\n * ```\n */\n async matchRedirect(\n path: string,\n options?: BaseRequestOptions\n ): Promise<Redirect | null> {\n try {\n const response = await this.get<{ data: Redirect }>(\n '/redirects/match',\n { path },\n options\n )\n return response.data\n } catch (error: unknown) {\n // 404 = no redirect found\n if (error instanceof LynkowError && error.status === 404) {\n return null\n }\n throw error\n }\n }\n\n /**\n * Clear paths cache\n */\n clearCache(): void {\n this.invalidateCache(CACHE_PREFIX)\n }\n}\n","/**\n * Environment detection utilities\n * Determines if code is running in browser or server environment\n */\n\n/**\n * Check if running in a browser environment\n */\nexport const isBrowser: boolean =\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.document.createElement !== 'undefined'\n\n/**\n * Check if running in a server environment (Node.js, Deno, etc.)\n */\nexport const isServer: boolean = !isBrowser\n\n/**\n * Execute a function only in browser environment\n * Returns the fallback value in server environment\n *\n * @param fn - Function to execute in browser\n * @param fallback - Value to return in server environment\n * @returns Result of fn() in browser, fallback in server\n *\n * @example\n * ```typescript\n * const visitorId = browserOnly(\n * () => localStorage.getItem('visitor_id'),\n * null\n * )\n * ```\n */\nexport function browserOnly<T>(fn: () => T, fallback: T): T {\n if (isBrowser) {\n return fn()\n }\n return fallback\n}\n\n/**\n * Execute an async function only in browser environment\n * Returns the fallback value in server environment\n *\n * @param fn - Async function to execute in browser\n * @param fallback - Value to return in server environment\n * @returns Promise resolving to result of fn() in browser, fallback in server\n *\n * @example\n * ```typescript\n * const config = await browserOnlyAsync(\n * () => fetchConfig(),\n * defaultConfig\n * )\n * ```\n */\nexport async function browserOnlyAsync<T>(fn: () => Promise<T>, fallback: T): Promise<T> {\n if (isBrowser) {\n return fn()\n }\n return fallback\n}\n\n/**\n * No-op function for browser-only features in server environment\n * Useful for methods that should silently do nothing on server\n */\nexport function noop(): void {\n // Intentionally empty\n}\n\n/**\n * Create a no-op version of a function for server environment\n *\n * @param fn - Function to wrap\n * @returns Original function in browser, no-op in server\n */\nexport function browserOnlyFn<T extends (...args: any[]) => any>(fn: T): T {\n if (isBrowser) {\n return fn\n }\n return noop as T\n}\n","/**\n * Analytics module for Lynkow SDK\n *\n * Browser-only module that loads and wraps the Lynkow tracker.js\n * All methods are no-op on server.\n */\n\nimport { isBrowser } from '../core/environment'\nimport type { InternalConfig } from './base'\n\n/**\n * Data for tracking pageviews\n */\nexport interface PageviewData {\n /** Page path (default: window.location.pathname) */\n path?: string\n /** Page title (default: document.title) */\n title?: string\n /** Referrer URL */\n referrer?: string\n}\n\n/**\n * Data for tracking custom events\n */\nexport interface EventData {\n /** Event type */\n type: string\n /** Additional event data */\n [key: string]: unknown\n}\n\n/**\n * Funnel step data\n */\nexport interface FunnelStepData {\n /** Funnel identifier */\n funnelId: string\n /** Step number (1-based) */\n stepNumber: number\n /** Step name */\n stepName: string\n /** Funnel name (optional) */\n funnelName?: string\n}\n\n/**\n * LynkowAnalytics global interface (from tracker.js)\n */\ninterface LynkowAnalyticsGlobal {\n init: (siteId: string, options?: { endpoint?: string }) => void\n track: (event: Record<string, unknown>) => void\n trackFunnel: (funnelId: string, stepNumber: number, stepName: string, funnelName?: string) => void\n}\n\ndeclare global {\n interface Window {\n LynkowAnalytics?: LynkowAnalyticsGlobal\n }\n}\n\nconst TRACKER_SCRIPT_ID = 'lynkow-tracker'\n\n/**\n * Analytics service that loads and wraps the Lynkow tracker.js\n *\n * Browser-only. All methods are no-op on server.\n */\nexport class AnalyticsService {\n private config: InternalConfig\n private enabled = true\n private initialized = false\n private loading = false\n private loadPromise: Promise<void> | null = null\n\n constructor(config: InternalConfig) {\n this.config = config\n }\n\n /**\n * Get the tracker script URL\n */\n private getTrackerUrl(): string {\n return `${this.config.baseUrl}/analytics/tracker.js`\n }\n\n /**\n * Load the tracker.js script\n */\n private loadTracker(): Promise<void> {\n if (!isBrowser) return Promise.resolve()\n\n // Already loaded\n if (window.LynkowAnalytics) {\n return Promise.resolve()\n }\n\n // Already loading\n if (this.loadPromise) {\n return this.loadPromise\n }\n\n this.loading = true\n this.loadPromise = new Promise((resolve, reject) => {\n // Check if script tag already exists\n if (document.getElementById(TRACKER_SCRIPT_ID)) {\n // Wait for it to load\n const checkLoaded = setInterval(() => {\n if (window.LynkowAnalytics) {\n clearInterval(checkLoaded)\n this.loading = false\n resolve()\n }\n }, 50)\n\n // Timeout after 10 seconds\n setTimeout(() => {\n clearInterval(checkLoaded)\n this.loading = false\n reject(new Error('Tracker script load timeout'))\n }, 10000)\n\n return\n }\n\n // Create and inject script\n const script = document.createElement('script')\n script.id = TRACKER_SCRIPT_ID\n script.src = this.getTrackerUrl()\n script.async = true\n script.setAttribute('data-site-id', this.config.siteId)\n if (this.config.baseUrl) {\n script.setAttribute('data-api-url', this.config.baseUrl)\n }\n\n script.onload = () => {\n this.loading = false\n // Wait a tick for the tracker to auto-initialize\n setTimeout(() => {\n if (window.LynkowAnalytics) {\n resolve()\n } else {\n reject(new Error('Tracker script loaded but LynkowAnalytics not found'))\n }\n }, 0)\n }\n\n script.onerror = () => {\n this.loading = false\n reject(new Error('Failed to load tracker script'))\n }\n\n document.head.appendChild(script)\n })\n\n return this.loadPromise\n }\n\n /**\n * Initialize analytics tracking\n * Loads the tracker.js script and initializes it\n */\n async init(): Promise<void> {\n if (!isBrowser || this.initialized) return\n\n try {\n await this.loadTracker()\n\n // The tracker auto-initializes via data-site-id attribute\n // But we can also manually init if needed\n if (window.LynkowAnalytics && !this.initialized) {\n // Tracker already auto-initialized via data-site-id\n this.initialized = true\n }\n } catch (error) {\n console.error('[Lynkow] Failed to initialize analytics:', error)\n }\n }\n\n /**\n * Track a custom event\n *\n * @example\n * ```typescript\n * lynkow.analytics.trackEvent({\n * type: 'purchase',\n * productId: 'abc123',\n * amount: 99.99\n * })\n * ```\n */\n async trackEvent(event: EventData): Promise<void> {\n if (!isBrowser || !this.enabled) return\n\n await this.init()\n\n if (window.LynkowAnalytics) {\n window.LynkowAnalytics.track(event)\n }\n }\n\n /**\n * Track a funnel step\n *\n * @example\n * ```typescript\n * lynkow.analytics.trackFunnelStep({\n * funnelId: 'checkout',\n * stepNumber: 2,\n * stepName: 'payment',\n * funnelName: 'Checkout Flow'\n * })\n * ```\n */\n async trackFunnelStep(data: FunnelStepData): Promise<void> {\n if (!isBrowser || !this.enabled) return\n\n await this.init()\n\n if (window.LynkowAnalytics) {\n window.LynkowAnalytics.trackFunnel(\n data.funnelId,\n data.stepNumber,\n data.stepName,\n data.funnelName\n )\n }\n }\n\n /**\n * Track a pageview manually\n * Note: The tracker automatically tracks pageviews, this is for SPA navigation\n *\n * @example\n * ```typescript\n * // After SPA navigation\n * lynkow.analytics.trackPageview({ path: '/new-page' })\n * ```\n */\n async trackPageview(data?: PageviewData): Promise<void> {\n if (!isBrowser || !this.enabled) return\n\n await this.init()\n\n if (window.LynkowAnalytics) {\n window.LynkowAnalytics.track({\n type: 'pageview',\n path: data?.path || window.location.pathname,\n title: data?.title || document.title,\n referrer: data?.referrer || document.referrer,\n })\n }\n }\n\n /**\n * Enable analytics tracking\n */\n enable(): void {\n this.enabled = true\n }\n\n /**\n * Disable analytics tracking\n */\n disable(): void {\n this.enabled = false\n }\n\n /**\n * Check if analytics is enabled\n */\n isEnabled(): boolean {\n return this.enabled\n }\n\n /**\n * Check if tracker is loaded and initialized\n */\n isInitialized(): boolean {\n return this.initialized && !!window.LynkowAnalytics\n }\n\n /**\n * Get the underlying LynkowAnalytics global object\n * For advanced usage when you need direct access to the tracker\n */\n getTracker(): LynkowAnalyticsGlobal | undefined {\n if (!isBrowser) return undefined\n return window.LynkowAnalytics\n }\n\n /**\n * Clean up resources (removes the tracker script)\n */\n destroy(): void {\n if (!isBrowser) return\n\n const script = document.getElementById(TRACKER_SCRIPT_ID)\n script?.remove()\n\n this.initialized = false\n this.loadPromise = null\n }\n}\n","/**\n * Consent module for Lynkow SDK\n *\n * Hybrid module: API everywhere + UI browser-only\n */\n\nimport { isBrowser } from '../core/environment'\nimport type { InternalConfig } from './base'\nimport type { CookieConfig, CookiePreferences } from '../types'\nimport type { EventEmitter } from '../utils/events'\n\n// Use same key as tracker.js for consistency\nconst STORAGE_KEY = '_lkw_consent'\n\n/**\n * Consent categories\n */\nexport interface ConsentCategories {\n /** Always true, not modifiable */\n necessary: boolean\n /** Analytics cookies */\n analytics: boolean\n /** Marketing cookies */\n marketing: boolean\n /** Preference cookies */\n preferences: boolean\n}\n\n/**\n * Default consent categories (no consent given)\n */\nconst DEFAULT_CATEGORIES: ConsentCategories = {\n necessary: true,\n analytics: false,\n marketing: false,\n preferences: false,\n}\n\n/**\n * Consent service for cookie consent management\n *\n * Provides:\n * - API methods that work everywhere (getConfig, logConsent)\n * - UI methods that work only in browser (show, hide, acceptAll, etc.)\n */\nexport class ConsentService {\n private config: InternalConfig\n private events: EventEmitter\n private bannerElement: HTMLElement | null = null\n private preferencesElement: HTMLElement | null = null\n private configCache: CookieConfig | null = null\n\n constructor(config: InternalConfig, events: EventEmitter) {\n this.config = config\n this.events = events\n }\n\n // === API Methods (work everywhere) ===\n\n /**\n * Get cookie consent configuration from API\n */\n async getConfig(): Promise<CookieConfig> {\n if (this.configCache) return this.configCache\n\n const url = `${this.config.baseUrl}/public/${this.config.siteId}/cookie-consent/config`\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n ...this.config.fetchOptions,\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch consent config: ${response.status}`)\n }\n\n const data = await response.json()\n this.configCache = data.data as CookieConfig\n return this.configCache\n }\n\n /**\n * Log consent to server\n */\n async logConsent(preferences: CookiePreferences): Promise<void> {\n const url = `${this.config.baseUrl}/public/${this.config.siteId}/cookie-consent/log`\n\n await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ preferences }),\n ...this.config.fetchOptions,\n }).catch(() => {\n // Silently ignore errors\n })\n }\n\n // === Storage Methods ===\n // Format: { choices: { necessary, analytics, marketing, preferences } }\n // This format is compatible with tracker.js\n\n private getStoredConsent(): ConsentCategories | null {\n if (!isBrowser) return null\n\n try {\n const stored = localStorage.getItem(STORAGE_KEY)\n if (stored) {\n const data = JSON.parse(stored)\n // Handle both old format and new { choices: {...} } format\n if (data.choices) {\n return data.choices as ConsentCategories\n }\n return data as ConsentCategories\n }\n } catch {\n // localStorage unavailable\n }\n\n return null\n }\n\n private saveConsent(categories: ConsentCategories): void {\n if (!isBrowser) return\n\n try {\n // Save in { choices: {...} } format for tracker.js compatibility\n localStorage.setItem(STORAGE_KEY, JSON.stringify({ choices: categories }))\n } catch {\n // localStorage unavailable\n }\n\n this.events.emit('consent-changed', categories as unknown as Record<string, boolean>)\n\n // Dispatch custom event for tracker.js\n document.dispatchEvent(new CustomEvent('lynkow:consent:update', {\n detail: categories\n }))\n }\n\n // === UI Methods (browser-only) ===\n\n /**\n * Show the consent banner\n */\n show(): void {\n if (!isBrowser) return\n if (this.bannerElement) return\n\n this.getConfig().then((config) => {\n if (!config.enabled) return\n\n const wrapper = document.createElement('div')\n wrapper.innerHTML = this.createBannerHTML(config)\n this.bannerElement = wrapper.firstElementChild as HTMLElement\n document.body.appendChild(this.bannerElement)\n this.attachBannerEvents()\n })\n }\n\n /**\n * Hide the consent banner\n */\n hide(): void {\n if (!isBrowser) return\n\n this.bannerElement?.remove()\n this.bannerElement = null\n }\n\n /**\n * Show the preferences modal\n */\n showPreferences(): void {\n if (!isBrowser) return\n if (this.preferencesElement) return\n\n this.getConfig().then((config) => {\n const categories = this.getCategories()\n\n const wrapper = document.createElement('div')\n wrapper.innerHTML = this.createPreferencesHTML(config, categories)\n this.preferencesElement = wrapper.firstElementChild as HTMLElement\n document.body.appendChild(this.preferencesElement)\n this.attachPreferencesEvents(config)\n })\n }\n\n /**\n * Get current consent categories\n */\n getCategories(): ConsentCategories {\n if (!isBrowser) return { ...DEFAULT_CATEGORIES }\n return this.getStoredConsent() || { ...DEFAULT_CATEGORIES }\n }\n\n /**\n * Check if user has already consented\n */\n hasConsented(): boolean {\n if (!isBrowser) return false\n return this.getStoredConsent() !== null\n }\n\n /**\n * Accept all cookies\n */\n acceptAll(): void {\n if (!isBrowser) return\n\n const categories: ConsentCategories = {\n necessary: true,\n analytics: true,\n marketing: true,\n preferences: true,\n }\n this.saveConsent(categories)\n this.logConsent(categories as unknown as CookiePreferences)\n this.hide()\n }\n\n /**\n * Reject all optional cookies\n */\n rejectAll(): void {\n if (!isBrowser) return\n\n const categories: ConsentCategories = {\n necessary: true,\n analytics: false,\n marketing: false,\n preferences: false,\n }\n this.saveConsent(categories)\n this.logConsent(categories as unknown as CookiePreferences)\n this.hide()\n }\n\n /**\n * Set specific consent categories\n */\n setCategories(categories: Partial<ConsentCategories>): void {\n if (!isBrowser) return\n\n const current = this.getCategories()\n const newCategories: ConsentCategories = {\n ...current,\n ...categories,\n necessary: true, // Always required\n }\n this.saveConsent(newCategories)\n this.logConsent(newCategories as unknown as CookiePreferences)\n }\n\n /**\n * Reset consent and show banner again\n */\n reset(): void {\n if (!isBrowser) return\n\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Silently ignore\n }\n\n this.events.emit('consent-changed', { ...DEFAULT_CATEGORIES } as unknown as Record<string, boolean>)\n this.show()\n }\n\n // === Private UI Helpers ===\n\n private createBannerHTML(config: CookieConfig): string {\n const position = config.position || 'bottom'\n const theme = config.theme || 'light'\n const layout = config.layout || 'banner'\n const primaryColor = config.primaryColor || '#0066cc'\n const borderRadius = config.borderRadius ?? 8\n\n // Position styles based on layout type\n const bannerStyles: Record<string, string> = {\n bottom: 'bottom: 0; left: 0; right: 0;',\n top: 'top: 0; left: 0; right: 0;',\n 'bottom-left': 'bottom: 0; left: 0; right: 0;',\n 'bottom-right': 'bottom: 0; left: 0; right: 0;',\n center: 'top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px);',\n }\n\n const floatingStyles: Record<string, string> = {\n bottom: `bottom: 20px; left: 50%; transform: translateX(-50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n top: `top: 20px; left: 50%; transform: translateX(-50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n 'bottom-left': `bottom: 20px; left: 20px; max-width: 400px; border-radius: ${borderRadius}px;`,\n 'bottom-right': `bottom: 20px; right: 20px; max-width: 400px; border-radius: ${borderRadius}px;`,\n center: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n }\n\n const modalStyles: Record<string, string> = {\n center: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n bottom: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n top: `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n 'bottom-left': `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n 'bottom-right': `top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 500px; width: calc(100% - 40px); border-radius: ${borderRadius}px;`,\n }\n\n let layoutStyles: Record<string, string>\n if (layout === 'floating') {\n layoutStyles = floatingStyles\n } else if (layout === 'modal') {\n layoutStyles = modalStyles\n } else {\n layoutStyles = bannerStyles\n }\n const positionStyle = layoutStyles[position] || layoutStyles['bottom'] || ''\n\n const isDark = theme === 'dark'\n const bgColor = isDark ? '#1a1a1a' : '#ffffff'\n const textColor = isDark ? '#ffffff' : '#1a1a1a'\n\n const texts = config.texts || {\n title: 'Nous utilisons des cookies',\n description:\n 'Ce site utilise des cookies pour ameliorer votre experience.',\n acceptAll: 'Accepter tout',\n rejectAll: 'Refuser',\n customize: 'Personnaliser',\n save: 'Enregistrer',\n }\n\n // Modal needs a backdrop\n const modalBackdrop = layout === 'modal' ? `\n <div id=\"lynkow-consent-backdrop\" style=\"\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0,0,0,0.5);\n z-index: 99998;\n \"></div>\n ` : ''\n\n return `\n ${modalBackdrop}\n <div id=\"lynkow-consent-banner\" style=\"\n position: fixed;\n ${positionStyle}\n z-index: 99999;\n padding: 20px;\n background: ${bgColor};\n color: ${textColor};\n box-shadow: 0 4px 20px rgba(0,0,0,0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 14px;\n \">\n <div style=\"max-width: 1200px; margin: 0 auto;\">\n <h3 style=\"margin: 0 0 10px 0; font-size: 16px;\">${texts.title}</h3>\n <p style=\"margin: 0 0 15px 0; line-height: 1.5;\">\n ${texts.description}\n </p>\n <div style=\"display: flex; gap: 10px; flex-wrap: wrap;\">\n <button id=\"lynkow-consent-accept\" style=\"\n padding: 10px 20px;\n background: ${primaryColor};\n color: white;\n border: none;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">${texts.acceptAll}</button>\n <button id=\"lynkow-consent-reject\" style=\"\n padding: 10px 20px;\n background: transparent;\n color: inherit;\n border: 1px solid currentColor;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">${texts.rejectAll}</button>\n <button id=\"lynkow-consent-preferences\" style=\"\n padding: 10px 20px;\n background: transparent;\n color: inherit;\n border: none;\n cursor: pointer;\n font-size: 14px;\n text-decoration: underline;\n \">${texts.customize}</button>\n </div>\n </div>\n </div>\n `\n }\n\n private createPreferencesHTML(\n config: CookieConfig,\n currentCategories: ConsentCategories\n ): string {\n const theme = config.theme || 'light'\n const primaryColor = config.primaryColor || '#0066cc'\n const borderRadius = config.borderRadius ?? 8\n const isDark = theme === 'dark'\n const bgColor = isDark ? '#1a1a1a' : '#ffffff'\n const textColor = isDark ? '#ffffff' : '#1a1a1a'\n\n const texts = config.texts || {\n title: 'Preferences de cookies',\n save: 'Enregistrer',\n acceptAll: 'Accepter tout',\n rejectAll: 'Refuser',\n customize: 'Personnaliser',\n description: '',\n }\n\n const categories = config.categories || []\n const categoriesHTML = categories\n .map(\n (cat) => `\n <label style=\"display: flex; align-items: flex-start; gap: 10px; margin: 15px 0; cursor: ${cat.required ? 'not-allowed' : 'pointer'};\">\n <input\n type=\"checkbox\"\n name=\"${cat.id}\"\n ${currentCategories[cat.id as keyof ConsentCategories] ? 'checked' : ''}\n ${cat.required ? 'disabled checked' : ''}\n style=\"width: 18px; height: 18px; margin-top: 2px; accent-color: ${primaryColor};\"\n />\n <div style=\"flex: 1;\">\n <strong style=\"opacity: ${cat.required ? '0.6' : '1'};\">\n ${cat.name}${cat.required ? ' (requis)' : ''}\n </strong>\n <p style=\"margin: 5px 0 0 0; font-size: 13px; opacity: 0.8;\">\n ${cat.description}\n </p>\n </div>\n </label>\n `\n )\n .join('')\n\n return `\n <div id=\"lynkow-consent-preferences-modal\" style=\"\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 100000;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n \">\n <div style=\"\n background: ${bgColor};\n color: ${textColor};\n padding: 30px;\n border-radius: ${borderRadius}px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow-y: auto;\n \">\n <h2 style=\"margin: 0 0 20px 0; font-size: 20px;\">${texts.title || 'Preferences de cookies'}</h2>\n\n <form id=\"lynkow-consent-form\">\n ${categoriesHTML}\n\n <div style=\"display: flex; gap: 10px; margin-top: 25px; padding-top: 20px; border-top: 1px solid rgba(128,128,128,0.3);\">\n <button type=\"submit\" style=\"\n padding: 10px 20px;\n background: ${primaryColor};\n color: white;\n border: none;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">${texts.save || 'Enregistrer'}</button>\n <button type=\"button\" id=\"lynkow-consent-close\" style=\"\n padding: 10px 20px;\n background: transparent;\n color: inherit;\n border: 1px solid currentColor;\n border-radius: ${borderRadius}px;\n cursor: pointer;\n font-size: 14px;\n \">Annuler</button>\n </div>\n </form>\n </div>\n </div>\n `\n }\n\n private attachBannerEvents(): void {\n const acceptBtn = document.getElementById('lynkow-consent-accept')\n const rejectBtn = document.getElementById('lynkow-consent-reject')\n const prefsBtn = document.getElementById('lynkow-consent-preferences')\n\n acceptBtn?.addEventListener('click', () => {\n this.acceptAll()\n })\n\n rejectBtn?.addEventListener('click', () => {\n this.rejectAll()\n })\n\n prefsBtn?.addEventListener('click', () => {\n this.showPreferences()\n })\n }\n\n private attachPreferencesEvents(_config: CookieConfig): void {\n const form = document.getElementById(\n 'lynkow-consent-form'\n ) as HTMLFormElement\n const closeBtn = document.getElementById('lynkow-consent-close')\n const modal = document.getElementById('lynkow-consent-preferences-modal')\n\n form?.addEventListener('submit', (e) => {\n e.preventDefault()\n const formData = new FormData(form)\n\n const newCategories: ConsentCategories = {\n necessary: true,\n analytics: formData.has('analytics'),\n marketing: formData.has('marketing'),\n preferences: formData.has('preferences'),\n }\n\n this.setCategories(newCategories)\n this.hide()\n\n this.preferencesElement?.remove()\n this.preferencesElement = null\n })\n\n closeBtn?.addEventListener('click', () => {\n this.preferencesElement?.remove()\n this.preferencesElement = null\n })\n\n modal?.addEventListener('click', (e) => {\n if (e.target === modal) {\n this.preferencesElement?.remove()\n this.preferencesElement = null\n }\n })\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.hide()\n this.preferencesElement?.remove()\n this.preferencesElement = null\n }\n}\n","/**\n * Branding module for Lynkow SDK\n *\n * Browser-only module. Displays \"Powered by Lynkow\" badge for free plan users.\n */\n\nimport { isBrowser } from '../core/environment'\n\nconst BADGE_ID = 'lynkow-badge'\nconst STYLES_ID = 'lynkow-badge-styles'\n\nconst BADGE_STYLES = `\n #${BADGE_ID} {\n position: fixed;\n bottom: 16px;\n right: 16px;\n background: #1a1a1a;\n color: #888;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 11px;\n padding: 6px 10px;\n border-radius: 4px;\n text-decoration: none;\n opacity: 0.7;\n transition: opacity 0.2s, color 0.2s;\n z-index: 9999;\n line-height: 1;\n }\n\n #${BADGE_ID}:hover {\n opacity: 1;\n color: #fff;\n }\n\n @media (max-width: 480px) {\n #${BADGE_ID} {\n bottom: 10px;\n right: 10px;\n font-size: 10px;\n padding: 5px 8px;\n }\n }\n\n @media (prefers-color-scheme: light) {\n #${BADGE_ID} {\n background: #f5f5f5;\n color: #666;\n }\n\n #${BADGE_ID}:hover {\n color: #1a1a1a;\n }\n }\n`\n\n/**\n * Branding service for \"Powered by Lynkow\" badge\n *\n * Browser-only. All methods are no-op on server.\n */\nexport class BrandingService {\n private badgeElement: HTMLElement | null = null\n\n /**\n * Inject styles into document head\n */\n private injectStyles(): void {\n if (document.getElementById(STYLES_ID)) return\n\n const styleElement = document.createElement('style')\n styleElement.id = STYLES_ID\n styleElement.textContent = BADGE_STYLES\n document.head.appendChild(styleElement)\n }\n\n /**\n * Inject the branding badge into the page\n */\n inject(): void {\n if (!isBrowser) return\n if (document.getElementById(BADGE_ID)) return\n\n // Inject styles\n this.injectStyles()\n\n // Create badge element\n const badge = document.createElement('a')\n badge.id = BADGE_ID\n badge.href = 'https://lynkow.com?ref=badge'\n badge.target = '_blank'\n badge.rel = 'noopener noreferrer'\n badge.textContent = 'Powered by Lynkow'\n badge.setAttribute('aria-label', 'Powered by Lynkow - Visit lynkow.com')\n\n document.body.appendChild(badge)\n this.badgeElement = badge\n }\n\n /**\n * Remove the branding badge from the page\n */\n remove(): void {\n if (!isBrowser) return\n\n this.badgeElement?.remove()\n this.badgeElement = null\n\n // Also remove styles\n document.getElementById(STYLES_ID)?.remove()\n }\n\n /**\n * Check if the badge is currently visible\n */\n isVisible(): boolean {\n if (!isBrowser) return false\n return document.getElementById(BADGE_ID) !== null\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.remove()\n }\n}\n","/**\n * Cache manager for Lynkow SDK\n * Uses memory cache on server, localStorage on browser\n */\n\nimport { isBrowser } from './environment'\n\n/**\n * Cache entry with TTL\n */\ninterface CacheEntry<T> {\n value: T\n expiresAt: number\n}\n\n/**\n * Cache configuration\n */\nexport interface CacheConfig {\n /** Default TTL in milliseconds (default: 5 minutes) */\n defaultTtl?: number\n /** Storage key prefix */\n prefix?: string\n}\n\nconst DEFAULT_TTL = 5 * 60 * 1000 // 5 minutes\nconst STORAGE_PREFIX = 'lynkow_cache_'\n\n/**\n * In-memory cache for server environment\n */\nconst memoryCache = new Map<string, CacheEntry<unknown>>()\n\n/**\n * Create a cache manager\n */\nexport function createCache(config: CacheConfig = {}) {\n const defaultTtl = config.defaultTtl ?? DEFAULT_TTL\n const prefix = config.prefix ?? STORAGE_PREFIX\n\n /**\n * Get full cache key with prefix\n */\n function getKey(key: string): string {\n return `${prefix}${key}`\n }\n\n /**\n * Check if an entry is expired\n */\n function isExpired(entry: CacheEntry<unknown>): boolean {\n return Date.now() > entry.expiresAt\n }\n\n /**\n * Get value from cache\n */\n function get<T>(key: string): T | null {\n const fullKey = getKey(key)\n\n if (isBrowser) {\n try {\n const stored = localStorage.getItem(fullKey)\n if (!stored) return null\n\n const entry = JSON.parse(stored) as CacheEntry<T>\n if (isExpired(entry)) {\n localStorage.removeItem(fullKey)\n return null\n }\n return entry.value\n } catch {\n return null\n }\n }\n\n // Server: use memory cache\n const entry = memoryCache.get(fullKey) as CacheEntry<T> | undefined\n if (!entry) return null\n\n if (isExpired(entry)) {\n memoryCache.delete(fullKey)\n return null\n }\n return entry.value\n }\n\n /**\n * Set value in cache\n */\n function set<T>(key: string, value: T, ttl: number = defaultTtl): void {\n const fullKey = getKey(key)\n const entry: CacheEntry<T> = {\n value,\n expiresAt: Date.now() + ttl,\n }\n\n if (isBrowser) {\n try {\n localStorage.setItem(fullKey, JSON.stringify(entry))\n } catch {\n // localStorage full or unavailable, silently fail\n }\n return\n }\n\n // Server: use memory cache\n memoryCache.set(fullKey, entry)\n }\n\n /**\n * Remove value from cache\n */\n function remove(key: string): void {\n const fullKey = getKey(key)\n\n if (isBrowser) {\n try {\n localStorage.removeItem(fullKey)\n } catch {\n // Silently fail\n }\n return\n }\n\n memoryCache.delete(fullKey)\n }\n\n /**\n * Invalidate cache entries matching a pattern\n * If no pattern is provided, clears all cache entries\n */\n function invalidate(pattern?: string): void {\n if (isBrowser) {\n try {\n const keysToRemove: string[] = []\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i)\n if (key && key.startsWith(prefix)) {\n if (!pattern || key.includes(pattern)) {\n keysToRemove.push(key)\n }\n }\n }\n keysToRemove.forEach((key) => localStorage.removeItem(key))\n } catch {\n // Silently fail\n }\n return\n }\n\n // Server: clear memory cache\n if (!pattern) {\n // Clear all entries with our prefix\n for (const key of memoryCache.keys()) {\n if (key.startsWith(prefix)) {\n memoryCache.delete(key)\n }\n }\n } else {\n // Clear entries matching pattern\n for (const key of memoryCache.keys()) {\n if (key.startsWith(prefix) && key.includes(pattern)) {\n memoryCache.delete(key)\n }\n }\n }\n }\n\n /**\n * Get or set value in cache\n * If value exists and is not expired, returns cached value\n * Otherwise, calls factory function and caches the result\n */\n async function getOrSet<T>(\n key: string,\n factory: () => Promise<T>,\n ttl: number = defaultTtl\n ): Promise<T> {\n const cached = get<T>(key)\n if (cached !== null) {\n return cached\n }\n\n const value = await factory()\n set(key, value, ttl)\n return value\n }\n\n return {\n get,\n set,\n remove,\n invalidate,\n getOrSet,\n }\n}\n\nexport type Cache = ReturnType<typeof createCache>\n","/**\n * Conditional logging utility for Lynkow SDK\n * Only logs when debug mode is enabled\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/**\n * Logger configuration\n */\nexport interface LoggerConfig {\n debug: boolean\n prefix?: string\n}\n\n/**\n * Create a logger instance with the given configuration\n *\n * @param config - Logger configuration\n * @returns Logger instance\n */\nexport function createLogger(config: LoggerConfig) {\n const prefix = config.prefix || '[Lynkow]'\n\n return {\n /**\n * Log a debug message (only when debug mode is enabled)\n */\n debug(...args: unknown[]): void {\n if (config.debug) {\n console.debug(prefix, ...args)\n }\n },\n\n /**\n * Log an info message\n */\n info(...args: unknown[]): void {\n console.info(prefix, ...args)\n },\n\n /**\n * Log a warning message\n */\n warn(...args: unknown[]): void {\n console.warn(prefix, ...args)\n },\n\n /**\n * Log an error message\n */\n error(...args: unknown[]): void {\n console.error(prefix, ...args)\n },\n\n /**\n * Log a message at the specified level\n */\n log(level: LogLevel, ...args: unknown[]): void {\n switch (level) {\n case 'debug':\n this.debug(...args)\n break\n case 'info':\n this.info(...args)\n break\n case 'warn':\n this.warn(...args)\n break\n case 'error':\n this.error(...args)\n break\n }\n },\n }\n}\n\nexport type Logger = ReturnType<typeof createLogger>\n","/**\n * Simple event emitter for Lynkow SDK\n */\n\n/**\n * Event types for the SDK\n */\nexport interface LynkowEvents {\n ready: void\n 'locale-changed': string\n 'consent-changed': Record<string, boolean>\n error: Error\n}\n\nexport type EventName = keyof LynkowEvents\n\n/**\n * Event listener function type\n */\nexport type EventListener<T> = (data: T) => void\n\n/**\n * Create an event emitter\n */\nexport function createEventEmitter() {\n const listeners = new Map<string, Set<EventListener<unknown>>>()\n\n /**\n * Subscribe to an event\n * @returns Unsubscribe function\n */\n function on<K extends EventName>(\n event: K,\n listener: EventListener<LynkowEvents[K]>\n ): () => void {\n if (!listeners.has(event)) {\n listeners.set(event, new Set())\n }\n listeners.get(event)!.add(listener as EventListener<unknown>)\n\n // Return unsubscribe function\n return () => off(event, listener)\n }\n\n /**\n * Unsubscribe from an event\n */\n function off<K extends EventName>(\n event: K,\n listener: EventListener<LynkowEvents[K]>\n ): void {\n const eventListeners = listeners.get(event)\n if (eventListeners) {\n eventListeners.delete(listener as EventListener<unknown>)\n }\n }\n\n /**\n * Emit an event to all listeners\n */\n function emit<K extends EventName>(event: K, data: LynkowEvents[K]): void {\n const eventListeners = listeners.get(event)\n if (!eventListeners) return\n\n for (const listener of eventListeners) {\n try {\n listener(data)\n } catch (error) {\n // Don't let one listener's error affect others\n console.error(`[Lynkow] Error in event listener for \"${event}\":`, error)\n }\n }\n }\n\n /**\n * Subscribe to an event, automatically unsubscribe after first emission\n */\n function once<K extends EventName>(\n event: K,\n listener: EventListener<LynkowEvents[K]>\n ): () => void {\n const wrappedListener = ((data: LynkowEvents[K]) => {\n off(event, wrappedListener as EventListener<LynkowEvents[K]>)\n listener(data)\n }) as EventListener<LynkowEvents[K]>\n\n return on(event, wrappedListener)\n }\n\n /**\n * Remove all listeners for an event or all events\n */\n function removeAllListeners(event?: EventName): void {\n if (event) {\n listeners.delete(event)\n } else {\n listeners.clear()\n }\n }\n\n return {\n on,\n off,\n emit,\n once,\n removeAllListeners,\n }\n}\n\nexport type EventEmitter = ReturnType<typeof createEventEmitter>\n","/**\n * Locale detection and management utilities\n */\n\nimport { isBrowser } from '../core/environment'\n\nconst STORAGE_KEY = 'lynkow_locale'\n\n/**\n * Detect the locale based on priority order:\n * 1. localStorage (previous user choice)\n * 2. URL path prefix (/en/, /fr/)\n * 3. HTML lang attribute\n * 4. Default locale\n *\n * @param enabledLocales - List of enabled locales for the site\n * @param defaultLocale - Default locale to use as fallback\n * @returns Detected locale\n */\nexport function detectLocale(enabledLocales: string[], defaultLocale: string): string {\n if (!isBrowser) {\n return defaultLocale\n }\n\n // 1. localStorage (previous user choice)\n const stored = getStoredLocale()\n if (stored && enabledLocales.includes(stored)) {\n return stored\n }\n\n // 2. URL path prefix\n const pathLocale = getLocaleFromPath(enabledLocales)\n if (pathLocale) {\n return pathLocale\n }\n\n // 3. HTML lang attribute\n const htmlLang = document.documentElement.lang\n if (htmlLang) {\n // Normalize (fr-FR → fr)\n const normalized = htmlLang.split('-')[0]?.toLowerCase()\n if (normalized && enabledLocales.includes(normalized)) {\n return normalized\n }\n }\n\n // 4. Default\n return defaultLocale\n}\n\n/**\n * Get locale from localStorage\n */\nexport function getStoredLocale(): string | null {\n if (!isBrowser) return null\n\n try {\n return localStorage.getItem(STORAGE_KEY)\n } catch {\n return null\n }\n}\n\n/**\n * Save locale to localStorage\n */\nexport function setStoredLocale(locale: string): void {\n if (!isBrowser) return\n\n try {\n localStorage.setItem(STORAGE_KEY, locale)\n } catch {\n // localStorage unavailable, silently fail\n }\n}\n\n/**\n * Remove locale from localStorage\n */\nexport function removeStoredLocale(): void {\n if (!isBrowser) return\n\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Silently fail\n }\n}\n\n/**\n * Extract locale from URL path\n * /en/about → en\n * /fr/services → fr\n * /about → null\n *\n * @param enabledLocales - List of enabled locales to check against\n * @returns Locale from path or null\n */\nexport function getLocaleFromPath(enabledLocales: string[]): string | null {\n if (!isBrowser) return null\n\n const path = window.location.pathname\n const segments = path.split('/').filter(Boolean)\n\n if (segments.length > 0) {\n const firstSegment = segments[0]?.toLowerCase()\n if (firstSegment && enabledLocales.includes(firstSegment)) {\n return firstSegment\n }\n }\n\n return null\n}\n\n/**\n * Check if a locale is valid (exists in enabled locales)\n */\nexport function isValidLocale(locale: string, enabledLocales: string[]): boolean {\n return enabledLocales.includes(locale)\n}\n","/**\n * Lynkow SDK Client\n * Main entry point for the SDK\n */\n\nimport type { LynkowConfig, LynkowClient, SiteConfig } from './types'\nimport type { InternalConfig } from './services/base'\nimport { ContentsService } from './services/contents'\nimport { CategoriesService } from './services/categories'\nimport { TagsService } from './services/tags'\nimport { PagesService } from './services/pages'\nimport { BlocksService } from './services/blocks'\nimport { FormsService } from './services/forms'\nimport { ReviewsService } from './services/reviews'\nimport { SiteService } from './services/site'\nimport { LegalService } from './services/legal'\nimport { CookiesService } from './services/cookies'\nimport { SeoService } from './services/seo'\nimport { PathsService } from './services/paths'\nimport { AnalyticsService } from './services/analytics'\nimport { ConsentService } from './services/consent'\nimport { BrandingService } from './services/branding'\n\n// Core modules\nimport { createCache, type Cache } from './core/cache'\nimport { createLogger, type Logger } from './core/logger'\nimport { createEventEmitter, type EventEmitter, type EventName, type LynkowEvents } from './utils/events'\nimport { isBrowser } from './core/environment'\nimport { detectLocale, setStoredLocale, isValidLocale } from './utils/locale'\n\n/**\n * Default Lynkow API base URL\n */\nconst DEFAULT_BASE_URL = 'https://api.lynkow.com'\n\n/**\n * Extended configuration for SDK v3\n */\nexport interface ClientConfig extends LynkowConfig {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean\n}\n\n/**\n * Extended client interface for SDK v3\n */\nexport interface Client extends LynkowClient {\n /**\n * Current locale\n */\n readonly locale: string\n\n /**\n * Available locales from site configuration\n */\n readonly availableLocales: string[]\n\n /**\n * Client configuration (readonly)\n */\n readonly config: Readonly<{\n siteId: string\n baseUrl: string\n debug: boolean\n }>\n\n /**\n * Set the current locale\n * @param locale - New locale to use\n */\n setLocale(locale: string): void\n\n /**\n * Clear all cached data\n */\n clearCache(): void\n\n /**\n * Destroy the client and clean up resources\n */\n destroy(): void\n\n /**\n * Subscribe to an event\n * @param event - Event name\n * @param listener - Event listener\n * @returns Unsubscribe function\n */\n on<K extends EventName>(event: K, listener: (data: LynkowEvents[K]) => void): () => void\n\n /**\n * Alias for blocks (v3 naming)\n * @deprecated Use `globals` instead in v3\n */\n blocks: BlocksService\n\n /**\n * Global blocks service (v3 naming)\n */\n globals: BlocksService\n\n /**\n * Analytics service (browser-only)\n */\n analytics: AnalyticsService\n\n /**\n * Consent service (cookie consent management)\n */\n consent: ConsentService\n\n /**\n * Branding service (badge for free plan)\n */\n branding: BrandingService\n}\n\n/**\n * Internal state for the client\n */\ninterface ClientState {\n locale: string\n availableLocales: string[]\n siteConfig: SiteConfig | null\n initialized: boolean\n}\n\n/**\n * Creates a Lynkow client instance (SDK v3)\n *\n * @param config - Client configuration\n * @returns Client instance with all services\n *\n * @example\n * ```typescript\n * const lynkow = createClient({\n * siteId: 'your-site-uuid',\n * locale: 'fr',\n * debug: true\n * })\n *\n * const posts = await lynkow.contents.list()\n * ```\n */\nexport function createClient(config: ClientConfig): Client {\n // Validation\n if (!config.siteId) {\n throw new Error('Lynkow SDK: siteId is required')\n }\n\n // Create core utilities\n const cache = createCache()\n const logger = createLogger({ debug: config.debug ?? false })\n const events = createEventEmitter()\n\n // Normalize configuration\n const normalizedBaseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, '')\n\n const internalConfig: InternalConfig = {\n siteId: config.siteId,\n baseUrl: normalizedBaseUrl,\n locale: config.locale,\n fetchOptions: config.fetchOptions || {},\n cache,\n }\n\n // Client state\n const state: ClientState = {\n locale: config.locale || 'fr',\n availableLocales: ['fr'],\n siteConfig: null,\n initialized: false,\n }\n\n // Create services\n const services = {\n contents: new ContentsService(internalConfig),\n categories: new CategoriesService(internalConfig),\n tags: new TagsService(internalConfig),\n pages: new PagesService(internalConfig),\n blocks: new BlocksService(internalConfig),\n forms: new FormsService(internalConfig),\n reviews: new ReviewsService(internalConfig),\n site: new SiteService(internalConfig),\n legal: new LegalService(internalConfig),\n cookies: new CookiesService(internalConfig),\n seo: new SeoService(internalConfig),\n paths: new PathsService(internalConfig),\n analytics: new AnalyticsService(internalConfig),\n consent: new ConsentService(internalConfig, events),\n branding: new BrandingService(),\n }\n\n /**\n * Update internal config locale for all services\n */\n function updateServicesLocale(locale: string): void {\n internalConfig.locale = locale\n }\n\n /**\n * Initialize client (fetch site config, detect locale)\n */\n async function initialize(): Promise<void> {\n if (state.initialized) return\n\n try {\n // Fetch site configuration\n const siteConfig = await services.site.getConfig()\n state.siteConfig = siteConfig\n const defaultLocale = siteConfig.defaultLocale || 'fr'\n state.availableLocales = siteConfig.enabledLocales || [defaultLocale]\n\n // Detect locale (browser only)\n if (isBrowser && !config.locale) {\n const detected = detectLocale(state.availableLocales, defaultLocale)\n state.locale = detected\n updateServicesLocale(detected)\n }\n\n state.initialized = true\n logger.debug('Client initialized', { locale: state.locale, availableLocales: state.availableLocales })\n\n // Initialize browser-only features\n if (isBrowser) {\n // Load and initialize the analytics tracker\n // The tracker handles consent checking internally via localStorage\n services.analytics.init()\n\n // Show consent banner if user hasn't made a choice yet\n if (!services.consent.hasConsented()) {\n services.consent.show()\n }\n\n // Inject branding badge if required (free plan)\n if (siteConfig.showBranding) {\n services.branding.inject()\n }\n }\n\n events.emit('ready', undefined as void)\n } catch (error) {\n logger.error('Failed to initialize client', error)\n events.emit('error', error as Error)\n }\n }\n\n // Auto-initialize in browser\n if (isBrowser) {\n // Defer initialization to next tick to allow event listeners to be set up\n setTimeout(() => initialize(), 0)\n }\n\n // Build the client object\n const client: Client = {\n // Services\n ...services,\n\n // v3 alias: globals = blocks\n globals: services.blocks,\n\n // Readonly config\n config: Object.freeze({\n siteId: config.siteId,\n baseUrl: normalizedBaseUrl,\n debug: config.debug ?? false,\n }),\n\n // Locale getter\n get locale(): string {\n return state.locale\n },\n\n // Available locales getter\n get availableLocales(): string[] {\n return [...state.availableLocales]\n },\n\n // Set locale\n setLocale(locale: string): void {\n if (!isValidLocale(locale, state.availableLocales)) {\n logger.warn(`Locale \"${locale}\" is not available. Available: ${state.availableLocales.join(', ')}`)\n return\n }\n\n if (locale === state.locale) return\n\n state.locale = locale\n updateServicesLocale(locale)\n\n // Save to localStorage (browser)\n if (isBrowser) {\n setStoredLocale(locale)\n }\n\n // Invalidate cache (content changes with locale)\n cache.invalidate()\n\n // Emit event\n events.emit('locale-changed', locale)\n logger.debug('Locale changed to', locale)\n },\n\n // Clear cache\n clearCache(): void {\n cache.invalidate()\n logger.debug('Cache cleared')\n },\n\n // Destroy client\n destroy(): void {\n services.analytics.destroy()\n services.consent.destroy()\n services.branding.destroy()\n cache.invalidate()\n events.removeAllListeners()\n logger.debug('Client destroyed')\n },\n\n // Event subscription\n on<K extends EventName>(event: K, listener: (data: LynkowEvents[K]) => void): () => void {\n return events.on(event, listener)\n },\n }\n\n return client\n}\n\n/**\n * Creates a Lynkow client instance (legacy naming)\n *\n * @deprecated Use `createClient` instead\n * @param config - Client configuration\n * @returns Client instance with all services\n */\nexport function createLynkowClient(config: LynkowConfig): LynkowClient {\n // For backward compatibility, return the basic client without v3 features\n if (!config.siteId) {\n throw new Error('Lynkow SDK: siteId is required')\n }\n\n const internalConfig: InternalConfig = {\n siteId: config.siteId,\n baseUrl: (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, ''),\n locale: config.locale,\n fetchOptions: config.fetchOptions || {},\n }\n\n return {\n contents: new ContentsService(internalConfig),\n categories: new CategoriesService(internalConfig),\n tags: new TagsService(internalConfig),\n pages: new PagesService(internalConfig),\n blocks: new BlocksService(internalConfig),\n forms: new FormsService(internalConfig),\n reviews: new ReviewsService(internalConfig),\n site: new SiteService(internalConfig),\n legal: new LegalService(internalConfig),\n cookies: new CookiesService(internalConfig),\n seo: new SeoService(internalConfig),\n paths: new PathsService(internalConfig),\n }\n}\n","// Config\nexport type { LynkowConfig, LynkowClient } from './config'\n\n// Entities\nexport type {\n Content,\n ContentSummary,\n ContentBody,\n TipTapNode,\n TipTapMark,\n Author,\n} from './content'\n\nexport type {\n Category,\n CategoryWithCount,\n CategoryDetail,\n CategoryTreeNode,\n} from './category'\n\nexport type { Tag } from './tag'\n\nexport type { Page, PageSummary, PageSeo, Alternate } from './page'\n\nexport type { GlobalBlock } from './block'\n\nexport type {\n Form,\n FormField,\n FormFieldType,\n FormFieldOption,\n FormFieldValidation,\n FormSettings,\n FormSubmitData,\n} from './form'\n\nexport type {\n Review,\n ReviewResponse,\n ReviewSettings,\n ReviewSubmitData,\n} from './review'\n\nexport type { SiteConfig } from './site'\n\nexport type {\n LegalDocument,\n LegalListResponse,\n LegalDocumentResponse,\n} from './legal'\n\nexport type {\n CookieConfig,\n CookieCategory,\n CookieTexts,\n CookiePreferences,\n} from './cookie'\n\nexport type { Path, Redirect } from './path'\n\n// Responses\nexport type {\n PaginationMeta,\n PaginatedResponse,\n ContentsListResponse,\n CategoriesListResponse,\n CategoryTreeResponse,\n CategoryDetailResponse,\n TagsListResponse,\n PagesListResponse,\n SiteConfigResponse,\n GlobalBlockResponse,\n ReviewsListResponse,\n FormSubmitResponse,\n ReviewSubmitResponse,\n ConsentLogResponse,\n PathsListResponse,\n ContentResolveResponse,\n CategoryResolveResponse,\n ResolveResponse,\n} from './response'\n\n// Filters\nexport type {\n BaseRequestOptions,\n PaginationOptions,\n SortOptions,\n ContentsFilters,\n CategoryOptions,\n ReviewsFilters,\n SubmitOptions,\n} from './filters'\n\n// Errors\nexport type { ErrorCode, ApiErrorDetail } from './error'\n\n// Type guards\nimport type { ResolveResponse, ContentResolveResponse, CategoryResolveResponse } from './response'\n\n/**\n * Checks if a resolution response is a content\n */\nexport function isContentResolve(\n response: ResolveResponse\n): response is ContentResolveResponse {\n return response.type === 'content'\n}\n\n/**\n * Checks if a resolution response is a category\n */\nexport function isCategoryResolve(\n response: ResolveResponse\n): response is CategoryResolveResponse {\n return response.type === 'category'\n}\n"]}