Files
image-platform/docs/development.md
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

6.1 KiB
Raw Permalink Blame History

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

Принцип

В Docker запускаем стабильную инфраструктуру. Кодовые сервисы запускаем нодой с hot reload.

Сейчас в Docker есть только:

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

backend уже умеет регистрировать assets и выполнять internal ensure. gateway уже ходит в Backend и держит L1 memory cache. worker уже читает RabbitMQ jobs, вызывает imgproxy и пишет variants в S3. Gateway обязателен для Cloudinary-like поведения и интеграции с next/image.

Запуск инфраструктуры

cp .env.example .env
pnpm install
pnpm infra:up
pnpm db:migrate

.env используется только локально и игнорируется git. Backend, Gateway, Worker и Drizzle scripts автоматически подхватывают его через Node --env-file-if-exists; в production эти переменные должны приходить из окружения процесса.

Проверить compose config:

pnpm infra:config

Остановить:

pnpm infra:down

Логи:

pnpm infra:logs

Порты

Сервис 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

Если localhost:8888 занят старым image-gateway, остановите старый stack или задайте GATEWAY_PORT=8890 в .env.

Backend

Запустить NestJS backend:

pnpm backend:dev

Проверки:

curl http://localhost:3001/api/health
open http://localhost:3001/docs

Зарегистрировать source image в dev mode:

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"}'

Посмотреть 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
curl -sS 'http://localhost:3001/api/assets/asset_demo/picture?preset=card&sizes=100vw'
curl -sS http://localhost:3001/api/assets/asset_demo/variants

Создать новую source version для asset:

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"}'

Явно поставить jobs на генерацию family variants без Gateway lazy request:

curl -sS -X POST http://localhost:3001/api/assets/asset_demo/variants \
  -H 'content-type: application/json' \
  -d '{"preset":"card","mode":"family"}'

Database

Drizzle schema живёт в packages/database/src/schema.ts, миграции - в packages/database/drizzle.

Сгенерировать миграцию после изменения schema:

pnpm db:generate

Применить миграции к локальному PostgreSQL:

pnpm db:migrate

Открыть Drizzle Studio из корня проекта:

pnpm db:studio

Проверить database package:

pnpm db:typecheck
pnpm db:build

Admin

Запустить React/Vite admin:

pnpm admin:dev

Открыть:

open http://localhost:5173

Gateway

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

pnpm gateway:dev

Проверить gateway health:

curl http://localhost:8888/health

Проверить image origin route после запуска Backend и Worker:

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"
curl -i "http://localhost:8888/images/asset_demo/v1/custom?w=777&h=333&q=72&fit=fill&f=webp"

Первый запрос должен пройти через Backend/RabbitMQ/Worker/imgproxy/S3 и вернуться с x-image-platform-l1: MISS. Повторный запрос должен вернуться из gateway L1 с x-image-platform-l1: HIT.

Статические presets сейчас лежат в packages/image-config:

  • card - responsive, widths 320, 640, 960.
  • hero - responsive, widths 1280, 1920.
  • avatar - fixed 256x256.

Mock allowlist source hosts задаётся через SOURCE_ALLOWED_HOSTS. В dev по умолчанию разрешён storage.yandexcloud.net.

Worker

Worker запускается нодой, объявляет RabbitMQ topology, слушает image.generate-variant, вызывает imgproxy и пишет готовый variant в S3.

pnpm worker:dev

Проверить worker package без запуска consumer:

pnpm worker:typecheck
pnpm worker:build

Будущий dev flow

Текущая и будущая схема:

React/Vite admin localhost:5173
-> NestJS backend localhost:3001
-> PostgreSQL localhost:5433
-> MinIO localhost:9000
-> RabbitMQ localhost:5672

worker node process
-> PostgreSQL
-> MinIO
-> RabbitMQ
-> imgproxy localhost:18080

Fastify gateway localhost:8888
-> L1 memory cache
-> Backend internal ensure endpoint

imgproxy для разработки

В dev compose поднимается локальный imgproxy, опубликованный только на 127.0.0.1:18080:

IMGPROXY_UPSTREAM=http://localhost:18080

Для production imgproxy всё равно рассматривается как внешняя зависимость и может жить на отдельном мощном сервере.