# Publications Service — всё для публикаций

Сервис публикаций в папке `posts-microservice`: CRUD, планирование, rich-контент (изображения, видео, аудио, таблицы и т.д.), календарь выпусков и API для SearXNG.

## Запуск

```bash
cd posts-microservice
npm install
npm run dev
```

Сервис: `http://localhost:4001`

## API

### Публикации

| Метод | URL | Описание |
|-------|-----|----------|
| POST | `/api/publications` | Создать |
| GET | `/api/publications` | Список (`?status=`, `?q=`, `?limit=`, `?offset=`) |
| GET | `/api/publications/calendar` | Календарь (`?year=`, `?month=`) |
| GET | `/api/publications/:id` | По ID |
| GET | `/api/publications/slug/:slug` | По slug |
| PATCH | `/api/publications/:id` | Обновить |
| DELETE | `/api/publications/:id` | Удалить |

### Поля публикации

- `title` — заголовок
- `slug` — URL-slug (генерируется из title)
- `excerpt` — краткое описание
- `contentBlocks` — массив блоков (текст, изображения, видео, аудио, таблицы, embed)
- `previewImage` — URL превью
- `url` — ссылка на страницу
- `author` — автор
- `status` — `draft` | `scheduled` | `published`
- `scheduledAt` — время публикации (ISO)
- `publishedAt` — время фактической публикации

### Блоки контента (`contentBlocks`)

```json
[
  { "type": "text", "data": { "html": "<p>Текст</p>" } },
  { "type": "image", "data": { "src": "https://...", "alt": "...", "caption": "..." } },
  { "type": "video", "data": { "src": "https://...", "poster": "...", "caption": "..." } },
  { "type": "audio", "data": { "src": "https://...", "caption": "..." } },
  { "type": "table", "data": { "html": "<table>...</table>", "caption": "..." } },
  { "type": "embed", "data": { "url": "https://...", "caption": "..." } },
  { "type": "heading", "data": { "level": 1, "text": "Заголовок" } },
  { "type": "divider" }
]
```

### Планирование

- Публикация со `status: "scheduled"` и `scheduledAt` автоматически переходит в `published` при наступлении времени.
- Планировщик запускается каждую минуту.

### SearXNG

Эндпоинт `/search?q={query}&page={pageno}` отдаёт только опубликованные публикации в формате JSON engine SearXNG.

Конфиг в `searxng-engine-example.yml`.

## Алиасы

- `/api/posts` → тот же API (для обратной совместимости)
