Skip to content

Commit

Permalink
Merge pull request serverless#1128 from serverless/add-plugin-managem…
Browse files Browse the repository at this point in the history
…ent-class

Add PluginManagement class
  • Loading branch information
flomotlik committed May 19, 2016
2 parents 07fbae5 + 478e4b9 commit 57948f0
Show file tree
Hide file tree
Showing 8 changed files with 585 additions and 1 deletion.
118 changes: 118 additions & 0 deletions lib/classes/PluginManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'use strict';

const Utils = require('./Utils');
const path = require('path');
const has = require('lodash').has;
const forEach = require('lodash').forEach;

class PluginManager {
constructor(serverless) {
this.serverless = serverless;
this.plugins = [];
this.commandsList = [];
this.commands = {};
}

loadAllPlugins(servicePlugins) {
this.loadCorePlugins();
this.loadServicePlugins(servicePlugins);
}

runCommand(commandsArray) {
const events = this.getEvents(commandsArray, this.commands);
// collect all relevant hooks
let hooks = [];
events.forEach((event) => {
const hooksForEvent = [];
this.plugins.forEach((pluginInstance) => {
forEach(pluginInstance.hooks, (hook, hookKey) => {
if (hookKey === event) {
hooksForEvent.push(hook);
}
});
});
hooks = hooks.concat(hooksForEvent);
});

if (hooks.length === 0) {
throw new Error('The command you entered was not found. Did you spell it correctly?');
}

// run all relevant hooks one after another
hooks.forEach((hook) => {
const returnValue = hook();

// check if a Promise is returned
if (returnValue && returnValue.then instanceof Function) {
returnValue.then((value) => {
return value;
});
}
});
}

addPlugin(Plugin) {
this.plugins.push(new Plugin());

this.loadCommands(Plugin);
}

loadCorePlugins() {
const utils = new Utils();
const pluginsDirectoryPath = path.join(__dirname, '../plugins');

const corePlugins = utils.readFileSync(path.join(pluginsDirectoryPath, 'Plugins.json')).plugins;

corePlugins.forEach((corePlugin) => {
const Plugin = require(path.join(pluginsDirectoryPath, corePlugin));

this.addPlugin(Plugin);
});
}

loadServicePlugins(servicePlugins) {
servicePlugins = (typeof servicePlugins !== 'undefined' ? servicePlugins : []);

servicePlugins.forEach((servicePlugins) => {
this.addPlugin(servicePlugins);
});
}

loadCommands(Plugin) {
this.commandsList.push((new Plugin()).commands);

// TODO: refactor ASAP as it slows down overall performance
// rebuild the commands
forEach(this.commandsList, (commands) => {
forEach(commands, (commandDetails, command) => {
this.commands[command] = commandDetails;
});
});
}

getEvents(commandsArray, availableCommands, prefix) {
prefix = (typeof prefix !== 'undefined' ? prefix : '');
const commandPart = commandsArray[0];

if (has(availableCommands, commandPart)) {
const commandDetails = availableCommands[commandPart];
if (commandsArray.length === 1) {
const events = [];
commandDetails.lifeCycleEvents.forEach((event) => {
events.push(`before:${prefix}${commandPart}:${event}`);
events.push(`${prefix}${commandPart}:${event}`);
events.push(`after:${prefix}${commandPart}:${event}`);
});
return events;
}
if (has(commandDetails, 'commands')) {
return this.getEvents(commandsArray.slice(1, commandsArray.length),
commandDetails.commands, `${commandPart}:`);
}
}

return [];
}
}

module.exports = PluginManager;
42 changes: 42 additions & 0 deletions lib/plugins/HelloWorld/HelloWorld.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

class HelloWorld {
constructor() {
this.commands = {
greet: {
usage: 'Run this command to get greeted.',
lifeCycleEvents: [
'printGoodMorning',
'printHello',
'printGoodEvening'
]
},
};

this.hooks = {
'before:greet:printHello': this.printGoodMorning,
'greet:printHello': this.printHello,
'after:greet:printHello': this.printGoodEvening,
};
}

printGoodMorning() {
const message = 'Good morning';
console.log(message);
return message;
}

printHello() {
const message = 'Hello';
console.log(message);
return message;
}

printGoodEvening() {
const message = 'Good evening';
console.log(message);
return message;
}
}

module.exports = HelloWorld;
8 changes: 8 additions & 0 deletions lib/plugins/HelloWorld/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Hello world
This plugin is a simple "Hello World" plugin which shows how the plugin system works.

## Setup
Run `npm install` to install all dependencies.

## Tests
Tests live inside the `tests` directory. Run `npm test` inside the root of this plugin to run the tests.
13 changes: 13 additions & 0 deletions lib/plugins/HelloWorld/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "serverless-plugins-hello-world",
"version": "0.0.1",
"description": "",
"license": "MIT",
"scripts": {
"test": "node_modules/.bin/mocha ./tests/HelloWorld.js"
},
"devDependencies": {
"chai": "^3.5.0",
"mocha": "^2.4.5"
}
}
51 changes: 51 additions & 0 deletions lib/plugins/HelloWorld/tests/HelloWorld.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

/**
* Test: HelloWorld Plugin
*/

const expect = require('chai').expect;
const HelloWorld = require('../HelloWorld');


describe('HelloWorld', () => {
let helloWorld;

beforeEach(() => {
helloWorld = new HelloWorld();
});

describe('#constructor()', () => {
it('should have commands', () => {
expect(helloWorld.commands).to.be.not.empty;
});

it('should have hooks', () => {
expect(helloWorld.hooks).to.be.not.empty;
});
});

describe('#printGoodMorning()', () => {
it('should print "Good morning"', () => {
const greeting = helloWorld.printGoodMorning();

expect(greeting).to.equal('Good morning');
});
});

describe('#printHello()', () => {
it('should print "Hello"', () => {
const greeting = helloWorld.printHello();

expect(greeting).to.equal('Hello');
});
});

describe('#printGoodEvening()', () => {
it('should print "Good evening"', () => {
const greeting = helloWorld.printGoodEvening();

expect(greeting).to.equal('Good evening');
});
});
});
5 changes: 5 additions & 0 deletions lib/plugins/Plugins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
"./HelloWorld/HelloWorld.js"
]
}
3 changes: 2 additions & 1 deletion tests/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ describe('All Tests', function() {
before(function() {});
after(function() {});

require('./tests/classes/Serverless');
// require('./tests/classes/Serverless');
require('./tests/classes/PluginManager');
// require('./tests/classes/Utils');
// require('./tests/classes/Plugin');
// require('./tests/classes/YamlParser');
Expand Down
Loading

0 comments on commit 57948f0

Please sign in to comment.