/**
* Bot Language Controller Layer
*
* HTTP-Schicht für die Labels der Bot-UIs. Die Ablage ist pro **Bot-Repo**
* (z. B. `basic-bots`): mehrere Bots rendern dieselben geteilten Komponenten,
* ein Text ist also einmal zu pflegen.
*
* Die Organisation kommt beim Lesen aus der Session (`req.session.root`, gesetzt
* von `checkRoot`) — nicht aus der URL, damit ein Aufrufer nicht in einer
* fremden Organisation lesen kann.
*/
// @ts-check
/**
* @import {ExpressRequestAuthorized, ExpressResponse} from './../../types.js'
*/
import { errorLoggerUpdate } from '../../utils/requestLogger.js';
import * as botLanguageService from './service.js';
const DEFAULT_LANG = 'de';
/**
* Sprachcode aus Query oder Pfad, mit Default.
*
* @param {ExpressRequestAuthorized} req
* @returns {string}
*/
const readLang = (req) => {
const lang = req.query?.lang ?? req.params?.lang ?? DEFAULT_LANG;
return typeof lang === 'string' && lang.length > 0 ? lang : DEFAULT_LANG;
};
/**
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @param {number} status
* @param {string} message
* @returns {void}
*/
const fail = (req, res, status, message) => {
res.status(status).json({ success: false, message });
};
/**
* Dünne Überschicht aller Bot-Repos für die Session-Organisation.
* Handles GET /?lang=de
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const listRepoLanguageSlicesController = async (req, res) => {
try {
const UIDroot = req.session?.root;
if (!UIDroot) return fail(req, res, 400, 'Keine Organisation in der Session');
const lang = readLang(req);
const result = await botLanguageService.listRepoLanguageSlices(UIDroot, lang);
res.json({ success: true, lang, result });
} catch (e) {
errorLoggerUpdate(e);
const err = /** @type {any} */ (e);
if (err?.code === 'InvalidSegment') return fail(req, res, 400, err.message);
res.status(500).json({ success: false, message: err.message });
}
};
/**
* Ein Bot-Repo mit getrennten Ebenen (Editor).
* Handles GET /:repo?lang=de
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const getRepoLanguageController = async (req, res) => {
try {
const UIDroot = req.session?.root ?? null;
const result = await botLanguageService.getRepoLanguage(req.params.repo, readLang(req), UIDroot);
res.json({ success: true, result });
} catch (e) {
errorLoggerUpdate(e);
const err = /** @type {any} */ (e);
if (err?.code === 'InvalidSegment') return fail(req, res, 400, err.message);
res.status(500).json({ success: false, message: err.message });
}
};
/**
* Schreibt eine Ebene. Ohne `:UIDroot` die geteilte Ebene, sonst die der
* angegebenen Organisation.
* Handles PUT /:repo/:lang und PUT /:repo/:UIDroot/:lang
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const putRepoLanguageController = async (req, res) => {
try {
const { labels, remove } = req.body ?? {};
if (labels !== undefined && (typeof labels !== 'object' || labels === null || Array.isArray(labels))) {
return fail(req, res, 400, '"labels" muss ein Objekt sein');
}
if (remove !== undefined && !Array.isArray(remove)) {
return fail(req, res, 400, '"remove" muss ein Array sein');
}
const result = await botLanguageService.putRepoLanguage({
repo: req.params.repo,
lang: readLang(req),
UIDroot: req.params.UIDroot ?? null,
labels: labels ?? {},
remove: remove ?? [],
});
res.json({ success: true, result });
} catch (e) {
errorLoggerUpdate(e);
const err = /** @type {any} */ (e);
if (err?.code === 'InvalidSegment') return fail(req, res, 400, err.message);
res.status(500).json({ success: false, message: err.message });
}
};