lynkow 1.0.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 ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';var a=class extends Error{status;code;errors;constructor(e,t,s,r=[]){super(s),this.name="LynkowError",this.status=e,this.code=t,this.errors=r;}};function v(o){switch(o){case 400:return "BAD_REQUEST";case 401:return "UNAUTHORIZED";case 403:return "FORBIDDEN";case 404:return "NOT_FOUND";case 422:return "VALIDATION_ERROR";case 429:return "TOO_MANY_REQUESTS";case 503:return "SERVICE_UNAVAILABLE";default:return "INTERNAL_ERROR"}}async function L(o,e){let t;try{t=await fetch(o,e);}catch(p){throw new a(0,"NETWORK_ERROR","Network error: Unable to reach the server",[{message:p instanceof Error?p.message:"Unknown error"}])}if(t.ok)return t.json();let s={};try{s=await t.json();}catch{}let r=v(t.status),i=s.error||s.message||`HTTP error: ${t.status}`,O=s.errors||[{message:i}];throw new a(t.status,r,i,O)}function P(o){let e=new URLSearchParams;for(let[t,s]of Object.entries(o))s!=null&&s!==""&&e.append(t,String(s));return e.toString()}var n=class{config;constructor(e){this.config=e;}buildEndpointUrl(e,t){let s=`${this.config.baseUrl}/public/${this.config.siteId}${e}`;if(t&&Object.keys(t).length>0){let r=P(t);return `${s}?${r}`}return s}async get(e,t,s){let r=s?.locale||this.config.locale,i=r?{...t,locale:r}:t,O=this.buildEndpointUrl(e,i),p=this.mergeFetchOptions(s?.fetchOptions);return L(O,{method:"GET",...p})}async post(e,t,s){let r=this.buildEndpointUrl(e),i=this.mergeFetchOptions(s?.fetchOptions);return L(r,{method:"POST",...i,headers:{"Content-Type":"application/json",...i.headers},body:JSON.stringify(t)})}async getText(e,t){let s=this.buildEndpointUrl(e),r=this.mergeFetchOptions(t?.fetchOptions),i=await fetch(s,{method:"GET",...r});if(!i.ok)throw new Error(`HTTP error: ${i.status}`);return i.text()}mergeFetchOptions(e){return {...this.config.fetchOptions,...e,headers:{...this.config.fetchOptions.headers,...e?.headers}}}};var g=class extends n{async list(e,t){let s={};return e?.page&&(s.page=e.page),e?.perPage&&(s.perPage=e.perPage),e?.category&&(s.category=e.category),e?.tag&&(s.tag=e.tag),e?.search&&(s.search=e.search),e?.sort&&(s.sort=e.sort),e?.order&&(s.order=e.order),e?.locale&&(s.locale=e.locale),this.get("/contents",s,t)}async getBySlug(e,t){return this.get(`/contents/slug/${encodeURIComponent(e)}`,void 0,t)}};var m=class extends n{async list(e){return this.get("/categories",void 0,e)}async tree(e){return this.get("/categories/tree",void 0,e)}async getBySlug(e,t){let s={};return t?.page&&(s.page=t.page),t?.perPage&&(s.limit=t.perPage),this.get(`/categories/${encodeURIComponent(e)}`,s,t)}};var c=class extends n{async list(e){return this.get("/tags",void 0,e)}};var R=class extends n{async list(e){return this.get("/pages",void 0,e)}async getBySlug(e,t){return (await this.get(`/pages/${encodeURIComponent(e)}`,void 0,t)).data}async getByPath(e,t){return (await this.get("/page-by-path",{path:e},t)).data}async getJsonLd(e,t){return (await this.get(`/pages/${encodeURIComponent(e)}/json-ld`,void 0,t)).data}};var u=class extends n{async siteConfig(e){return this.get("/site-config",void 0,e)}async global(e,t){return this.get(`/global/${encodeURIComponent(e)}`,void 0,t)}};function l(o){return {_hp:"",_ts:o}}var y=class extends n{sessionStartTime;constructor(e){super(e),this.sessionStartTime=Date.now();}async getBySlug(e){return (await this.get(`/forms/${encodeURIComponent(e)}`)).data}async submit(e,t,s){let r=l(this.sessionStartTime),i={...t,...r};return s?.recaptchaToken&&(i._recaptcha_token=s.recaptchaToken),this.post(`/forms/${encodeURIComponent(e)}/submit`,i,s)}};var d=class extends n{sessionStartTime;constructor(e){super(e),this.sessionStartTime=Date.now();}async list(e,t){let s={};return e?.page&&(s.page=e.page),e?.perPage&&(s.perPage=e.perPage),e?.minRating&&(s.minRating=e.minRating),e?.maxRating&&(s.maxRating=e.maxRating),e?.sort&&(s.sort=e.sort),e?.order&&(s.order=e.order),this.get("/reviews",s,t)}async getBySlug(e){return (await this.get(`/reviews/${encodeURIComponent(e)}`)).data}async settings(){return this.get("/reviews/settings")}async submit(e,t){let s=l(this.sessionStartTime),r={...e,...s};return t?.recaptchaToken&&(r._recaptcha_token=t.recaptchaToken),this.post("/reviews",r,t)}};var f=class extends n{async getConfig(){return (await this.get("/site")).data}};var C=class extends n{async list(e){return this.get("/legal",void 0,e)}async getByType(e,t){return (await this.get(`/legal/${e}`,void 0,t)).data}};var h=class extends n{async getConfig(){return (await this.get("/cookie-consent/config")).data}async logConsent(e,t){return this.post("/cookie-consent/log",{preferences:e},t)}};var w=class extends n{async sitemap(e){return this.getText("/sitemap.xml",e)}async robots(e){return this.getText("/robots.txt",e)}};var S=class extends n{async list(e){return this.get("/paths",void 0,e)}async resolve(e,t){return this.get("/resolve",{path:e},t)}async matchRedirect(e,t){try{return (await this.get("/redirects/match",{path:e},t)).data}catch(s){if(s instanceof a&&s.status===404)return null;throw s}}};var B="https://api.lynkow.com";function k(o){if(!o.siteId)throw new Error("Lynkow SDK: siteId is required");let e={siteId:o.siteId,baseUrl:(o.baseUrl||B).replace(/\/$/,""),locale:o.locale,fetchOptions:o.fetchOptions||{}};return {contents:new g(e),categories:new m(e),tags:new c(e),pages:new R(e),blocks:new u(e),forms:new y(e),reviews:new d(e),site:new f(e),legal:new C(e),cookies:new h(e),seo:new w(e),paths:new S(e)}}function b(o){return o.type==="content"}function x(o){return o.type==="category"}function T(o){return o instanceof a}
2
+ exports.LynkowError=a;exports.createLynkowClient=k;exports.isCategoryResolve=x;exports.isContentResolve=b;exports.isLynkowError=T;//# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../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/client.ts","../src/types/index.ts"],"names":["LynkowError","status","code","message","errors","getErrorCode","fetchWithError","url","options","response","error","errorData","buildQueryString","params","searchParams","key","value","BaseService","config","path","query","baseUrl","queryString","locale","queryWithLocale","fetchOptions","body","localOptions","ContentsService","filters","slug","CategoriesService","TagsService","PagesService","BlocksService","generateSpamFields","sessionStartTime","FormsService","data","spamFields","ReviewsService","slugOrId","SiteService","LegalService","type","CookiesService","preferences","SeoService","PathsService","DEFAULT_BASE_URL","createLynkowClient","internalConfig","isContentResolve","isCategoryResolve","isLynkowError"],"mappings":"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","file":"index.js","sourcesContent":["import type { ApiErrorDetail, ErrorCode } from '../types'\n\n/**\n * Erreur specifique au SDK Lynkow\n */\nexport class LynkowError extends Error {\n /** Code HTTP */\n status: number\n\n /** Code d'erreur */\n code: ErrorCode\n\n /** Liste des erreurs detaillees */\n errors: ApiErrorDetail[]\n\n constructor(\n status: number,\n code: ErrorCode,\n message: string,\n errors: ApiErrorDetail[] = []\n ) {\n super(message)\n this.name = 'LynkowError'\n this.status = status\n this.code = code\n this.errors = errors\n }\n}\n\n/**\n * Convertit un code HTTP en code d'erreur\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 * Effectue une requete fetch avec gestion des erreurs\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 // Erreur reseau\n throw new LynkowError(\n 0,\n 'NETWORK_ERROR',\n 'Network error: Unable to reach the server',\n [{ message: error instanceof Error ? error.message : 'Unknown error' }]\n )\n }\n\n // Reponse OK\n if (response.ok) {\n return response.json()\n }\n\n // Erreur HTTP\n let errorData: Record<string, unknown> = {}\n try {\n errorData = await response.json()\n } catch {\n // Pas de body JSON\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(response.status, code, message, errors)\n}\n","/**\n * Construit une query string a partir d'un objet\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 { fetchWithError } from '../utils/fetch'\nimport { buildQueryString } from '../utils/query'\n\n/**\n * Configuration interne normalisee\n */\nexport interface InternalConfig {\n siteId: string\n baseUrl: string\n locale?: string\n fetchOptions: RequestInit\n}\n\n/**\n * Service de base dont heritent tous les services specifiques\n */\nexport abstract class BaseService {\n protected config: InternalConfig\n\n constructor(config: InternalConfig) {\n this.config = config\n }\n\n /**\n * Construit l'URL complete pour un 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 * Effectue une requete GET\n */\n protected async get<T>(\n path: string,\n query?: Record<string, unknown>,\n options?: BaseRequestOptions\n ): Promise<T> {\n // Ajouter la locale si configuree\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 * Effectue une requete POST\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 * Effectue une requete GET qui retourne du texte brut (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 * Fusionne les options fetch locales avec celles globales\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 } from './base'\nimport type {\n Content,\n ContentsFilters,\n ContentsListResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les contenus (articles de blog)\n */\nexport class ContentsService extends BaseService {\n /**\n * Recupere une liste paginee de contenus publies\n *\n * @param filters - Filtres optionnels (pagination, categorie, tag, recherche)\n * @param options - Options de requete\n * @returns Liste paginee de contenus\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 return this.get<ContentsListResponse>('/contents', query, options)\n }\n\n /**\n * Recupere un contenu par son slug\n *\n * @param slug - Slug du contenu\n * @param options - Options de requete (locale)\n * @returns Contenu complet\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 return this.get<Content>(\n `/contents/slug/${encodeURIComponent(slug)}`,\n undefined,\n options\n )\n }\n}\n","import { BaseService } from './base'\nimport type {\n CategoriesListResponse,\n CategoryTreeResponse,\n CategoryDetailResponse,\n CategoryOptions,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les categories\n */\nexport class CategoriesService extends BaseService {\n /**\n * Recupere la liste des categories\n *\n * @param options - Options de requete (locale)\n * @returns Liste des categories avec compteurs\n *\n * @example\n * ```typescript\n * const { data, blogUrlMode } = await lynkow.categories.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<CategoriesListResponse> {\n return this.get<CategoriesListResponse>('/categories', undefined, options)\n }\n\n /**\n * Recupere l'arborescence des categories\n *\n * @param options - Options de requete (locale)\n * @returns Arborescence complete\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 return this.get<CategoryTreeResponse>(\n '/categories/tree',\n undefined,\n options\n )\n }\n\n /**\n * Recupere une categorie avec ses contenus pagines\n *\n * @param slug - Slug de la categorie\n * @param options - Options (locale, pagination)\n * @returns Categorie avec contenus\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 return this.get<CategoryDetailResponse>(\n `/categories/${encodeURIComponent(slug)}`,\n query,\n options\n )\n }\n}\n","import { BaseService } from './base'\nimport type { TagsListResponse, BaseRequestOptions } from '../types'\n\n/**\n * Service pour les tags\n */\nexport class TagsService extends BaseService {\n /**\n * Recupere la liste des tags\n *\n * @param options - Options de requete (locale)\n * @returns Liste des tags\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.tags.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<TagsListResponse> {\n return this.get<TagsListResponse>('/tags', undefined, options)\n }\n}\n","import { BaseService } from './base'\nimport type { Page, PagesListResponse, BaseRequestOptions } from '../types'\n\n/**\n * Service pour les pages (Site Blocks de type \"page\")\n */\nexport class PagesService extends BaseService {\n /**\n * Recupere la liste des pages publiees\n *\n * @param options - Options de requete (locale)\n * @returns Liste des pages\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.pages.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<PagesListResponse> {\n return this.get<PagesListResponse>('/pages', undefined, options)\n }\n\n /**\n * Recupere une page par son slug\n *\n * @param slug - Slug de la page\n * @param options - Options de requete (locale)\n * @returns Page complete avec donnees resolues\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 response = await this.get<{ data: Page }>(\n `/pages/${encodeURIComponent(slug)}`,\n undefined,\n options\n )\n return response.data\n }\n\n /**\n * Recupere une page par son chemin\n *\n * @param path - Chemin de la page (ex: /services/consulting)\n * @param options - Options de requete (locale)\n * @returns Page complete avec donnees resolues\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 response = await this.get<{ data: Page }>(\n '/page-by-path',\n { path },\n options\n )\n return response.data\n }\n\n /**\n * Recupere les donnees JSON-LD pour une page\n *\n * @param slug - Slug de la page\n * @param options - Options de requete (locale)\n * @returns Donnees JSON-LD (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 response = await this.get<{ data: Record<string, unknown> }>(\n `/pages/${encodeURIComponent(slug)}/json-ld`,\n undefined,\n options\n )\n return response.data\n }\n}\n","import { BaseService } from './base'\nimport type {\n SiteConfigResponse,\n GlobalBlockResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les blocs globaux (header, footer, etc.)\n */\nexport class BlocksService extends BaseService {\n /**\n * Recupere la configuration du site avec tous les blocs globaux\n *\n * @param options - Options de requete (locale)\n * @returns Configuration et blocs globaux\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.blocks.siteConfig()\n * const header = data.globals['header']\n * const footer = data.globals['footer']\n * ```\n */\n async siteConfig(options?: BaseRequestOptions): Promise<SiteConfigResponse> {\n return this.get<SiteConfigResponse>('/site-config', undefined, options)\n }\n\n /**\n * Recupere un bloc global specifique par son slug\n *\n * @param slug - Slug du bloc (ex: 'header', 'footer')\n * @param options - Options de requete (locale)\n * @returns Bloc global avec donnees resolues\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.blocks.global('header')\n * // data.data contient les donnees du bloc\n * ```\n */\n async global(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<GlobalBlockResponse> {\n return this.get<GlobalBlockResponse>(\n `/global/${encodeURIComponent(slug)}`,\n undefined,\n options\n )\n }\n}\n","/**\n * Champs anti-spam pour les soumissions publiques\n */\nexport interface SpamFields {\n /** Champ honeypot (doit etre vide) */\n _hp: string\n\n /** Timestamp de debut de session */\n _ts: number\n}\n\n/**\n * Genere les champs anti-spam pour une soumission\n *\n * @param sessionStartTime - Timestamp de creation du client\n * @returns Champs anti-spam\n */\nexport function generateSpamFields(sessionStartTime: number): SpamFields {\n return {\n _hp: '', // Honeypot - toujours vide\n _ts: sessionStartTime, // Timestamp de session\n }\n}\n","import { BaseService, 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\n/**\n * Service pour les formulaires\n */\nexport class FormsService extends BaseService {\n /**\n * Timestamp de creation du client (pour anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Recupere un formulaire par son slug\n *\n * @param slug - Slug du formulaire\n * @returns Schema du formulaire\n *\n * @example\n * ```typescript\n * const form = await lynkow.forms.getBySlug('contact')\n * // Utiliser form.schema pour generer le formulaire\n * ```\n */\n async getBySlug(slug: string): Promise<Form> {\n const response = await this.get<{ data: Form }>(\n `/forms/${encodeURIComponent(slug)}`\n )\n return response.data\n }\n\n /**\n * Soumet un formulaire\n *\n * Les champs anti-spam (_hp, _ts) sont ajoutes automatiquement.\n *\n * @param slug - Slug du formulaire\n * @param data - Donnees du formulaire\n * @param options - Options (token reCAPTCHA si active)\n * @returns Reponse de soumission\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 // Ajouter les champs anti-spam\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Construire le body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Ajouter le token reCAPTCHA si fourni\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","import { BaseService, 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\n/**\n * Service pour les avis clients\n */\nexport class ReviewsService extends BaseService {\n /**\n * Timestamp de creation du client (pour anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Recupere la liste des avis approuves\n *\n * @param filters - Filtres (pagination, note)\n * @param options - Options de requete\n * @returns Liste paginee des avis\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 return this.get<ReviewsListResponse>('/reviews', query, options)\n }\n\n /**\n * Recupere un avis par son slug ou ID\n *\n * @param slugOrId - Slug ou ID de l'avis\n * @returns Avis complet\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 response = await this.get<{ data: Review }>(\n `/reviews/${encodeURIComponent(slugOrId)}`\n )\n return response.data\n }\n\n /**\n * Recupere les parametres publics des avis\n *\n * @returns Parametres (champs requis, echelle de notes, 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 return this.get<ReviewSettings>('/reviews/settings')\n }\n\n /**\n * Soumet un nouvel avis\n *\n * Les champs anti-spam (_hp, _ts) sont ajoutes automatiquement.\n *\n * @param data - Donnees de l'avis\n * @param options - Options (token reCAPTCHA si active)\n * @returns Reponse de soumission\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 // Ajouter les champs anti-spam\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Construire le body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Ajouter le token reCAPTCHA si fourni\n if (options?.recaptchaToken) {\n body['_recaptcha_token'] = options.recaptchaToken\n }\n\n return this.post<ReviewSubmitResponse>('/reviews', body, options)\n }\n}\n","import { BaseService } from './base'\nimport type { SiteConfig } from '../types'\n\n/**\n * Service pour la configuration du site\n */\nexport class SiteService extends BaseService {\n /**\n * Recupere la configuration publique du site\n *\n * @returns Configuration du site\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 response = await this.get<{ data: SiteConfig }>('/site')\n return response.data\n }\n}\n","import { BaseService } from './base'\nimport type {\n LegalDocument,\n LegalDocumentType,\n LegalListResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les documents legaux\n */\nexport class LegalService extends BaseService {\n /**\n * Recupere la liste des documents legaux\n *\n * @param options - Options de requete (locale)\n * @returns Liste des documents disponibles\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.legal.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<LegalListResponse> {\n return this.get<LegalListResponse>('/legal', undefined, options)\n }\n\n /**\n * Recupere un document legal par son type\n *\n * @param type - Type de document ('terms', 'privacy', etc.)\n * @param options - Options de requete (locale)\n * @returns Document legal complet\n *\n * @example\n * ```typescript\n * const privacy = await lynkow.legal.getByType('privacy')\n * // privacy.content contient le HTML\n * ```\n */\n async getByType(\n type: LegalDocumentType,\n options?: BaseRequestOptions\n ): Promise<LegalDocument> {\n const response = await this.get<{ data: LegalDocument }>(\n `/legal/${type}`,\n undefined,\n options\n )\n return response.data\n }\n}\n","import { BaseService } from './base'\nimport type {\n CookieConfig,\n CookiePreferences,\n ConsentLogResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour le consentement cookies\n */\nexport class CookiesService extends BaseService {\n /**\n * Recupere la configuration du bandeau de cookies\n *\n * @returns Configuration du bandeau\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 response = await this.get<{ data: CookieConfig }>(\n '/cookie-consent/config'\n )\n return response.data\n }\n\n /**\n * Enregistre le consentement de l'utilisateur\n *\n * @param preferences - Preferences par categorie\n * @returns Confirmation avec ID du consentement\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","import { BaseService } from './base'\nimport type { BaseRequestOptions } from '../types'\n\n/**\n * Service pour les fichiers SEO\n */\nexport class SeoService extends BaseService {\n /**\n * Recupere le sitemap XML\n *\n * @returns Contenu XML du sitemap\n *\n * @example\n * ```typescript\n * // Dans une route API Next.js\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 * Recupere le fichier robots.txt\n *\n * @returns Contenu du robots.txt\n *\n * @example\n * ```typescript\n * // Dans une route API Next.js\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 } from './base'\nimport type {\n PathsListResponse,\n ResolveResponse,\n Redirect,\n BaseRequestOptions,\n} from '../types'\nimport { LynkowError } from '../utils/fetch'\n\n/**\n * Service pour les chemins (SSG, resolution)\n */\nexport class PathsService extends BaseService {\n /**\n * Recupere tous les chemins pour la generation statique\n *\n * @param options - Options de requete (locale)\n * @returns Liste des chemins\n *\n * @example\n * ```typescript\n * // Dans generateStaticParams() de Next.js\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 return this.get<PathsListResponse>('/paths', undefined, options)\n }\n\n /**\n * Resout un chemin vers son contenu ou categorie\n *\n * @param path - Chemin a resoudre\n * @param options - Options de requete\n * @returns Contenu ou categorie correspondant\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 return this.get<ResolveResponse>('/resolve', { path }, options)\n }\n\n /**\n * Verifie si un chemin a une redirection configuree\n *\n * @param path - Chemin a verifier\n * @returns Redirection ou null\n *\n * @example\n * ```typescript\n * // Dans un middleware Next.js\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 = pas de redirection trouvee\n if (error instanceof LynkowError && error.status === 404) {\n return null\n }\n throw error\n }\n }\n}\n","import type { LynkowConfig, LynkowClient } 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'\n\n/**\n * URL de base par defaut de l'API Lynkow\n */\nconst DEFAULT_BASE_URL = 'https://api.lynkow.com'\n\n/**\n * Cree une instance du client Lynkow\n *\n * @param config - Configuration du client\n * @returns Instance du client avec tous les services\n *\n * @example\n * ```typescript\n * const lynkow = createLynkowClient({\n * siteId: 'your-site-uuid',\n * locale: 'fr'\n * })\n *\n * const posts = await lynkow.contents.list()\n * ```\n */\nexport function createLynkowClient(config: LynkowConfig): LynkowClient {\n // Validation\n if (!config.siteId) {\n throw new Error('Lynkow SDK: siteId is required')\n }\n\n // Normaliser la configuration\n const internalConfig: InternalConfig = {\n siteId: config.siteId,\n baseUrl: (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, ''), // Retirer le slash final\n locale: config.locale,\n fetchOptions: config.fetchOptions || {},\n }\n\n // Creer les services\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// Entites\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 LegalDocumentType,\n LegalDocumentSummary,\n LegalDocument,\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// Reponses\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 LegalListResponse,\n ConsentLogResponse,\n PathsListResponse,\n ContentResolveResponse,\n CategoryResolveResponse,\n ResolveResponse,\n} from './response'\n\n// Filtres\nexport type {\n BaseRequestOptions,\n PaginationOptions,\n SortOptions,\n ContentsFilters,\n CategoryOptions,\n ReviewsFilters,\n SubmitOptions,\n} from './filters'\n\n// Erreurs\nexport type { ErrorCode, ApiErrorDetail } from './error'\n\n// Type guards\nimport type { ResolveResponse, ContentResolveResponse, CategoryResolveResponse } from './response'\nimport { LynkowError } from '../utils/fetch'\n\n/**\n * Verifie si une reponse de resolution est un contenu\n */\nexport function isContentResolve(\n response: ResolveResponse\n): response is ContentResolveResponse {\n return response.type === 'content'\n}\n\n/**\n * Verifie si une reponse de resolution est une categorie\n */\nexport function isCategoryResolve(\n response: ResolveResponse\n): response is CategoryResolveResponse {\n return response.type === 'category'\n}\n\n/**\n * Verifie si une erreur est une erreur Lynkow\n */\nexport function isLynkowError(error: unknown): error is LynkowError {\n return error instanceof LynkowError\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ var a=class extends Error{status;code;errors;constructor(e,t,s,r=[]){super(s),this.name="LynkowError",this.status=e,this.code=t,this.errors=r;}};function v(o){switch(o){case 400:return "BAD_REQUEST";case 401:return "UNAUTHORIZED";case 403:return "FORBIDDEN";case 404:return "NOT_FOUND";case 422:return "VALIDATION_ERROR";case 429:return "TOO_MANY_REQUESTS";case 503:return "SERVICE_UNAVAILABLE";default:return "INTERNAL_ERROR"}}async function L(o,e){let t;try{t=await fetch(o,e);}catch(p){throw new a(0,"NETWORK_ERROR","Network error: Unable to reach the server",[{message:p instanceof Error?p.message:"Unknown error"}])}if(t.ok)return t.json();let s={};try{s=await t.json();}catch{}let r=v(t.status),i=s.error||s.message||`HTTP error: ${t.status}`,O=s.errors||[{message:i}];throw new a(t.status,r,i,O)}function P(o){let e=new URLSearchParams;for(let[t,s]of Object.entries(o))s!=null&&s!==""&&e.append(t,String(s));return e.toString()}var n=class{config;constructor(e){this.config=e;}buildEndpointUrl(e,t){let s=`${this.config.baseUrl}/public/${this.config.siteId}${e}`;if(t&&Object.keys(t).length>0){let r=P(t);return `${s}?${r}`}return s}async get(e,t,s){let r=s?.locale||this.config.locale,i=r?{...t,locale:r}:t,O=this.buildEndpointUrl(e,i),p=this.mergeFetchOptions(s?.fetchOptions);return L(O,{method:"GET",...p})}async post(e,t,s){let r=this.buildEndpointUrl(e),i=this.mergeFetchOptions(s?.fetchOptions);return L(r,{method:"POST",...i,headers:{"Content-Type":"application/json",...i.headers},body:JSON.stringify(t)})}async getText(e,t){let s=this.buildEndpointUrl(e),r=this.mergeFetchOptions(t?.fetchOptions),i=await fetch(s,{method:"GET",...r});if(!i.ok)throw new Error(`HTTP error: ${i.status}`);return i.text()}mergeFetchOptions(e){return {...this.config.fetchOptions,...e,headers:{...this.config.fetchOptions.headers,...e?.headers}}}};var g=class extends n{async list(e,t){let s={};return e?.page&&(s.page=e.page),e?.perPage&&(s.perPage=e.perPage),e?.category&&(s.category=e.category),e?.tag&&(s.tag=e.tag),e?.search&&(s.search=e.search),e?.sort&&(s.sort=e.sort),e?.order&&(s.order=e.order),e?.locale&&(s.locale=e.locale),this.get("/contents",s,t)}async getBySlug(e,t){return this.get(`/contents/slug/${encodeURIComponent(e)}`,void 0,t)}};var m=class extends n{async list(e){return this.get("/categories",void 0,e)}async tree(e){return this.get("/categories/tree",void 0,e)}async getBySlug(e,t){let s={};return t?.page&&(s.page=t.page),t?.perPage&&(s.limit=t.perPage),this.get(`/categories/${encodeURIComponent(e)}`,s,t)}};var c=class extends n{async list(e){return this.get("/tags",void 0,e)}};var R=class extends n{async list(e){return this.get("/pages",void 0,e)}async getBySlug(e,t){return (await this.get(`/pages/${encodeURIComponent(e)}`,void 0,t)).data}async getByPath(e,t){return (await this.get("/page-by-path",{path:e},t)).data}async getJsonLd(e,t){return (await this.get(`/pages/${encodeURIComponent(e)}/json-ld`,void 0,t)).data}};var u=class extends n{async siteConfig(e){return this.get("/site-config",void 0,e)}async global(e,t){return this.get(`/global/${encodeURIComponent(e)}`,void 0,t)}};function l(o){return {_hp:"",_ts:o}}var y=class extends n{sessionStartTime;constructor(e){super(e),this.sessionStartTime=Date.now();}async getBySlug(e){return (await this.get(`/forms/${encodeURIComponent(e)}`)).data}async submit(e,t,s){let r=l(this.sessionStartTime),i={...t,...r};return s?.recaptchaToken&&(i._recaptcha_token=s.recaptchaToken),this.post(`/forms/${encodeURIComponent(e)}/submit`,i,s)}};var d=class extends n{sessionStartTime;constructor(e){super(e),this.sessionStartTime=Date.now();}async list(e,t){let s={};return e?.page&&(s.page=e.page),e?.perPage&&(s.perPage=e.perPage),e?.minRating&&(s.minRating=e.minRating),e?.maxRating&&(s.maxRating=e.maxRating),e?.sort&&(s.sort=e.sort),e?.order&&(s.order=e.order),this.get("/reviews",s,t)}async getBySlug(e){return (await this.get(`/reviews/${encodeURIComponent(e)}`)).data}async settings(){return this.get("/reviews/settings")}async submit(e,t){let s=l(this.sessionStartTime),r={...e,...s};return t?.recaptchaToken&&(r._recaptcha_token=t.recaptchaToken),this.post("/reviews",r,t)}};var f=class extends n{async getConfig(){return (await this.get("/site")).data}};var C=class extends n{async list(e){return this.get("/legal",void 0,e)}async getByType(e,t){return (await this.get(`/legal/${e}`,void 0,t)).data}};var h=class extends n{async getConfig(){return (await this.get("/cookie-consent/config")).data}async logConsent(e,t){return this.post("/cookie-consent/log",{preferences:e},t)}};var w=class extends n{async sitemap(e){return this.getText("/sitemap.xml",e)}async robots(e){return this.getText("/robots.txt",e)}};var S=class extends n{async list(e){return this.get("/paths",void 0,e)}async resolve(e,t){return this.get("/resolve",{path:e},t)}async matchRedirect(e,t){try{return (await this.get("/redirects/match",{path:e},t)).data}catch(s){if(s instanceof a&&s.status===404)return null;throw s}}};var B="https://api.lynkow.com";function k(o){if(!o.siteId)throw new Error("Lynkow SDK: siteId is required");let e={siteId:o.siteId,baseUrl:(o.baseUrl||B).replace(/\/$/,""),locale:o.locale,fetchOptions:o.fetchOptions||{}};return {contents:new g(e),categories:new m(e),tags:new c(e),pages:new R(e),blocks:new u(e),forms:new y(e),reviews:new d(e),site:new f(e),legal:new C(e),cookies:new h(e),seo:new w(e),paths:new S(e)}}function b(o){return o.type==="content"}function x(o){return o.type==="category"}function T(o){return o instanceof a}
2
+ export{a as LynkowError,k as createLynkowClient,x as isCategoryResolve,b as isContentResolve,T as isLynkowError};//# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../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/client.ts","../src/types/index.ts"],"names":["LynkowError","status","code","message","errors","getErrorCode","fetchWithError","url","options","response","error","errorData","buildQueryString","params","searchParams","key","value","BaseService","config","path","query","baseUrl","queryString","locale","queryWithLocale","fetchOptions","body","localOptions","ContentsService","filters","slug","CategoriesService","TagsService","PagesService","BlocksService","generateSpamFields","sessionStartTime","FormsService","data","spamFields","ReviewsService","slugOrId","SiteService","LegalService","type","CookiesService","preferences","SeoService","PathsService","DEFAULT_BASE_URL","createLynkowClient","internalConfig","isContentResolve","isCategoryResolve","isLynkowError"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { ApiErrorDetail, ErrorCode } from '../types'\n\n/**\n * Erreur specifique au SDK Lynkow\n */\nexport class LynkowError extends Error {\n /** Code HTTP */\n status: number\n\n /** Code d'erreur */\n code: ErrorCode\n\n /** Liste des erreurs detaillees */\n errors: ApiErrorDetail[]\n\n constructor(\n status: number,\n code: ErrorCode,\n message: string,\n errors: ApiErrorDetail[] = []\n ) {\n super(message)\n this.name = 'LynkowError'\n this.status = status\n this.code = code\n this.errors = errors\n }\n}\n\n/**\n * Convertit un code HTTP en code d'erreur\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 * Effectue une requete fetch avec gestion des erreurs\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 // Erreur reseau\n throw new LynkowError(\n 0,\n 'NETWORK_ERROR',\n 'Network error: Unable to reach the server',\n [{ message: error instanceof Error ? error.message : 'Unknown error' }]\n )\n }\n\n // Reponse OK\n if (response.ok) {\n return response.json()\n }\n\n // Erreur HTTP\n let errorData: Record<string, unknown> = {}\n try {\n errorData = await response.json()\n } catch {\n // Pas de body JSON\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(response.status, code, message, errors)\n}\n","/**\n * Construit une query string a partir d'un objet\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 { fetchWithError } from '../utils/fetch'\nimport { buildQueryString } from '../utils/query'\n\n/**\n * Configuration interne normalisee\n */\nexport interface InternalConfig {\n siteId: string\n baseUrl: string\n locale?: string\n fetchOptions: RequestInit\n}\n\n/**\n * Service de base dont heritent tous les services specifiques\n */\nexport abstract class BaseService {\n protected config: InternalConfig\n\n constructor(config: InternalConfig) {\n this.config = config\n }\n\n /**\n * Construit l'URL complete pour un 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 * Effectue une requete GET\n */\n protected async get<T>(\n path: string,\n query?: Record<string, unknown>,\n options?: BaseRequestOptions\n ): Promise<T> {\n // Ajouter la locale si configuree\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 * Effectue une requete POST\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 * Effectue une requete GET qui retourne du texte brut (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 * Fusionne les options fetch locales avec celles globales\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 } from './base'\nimport type {\n Content,\n ContentsFilters,\n ContentsListResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les contenus (articles de blog)\n */\nexport class ContentsService extends BaseService {\n /**\n * Recupere une liste paginee de contenus publies\n *\n * @param filters - Filtres optionnels (pagination, categorie, tag, recherche)\n * @param options - Options de requete\n * @returns Liste paginee de contenus\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 return this.get<ContentsListResponse>('/contents', query, options)\n }\n\n /**\n * Recupere un contenu par son slug\n *\n * @param slug - Slug du contenu\n * @param options - Options de requete (locale)\n * @returns Contenu complet\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 return this.get<Content>(\n `/contents/slug/${encodeURIComponent(slug)}`,\n undefined,\n options\n )\n }\n}\n","import { BaseService } from './base'\nimport type {\n CategoriesListResponse,\n CategoryTreeResponse,\n CategoryDetailResponse,\n CategoryOptions,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les categories\n */\nexport class CategoriesService extends BaseService {\n /**\n * Recupere la liste des categories\n *\n * @param options - Options de requete (locale)\n * @returns Liste des categories avec compteurs\n *\n * @example\n * ```typescript\n * const { data, blogUrlMode } = await lynkow.categories.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<CategoriesListResponse> {\n return this.get<CategoriesListResponse>('/categories', undefined, options)\n }\n\n /**\n * Recupere l'arborescence des categories\n *\n * @param options - Options de requete (locale)\n * @returns Arborescence complete\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 return this.get<CategoryTreeResponse>(\n '/categories/tree',\n undefined,\n options\n )\n }\n\n /**\n * Recupere une categorie avec ses contenus pagines\n *\n * @param slug - Slug de la categorie\n * @param options - Options (locale, pagination)\n * @returns Categorie avec contenus\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 return this.get<CategoryDetailResponse>(\n `/categories/${encodeURIComponent(slug)}`,\n query,\n options\n )\n }\n}\n","import { BaseService } from './base'\nimport type { TagsListResponse, BaseRequestOptions } from '../types'\n\n/**\n * Service pour les tags\n */\nexport class TagsService extends BaseService {\n /**\n * Recupere la liste des tags\n *\n * @param options - Options de requete (locale)\n * @returns Liste des tags\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.tags.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<TagsListResponse> {\n return this.get<TagsListResponse>('/tags', undefined, options)\n }\n}\n","import { BaseService } from './base'\nimport type { Page, PagesListResponse, BaseRequestOptions } from '../types'\n\n/**\n * Service pour les pages (Site Blocks de type \"page\")\n */\nexport class PagesService extends BaseService {\n /**\n * Recupere la liste des pages publiees\n *\n * @param options - Options de requete (locale)\n * @returns Liste des pages\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.pages.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<PagesListResponse> {\n return this.get<PagesListResponse>('/pages', undefined, options)\n }\n\n /**\n * Recupere une page par son slug\n *\n * @param slug - Slug de la page\n * @param options - Options de requete (locale)\n * @returns Page complete avec donnees resolues\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 response = await this.get<{ data: Page }>(\n `/pages/${encodeURIComponent(slug)}`,\n undefined,\n options\n )\n return response.data\n }\n\n /**\n * Recupere une page par son chemin\n *\n * @param path - Chemin de la page (ex: /services/consulting)\n * @param options - Options de requete (locale)\n * @returns Page complete avec donnees resolues\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 response = await this.get<{ data: Page }>(\n '/page-by-path',\n { path },\n options\n )\n return response.data\n }\n\n /**\n * Recupere les donnees JSON-LD pour une page\n *\n * @param slug - Slug de la page\n * @param options - Options de requete (locale)\n * @returns Donnees JSON-LD (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 response = await this.get<{ data: Record<string, unknown> }>(\n `/pages/${encodeURIComponent(slug)}/json-ld`,\n undefined,\n options\n )\n return response.data\n }\n}\n","import { BaseService } from './base'\nimport type {\n SiteConfigResponse,\n GlobalBlockResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les blocs globaux (header, footer, etc.)\n */\nexport class BlocksService extends BaseService {\n /**\n * Recupere la configuration du site avec tous les blocs globaux\n *\n * @param options - Options de requete (locale)\n * @returns Configuration et blocs globaux\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.blocks.siteConfig()\n * const header = data.globals['header']\n * const footer = data.globals['footer']\n * ```\n */\n async siteConfig(options?: BaseRequestOptions): Promise<SiteConfigResponse> {\n return this.get<SiteConfigResponse>('/site-config', undefined, options)\n }\n\n /**\n * Recupere un bloc global specifique par son slug\n *\n * @param slug - Slug du bloc (ex: 'header', 'footer')\n * @param options - Options de requete (locale)\n * @returns Bloc global avec donnees resolues\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.blocks.global('header')\n * // data.data contient les donnees du bloc\n * ```\n */\n async global(\n slug: string,\n options?: BaseRequestOptions\n ): Promise<GlobalBlockResponse> {\n return this.get<GlobalBlockResponse>(\n `/global/${encodeURIComponent(slug)}`,\n undefined,\n options\n )\n }\n}\n","/**\n * Champs anti-spam pour les soumissions publiques\n */\nexport interface SpamFields {\n /** Champ honeypot (doit etre vide) */\n _hp: string\n\n /** Timestamp de debut de session */\n _ts: number\n}\n\n/**\n * Genere les champs anti-spam pour une soumission\n *\n * @param sessionStartTime - Timestamp de creation du client\n * @returns Champs anti-spam\n */\nexport function generateSpamFields(sessionStartTime: number): SpamFields {\n return {\n _hp: '', // Honeypot - toujours vide\n _ts: sessionStartTime, // Timestamp de session\n }\n}\n","import { BaseService, 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\n/**\n * Service pour les formulaires\n */\nexport class FormsService extends BaseService {\n /**\n * Timestamp de creation du client (pour anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Recupere un formulaire par son slug\n *\n * @param slug - Slug du formulaire\n * @returns Schema du formulaire\n *\n * @example\n * ```typescript\n * const form = await lynkow.forms.getBySlug('contact')\n * // Utiliser form.schema pour generer le formulaire\n * ```\n */\n async getBySlug(slug: string): Promise<Form> {\n const response = await this.get<{ data: Form }>(\n `/forms/${encodeURIComponent(slug)}`\n )\n return response.data\n }\n\n /**\n * Soumet un formulaire\n *\n * Les champs anti-spam (_hp, _ts) sont ajoutes automatiquement.\n *\n * @param slug - Slug du formulaire\n * @param data - Donnees du formulaire\n * @param options - Options (token reCAPTCHA si active)\n * @returns Reponse de soumission\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 // Ajouter les champs anti-spam\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Construire le body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Ajouter le token reCAPTCHA si fourni\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","import { BaseService, 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\n/**\n * Service pour les avis clients\n */\nexport class ReviewsService extends BaseService {\n /**\n * Timestamp de creation du client (pour anti-spam)\n */\n private sessionStartTime: number\n\n constructor(config: InternalConfig) {\n super(config)\n this.sessionStartTime = Date.now()\n }\n\n /**\n * Recupere la liste des avis approuves\n *\n * @param filters - Filtres (pagination, note)\n * @param options - Options de requete\n * @returns Liste paginee des avis\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 return this.get<ReviewsListResponse>('/reviews', query, options)\n }\n\n /**\n * Recupere un avis par son slug ou ID\n *\n * @param slugOrId - Slug ou ID de l'avis\n * @returns Avis complet\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 response = await this.get<{ data: Review }>(\n `/reviews/${encodeURIComponent(slugOrId)}`\n )\n return response.data\n }\n\n /**\n * Recupere les parametres publics des avis\n *\n * @returns Parametres (champs requis, echelle de notes, 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 return this.get<ReviewSettings>('/reviews/settings')\n }\n\n /**\n * Soumet un nouvel avis\n *\n * Les champs anti-spam (_hp, _ts) sont ajoutes automatiquement.\n *\n * @param data - Donnees de l'avis\n * @param options - Options (token reCAPTCHA si active)\n * @returns Reponse de soumission\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 // Ajouter les champs anti-spam\n const spamFields = generateSpamFields(this.sessionStartTime)\n\n // Construire le body\n const body: Record<string, unknown> = {\n ...data,\n ...spamFields,\n }\n\n // Ajouter le token reCAPTCHA si fourni\n if (options?.recaptchaToken) {\n body['_recaptcha_token'] = options.recaptchaToken\n }\n\n return this.post<ReviewSubmitResponse>('/reviews', body, options)\n }\n}\n","import { BaseService } from './base'\nimport type { SiteConfig } from '../types'\n\n/**\n * Service pour la configuration du site\n */\nexport class SiteService extends BaseService {\n /**\n * Recupere la configuration publique du site\n *\n * @returns Configuration du site\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 response = await this.get<{ data: SiteConfig }>('/site')\n return response.data\n }\n}\n","import { BaseService } from './base'\nimport type {\n LegalDocument,\n LegalDocumentType,\n LegalListResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour les documents legaux\n */\nexport class LegalService extends BaseService {\n /**\n * Recupere la liste des documents legaux\n *\n * @param options - Options de requete (locale)\n * @returns Liste des documents disponibles\n *\n * @example\n * ```typescript\n * const { data } = await lynkow.legal.list()\n * ```\n */\n async list(options?: BaseRequestOptions): Promise<LegalListResponse> {\n return this.get<LegalListResponse>('/legal', undefined, options)\n }\n\n /**\n * Recupere un document legal par son type\n *\n * @param type - Type de document ('terms', 'privacy', etc.)\n * @param options - Options de requete (locale)\n * @returns Document legal complet\n *\n * @example\n * ```typescript\n * const privacy = await lynkow.legal.getByType('privacy')\n * // privacy.content contient le HTML\n * ```\n */\n async getByType(\n type: LegalDocumentType,\n options?: BaseRequestOptions\n ): Promise<LegalDocument> {\n const response = await this.get<{ data: LegalDocument }>(\n `/legal/${type}`,\n undefined,\n options\n )\n return response.data\n }\n}\n","import { BaseService } from './base'\nimport type {\n CookieConfig,\n CookiePreferences,\n ConsentLogResponse,\n BaseRequestOptions,\n} from '../types'\n\n/**\n * Service pour le consentement cookies\n */\nexport class CookiesService extends BaseService {\n /**\n * Recupere la configuration du bandeau de cookies\n *\n * @returns Configuration du bandeau\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 response = await this.get<{ data: CookieConfig }>(\n '/cookie-consent/config'\n )\n return response.data\n }\n\n /**\n * Enregistre le consentement de l'utilisateur\n *\n * @param preferences - Preferences par categorie\n * @returns Confirmation avec ID du consentement\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","import { BaseService } from './base'\nimport type { BaseRequestOptions } from '../types'\n\n/**\n * Service pour les fichiers SEO\n */\nexport class SeoService extends BaseService {\n /**\n * Recupere le sitemap XML\n *\n * @returns Contenu XML du sitemap\n *\n * @example\n * ```typescript\n * // Dans une route API Next.js\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 * Recupere le fichier robots.txt\n *\n * @returns Contenu du robots.txt\n *\n * @example\n * ```typescript\n * // Dans une route API Next.js\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 } from './base'\nimport type {\n PathsListResponse,\n ResolveResponse,\n Redirect,\n BaseRequestOptions,\n} from '../types'\nimport { LynkowError } from '../utils/fetch'\n\n/**\n * Service pour les chemins (SSG, resolution)\n */\nexport class PathsService extends BaseService {\n /**\n * Recupere tous les chemins pour la generation statique\n *\n * @param options - Options de requete (locale)\n * @returns Liste des chemins\n *\n * @example\n * ```typescript\n * // Dans generateStaticParams() de Next.js\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 return this.get<PathsListResponse>('/paths', undefined, options)\n }\n\n /**\n * Resout un chemin vers son contenu ou categorie\n *\n * @param path - Chemin a resoudre\n * @param options - Options de requete\n * @returns Contenu ou categorie correspondant\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 return this.get<ResolveResponse>('/resolve', { path }, options)\n }\n\n /**\n * Verifie si un chemin a une redirection configuree\n *\n * @param path - Chemin a verifier\n * @returns Redirection ou null\n *\n * @example\n * ```typescript\n * // Dans un middleware Next.js\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 = pas de redirection trouvee\n if (error instanceof LynkowError && error.status === 404) {\n return null\n }\n throw error\n }\n }\n}\n","import type { LynkowConfig, LynkowClient } 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'\n\n/**\n * URL de base par defaut de l'API Lynkow\n */\nconst DEFAULT_BASE_URL = 'https://api.lynkow.com'\n\n/**\n * Cree une instance du client Lynkow\n *\n * @param config - Configuration du client\n * @returns Instance du client avec tous les services\n *\n * @example\n * ```typescript\n * const lynkow = createLynkowClient({\n * siteId: 'your-site-uuid',\n * locale: 'fr'\n * })\n *\n * const posts = await lynkow.contents.list()\n * ```\n */\nexport function createLynkowClient(config: LynkowConfig): LynkowClient {\n // Validation\n if (!config.siteId) {\n throw new Error('Lynkow SDK: siteId is required')\n }\n\n // Normaliser la configuration\n const internalConfig: InternalConfig = {\n siteId: config.siteId,\n baseUrl: (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, ''), // Retirer le slash final\n locale: config.locale,\n fetchOptions: config.fetchOptions || {},\n }\n\n // Creer les services\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// Entites\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 LegalDocumentType,\n LegalDocumentSummary,\n LegalDocument,\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// Reponses\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 LegalListResponse,\n ConsentLogResponse,\n PathsListResponse,\n ContentResolveResponse,\n CategoryResolveResponse,\n ResolveResponse,\n} from './response'\n\n// Filtres\nexport type {\n BaseRequestOptions,\n PaginationOptions,\n SortOptions,\n ContentsFilters,\n CategoryOptions,\n ReviewsFilters,\n SubmitOptions,\n} from './filters'\n\n// Erreurs\nexport type { ErrorCode, ApiErrorDetail } from './error'\n\n// Type guards\nimport type { ResolveResponse, ContentResolveResponse, CategoryResolveResponse } from './response'\nimport { LynkowError } from '../utils/fetch'\n\n/**\n * Verifie si une reponse de resolution est un contenu\n */\nexport function isContentResolve(\n response: ResolveResponse\n): response is ContentResolveResponse {\n return response.type === 'content'\n}\n\n/**\n * Verifie si une reponse de resolution est une categorie\n */\nexport function isCategoryResolve(\n response: ResolveResponse\n): response is CategoryResolveResponse {\n return response.type === 'category'\n}\n\n/**\n * Verifie si une erreur est une erreur Lynkow\n */\nexport function isLynkowError(error: unknown): error is LynkowError {\n return error instanceof LynkowError\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "lynkow",
3
+ "version": "1.0.0",
4
+ "description": "Official SDK for Lynkow Headless CMS",
5
+ "author": "Lynkow",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/lynkow/sdk"
10
+ },
11
+ "keywords": [
12
+ "lynkow",
13
+ "cms",
14
+ "headless",
15
+ "sdk",
16
+ "api",
17
+ "content-management"
18
+ ],
19
+ "main": "./dist/index.js",
20
+ "module": "./dist/index.mjs",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "import": {
25
+ "types": "./dist/index.d.mts",
26
+ "default": "./dist/index.mjs"
27
+ },
28
+ "require": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ }
32
+ }
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "sideEffects": false,
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
41
+ "scripts": {
42
+ "build": "tsup",
43
+ "dev": "tsup --watch",
44
+ "test": "vitest",
45
+ "test:run": "vitest run",
46
+ "test:coverage": "vitest run --coverage",
47
+ "typecheck": "tsc --noEmit",
48
+ "lint": "eslint src --ext .ts",
49
+ "prepublishOnly": "npm run build"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.10.0",
53
+ "@vitest/coverage-v8": "^1.1.0",
54
+ "tsup": "^8.0.1",
55
+ "typescript": "^5.3.3",
56
+ "vitest": "^1.1.0"
57
+ }
58
+ }