Files
clsi/app/coffee/CompileController.js

164 lines
5.5 KiB
JavaScript

/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let CompileController;
const RequestParser = require("./RequestParser");
const CompileManager = require("./CompileManager");
const Settings = require("settings-sharelatex");
const Metrics = require("./Metrics");
const ProjectPersistenceManager = require("./ProjectPersistenceManager");
const logger = require("logger-sharelatex");
const Errors = require("./Errors");
module.exports = (CompileController = {
compile(req, res, next) {
if (next == null) { next = function(error) {}; }
const timer = new Metrics.Timer("compile-request");
return RequestParser.parse(req.body, function(error, request) {
if (error != null) { return next(error); }
request.project_id = req.params.project_id;
if (req.params.user_id != null) { request.user_id = req.params.user_id; }
return ProjectPersistenceManager.markProjectAsJustAccessed(request.project_id, function(error) {
if (error != null) { return next(error); }
return CompileManager.doCompileWithLock(request, function(error, outputFiles) {
let code, status;
if (outputFiles == null) { outputFiles = []; }
if (error instanceof Errors.AlreadyCompilingError) {
code = 423; // Http 423 Locked
status = "compile-in-progress";
} else if (error instanceof Errors.FilesOutOfSyncError) {
code = 409; // Http 409 Conflict
status = "retry";
} else if (error != null ? error.terminated : undefined) {
status = "terminated";
} else if (error != null ? error.validate : undefined) {
status = `validation-${error.validate}`;
} else if (error != null ? error.timedout : undefined) {
status = "timedout";
logger.log({err: error, project_id: request.project_id}, "timeout running compile");
} else if (error != null) {
status = "error";
code = 500;
logger.warn({err: error, project_id: request.project_id}, "error running compile");
} else {
let file;
status = "failure";
for (file of Array.from(outputFiles)) {
if (file.path != null ? file.path.match(/output\.pdf$/) : undefined) {
status = "success";
}
}
if (status === "failure") {
logger.warn({project_id: request.project_id, outputFiles}, "project failed to compile successfully, no output.pdf generated");
}
// log an error if any core files are found
for (file of Array.from(outputFiles)) {
if (file.path === "core") {
logger.error({project_id:request.project_id, req, outputFiles}, "core file found in output");
}
}
}
if (error != null) {
outputFiles = error.outputFiles || [];
}
timer.done();
return res.status(code || 200).send({
compile: {
status,
error: (error != null ? error.message : undefined) || error,
outputFiles: outputFiles.map(file =>
({
url:
`${Settings.apis.clsi.url}/project/${request.project_id}` +
((request.user_id != null) ? `/user/${request.user_id}` : "") +
((file.build != null) ? `/build/${file.build}` : "") +
`/output/${file.path}`,
path: file.path,
type: file.type,
build: file.build
})
)
}
});
});
});
});
},
stopCompile(req, res, next) {
const {project_id, user_id} = req.params;
return CompileManager.stopCompile(project_id, user_id, function(error) {
if (error != null) { return next(error); }
return res.sendStatus(204);
});
},
clearCache(req, res, next) {
if (next == null) { next = function(error) {}; }
return ProjectPersistenceManager.clearProject(req.params.project_id, req.params.user_id, function(error) {
if (error != null) { return next(error); }
return res.sendStatus(204);
});
}, // No content
syncFromCode(req, res, next) {
if (next == null) { next = function(error) {}; }
const { file } = req.query;
const line = parseInt(req.query.line, 10);
const column = parseInt(req.query.column, 10);
const { project_id } = req.params;
const { user_id } = req.params;
return CompileManager.syncFromCode(project_id, user_id, file, line, column, function(error, pdfPositions) {
if (error != null) { return next(error); }
return res.json({
pdf: pdfPositions
});
});
},
syncFromPdf(req, res, next) {
if (next == null) { next = function(error) {}; }
const page = parseInt(req.query.page, 10);
const h = parseFloat(req.query.h);
const v = parseFloat(req.query.v);
const { project_id } = req.params;
const { user_id } = req.params;
return CompileManager.syncFromPdf(project_id, user_id, page, h, v, function(error, codePositions) {
if (error != null) { return next(error); }
return res.json({
code: codePositions
});
});
},
wordcount(req, res, next) {
if (next == null) { next = function(error) {}; }
const file = req.query.file || "main.tex";
const { project_id } = req.params;
const { user_id } = req.params;
const { image } = req.query;
logger.log({image, file, project_id}, "word count request");
return CompileManager.wordcount(project_id, user_id, file, image, function(error, result) {
if (error != null) { return next(error); }
return res.json({
texcount: result
});
});
},
status(req, res, next ){
if (next == null) { next = function(error){}; }
return res.send("OK");
}
});