S.Gromov 56d551b43b feat: добавить endpoint picture/srcset
- добавлен contract DTO для picture sources и fallback image
- реализована выдача versioned Gateway URLs по static presets
- обновлена документация business API и dev smoke flow
2026-05-05 13:35:25 +03:00

Image Platform

Image Platform - отдельная площадка для управления изображениями, variants, PostgreSQL metadata и S3/Object Storage.

Статус

Сейчас создан базовый monorepo, dev-инфраструктура, NestJS backend с Swagger, чистый Vite React TS admin, Fastify gateway, Drizzle database package, shared queue/storage packages и worker. Минимальный read-through flow уже реализован для dev.

Целевая схема

client
-> CDN optional
-> Fastify gateway + L1 memory cache
-> NestJS backend
-> S3/Object Storage persistent variants
-> generator/worker on miss
-> RabbitMQ
-> external imgproxy
-> source/original image

imgproxy всегда считается внешним сервисом и подключается через IMGPROXY_UPSTREAM.

Локальная разработка

В Docker поднимается только базовая инфраструктура:

  • PostgreSQL
  • MinIO
  • MinIO bucket init
  • imgproxy dev instance
  • RabbitMQ

Нодой запускается:

  • NestJS backend
  • React/Vite admin
  • Fastify gateway
  • worker

Gateway принимает /images/{assetId}/v{version}/{preset}?w={width}&q={quality}&f=auto, выбирает фактический формат по Accept, вызывает Backend ensure endpoint и кэширует готовые bytes в L1 memory cache.

cp .env.example .env
pnpm install
pnpm infra:up
pnpm db:migrate
pnpm infra:config
pnpm backend:dev
pnpm admin:dev
pnpm gateway:dev
pnpm worker:dev

.env игнорируется git. Runtime-код не содержит dev credentials fallback: для production нужно передать реальные DATABASE_URL, RABBITMQ_URL, S3_* и IMGPROXY_UPSTREAM через окружение.

Минимальный smoke flow:

curl -sS -X POST http://localhost:3001/api/assets \
  -H 'content-type: application/json' \
  -d '{"sourceUrl":"https://storage.yandexcloud.net/shared1318/img/1.jpg","publicId":"asset_demo"}'

curl -i "http://localhost:8888/images/asset_demo/v1/card?w=640&q=80&f=auto"
curl -i "http://localhost:8888/images/asset_demo/v1/avatar?f=auto"

Сейчас доступны static presets из packages/image-config: card, hero, avatar. Произвольный single-image режим доступен через /images/{assetId}/v{version}/custom?..., если включён IMAGE_ALLOW_CUSTOM_TRANSFORMS=true.

Business API без админки:

curl -sS http://localhost:3001/api/presets
curl -sS http://localhost:3001/api/assets
curl -sS 'http://localhost:3001/api/assets/asset_demo/picture?preset=card&sizes=100vw'
curl -sS http://localhost:3001/api/assets/asset_demo/variants
curl -sS -X POST http://localhost:3001/api/assets/asset_demo/versions \
  -H 'content-type: application/json' \
  -d '{"sourceUrl":"https://storage.yandexcloud.net/shared1318/img/1.jpg"}'
curl -sS -X POST http://localhost:3001/api/assets/asset_demo/variants \
  -H 'content-type: application/json' \
  -d '{"preset":"card","mode":"family"}'

Порты по умолчанию:

Сервис URL
PostgreSQL localhost:5433
MinIO API http://localhost:9000
MinIO Console http://localhost:9001
imgproxy http://localhost:18080
RabbitMQ amqp://localhost:5672
RabbitMQ Management http://localhost:15672
Backend API http://localhost:3001/api
Swagger http://localhost:3001/docs
Admin http://localhost:5173
Gateway http://localhost:8888

Если старый локальный image-gateway уже занимает 8888, остановите его или задайте другой GATEWAY_PORT в .env.

Документация

  • docs/architecture.md - целевая архитектура и ответственность компонентов.
  • docs/development.md - локальный dev flow.
  • docs/data-model.md - текущая Drizzle/PostgreSQL модель.
  • docs/backend-contract-draft.md - черновик будущего backend-контракта.
  • docs/imgproxy-contract.md - контракт с external imgproxy.
  • docs/next-image-provider.md - контракт custom provider для next/image.
Description
No description provided
Readme 292 KiB
Languages
TypeScript 98.2%
CSS 1.5%
HTML 0.3%