Архитектура backend API
Архитектура backend API (@lowcode/api)
Как устроен сервер приложений: модули NestJS, слои, потоки запросов и работа с БД.
🎯 Задача страницы
Эта страница описывает архитектуру приложения @lowcode/api:
- как организованы модули и слои NestJS;
- как устроен жизненный цикл HTTP-запроса;
- как API работает с БД через Prisma;
- как реализованы основные сценарии: проекты, версии, компиляция DSL;
- где искать код и как добавлять новые функции.
1. Роль @lowcode/api в общей архитектуре
@lowcode/api — центральный backend-сервис платформы. Он:
- хранит проекты и их версии в PostgreSQL;
- принимает и валидирует DSL-структуры;
- вызывает
dsl-compilerдля генерации бандла; - отдаёт данные редактору
builder-webи runtime-хосту; - предоставляет REST API для всех ключевых операций.
Высокоуровневая схема:
graph TD
BW[builder-web] -->|HTTP| API[@lowcode/api]
API --> DB[(PostgreSQL)]
API --> DSL[dsl-compiler]
DSL --> BNDL[JS Bundle]
BNDL --> RH[runtime-host]
2. Структура приложения NestJS
Архитектурно @lowcode/api использует стандартный подход NestJS:
- модули (modules) — логические блоки функциональности;
- контроллеры (controllers) — HTTP-эндпоинты;
- сервисы (services) — бизнес-логика;
- инфраструктурный слой — Prisma, конфигурация, фильтры, пайпы.
Типичная структура каталога:
apps/api/src/
main.ts ← точка входа (NestFactory + FastifyAdapter)
app.module.ts ← корневой модуль
projects/ ← работа с проектами
projects.module.ts
projects.controller.ts
projects.service.ts
dto/
versions/ ← работа с версиями проектов
dsl/ ← валидация и операции с DSL
compile/ ← компиляция DSL → bundle
database/ ← PrismaService, PrismaModule
common/ ← общие фильтры, пайпы, декораторы
Для деталей реализации см. также:
3. Жизненный цикл HTTP-запроса
Упрощённый путь любого запроса:
Fastify → NestJS → Controller → Service → Prisma/DSL → Response
3.1. Fastify + NestFactory
В main.ts создаётся приложение NestJS на основе Fastify:
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
Также на этом этапе:
- настраиваются глобальные пайпы (
ValidationPipe); - включается CORS (для доступа builder-web);
- конфигурируются префиксы роутов и пр.
См. подробности в AppModule.
3.2. Контроллер
Контроллер отвечает за приём HTTP-запросов:
@Controller('projects')
export class ProjectsController {
constructor(private readonly service: ProjectsService) {}
@Get()
findAll() {
return this.service.findAll();
}
@Post()
create(@Body() dto: CreateProjectDto) {
return this.service.create(dto);
}
}
Особенности:
- маршруты объявляются через декораторы
@Get,@Post,@Patchи т.д.; - входные данные типизируются DTO-классами и валидируются пайпами.
Реализация контроллера проектов описана в ProjectsController.
3.3. Сервис
Сервис инкапсулирует бизнес-логику и работу с БД:
@Injectable()
export class ProjectsService {
constructor(private readonly prisma: PrismaService) {}
findAll() {
return this.prisma.project.findMany();
}
create(dto: CreateProjectDto) {
return this.prisma.project.create({ data: dto });
}
}
Сервисы не знают о деталях HTTP — только о доменной логике.
Подробное описание сервиса проектов см. в ProjectsService. Инфраструктурный слой доступа к БД реализован в PrismaService.
3.4. Ответ
NestJS автоматически сериализует возвращаемые объекты в JSON и отправляет их клиенту (builder-web или runtime-host).
4. Работа с БД: Prisma + PostgreSQL
4.1. Prisma schema
Модели данных находятся в apps/api/prisma/schema.prisma. Там описаны сущности:
Project— проект пользователя;ProjectVersion— версии проекта;- дополнительные сущности (шаблоны, пользователи и т.п. при расширении).
Пример условной модели:
model Project {
id String @id @default(cuid())
name String
createdAt DateTime @default(now())
versions ProjectVersion[]
}
4.2. PrismaService и PrismaModule
Для интеграции Prisma с NestJS используется обёртка PrismaService:
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}
Она регистрируется в PrismaModule и импортируется в AppModule.
Сервисы получают PrismaService через DI и используют его для запросов:
this.prisma.project.findMany();
4.3. Миграции и окружения
- миграции лежат в
apps/api/prisma/migrations/*; - в Docker-окружениях они применяются автоматически при старте API;
- локально миграции выполняются через скрипты
pnpm prisma:migrate-dev/deploy.
5. Доменные модули: проекты, версии, DSL, компиляция
5.1. Модуль Projects
Отвечает за:
- создание, обновление, удаление проектов;
- получение списка и деталей проекта.
Типичные эндпоинты:
GET /projects
GET /projects/:id
POST /projects
PATCH /projects/:id
DELETE /projects/:id
Реализация доменной логики и HTTP-слоя для проектов:
- модуль:
ProjectsModule; - контроллер:
ProjectsController; - сервис:
ProjectsService; - сущность:
Project; - DTO:
CreateProjectDto,UpdateProjectDto.
5.2. Модуль Versions
Модуль версий (ProjectVersion):
- хранит снимки состояния проекта во времени;
- позволяет откатываться к предыдущим версиям;
- обеспечивает совместимость с компилятором.
Примерный набор эндпоинтов:
GET /projects/:id/versions
GET /project-versions/:versionId
POST /projects/:id/versions
Реализация версий проекта:
- модуль:
ProjectVersionsModule; - контроллер:
ProjectVersionsController; - сервис:
ProjectVersionsService; - сущность:
ProjectVersionEntity; - DTO:
CreateProjectVersionDto.
5.3. Модуль DSL
Роль:
- валидация DSL-дерева, которое приходит от builder-web;
- базовые проверки структуры, типов компонентов, связей.
API-слой может предоставлять эндпоинты вида:
POST /dsl/validate
При вызове:
- принимается JSON-описание проекта;
- запускаются валидаторы из
dsl-compiler; - возвращается результат валидации (ошибки, предупреждения).
Ключевые элементы модуля DSL:
- модуль:
DslModule; - контроллер:
DslController; - сервис:
DslService; - DTO:
ValidateDslDto; - результат валидации:
DslValidationResult,DslValidationIssue.
Для низкоуровневой трансляции DSL в AST и дальше в React/HTML см. документацию к пакету dsl-compiler и его индексным функциям, например compileDslToReact и buildAstFromDsl.
5.4. Модуль Compile
Роль:
- принимать DSL-дерево и проходить весь цикл DSL → AST → Bundle;
- возвращать готовый JS-бандл редактору или runtime-host.
Эндпоинт, например:
POST /compile/react
POST /compile/html
Внутри сервис компиляции использует DTO для разных целевых форматов и вызывает функции dsl-compiler:
Сервис и контроллер компиляции входят в модуль DslModule и разделяют инфраструктуру с валидацией.
6. Общие компоненты: DTO, валидация, ошибки
6.1. DTO и ValidationPipe
DTO-классы используют декораторы class-validator:
export class CreateProjectDto {
@IsString()
name: string;
}
Типичный пример DTO для проектов — CreateProjectDto и UpdateProjectDto.
Глобальный ValidationPipe в main.ts гарантирует, что:
- входные данные соответствуют типам;
- лишние поля отбрасываются (
whitelist: true).
6.2. Фильтры ошибок
Через NestJS ExceptionFilter можно:
- унифицировать формат ошибок;
- логировать непойманные исключения;
- возвращать понятные ответы клиенту.
Пример: глобальный фильтр HTTP-ошибок, оформляющий ошибки в стандартный JSON-формат.
7. Тестирование API
@lowcode/api покрывается тестами на нескольких уровнях:
- unit-тесты сервисов (мокаем
PrismaService); - integration-тесты модулей (через
Test.createTestingModule); - e2e-тесты в Docker-окружении (API тестируется через HTTP как чёрный ящик).
Тесты лежат в:
apps/api/src/**/*.spec.ts
Подробнее система тестирования описана на странице Frameworks → Jest.
8. Где искать ключевые части кода
| Компонент | Путь | Описание |
|---|---|---|
| Точка входа | apps/api/src/main.ts | NestFactory, FastifyAdapter, глобальные пайпы |
| Корневой модуль | apps/api/src/app.module.ts | Подключение доменных модулей и инфраструктуры |
| Модуль Projects | apps/api/src/projects/* | CRUD операций над проектами |
| Модуль Versions | apps/api/src/versions/* | Управление версиями проектов |
| Модуль DSL/Compile | apps/api/src/dsl/*, apps/api/src/compile/* | Валидация и компиляция DSL |
| Prisma schema | apps/api/prisma/schema.prisma | Модели БД |
| Prisma migrations | apps/api/prisma/migrations/* | Миграции схемы БД |
| PrismaService/Module | apps/api/src/database/* | Интеграция Prisma с NestJS |
Документацию по основным классам и модулям см. в разделе reference:
- API:
@lowcode/api; - модули и классы проектов:
ProjectsModule,ProjectsController,ProjectsService; - модули и классы версий:
ProjectVersionsModule,ProjectVersionsController,ProjectVersionsService; - модуль DSL и компиляции:
DslModule,DslController,DslService; - инфраструктура БД:
PrismaService,PrismaModule.
9. Как расширять API безопасно
При добавлении новой функциональности рекомендуется придерживаться паттерна:
- Создать модуль:
feature/feature.module.ts. - Создать сервис с бизнес-логикой.
- Создать контроллер с HTTP-эндпоинтами.
- Описать DTO и включить их в валидацию.
- При необходимости добавить модели в
schema.prismaи миграции. - Написать unit-/integration-тесты.
- Зарегистрировать новый модуль в
AppModule.
Так архитектура остаётся модульной, предсказуемой и масштабируемой.