piston/api/src/index.js

111 lines
4.2 KiB
JavaScript

#!/usr/bin/env node
require('nocamel');
const Logger = require('logplease');
const express = require('express');
const globals = require('./globals');
const config = require('./config');
const cache = require('./cache');
const state = require('./state');
const path = require('path');
const fs = require('fs/promises');
const fss = require('fs');
const body_parser = require('body-parser');
const runtime = require('./runtime');
const {validationResult} = require('express-validator');
const logger = Logger.create('index');
const app = express();
(async () => {
logger.info('Setting loglevel to',config.log_level);
Logger.setLogLevel(config.log_level); //eslint-disable-line snakecasejs/snakecasejs
logger.debug('Ensuring data directories exist');
Object.values(globals.data_directories).forEach(dir => {
var data_path = path.join(config.data_directory, dir);
logger.debug(`Ensuring ${data_path} exists`);
if(!fss.exists_sync(data_path)){
logger.info(`${data_path} does not exist.. Creating..`);
try{
fss.mkdir_sync(data_path);
}catch(err){
logger.error(`Failed to create ${data_path}: `, err.message);
}
}
});
logger.info('Loading state');
await state.load(path.join(config.data_directory,globals.data_files.state));
logger.info('Loading cache');
await cache.load(path.join(config.data_directory,globals.data_directories.cache));
logger.info('Loading packages');
const pkgdir = path.join(config.data_directory,globals.data_directories.packages);
await fs.readdir(pkgdir)
.then(langs => Promise.all(
langs.map(lang=>
fs.readdir(path.join(pkgdir,lang))
.then(x=>x.map(y=>path.join(pkgdir, lang, y)))
)))
.then(pkgs=>pkgs.flat().filter(pkg=>fss.exists_sync(path.join(pkg, globals.pkg_installed_file))))
.then(pkgs=>pkgs.forEach(pkg => new runtime.Runtime(pkg)));
logger.info('Starting API Server');
logger.debug('Constructing Express App');
logger.debug('Registering custom message wrappers');
express.response.json_error = function(message, code) {
this.status(code);
return this.json({success: false, message, code});
};
express.response.json_success = function(obj) {
return this.json({success: true, data: obj});
};
logger.debug('Registering middleware');
app.use(body_parser.urlencoded({extended: true}));
app.use(body_parser.json());
function validate(req, res, next) {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.json_error(errors.array(), 422);
next();
}
logger.debug('Registering Routes');
const ppman_routes = require('./ppman/routes');
app.get ('/repos', validate, ppman_routes.repo_list);
app.post ('/repos', ppman_routes.repo_add_validators, validate, ppman_routes.repo_add);
app.get ('/repos/:repo_slug', ppman_routes.repo_info_validators, validate, ppman_routes.repo_info);
app.get ('/repos/:repo_slug/packages', ppman_routes.repo_packages_validators, validate, ppman_routes.repo_packages);
app.get ('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info_validators, validate, ppman_routes.package_info);
app.post ('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info_validators, validate, ppman_routes.package_install);
app.delete('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info_validators, validate, ppman_routes.package_uninstall); //TODO
const executor_routes = require('./executor/routes');
app.post ('/jobs', executor_routes.run_job_validators, validate, executor_routes.run_job);
logger.debug('Calling app.listen');
const [address,port] = config.bind_address.split(':');
app.listen(port, address, ()=>{
logger.info('API server started on', config.bind_address);
});
logger.debug('Setting up flush timers');
setInterval(cache.flush,config.cache_flush_time,path.join(config.data_directory,globals.data_directories.cache));
setInterval(state.save,config.state_flush_time,path.join(config.data_directory,globals.data_files.state));
})();