1 | const logger = require('./logger').plugins;
|
2 | const eventBus = require('./eventBus');
|
3 | const schemas = require('./schemas');
|
4 | const parentRequire = require('parent-require');
|
5 | const engineVersion = '1.2.0';
|
6 | const semver = require('semver');
|
7 | const prefix = 'express-gateway-plugin-';
|
8 | module.exports.load = function ({ config }) {
|
9 | config = config || require('./config');
|
10 | const pluginsSettings = config.systemConfig.plugins || {};
|
11 |
|
12 | const loadedPlugins = [];
|
13 | logger.debug(`Loading plugins. Plugin engine version: ${engineVersion}`);
|
14 | for (const pluginName in pluginsSettings) {
|
15 | const settings = pluginsSettings[pluginName] || {};
|
16 | let requireName = pluginName;
|
17 | if (settings.package) {
|
18 | requireName = settings.package;
|
19 | } else if (pluginName.indexOf(prefix) !== 0) {
|
20 | requireName = prefix + pluginName;
|
21 | }
|
22 |
|
23 | try {
|
24 | logger.debug(`Loading plugin ${requireName}`);
|
25 | let plugin;
|
26 | try {
|
27 | plugin = require(requireName);
|
28 | } catch (err) {
|
29 | plugin = parentRequire(requireName);
|
30 | }
|
31 | if (semver.lt(engineVersion, plugin.version)) {
|
32 | logger.warn(`${plugin.version} is higher than engine version: ${engineVersion}; trying to load`);
|
33 | }
|
34 |
|
35 |
|
36 | const validate = schemas.register('plugin', pluginName, plugin.schema);
|
37 | const { isValid, error } = validate(settings);
|
38 | if (!isValid) {
|
39 |
|
40 | throw new Error(`Failed to validate settings: ${error}`);
|
41 | }
|
42 |
|
43 | const services = require('./services');
|
44 | const context = new PluginContext({ settings, config, services });
|
45 | plugin.init(context);
|
46 | loadedPlugins.push(context);
|
47 | logger.info(`Loaded plugin ${pluginName} from package ${requireName}`);
|
48 | } catch (err) {
|
49 | logger.error(`Failed to load plugin ${requireName}: ${err}`);
|
50 | }
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 | return {
|
56 | policies: extract(loadedPlugins, 'policies'),
|
57 | conditions: extract(loadedPlugins, 'conditions'),
|
58 | gatewayRoutes: extract(loadedPlugins, 'gatewayRoutes'),
|
59 | adminRoutes: extract(loadedPlugins, 'adminRoutes'),
|
60 | cliExtensions: extract(loadedPlugins, 'cliExtensions')
|
61 | };
|
62 | };
|
63 |
|
64 | class PluginContext {
|
65 | constructor ({ settings, config, services }) {
|
66 | this.logger = logger;
|
67 | this.services = services;
|
68 | this.settings = settings || {};
|
69 | this.config = config;
|
70 | this.policies = [];
|
71 | this.conditions = [];
|
72 | this.gatewayRoutes = [];
|
73 | this.adminRoutes = [];
|
74 | this.cliExtensions = [];
|
75 | this.eventBus = eventBus;
|
76 | }
|
77 |
|
78 | registerPolicy (policy) {
|
79 | this.policies.push(policy);
|
80 | }
|
81 |
|
82 | registerCondition (condition) {
|
83 | this.conditions.push(condition);
|
84 | }
|
85 |
|
86 | registerGatewayRoute (gatewayRoutesDeclaration) {
|
87 | this.gatewayRoutes.push(gatewayRoutesDeclaration);
|
88 | }
|
89 |
|
90 | registerAdminRoute (adminRoutesDeclaration) {
|
91 | this.adminRoutes.push(adminRoutesDeclaration);
|
92 | }
|
93 |
|
94 | registerCLIExtension (cliExtension) {
|
95 | this.cliExtensions.push(cliExtension);
|
96 | }
|
97 | }
|
98 |
|
99 | function extract (loadedPlugins, propName) {
|
100 | return loadedPlugins.reduce((result, current) => {
|
101 | return result.concat(current[propName] || []);
|
102 | }, []);
|
103 | };
|