Use custom plugins loader

This commit is contained in:
Chi Vinh Le
2017-04-03 14:19:51 +07:00
parent e0540a5031
commit 73e2b899d8
5 changed files with 87 additions and 41 deletions
+12 -41
View File
@@ -1,57 +1,23 @@
import {client as clientPlugins} from 'pluginsConfig';
import React from 'react';
import mapValues from 'lodash/mapValues';
import values from 'lodash/values';
import flatten from 'lodash/flatten';
import merge from 'lodash/merge';
// Gather require context information of different parts of the plugins.
const contextMap = {
actions: require.context('plugins', true, /\.\/(.*)\/client\/actions.js$/),
reducers: require.context('plugins', true, /\.\/(.*)\/client\/reducer.js$/),
graph: require.context('plugins', true, /\.\/(.*)\/client\/(mutations|queries)\/index.js$/),
configs: require.context('plugins', true, /\.\/(.*)\/client\/config.json$/),
components: require.context('plugins', true, /\.\/(.*)\/client\/index.js$/),
};
const getPluginName = (key) => key.match(/\.\/(.*)\/client\/.*$/)[1];
const isActivePlugin = (plugin) => clientPlugins.indexOf(plugin) > -1;
/**
* Returns a callback that loads enabled modules of the context and
* returns an Array with {plugin, module} entries. Consecutive calls
* will return a memoized result.
*/
function createLoader(context) {
let loaded = null;
return () => {
if (!loaded) {
loaded = context
.keys()
.map(key => ({key, plugin: getPluginName(key)}))
.filter(info => isActivePlugin(info.plugin))
.map(info => ({plugin: info.plugin, module: context(info.key)}));
}
return loaded;
};
}
const loaders = mapValues(contextMap, createLoader);
import plugins from 'pluginsConfig';
/**
* Returns the config object of given plugin.
*/
function getConfig(plugin) {
return loaders.configs().filter(o => o.plugin === plugin)[0].module;
return plugins.configs.filter(o => o.plugin === plugin)[0].module();
}
/**
* Returns React Elements for given slot.
*/
export function getSlotElements(slot, props = {}) {
return loaders.components()
return plugins.components
.map((o, i) => ({
component: o.module,
component: o.module(),
props: {...getConfig(o.plugin), ...props, key: i},
}))
.filter(o => o.props.slot === slot)
@@ -59,11 +25,16 @@ export function getSlotElements(slot, props = {}) {
}
// actions is a map of redux actions .
export const actions = merge(...loaders.actions().map(o => ({...o.module})));
export const actions = merge(...plugins.actions.map(o => ({...o.module()})));
// reducers is a map of redux reducers.
export const reducers = merge(...loaders.reducers().map(o => ({...o.module})));
export const reducers = merge(...plugins.reducers.map(o => ({...o.module()})));
// queriesAndMutators is an array of graphQL queries and mutators.
export const queriesAndMutators = flatten(loaders.graph().map(o => values(o.module)));
export const queriesAndMutators = flatten(
merge(
plugins.queries.map(o => values(o.module())),
plugins.mutators.map(o => values(o.module())),
)
);
@@ -0,0 +1,60 @@
const {stripIndent} = require('common-tags');
const fs = require('fs');
const path = require('path');
function moduleExists(loc) {
const fileExists = fs.existsSync(path.resolve(__dirname, loc));
if (fileExists) {
return true;
}
const hasExtension = /\..*$/.test(loc);
if (hasExtension) {
return false;
}
// Find file with appended `.js` extension.
return fs.existsSync(path.resolve(__dirname, `${loc}.js`));
}
function addIfExists(list, plugin, resource) {
if (moduleExists(`../../../plugins/${plugin}/client/${resource}`)) {
list.push(`{module: () => require('plugins/${plugin}/client/${resource}'), plugin: '${plugin}'}`);
}
}
module.exports = function(source) {
this.cacheable();
const plugins = this.exec(source, this.resourcePath).client;
const exports = {
configs: [],
actions: [],
reducers: [],
components: [],
queries: [],
mutators: [],
};
plugins.forEach(plugin => {
addIfExists(exports.components, plugin, 'index.js');
addIfExists(exports.configs, plugin, 'config.json');
addIfExists(exports.actions, plugin, 'actions');
addIfExists(exports.reducers, plugin, 'reducer');
addIfExists(exports.mutators, plugin, 'mutations');
addIfExists(exports.queries, plugin, 'queries');
});
let result = '';
Object.keys(exports).forEach(key => {
if (result) { result += '\n\n'; }
result += stripIndent`
module.exports.${key} = [
${exports[key].join(',')}
];
`;
});
return result;
};
+1
View File
@@ -114,6 +114,7 @@
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"chai-http": "^3.0.0",
"common-tags": "^1.4.0",
"copy-webpack-plugin": "^4.0.0",
"css-loader": "^0.27.3",
"dialog-polyfill": "^0.4.4",
+8
View File
@@ -61,6 +61,11 @@ module.exports = {
cacheDirectory: true
}
},
{
loader: 'plugins-loader',
test: /\.json$/,
include: path.join(__dirname, 'plugins.json')
},
{
loader: 'json-loader',
test: /\.json$/,
@@ -119,6 +124,9 @@ module.exports = {
}
})
],
resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, 'client/coral-framework/loaders')],
},
resolve: {
alias: {
plugins: path.resolve(__dirname, 'plugins/'),
+6
View File
@@ -1758,6 +1758,12 @@ commander@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781"
common-tags@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0"
dependencies:
babel-runtime "^6.18.0"
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"