Skip to content

Commit

Permalink
feat: remove plugnplay fetch CMS meta (#30)
Browse files Browse the repository at this point in the history
There is no pluginization for fetching CMS meta. It was very confusing.

BREAKING CHANGE: all plugins are now ignored.
  • Loading branch information
e0ipso authored Jun 12, 2019
1 parent 6d96071 commit ecfd3dd
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 552 deletions.
406 changes: 60 additions & 346 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
"keyv-null": "^1.0.0",
"lodash": "^4.17.10",
"pino": "^4.16.1",
"plugnplay": "^3.3.0",
"pm2": "^3.5.1",
"subrequests": "^2.16.1",
"subrequests-express": "^3.2.0",
Expand Down
16 changes: 7 additions & 9 deletions src/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ const startApp = require('./helpers/app');

module.exports = async port => {
// Initialize JSON RPC.
const fetched = await fetchCmsMeta();
const [map, jsonRpcResponse] = await fetchCmsMeta();
const mapped = {};
fetched.forEach(([map, jsonRpcResponse]) => {
Object.keys(map).forEach(variableName => {
const variableValue = _.get(jsonRpcResponse, [
'result',
...map[variableName].split('.'),
]);
mapped[variableName] = variableValue;
});
Object.keys(map).forEach(variableName => {
const variableValue = _.get(jsonRpcResponse, [
'result',
...map[variableName].split('.'),
]);
mapped[variableName] = variableValue;
});
// Proxy for the JSON API server in Contenta CMS.
const app = await startApp(mapped);
Expand Down
14 changes: 6 additions & 8 deletions src/bootstrap.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ const bootstrap = require('./bootstrap');

jest.mock('./helpers/fetchCmsMeta', () => () =>
Promise.resolve([
[
{ jsonApiPrefix: 'basePath' },
{
result: {
basePath: '/myPrefix',
paths: ['/foo', '/foo/{bar}', '/foo/{bar}/oof/{baz}'],
},
{ jsonApiPrefix: 'basePath' },
{
result: {
basePath: '/myPrefix',
paths: ['/foo', '/foo/{bar}', '/foo/{bar}/oof/{baz}'],
},
],
},
])
);

Expand Down
39 changes: 0 additions & 39 deletions src/helpers/cmsMeta/plugins/CmsMetaLoader.js

This file was deleted.

32 changes: 0 additions & 32 deletions src/helpers/cmsMeta/plugins/CmsMetaLoader.test.js

This file was deleted.

This file was deleted.

12 changes: 0 additions & 12 deletions src/helpers/cmsMeta/plugins/jsonapi/plugnplay.yml

This file was deleted.

17 changes: 0 additions & 17 deletions src/helpers/cmsMeta/plugins/pluginType/CmsMetaPluginTypeLoader.js

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions src/helpers/cmsMeta/plugins/pluginType/plugnplay.yml

This file was deleted.

88 changes: 34 additions & 54 deletions src/helpers/fetchCmsMeta.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,55 @@
// @flow

import type { JsonRpcResponseItem } from '../../flow/types/jsonrpc';
import type { PluginInstance } from 'plugnplay';
import type { ObjectLiteral } from '../../flow/types/common';

const config = require('config');
const { PluginManager } = require('plugnplay');
const _ = require('lodash');
const logger = require('pino')();

const cmsHost = config.get('cms.host');

const jsonrpc = require('./jsonrpc')(cmsHost);
const openApiPathToRegExp = require('./openApiPathToRegExp');

/**
* Connects to the CMS to get some important bootstrap information.
*
* @return {Promise<JsonRpcResponse>}
* The data from the CMS used to initialize the node proxy.
*/
module.exports = (): Promise<Array<[ObjectLiteral, JsonRpcResponseItem]>> => {
let requestor;
let pluginManager;
// Initialize the JSON RPC requestor.
return jsonrpc
module.exports = (): Promise<[ObjectLiteral, JsonRpcResponseItem]> =>
jsonrpc
.init()
.then(reqr => {
requestor = reqr;
// Instantiate a plugin manager to discover all possible
// cms-meta-plugin-type plugins.
pluginManager = new PluginManager({
discovery: {
rootPath:
'./{node_modules/@contentacms/**/lib,lib}/helpers/cmsMeta/plugins',
.then(requestor =>
requestor.execute([
{
jsonrpc: '2.0',
method: 'jsonapi.metadata',
id: 'req-jsonapi.metadata',
},
])
)
.then(res => {
const response = [].concat(res).pop();
// Contenta CMS will send the paths as the Open API specification, we need
// them to match incoming requests so we transform them into regular
// expressions.
const paths = openApiPathToRegExp(
Object.keys(_.get(response, 'result.openApi.paths', {}))
);
return {
jsonrpc: '2.0',
id: 'req-jsonapi.metadata',
result: {
basePath: _.get(response, 'result.openApi.basePath', ''),
paths: JSON.stringify(paths),
},
});
return pluginManager.instantiate('cms-meta-plugin');
// Instantiate all the CMS Meta Fetchers and fetch the data.
};
})
.catch(error => {
// If a particular fetcher returns an error, log it then swallow.
logger.error(error);
return error;
})
.then(pluginType =>
// Execute fetch() for all the plugins of type cms-meta-plugin.
Promise.all(
pluginType.exports.plugins.map(descriptor =>
pluginManager
.instantiate(descriptor.id, { requestor })
.then((plugin: PluginInstance) =>
Promise.all([
plugin.descriptor.resultMap,
plugin.exports
.fetch()
.then(res => {
// Contenta CMS will send the paths as the Open API
// specification, we need them to match incoming requests
// so we transform them into regular expressions.
const paths = openApiPathToRegExp(
Object.keys(res.result.openApi.paths)
);
return {
result: {
basePath: res.result.openApi.basePath,
paths: JSON.stringify(paths),
},
};
})
.catch(error => {
// If a particular fetcher returns an error, log it then swallow.
logger.error(error);
return error;
}),
])
)
)
)
);
};
.then(res => [{ jsonApiPrefix: 'basePath', jsonApiPaths: 'paths' }, res]);
12 changes: 7 additions & 5 deletions src/helpers/fetchCmsMeta.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ describe('The metadata bootstrap process', () => {
})
);
return fetchCmsMeta().then(() => {
expect(jsonrpc.execute).toHaveBeenCalledWith({
id: 'req-jsonapi.metadata',
jsonrpc: '2.0',
method: 'jsonapi.metadata',
});
expect(jsonrpc.execute).toHaveBeenCalledWith([
{
id: 'req-jsonapi.metadata',
jsonrpc: '2.0',
method: 'jsonapi.metadata',
},
]);
});
});
test('It swallows the errors', () => {
Expand Down
8 changes: 5 additions & 3 deletions src/routes/proxyHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ module.exports = (req: Request, res: Response, next: NextFunction): void => {
// non-existing resources.
filter(pRq, uRq) {
// Extract the path part, without query string, of the current request.
const parsed = url.parse(uRq.url);
const parsed = url.parse(uRq.req.url);
const pathIsWhitelisted =
// Only filter paths if there are any whitelisted paths.
uRq.jsonApiPaths.length &&
uRq.req.jsonApiPaths.length &&
// Return false if it doesn't apply any regular expression path.
!!uRq.jsonApiPaths.find(p => new RegExp(p).test(parsed.pathname || ''));
!!uRq.req.jsonApiPaths.find(p =>
new RegExp(p).test(parsed.pathname || '')
);
// Make sure that the JSON API entry point is also whitelisted.
return parsed.pathname === '/' || pathIsWhitelisted;
},
Expand Down
16 changes: 10 additions & 6 deletions src/routes/proxyHandler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,11 @@ describe('The fallback to CMS', () => {
proxyHandler(req, res);
const { filter } = proxy.mock.calls[0][1];
const actual = filter(null, {
...req,
url: 'https://example.org/lorem',
jsonApiPaths: ['/lorem/?'],
req: {
...req,
url: 'https://example.org/lorem',
jsonApiPaths: ['/lorem/?'],
},
});
expect(actual).toBe(true);
});
Expand All @@ -120,9 +122,11 @@ describe('The fallback to CMS', () => {
proxyHandler(req, res);
const { filter } = proxy.mock.calls[0][1];
const actual = filter(null, {
...req,
url: '',
jsonApiPaths: ['/lorem/?'],
req: {
...req,
url: '',
jsonApiPaths: ['/lorem/?'],
},
});
expect(actual).toBe(false);
});
Expand Down

0 comments on commit ecfd3dd

Please sign in to comment.