# Usage programmatique — Module Posts Idéal pour les cron jobs, scripts d'import ou fetchers automatisés. ## Fonctions disponibles ```js import { createPost, // Créer un post updatePost, // Modifier un post getPostBySlug, // Chercher par slug getPostByField, // Chercher par n'importe quel champ JSONB upsertPost, // Créer ou mettre à jour (idempotent) getPosts, // Liste avec pagination deletePost, // Supprimer } from '@zen/core/modules/posts/crud'; ``` --- ## `upsertPost(postType, rawData, uniqueField)` Crée le post s'il n'existe pas, le met à jour sinon. - `postType` : le type de post (`'cve'`, `'actualite'`...) - `rawData` : les données du post (mêmes champs que pour `createPost`) - `uniqueField` : le champ de déduplication (`'slug'` par défaut) Retourne `{ post, created: boolean }`. ### Champs `relation` dans `rawData` Les champs `relation` reçoivent un **tableau d'IDs** de posts existants. ```js // Correct { tags: [7, 8, 12], source: [3] } // Incorrect { tags: ['openssh', 'vuln'], source: { id: 3 } } ``` Si les posts liés n'existent pas encore, les créer d'abord avec `upsertPost` puis utiliser leurs IDs. --- ## Exemple : fetcher de CVE ```js // src/cron/fetch-cves.js import { upsertPost } from '@zen/core/modules/posts/crud'; export async function fetchAndImportCVEs() { const response = await fetch('https://api.example.com/cves/recent'); const { cves } = await response.json(); const results = { created: 0, updated: 0, errors: 0 }; for (const cve of cves) { try { // Résoudre les relations : s'assurer que les tags existent const tagIds = []; for (const tagName of (cve.tags || [])) { const { post: tag } = await upsertPost('tag', { title: tagName }, 'slug'); tagIds.push(tag.id); } // Upsert du CVE, dédupliqué sur cve_id const { created } = await upsertPost('cve', { title: cve.title, cve_id: cve.id, severity: cve.severity, score: String(cve.cvssScore), product: cve.affectedProduct, date: cve.publishedAt, description: cve.description, tags: tagIds, }, 'cve_id'); created ? results.created++ : results.updated++; } catch (err) { console.error(`[CVE import] Error for ${cve.id}:`, err.message); results.errors++; } } console.log(`[CVE import] Done — created: ${results.created}, updated: ${results.updated}, errors: ${results.errors}`); return results; } ``` --- ## Exemple : fetcher d'actualités avec source ```js import { upsertPost } from '@zen/core/modules/posts/crud'; export async function fetchAndImportActualites(sourceName, articles) { // S'assurer que la source existe const { post: source } = await upsertPost('source', { title: sourceName }, 'slug'); for (const article of articles) { await upsertPost('actualite', { title: article.title, date: article.publishedAt, resume: article.summary, content: article.content, source: [source.id], tags: [], }, 'slug'); } } ```