initial commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
import { Router } from 'express';
|
||||
import { authRequired } from '../middleware/authRequired.js';
|
||||
import { csrfRequired } from '../middleware/csrfRequired.js';
|
||||
import * as scenarioService from '../services/scenario.service.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* POST /api/scenario/:scenarioId/start
|
||||
* Запуск сценария. body должен быть пустым {}.
|
||||
*/
|
||||
router.post('/:scenarioId/start', authRequired, csrfRequired, async (req, res, next) => {
|
||||
try {
|
||||
const { scenarioId } = req.params;
|
||||
const input = req.body;
|
||||
|
||||
// 1) проверить, что пользователь имеет право на этот scenarioId
|
||||
await scenarioService.assertUserCanStartScenario({
|
||||
userId: req.user.id,
|
||||
scenarioId,
|
||||
});
|
||||
|
||||
// 2) создать generation и вызвать n8n
|
||||
const generation = await scenarioService.startScenario({
|
||||
userId: req.user.id,
|
||||
scenarioId,
|
||||
input,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
res.status(202).json({
|
||||
ok: true,
|
||||
generationUuid: generation.generationUuid,
|
||||
status: generation.status,
|
||||
currentStepId: generation.currentStepId,
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/scenario/:scenarioId/step/:stepId
|
||||
* Выполнение шага сценария. body должен соответствовать input_schema из БД.
|
||||
*/
|
||||
router.post('/:scenarioId/step/:stepId', authRequired, csrfRequired, async (req, res, next) => {
|
||||
try {
|
||||
const { scenarioId, stepId } = req.params;
|
||||
const input = req.body;
|
||||
|
||||
// 1) проверить, что пользователь может выполнять этот шаг
|
||||
await scenarioService.assertUserCanExecuteStep({
|
||||
userId: req.user.id,
|
||||
scenarioId,
|
||||
stepId,
|
||||
});
|
||||
|
||||
// 2) выполнить шаг (с валидацией input_schema)
|
||||
const result = await scenarioService.executeStep({
|
||||
userId: req.user.id,
|
||||
scenarioId,
|
||||
stepId,
|
||||
input,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
res.status(202).json({
|
||||
ok: true,
|
||||
generationUuid: result.generationUuid,
|
||||
stepState: result.stepState,
|
||||
nextStepId: result.nextStepId,
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/scenario/:scenarioId/step/:stepId/record
|
||||
* Создать запись generation_step и вернуть её ID (для загрузки файлов).
|
||||
* Используется когда нужно загрузить файл ДО выполнения шага.
|
||||
*/
|
||||
router.post('/:scenarioId/step/:stepId/record', authRequired, csrfRequired, async (req, res, next) => {
|
||||
try {
|
||||
const { scenarioId, stepId } = req.params;
|
||||
const input = req.body;
|
||||
const userId = req.user.id;
|
||||
|
||||
// Проверка прав
|
||||
await scenarioService.assertUserCanExecuteStep({
|
||||
userId,
|
||||
scenarioId,
|
||||
stepId,
|
||||
});
|
||||
|
||||
// Найти активную generation
|
||||
const { pool } = await import('../db.js');
|
||||
const genQuery = `
|
||||
SELECT generation_uuid, current_step_id, status
|
||||
FROM uno_bff.generations
|
||||
WHERE user_id = $1 AND scenario_id = $2 AND status IN ('running', 'waiting_for_input')
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
`;
|
||||
const genResult = await pool.query(genQuery, [userId, scenarioId]);
|
||||
const generation = genResult.rows[0];
|
||||
|
||||
if (!generation) {
|
||||
return res.status(400).json({
|
||||
ok: false,
|
||||
error: 'GENERATION_NOT_FOUND',
|
||||
message: `No active generation found for scenario '${scenarioId}'`,
|
||||
});
|
||||
}
|
||||
|
||||
// Найти шаг сценария для получения step_order
|
||||
const step = await scenarioService.getScenarioStep(scenarioId, stepId);
|
||||
if (!step) {
|
||||
return res.status(404).json({
|
||||
ok: false,
|
||||
error: 'STEP_NOT_FOUND',
|
||||
message: `Step '${stepId}' not found`,
|
||||
});
|
||||
}
|
||||
|
||||
// Создать/обновить запись generation_step
|
||||
const stepQuery = `
|
||||
INSERT INTO uno_bff.generation_steps (generation_uuid, scenario_id, step_id, step_order, status, request_payload)
|
||||
VALUES ($1, $2, $3, $4, 'running', $5)
|
||||
ON CONFLICT (generation_uuid, step_id) DO UPDATE
|
||||
SET status = 'running', request_payload = $5, updated_at = now()
|
||||
RETURNING id
|
||||
`;
|
||||
const stepResult = await pool.query(stepQuery, [
|
||||
generation.generation_uuid,
|
||||
scenarioId,
|
||||
stepId,
|
||||
step.step_order,
|
||||
JSON.stringify(input),
|
||||
]);
|
||||
|
||||
res.status(201).json({
|
||||
ok: true,
|
||||
stepRecordId: stepResult.rows[0].id,
|
||||
generationUuid: generation.generation_uuid,
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user