mirror of https://gitee.com/bigwinds/arangodb
318 lines
9.0 KiB
JavaScript
318 lines
9.0 KiB
JavaScript
'use strict';
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2013 triAGENS GmbH, Cologne, Germany
|
|
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Michael Hackstein
|
|
/// @author Alan Plum
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const fs = require('fs');
|
|
const joi = require('joi');
|
|
const dd = require('dedent');
|
|
const marked = require('marked');
|
|
const internal = require('internal');
|
|
const highlightAuto = require('highlight.js').highlightAuto;
|
|
const FoxxManager = require('@arangodb/foxx/manager');
|
|
const fmUtils = require('@arangodb/foxx/manager-utils');
|
|
const createRouter = require('@arangodb/foxx/router');
|
|
|
|
const DEFAULT_THUMBNAIL = module.context.fileName('default-thumbnail.png');
|
|
|
|
const router = createRouter();
|
|
module.exports = router;
|
|
|
|
|
|
router.use((req, res, next) => {
|
|
if (!internal.options()['server.disable-authentication'] && (!req.session || !req.session.uid)) {
|
|
res.throw('unauthorized');
|
|
}
|
|
next();
|
|
});
|
|
|
|
|
|
const foxxRouter = createRouter();
|
|
router.use(foxxRouter)
|
|
.queryParam('mount', joi.string().required(), dd`
|
|
The mount point of the service. Has to be url-encoded.
|
|
`);
|
|
|
|
|
|
const installer = createRouter();
|
|
foxxRouter.use(installer)
|
|
.queryParam('upgrade', joi.boolean().default(false), dd`
|
|
Flag to upgrade the service installed at the mountpoint.
|
|
Triggers setup.
|
|
`)
|
|
.queryParam('replace', joi.boolean().default(false), dd`
|
|
Flag to replace the service installed at the mountpoint.
|
|
Triggers teardown and setup.
|
|
`);
|
|
|
|
|
|
installer.use(function (req, res, next) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const upgrade = req.queryParams.upgrade;
|
|
const replace = req.queryParams.replace;
|
|
next();
|
|
let appInfo, options;
|
|
if (typeof req.body === 'object') {
|
|
appInfo = 'EMPTY';
|
|
options = req.body;
|
|
} else {
|
|
appInfo = req.body;
|
|
options = undefined;
|
|
}
|
|
let service;
|
|
if (upgrade) {
|
|
service = FoxxManager.upgrade(appInfo, mount, options);
|
|
} else if (replace) {
|
|
service = FoxxManager.replace(appInfo, mount, options);
|
|
} else {
|
|
service = FoxxManager.install(appInfo, mount, options);
|
|
}
|
|
const configuration = FoxxManager.configuration(mount);
|
|
res.json(Object.assign(
|
|
{error: false, configuration},
|
|
service
|
|
));
|
|
});
|
|
|
|
|
|
installer.put('/store', function (req) {
|
|
req.body = `${req.body.name}:${req.body.version}`;
|
|
})
|
|
.body(joi.object({
|
|
name: joi.string().required(),
|
|
version: joi.string().required()
|
|
}).required(), 'A Foxx service from the store.')
|
|
.summary('Install a Foxx from the store')
|
|
.description(dd`
|
|
Downloads a Foxx from the store and installs it at the given mount.
|
|
`);
|
|
|
|
|
|
installer.put('/git', function (req) {
|
|
req.body = `git:${req.body.url}:${req.body.version}`;
|
|
})
|
|
.body(joi.object({
|
|
url: joi.string().required(),
|
|
version: joi.string().default('master')
|
|
}).required(), 'A GitHub reference.')
|
|
.summary('Install a Foxx from Github')
|
|
.description(dd`
|
|
Install a Foxx with user/repository and version.
|
|
`);
|
|
|
|
|
|
installer.put('/generate', () => {})
|
|
.body(joi.object().required(), 'A Foxx generator configuration.')
|
|
.summary('Generate a new foxx')
|
|
.description(dd`
|
|
Generate a new empty foxx on the given mount point.
|
|
`);
|
|
|
|
|
|
installer.put('/zip', function (req) {
|
|
req.body = req.body.zipFile;
|
|
})
|
|
.body(joi.object({
|
|
zipFile: joi.string().required()
|
|
}).required(), 'A zip file path.')
|
|
.summary('Install a Foxx from temporary zip file')
|
|
.description(dd`
|
|
Install a Foxx from the given zip path.
|
|
This path has to be created via _api/upload.
|
|
`);
|
|
|
|
|
|
foxxRouter.delete('/', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const runTeardown = req.parameters.teardown;
|
|
const service = FoxxManager.uninstall(mount, {
|
|
teardown: runTeardown,
|
|
force: true
|
|
});
|
|
res.json(Object.assign(
|
|
{error: false},
|
|
service
|
|
));
|
|
})
|
|
.queryParam('teardown', joi.boolean().default(true))
|
|
.summary('Uninstall a Foxx')
|
|
.description(dd`
|
|
Uninstall the Foxx at the given mount-point.
|
|
`);
|
|
|
|
|
|
router.get('/', function (req, res) {
|
|
const foxxes = FoxxManager.listJson();
|
|
foxxes.forEach((foxx) => {
|
|
const readme = FoxxManager.readme(foxx.mount);
|
|
if (readme) {
|
|
foxx.readme = marked(readme, {
|
|
highlight: (code) => highlightAuto(code).value
|
|
});
|
|
}
|
|
});
|
|
res.json(foxxes);
|
|
})
|
|
.summary('List all Foxxes')
|
|
.description(dd`
|
|
Get a List of all running foxxes.
|
|
`);
|
|
|
|
|
|
foxxRouter.get('/thumbnail', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const service = FoxxManager.lookupApp(mount);
|
|
res.sendFile(service.thumbnail || DEFAULT_THUMBNAIL);
|
|
})
|
|
.summary('Get the thumbnail of a Foxx')
|
|
.description(dd`
|
|
Request the thumbnail of the given Foxx in order to display it on the screen.
|
|
`);
|
|
|
|
|
|
foxxRouter.get('/config', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
res.json(FoxxManager.configuration(mount));
|
|
})
|
|
.summary('Get the configuration for a service')
|
|
.description(dd`
|
|
Used to request the configuration options for services.
|
|
`);
|
|
|
|
|
|
foxxRouter.patch('/config', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const configuration = req.body;
|
|
res.json(FoxxManager.configure(mount, {configuration}));
|
|
})
|
|
.body(joi.object().optional(), 'Configuration to apply.')
|
|
.summary('Set the configuration for a service')
|
|
.description(dd`
|
|
Used to overwrite the configuration options for services.
|
|
`);
|
|
|
|
|
|
foxxRouter.get('/deps', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
res.json(FoxxManager.dependencies(mount));
|
|
})
|
|
.summary('Get the dependencies for a service')
|
|
.description(dd`
|
|
Used to request the dependencies options for services.
|
|
`);
|
|
|
|
|
|
foxxRouter.patch('/deps', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const dependencies = req.body;
|
|
res.json(FoxxManager.updateDeps(mount, {dependencies}));
|
|
})
|
|
.body(joi.object().optional(), 'Dependency settings to apply.')
|
|
.summary('Set the dependencies for a service')
|
|
.description(dd`
|
|
Used to overwrite the dependencies options for services.
|
|
`);
|
|
|
|
|
|
foxxRouter.post('/tests', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
res.json(FoxxManager.runTests(mount, req.body));
|
|
})
|
|
.body(joi.object().optional(), 'Options to pass to the test runner.')
|
|
.summary('Run tests for a service')
|
|
.description(dd`
|
|
Used to run the tests of a service.
|
|
`);
|
|
|
|
|
|
foxxRouter.post('/scripts/:name', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const name = req.queryParams.name;
|
|
try {
|
|
res.json(FoxxManager.runScript(name, mount, req.body));
|
|
} catch (e) {
|
|
throw e.cause || e;
|
|
}
|
|
})
|
|
.pathParam('name', joi.string().required(), 'The name of a service\'s script to run.')
|
|
.body(joi.any().default(null), 'Options to pass to the script.')
|
|
.summary('Run a script for a service')
|
|
.description(dd`
|
|
Used to trigger any script of a service.
|
|
`);
|
|
|
|
|
|
foxxRouter.patch('/devel', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const activate = Boolean(req.body);
|
|
res.json(FoxxManager[activate ? 'development' : 'production'](mount));
|
|
})
|
|
.body(joi.boolean().optional())
|
|
.summary('Activate/Deactivate development mode for a service')
|
|
.description(dd`
|
|
Used to toggle between production and development mode.
|
|
`);
|
|
|
|
|
|
foxxRouter.get('/download/zip', function (req, res) {
|
|
const mount = decodeURIComponent(req.queryParams.mount);
|
|
const service = FoxxManager.lookupApp(mount);
|
|
const dir = fs.join(fs.makeAbsolute(service.root), service.path);
|
|
const zipPath = fmUtils.zipDirectory(dir);
|
|
res.download(zipPath, `${service.name}@${service.version}.zip.`);
|
|
})
|
|
.summary('Download a service as zip archive')
|
|
.description(dd`
|
|
Download a foxx service packed in a zip archive.
|
|
`);
|
|
|
|
|
|
router.get('/fishbowl', function (req, res) {
|
|
try {
|
|
FoxxManager.update();
|
|
} catch (e) {
|
|
console.warnLines(`Failed to update Foxx store: ${e.stack}`);
|
|
}
|
|
res.json(FoxxManager.availableJson());
|
|
})
|
|
.summary('List of all foxx services submitted to the Foxx store.')
|
|
.description(dd`
|
|
This function contacts the fishbowl and reports which services are available for install.
|
|
`);
|
|
|
|
|
|
router.get('/docs/standalone/*', module.context.apiDocumentation(
|
|
(req) => ({
|
|
appPath: decodeURIComponent(req.queryParams.mount)
|
|
})
|
|
));
|
|
|
|
|
|
router.get('/docs/*', module.context.apiDocumentation(
|
|
(req) => ({
|
|
appPath: decodeURIComponent(req.queryParams.mount),
|
|
indexFile: 'index-alt.html'
|
|
})
|
|
));
|