Files
image-platform/docs/api-contract-draft.md
S.Gromov 37592c8b81 chore: добавить каркас image-platform
- добавлен базовый pnpm workspace для будущих приложений

- добавлена dev-инфраструктура PostgreSQL и MinIO

- добавлены env-пример и базовые правила репозитория

- зафиксированы архитектура, data model и API-контракт

- описан контракт с внешним imgproxy
2026-05-04 22:53:55 +03:00

2.5 KiB
Raw Blame History

Черновик API Контракта

Это не реализация API, а фиксация будущего контракта для NestJS backend.

Backend отдаёт JSON, metadata, statuses и URLs. Он не должен проксировать image bytes на каждый обычный запрос.

Allowed Hosts

GET /allowed-hosts
POST /allowed-hosts
PATCH /allowed-hosts/:id
DELETE /allowed-hosts/:id

Assets

GET /assets
POST /assets
GET /assets/:id
DELETE /assets/:id

POST /assets request:

{
  "sourceUrl": "https://example.com/photo.jpg"
}

Responsibilities:

  • validate source URL;
  • check allowed_image_hosts;
  • create or reuse image_assets row;
  • optionally save original to S3 later.

Variants

GET /assets/:id/variants
POST /assets/:id/variants
POST /variants/:id/regenerate
DELETE /variants/:id

POST /assets/:id/variants request:

{
  "preset": "card",
  "format": "webp",
  "width": 640
}

Response if ready:

{
  "id": "variant_123",
  "status": "ready",
  "url": "http://localhost:8888/images/asset_123/w640_q80_card.webp"
}

Response if generation is async:

{
  "id": "variant_123",
  "status": "pending",
  "url": null
}

Image URLs For UI

Для UI нужен endpoint, который возвращает готовый набор URLs для <picture>/srcset.

GET /assets/:id/picture?preset=card

Example response:

{
  "assetId": "asset_123",
  "preset": "card",
  "sources": [
    {
      "type": "image/avif",
      "srcset": "http://localhost:8888/images/asset_123/w320_card.avif 320w, http://localhost:8888/images/asset_123/w640_card.avif 640w"
    },
    {
      "type": "image/webp",
      "srcset": "http://localhost:8888/images/asset_123/w320_card.webp 320w, http://localhost:8888/images/asset_123/w640_card.webp 640w"
    }
  ],
  "fallback": {
    "src": "http://localhost:8888/images/asset_123/w640_card.jpg",
    "width": 640,
    "height": null
  }
}

Worker Lifecycle

Первый MVP может генерировать sync на request. Если генерация тяжёлая, variant создаётся как pending, а worker обрабатывает job.

PostgreSQL может выступить первой очередью:

SELECT * FROM image_variants
WHERE status = 'pending'
FOR UPDATE SKIP LOCKED
LIMIT 1

Позже можно добавить Redis/Valkey или отдельную queue, если PostgreSQL станет узким местом.