2021-02-20 23:39:03 +01:00
|
|
|
const repos = new Map();
|
|
|
|
const state = require('../state');
|
|
|
|
const logger = require('logplease').create('ppman/routes');
|
|
|
|
const {Repository} = require('./repo');
|
|
|
|
const semver = require('semver');
|
2021-02-27 00:58:30 +01:00
|
|
|
const { body, param } = require('express-validator');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
async function get_or_construct_repo(slug){
|
2021-02-20 23:39:03 +01:00
|
|
|
if(repos.has(slug))return repos.get(slug);
|
|
|
|
if(state.state.get('repositories').has(slug)){
|
|
|
|
const repo_url = state.state.get('repositories').get(slug);
|
|
|
|
const repo = new Repository(slug, repo_url);
|
|
|
|
await repo.load();
|
|
|
|
repos.set(slug, repo);
|
|
|
|
return repo;
|
2021-02-20 15:13:56 +01:00
|
|
|
}
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.warn(`Requested repo ${slug} does not exist`);
|
|
|
|
return null;
|
2021-02-20 15:13:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async function get_package(repo, lang, version){
|
|
|
|
var candidates = repo.packages.filter(
|
|
|
|
pkg => pkg.language == lang && semver.satisfies(pkg.version, version)
|
2021-02-20 23:39:03 +01:00
|
|
|
);
|
|
|
|
return candidates.sort((a,b)=>semver.rcompare(a.version,b.version))[0] || null;
|
2021-02-20 15:13:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
async repo_list(req,res){
|
|
|
|
// GET /repos
|
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Request for repoList');
|
2021-02-20 15:13:56 +01:00
|
|
|
res.json_success({
|
|
|
|
repos: (await Promise.all(
|
2021-02-20 23:39:03 +01:00
|
|
|
[...state.state.get('repositories').keys()].map( async slug => await get_or_construct_repo(slug))
|
2021-02-20 15:13:56 +01:00
|
|
|
)).map(repo=>({
|
|
|
|
slug: repo.slug,
|
|
|
|
url: repo.url,
|
|
|
|
packages: repo.packages.length
|
|
|
|
}))
|
2021-02-20 23:39:03 +01:00
|
|
|
});
|
2021-02-20 15:13:56 +01:00
|
|
|
},
|
2021-02-27 00:58:30 +01:00
|
|
|
repo_add_validators: [
|
|
|
|
body('slug')
|
2021-02-27 01:08:51 +01:00
|
|
|
.notEmpty() // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
2021-02-27 01:08:51 +01:00
|
|
|
.isSlug() // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
.not()
|
|
|
|
.custom(value=>state.state.get('repositories').keys().includes(value))
|
2021-02-27 01:08:51 +01:00
|
|
|
.withMessage('slug is already in use'), // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
body('url')
|
2021-02-27 01:08:51 +01:00
|
|
|
.notEmpty() // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
2021-02-27 01:08:51 +01:00
|
|
|
.isURL({require_protocol: true}) // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
|
|
|
|
],
|
2021-02-20 15:13:56 +01:00
|
|
|
async repo_add(req, res){
|
|
|
|
// POST /repos
|
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug(`Request for repoAdd slug=${req.body.slug} url=${req.body.url}`);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
const repo_state = state.state.get('repositories');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
repo_state.set(req.body.slug, req.body.url);
|
|
|
|
logger.info(`Repository ${req.body.slug} added url=${req.body.url}`);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
return res.json_success(req.body.slug);
|
2021-02-20 15:13:56 +01:00
|
|
|
},
|
2021-02-27 00:58:30 +01:00
|
|
|
repo_info_validators: [
|
|
|
|
param('repo_slug')
|
2021-02-27 01:08:51 +01:00
|
|
|
.isSlug() // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
.custom(value=>state.state.get('repositories').has(value))
|
2021-02-27 01:08:51 +01:00
|
|
|
.withMessage('repository does not exist') // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
],
|
2021-02-20 15:13:56 +01:00
|
|
|
async repo_info(req, res){
|
|
|
|
// GET /repos/:slug
|
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug(`Request for repoInfo for ${req.params.repo_slug}`);
|
|
|
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
res.json_success({
|
|
|
|
slug: repo.slug,
|
|
|
|
url: repo.url,
|
|
|
|
packages: repo.packages.length
|
2021-02-20 23:39:03 +01:00
|
|
|
});
|
2021-02-20 15:13:56 +01:00
|
|
|
},
|
2021-02-27 00:58:30 +01:00
|
|
|
repo_packages_validators: [
|
|
|
|
param('repo_slug')
|
2021-02-27 01:08:51 +01:00
|
|
|
.isSlug() // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
.custom(value=>state.state.get('repositories').has(value))
|
2021-02-27 01:08:51 +01:00
|
|
|
.withMessage('repository does not exist') // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
],
|
2021-02-20 15:13:56 +01:00
|
|
|
async repo_packages(req, res){
|
|
|
|
// GET /repos/:slug/packages
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Request to repoPackages');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
|
|
|
if(repo == null) return res.json_error(`Requested repo ${req.params.repo_slug} does not exist`, 404);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
res.json_success({
|
|
|
|
packages: repo.packages.map(pkg=>({
|
|
|
|
language: pkg.language,
|
|
|
|
language_version: pkg.version.raw,
|
|
|
|
installed: pkg.installed
|
|
|
|
}))
|
2021-02-20 23:39:03 +01:00
|
|
|
});
|
2021-02-20 15:13:56 +01:00
|
|
|
},
|
2021-02-27 00:58:30 +01:00
|
|
|
package_info_validators: [
|
|
|
|
param('repo_slug')
|
2021-02-27 01:08:51 +01:00
|
|
|
.isSlug() // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
.custom(value=>state.state.get('repositories').has(value))
|
2021-02-27 01:08:51 +01:00
|
|
|
.withMessage('repository does not exist') // eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
.bail()
|
|
|
|
],
|
2021-02-20 15:13:56 +01:00
|
|
|
async package_info(req, res){
|
|
|
|
// GET /repos/:slug/packages/:language/:version
|
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Request to packageInfo');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
const pkg = await get_package(repo, req.params.language, req.params.version);
|
|
|
|
if(pkg == null) return res.json_error(`Requested package ${req.params.language}-${req.params.version} does not exist`, 404);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
res.json_success({
|
2021-02-20 23:39:03 +01:00
|
|
|
language: pkg.language,
|
|
|
|
language_version: pkg.version.raw,
|
|
|
|
author: pkg.author,
|
|
|
|
buildfile: pkg.buildfile,
|
|
|
|
size: pkg.size,
|
|
|
|
dependencies: pkg.dependencies,
|
|
|
|
installed: pkg.installed
|
|
|
|
});
|
2021-02-20 15:13:56 +01:00
|
|
|
},
|
|
|
|
async package_install(req,res){
|
|
|
|
// POST /repos/:slug/packages/:language/:version
|
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Request to packageInstall');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
|
|
|
const pkg = await get_package(repo, req.params.language, req.params.version);
|
|
|
|
if(pkg == null) return res.json_error(`Requested package ${req.params.language}-${req.params.version} does not exist`, 404);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
try{
|
2021-02-20 23:39:03 +01:00
|
|
|
const response = await pkg.install();
|
|
|
|
return res.json_success(response);
|
2021-02-20 15:13:56 +01:00
|
|
|
}catch(err){
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.error(`Error while installing package ${pkg.language}-${pkg.version}:`, err.message);
|
|
|
|
res.json_error(err.message,500);
|
2021-02-20 15:13:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
async package_uninstall(req,res){
|
|
|
|
// DELETE /repos/:slug/packages/:language/:version
|
|
|
|
|
2021-02-27 00:58:30 +01:00
|
|
|
//res.json(req.body); //TODO
|
2021-02-27 01:08:51 +01:00
|
|
|
res.json_error('not implemented', 500);
|
2021-02-20 15:13:56 +01:00
|
|
|
}
|
2021-02-20 23:39:03 +01:00
|
|
|
};
|