Skip to main content

Lowcode Exporter

@lowcode/exporter (директория packages/exporter) — это пакет с шаблонами и артефактами для экспорта проектов. Он не выполняет экспорт сам по себе, а хранит базовые файлы, которые копируются в итоговый экспортируемый проект.

Основная цель пакета — дать стабильный каркас, в который экспорт‑пайплайн подставляет данные из DSL:

  • backend‑проект (REST‑endpoint’ы для dataSources, резолв SecretValue);
  • конфиги окружения (runtime‑config.example.json).

1. Где используется

Пакет используется экспорт‑пайплайном (эпик A):

  1. копировать templates/backend в /backend экспортируемого проекта;
  2. генерировать src/runtime/dataSources.ts по DSL;
  3. создавать runtime-config.example.json со списком ключей секретов.

Минимальный API экспортера уже существует:

  • exportBackendProject({ app, outputDir }) — копирует шаблон и генерирует файлы;
  • buildBackendDataSourcesFile(app) — генерация dataSources.ts;
  • buildRuntimeConfigExampleFile(app) — генерация runtime-config.example.json.
  • exportProject({ app, outputDir }) — общий экспорт /frontend, /backend, /db + DEPLOY.md.

1.1. Контракт запуска экспорта

Экспорт запускается через API и возвращает статус артефакта:

POST /projects/:projectId/versions/:versionNumber/export

Тело запроса:

{
"includeFrontend": true,
"includeBackend": true,
"includeDb": true,
"includeSeeds": false,
"mode": "server"
}

Ответ:

{
"exportId": "uuid",
"status": "pending",
"capabilities": {
"requiresBackend": true,
"requiresDb": true,
"staticExportAllowed": false,
"mode": "server",
"reasons": ["DB dataSources require backend and database."]
},
"missingSecrets": ["API_KEY"]
}

Статус и ссылка на скачивание:

GET /exports/:exportId

Ответ:

{
"exportId": "uuid",
"status": "ready",
"downloadUrl": "/exports/uuid/download",
"expiresAt": 1710000000000
}

TTL/очистка управляются на стороне API/хранилища.

Переменные окружения API:

  • EXPORT_STORAGE_DIR — директория для артефактов (/tmp/lowcode-exports по умолчанию).
  • EXPORT_TTL_MS — TTL экспорта в миллисекундах (1 час по умолчанию).

UI‑триггеры

  • runtime-host: кнопка "Export project" экспортирует открытую версию.
  • builder-web: кнопка "Export project" показывает подтверждение и затем запускает экспорт.

2. Backend template

Базовый backend — Fastify‑сервер с маршрутом /data/execute:

  • принимает dataSourceId и контекст исполнения;
  • резолвит SecretValue через runtime-config.json;
  • выполняет REST‑dataSources;
  • возвращает контракт { value, error, loading, lastResultAt } (где error — строка или null, а lastResultAt выставляется только при успехе).

2.1. Режимы экспорта (static vs server)

Экспорт поддерживает два режима:

  • Static export — возможен только если нет db dataSources и нет SecretValue.
  • Server export — требуется при наличии db dataSources или SecretValue.

Отчёт формируется функцией validateExportCapabilities(app) и содержит: requiresBackend, requiresDb, staticExportAllowed, mode и reasons.

Дополнительно buildExportPreflightReport(app) добавляет:

  • externalMediaUrls — список внешних URL, используемых в Image/Video и attachments.
  • Подсказку в capabilities.hints о риске протухающих ссылок.

Для parity‑проверок E4 предусмотрены тесты:

  • runtime-host: timeout, non‑OK ответы, маскирование секретов;
  • backend template: query/headers/body/timeout;
  • frontend export: корректный контекст (state/route/data) и обработка ошибок.

В export backend логируются события dataSource.call.* с durationMs, status и маскированным errorMessage.


3. Frontend template

Frontend‑экспорт использует Vite‑шаблон:

  • packages/exporter/templates/frontend → копируется в /frontend;
  • src/generated/bundle.ts генерируется из DSL‑compiler (React bundle);
  • src/generated/appSchema.ts содержит исходный DSL;
  • .env.example содержит VITE_BACKEND_URL для доступа к backend‑proxy.

В корне экспорта создаётся DEPLOY.md с инструкцией по запуску.

3.1. Внешние медиа‑URL в экспорте

По умолчанию внешние URL остаются как есть и будут работать только при доступности оригинального хоста. Для стабильной сборки доступна опция импорта:

  • флаг importExternalMedia в API POST /projects/:projectId/versions/:versionNumber/export;
  • внешние файлы скачиваются и сохраняются в frontend/public/external-media;
  • src в DSL заменяется на локальные пути /external-media/<hash>.<ext>.

4. Структура backend‑шаблона

packages/exporter/templates/backend/
├─ src/
│ ├─ index.ts # запуск Fastify
│ ├─ routes/
│ │ └─ dataSources.ts # /data/execute
│ └─ runtime/
│ ├─ dataSources.ts # плейсхолдер для генерации
│ ├─ httpExecutor.ts # REST executor
│ ├─ runtimeConfig.ts # загрузка runtime-config.json
│ └─ types.ts # локальные типы
├─ package.json
├─ tsconfig.json
├─ runtime-config.example.json
├─ .env.example
└─ Dockerfile

5. DB export (A2)

DB‑экспорт формирует структуру /db и compose‑файлы для локального и managed‑сценариев.

Что генерируется:

  • db/schema.prisma — Prisma схема из DSL (tables/fields/indexes/FK);
  • db/init.sql — базовый SQL для быстрого старта (Postgres SQL);
  • db/migrations/0001_init/migration.sql — init‑миграция (Postgres SQL, инкрементальные миграции пока не генерируются);
  • docker-compose.local.yml — frontend + backend + postgres;
  • docker-compose.managed.yml — frontend + backend с подключением к внешней DB.

Type mapping (DSL → Prisma / SQL):

DSL typePrisma typeSQL type
stringStringtext
textString @db.Texttext
numberFloatdouble precision
booleanBooleanboolean
dateDateTime @db.Datedate
datetimeDateTimetimestamptz
jsonJsonjsonb

Validation rules (DB schema):

  • references.table/field must exist and reference a PK or unique field.
  • FK field type must match referenced field type.
  • setNull in onDelete/onUpdate requires nullable: true on the FK field.

Seeds генерируются в db/seed.sql по флагу includeSeeds (если в DSL есть seeds). Формат: одиночные INSERT INTO ... VALUES ...; на строку, совместимы с локальным и managed‑сценариями.

Secrets можно передавать через runtime-config.json или через переменные окружения с теми же ключами.

Backend‑шаблон при старте применяет db/init.sql и db/migrations/*/migration.sql автоматически. Отключить можно через LOWCODE_APPLY_MIGRATIONS=false.

Перед экспортом формируется preflight‑отчёт:

  • список ключей SecretValue (missing secrets);
  • причины и подсказки (capabilities report).

6. Принципы

  • Шаблон минимальный, без бизнес‑логики платформы.
  • Секреты не хранятся в DSL — только ключи, значения подставляются в runtime‑config.
  • Контракт данных совпадает с runtime‑host, чтобы фронтенд работал без изменений.