@crowdin/app-project-module
Version:
Module that generates for you all common endpoints for serving standalone Crowdin App
161 lines (160 loc) • 7.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const util_1 = require("../../../util");
const files_1 = require("../util/files");
const types_1 = require("../types");
function handle(baseUrl, folder, config) {
if (!fs_1.default.existsSync(path_1.default.join(folder, 'custom-file-format'))) {
fs_1.default.mkdirSync(path_1.default.join(folder, 'custom-file-format'), { recursive: true });
}
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
const baseFilesUrl = `${baseUrl}/file/download`;
const body = req.body;
let logData;
if (body.strings) {
logData = Object.assign({}, body, { strings: body.strings.slice(0, 5) });
}
else {
logData = body;
}
req.logInfo(`Received request to process file ${JSON.stringify(logData, null, 2)}`);
let file;
if (body.file.content) {
file = Buffer.from(body.file.content, 'base64');
}
else if (body.file.contentUrl) {
file = yield (0, files_1.getFileContent)(body.file.contentUrl);
}
let response = {};
let error;
switch (body.jobType) {
case types_1.ProcessFileJobType.BUILD_FILE:
const buildFileResult = yield handleBuildFile(baseFilesUrl, folder, config, body, req.crowdinApiClient, req.crowdinContext, req.crowdinContext.jwtPayload.context.project_id, file);
response = buildFileResult.response;
error = buildFileResult.error;
break;
case types_1.ProcessFileJobType.PARSE_FILE:
const parseFileResult = yield handleParseFile(baseFilesUrl, folder, config, body, req.crowdinApiClient, req.crowdinContext, req.crowdinContext.jwtPayload.context.project_id, file);
response = parseFileResult.response;
error = parseFileResult.error;
break;
}
const responseLength = Buffer.byteLength(JSON.stringify(response), 'utf8');
req.logInfo(`Returning response (${responseLength} bytes) from process file action`);
res.send({ data: response, error: error ? { message: error } : undefined });
}));
}
exports.default = handle;
function handleBuildFile(baseUrl, dataFolder, config, req, client, context, projectId, file) {
return __awaiter(this, void 0, void 0, function* () {
const response = {};
if (!req.strings && !req.stringsUrl) {
throw new Error('Bad payload received: No strings found');
}
let strings;
if (req.strings) {
strings = req.strings;
}
else {
strings = yield (0, files_1.getFileStrings)(req.stringsUrl);
}
let res;
if ((req.file.id || !file) && config.exportStrings) {
res = yield config.exportStrings(req, strings, client, context, projectId);
}
else if (file && config.buildFile) {
res = yield config.buildFile(file, req, strings, client, context, projectId);
}
else {
return { response };
}
const contentFileEncoded = Buffer.from(res.contentFile).toString('base64');
if (Buffer.byteLength(contentFileEncoded, 'utf8') < files_1.MAX_BODY_SIZE) {
response.content = contentFileEncoded;
}
else {
let url;
if (config.storeFile) {
url = yield config.storeFile(res.contentFile);
}
else {
const storedFile = yield (0, files_1.storeFile)(res.contentFile, path_1.default.join(dataFolder, 'custom-file-format'));
url = `${baseUrl}?file=${storedFile}`;
}
response.contentUrl = url;
}
return { response, error: res.error };
});
}
function handleParseFile(baseUrl, dataFolder, config, req, client, context, projectId, file) {
return __awaiter(this, void 0, void 0, function* () {
const response = {};
if (!config.parseFile || !file) {
return { response };
}
const res = yield config.parseFile(file, req, client, context, projectId);
let maxSize = files_1.MAX_BODY_SIZE;
if (res.strings && res.previewFile) {
maxSize = maxSize / 2;
}
if (res.previewFile) {
if (Buffer.byteLength(res.previewFile) < maxSize) {
response.preview = res.previewFile.toString('base64');
}
else {
let url;
if (config.storeFile) {
url = yield config.storeFile(res.previewFile);
}
else {
const storedFile = yield (0, files_1.storeFile)(res.previewFile, path_1.default.join(dataFolder, 'custom-file-format'));
url = `${baseUrl}?file=${storedFile}`;
}
response.previewUrl = url;
}
}
if (res.strings) {
let strings = res.strings;
if (config.autoUploadTranslations) {
strings = strings.map((string) => {
const translations = {};
req.targetLanguages
.map((targetLanguage) => targetLanguage.id)
.forEach((targetLanguage) => (translations[targetLanguage] = { text: string.text }));
return Object.assign(Object.assign({}, string), { translations });
});
}
const stringsNDJson = strings.map((s) => JSON.stringify(s)).join('\n\r');
const bufferData = Buffer.from(stringsNDJson, 'utf8');
if (Buffer.byteLength(bufferData) < maxSize) {
response.strings = strings;
}
else {
let url;
if (config.storeFile) {
url = yield config.storeFile(bufferData);
}
else {
const storedFile = yield (0, files_1.storeFile)(bufferData, path_1.default.join(dataFolder, 'custom-file-format'));
url = `${baseUrl}?file=${storedFile}`;
}
response.stringsUrl = url;
}
}
return { response, error: res.error };
});
}