express-gateway
Version:
A microservices API gateway built on top of ExpressJS
201 lines (165 loc) • 4.94 kB
JavaScript
const fs = require('fs');
const path = require('path');
const express = require('express');
const parentRequire = require('parent-require');
const PluginInstaller = require('../../plugin-installer');
let pluginCache = null;
module.exports = function () {
const router = express.Router();
router.get('/', function (req, res, next) {
res.json({ plugins: getPlugins() });
next();
});
router.post('/', function (req, res, next) {
if (!req.body || !req.body.package) {
res.status(400);
next();
return;
}
const installer = PluginInstaller.create();
const packageSpecifier = req.body.package;
installer.runNPMInstallation({
packageSpecifier,
cwd: process.cwd(),
env: process.env
}).then(() => {
invalidatePluginCache();
const previousPluginOptions = installer.existingPluginOptions;
const optionsMeta = installer.pluginManifest.options || {};
const keys = Object.keys(optionsMeta);
const options = keys.map(key => {
return {
name: key,
schema: optionsMeta[key],
value: previousPluginOptions[key]
};
});
res.json({
name: installer.pluginKey,
description: installer.pluginManifest.description || null,
package: installer.packageName,
version: getPackageVersion(installer.packageName),
disabled: true,
state: 'awaiting-configuration',
options
});
next();
});
});
router.get('/:id', function (req, res, next) {
const filtered = getPlugins()
.filter(plugin => {
return plugin.name === req.params.id;
});
if (filtered.length) {
res.json(filtered[0]);
} else {
res.status(404);
}
next();
});
router.put('/:package', function (req, res, next) {
if (!req.body || !req.params.package) {
res.status(400);
next();
return;
}
const packageName = req.params.package;
const pluginManifest = getPluginManifest(packageName);
const installer = PluginInstaller.create({ packageName, pluginManifest });
installer.updateConfigurationFiles({
pluginOptions: req.body.options,
enablePlugin: true,
addPoliciesToWhitelist:
!!req.params.addPoliciesToGatewayConfig
}).then(() => {
const optionKeys = Object.keys(pluginManifest.options);
const options = optionKeys
.map(optionKey => {
return {
name: optionKey,
schema: pluginManifest.options[optionKey],
value: req.body.options[optionKey] ||
installer.existingPluginOptions[optionKey] ||
pluginManifest.options[optionKey].default
};
});
res.json({
name: installer.pluginKey,
description: pluginManifest.description || null,
package: packageName,
version: getPackageVersion(packageName),
disabled: false,
state: 'configured',
options: options
});
next();
})
.catch(err => {
next(err);
});
});
return router;
};
function getPlugins () {
if (pluginCache === null) {
loadPlugins();
}
return pluginCache;
}
function invalidatePluginCache () {
pluginCache = null;
}
function loadPlugins () {
const config = require('../../config');
const keys = Object.keys(config.systemConfig.plugins);
const plugins = keys.map(key => {
const plugin = config.systemConfig.plugins[key];
const packageName = plugin.package ||
PluginInstaller.PACKAGE_PREFIX + key;
const pluginManifest = getPluginManifest(packageName);
const version = getPackageVersion(packageName);
pluginManifest.options = pluginManifest.options || {};
const optionKeys = Object.keys(plugin);
const reserved = ['state', 'disabled', 'package'];
const options = optionKeys
.filter(optionKey => reserved.indexOf(optionKey) === -1)
.map(optionKey => {
return {
name: optionKey,
schema: pluginManifest.options[optionKey],
value: plugin[optionKey]
};
});
return {
name: key,
description: pluginManifest.description || null,
package: packageName,
version: version,
disabled: plugin.disabled || false,
state: 'configured',
options: options
};
});
pluginCache = plugins || [];
}
function getPackageVersion (packageName) {
let version = null;
try {
const packageJSON = fs.readFileSync(path.join(process.cwd(),
'node_modules', packageName, 'package.json'));
version = JSON.parse(packageJSON.toString()).version;
} catch (_) {
version = null;
}
return version;
}
function getPluginManifest (packageName) {
let pluginManifest;
try {
pluginManifest = require(packageName);
} catch (_) {
pluginManifest = parentRequire(packageName);
}
return pluginManifest;
}