/**
* Language File Controller Layer
* Handles HTTP request/response and delegates to the service layer.
*/
// @ts-check
/**
* @import {ExpressRequestAuthorized, ExpressResponse} from './../../types.js'
*/
import { s3 } from '../../utils/s3Client.js';
import { uploadLanguage } from '../../utils/uploadLanguage.js';
import { errorLoggerUpdate } from '../../utils/requestLogger.js';
import * as languageFileService from './service.js';
/**
* List all available language files.
* Handles GET /
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const listLanguageFilesController = async (req, res) => {
try {
const result = await languageFileService.listLanguageFiles();
res.json({ success: true, result });
} catch (e) {
errorLoggerUpdate(e);
const err = /** @type {Error} */ (e);
res.status(500).json({ success: false, message: err.message });
}
};
/**
* List language files for a specific application.
* Handles GET /:app
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const listLanguageFilesByAppController = async (req, res) => {
try {
const result = await languageFileService.listLanguageFilesByApp(req.params.app);
res.json({ success: true, result });
} catch (e) {
errorLoggerUpdate(e);
const err = /** @type {Error} */ (e);
res.status(500).json({ success: false, message: err.message });
}
};
/**
* Upload a language file.
* Handles POST /:api
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const uploadLanguageFileController = async (req, res) => {
try {
const uploadedFileData = await uploadLanguage(req, /** @type {any} */ ({
s3,
mimeFilter: languageFileService.filterJSON,
uploadUrlGen: languageFileService.languageUrlGen,
Bucket: languageFileService.bucket,
width: 300
}));
const urls = /** @type {any[]} */ (uploadedFileData).map(
/** @param {{Key: string}} el */ el => process.env.baseUrl + '/api/kpe20/languages/' + languageFileService.keyComponents(el.Key, req.params.UID)
) + '/languages';
const fileNames = /** @type {any[]} */ (uploadedFileData).map(
/** @param {{Key: string}} el */ el => el.Key.split('/')[el.Key.split('/').length - 1]
);
if (uploadedFileData.length > 0) {
res.json({
success: true,
message: 'OK',
files: uploadedFileData,
name: uploadedFileData[0].originalname,
url: urls[1] ? urls[1] : urls[0],
fileNames,
urls,
Data: uploadedFileData,
prefix: req.params.UID + '/avatar'
});
} else {
res.json({ success: true, message: 'file already existed' });
}
} catch (e) {
errorLoggerUpdate(e);
const err = /** @type {Error} */ (e);
res.status(500).json({ success: false, message: err.message });
}
};
/**
* Stream a language file to the client.
* Handles GET /:app/:filename
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const getLanguageFileController = async (req, res) => {
try {
const data = await languageFileService.getLanguageFile(
req.params.app,
req.params.filename
);
res.set('Content-Type', 'application/octetstream');
res.set('Content-Disposition', `attachment; filename="${req.params.filename}"`);
data.on('error', (streamErr) => {
console.error('Stream error:', streamErr);
if (!res.headersSent) {
res.status(500).json({ success: false, message: 'Stream error' });
}
});
data.pipe(res);
} catch (e) {
const err = /** @type {any} */ (e);
console.error(`S3 error for ${req.params.app}/languages/${req.params.filename}:`, err.code);
if (!res.headersSent) {
const status = err.code === 'NoSuchKey' || err.code === 'NotFound' ? 410 : 500;
res.status(status).json({ success: false, message: 'not available', code: err.code });
}
}
};
/**
* Delete a language file from the object store.
* Handles DELETE /:app/:filename
*
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
* @returns {Promise<void>}
*/
export const deleteLanguageFileController = async (req, res) => {
try {
const result = await languageFileService.deleteLanguageFile(
req.params.app,
req.params.filename
);
res.json({ success: true, result });
} catch (e) {
console.error('Error deleting language file:', e);
errorLoggerUpdate(e);
const err = /** @type {Error} */ (e);
if (!res.headersSent) {
res.status(500).json({ success: false, message: 'Error deleting file', error: err.message });
}
}
};