/** * Content Platform — modelo canónico de documento de contenido. * * Alineado con ADR-020 §2.1. Es el contrato compartido entre: * - Backend (servicio `content/` — DynamoDB tabla `content`). * - Pipeline estático (`scripts/build-content.ts` → `content-store.{locale}.ts`). * - Esta lib (`ContentService` + `provideValtechContent`). * - Web (`/blog`, `/news`, …). * * Modelo **unificado** con discriminador `type` — agregar un tipo de contenido * NO requiere tocar backend ni lib. El `body` es Markdown plano, renderizado en * la web vía el `markdown-article-parser` existente (`string MD → ArticleMetadata`). * * NOTA: existe un tipo homónimo `ContentDocument` (block-based, builder) en * `services/content/`, reexportado por el public-api como `ContentBuilderDocument` * para evitar colisión. Este (flat, markdown) es el canónico de la plataforma. */ /** * Tipo de contenido (discriminador). Extensible — agregar un valor no impacta * backend ni lib; solo la web decide qué rutas exponer. */ export type ContentDocumentType = 'blog' | 'news' | 'article' | 'documentation' | (string & {}); /** * Estado de publicación del documento. */ export type ContentDocumentStatus = 'draft' | 'published' | 'archived'; /** * Origen del documento — marca de la naturaleza híbrida del pipeline. * - `static`: autoría en repo, build-time (contenido curado de la empresa). * - `backend`: DynamoDB + API (publicación sin redeploy / editores). */ export type ContentDocumentSource = 'static' | 'backend'; /** * Autor de un documento de contenido. */ export interface ContentDocumentAuthor { /** Nombre visible del autor. */ name: string; /** URL del avatar del autor. */ avatar?: string; /** Rol o cargo del autor. */ role?: string; } /** * Documento de contenido unificado (canónico — ADR-020 §2.1). */ export interface ContentDocument { /** Identificador único — uuid (backend) o `static:{type}:{locale}:{slug}` (estático). */ id: string; /** AppID del producto dueño del documento. */ appId: string; /** Tipo de contenido (discriminador). */ type: ContentDocumentType; /** Slug — único por (appId, type, locale). */ slug: string; /** Locale del documento (`'es'` | `'en'` | …). */ locale: string; /** Título del documento. */ title: string; /** Resumen / extracto para listados y SEO. */ excerpt: string; /** URL de la imagen de portada (S3 vía storage service). */ coverImage?: string; /** Cuerpo en Markdown — render vía markdown-article-parser. */ body: string; /** Autor del documento. */ author?: ContentDocumentAuthor; /** Etiquetas para categorización. */ tags?: string[]; /** Categoría primaria. */ category?: string; /** Estado de publicación. */ status: ContentDocumentStatus; /** Origen del documento (marca híbrida). */ source: ContentDocumentSource; /** * Alcance del documento. * - `'app'`: contenido de la plataforma, visible a todos los users. * - `'org'`: contenido privado de una organización, acceso autenticado. */ scope?: 'app' | 'org'; /** OrgID propietaria — presente cuando `scope === 'org'`. */ orgId?: string; /** Fecha de publicación (ISO 8601). */ publishedAt?: string; /** Fecha de creación (ISO 8601). */ createdAt: string; /** Fecha de última actualización (ISO 8601). */ updatedAt?: string; } /** * Factory lazy de documentos estáticos para un locale. Generada build-time por * `scripts/build-content.ts`. Se usa con `import()` dinámico para que cada locale * quede code-split (igual patrón que `LegalContentFactory`). */ export type ContentStaticFactory = () => Promise; /** * Configuración de `provideValtechContent` (ADR-020 §2.5). */ export interface ValtechContentConfig { /** Base URL de la API backend (sin trailing slash). Ej. `environment.apiUrl`. */ apiUrl: string; /** AppID del producto — se envía como query param al backend. */ appId: string; /** * Fuentes estáticas lazy keyed por locale (generadas build-time). Opcional — * si no hay, el servicio opera solo contra el backend. * * @example * staticSources: { * es: () => import('./app/generated/content-store.es').then(m => m.CONTENT_STORE_ES), * en: () => import('./app/generated/content-store.en').then(m => m.CONTENT_STORE_EN), * } */ staticSources?: { [locale: string]: ContentStaticFactory; }; } /** * Opciones de carga/listado de contenido. */ export interface ContentLoadOptions { /** Locale a resolver (default `'es'`). */ locale?: string; }