Giter Site home page Giter Site logo

pluginbot's Introduction

Pluginbot

Lightweight, unopinionated plugin framework - create extremely extensible and scalable apps using a service-based architecture and dependency injection.

Gitter

Overview

At a high level - pluginbot is an app framework that consists of plugins which can provide/consume services. To define a plugin you define a function which provide services and a function that can consume services, consumption happens in the form of a redux-saga so your plugin can wait around for your desired service to be provided which elmiminates dependency chains entirely since your plugin will pause execution until the service it needs becomes available.

This architecture allows for a highly extensible application because a plugin that adds functionality would just provide services other plugins consume (or consume services other plugins provide) - for example a plugin could provide new routes to be consumed by a router plugin or a plugin could provide UI components such as navigation-menus which would be rendered by a navigation-menu consumer.

Configuration

In order for plugins to run, they have to be declared in a configuration which will contain at a minimum the path of the plugin. Here you would define environment specific data.

Configuration can either be json or a js file that exports an object/Promise that resolves to an object

The plugins array represents the enabled plugins in a pluginbot instance.

// ./config.js

//path should be relative to the config file location, or absolute, can refer to NPM modules as well
module.exports = {
        plugins: [
            {"path": "express-app", "apiBaseUrl" : "/api", "port" : 3001},
            {"path": "./route-provider", "port": 3001},
            ],
};

Plugin Interface

A plugin consists of a module which exports a generator function, each plugin takes the form of a redux-saga meaning they can wait for specific events to happens or services to be provided by other plugins before running their own code.

// ./express-app/express-app.js

//take used for consumption
let express = require("express");
const consume = require("pluginbot/effects/consume");
module.exports = {
    /**
    * This function is a saga which can consume or provide services and represents a plugin's lifecycle
    * 
    * @param config {Object.<string, Object.<string, *>>} 
    * - Keys the config option name to the config's value defined in the Pluginbot configuration
    *  
    * @param provide {function(Object)} -  provide services, key servicename value service, returns effect
    *
    * @param services {Object.<string, Channel>} -  
    * keyed by service name, value is a channel that can be consumed for a service 
    */    
    run : function*(config, provide, services){
        const app = express();
        const router = express.Router();
        
        app.use(config.apiBaseUrl, router);
        app.listen(config.port);
        
        //provide expressApp and baseRouter which can now be consumed by other plugins
        yield provide({
            expressApp: app,
            baseRouter: router
        });
        
        //loop pauses when it hits a yield
        while(true){
            //wait around for new expressRouter services to be provided
            let newRoute = yield consume(services.expressRouter);
            
            //add new route to the api router
            router.use(newRoute);
        }
    }  
}

Now if I wanted to create a plugin which adds a new route to my app all I need to do is provide an expressRoute service

// ./hello-world/hello-world.js
module.exports = {
    run : function*(config, provide, services){
        const router = require("express").Router();
        
        //would be called by GET /api/hello-world
        router.get("/hello-world", (req, res) => {
            res.json({hello : "world"});
        });
                
        //provide expressRouter to be used by the app's router
        yield provide({
            expressRouter: router
        });
        
    }
}

package.json

In order for a pluginbot plugin to be considered valid it requires a pluginbot section to be defined in the package.json. For a basic definition you just need to define where the entry point to your plugin is and the services the plugin consumes (if any)

// ./express-app/package.json
{
    "name": "express-app",
    "version": "0.0.1",
    "private": true,
    "pluginbot": {
        "main" : "express-app.js", 
        "consumes": ["expressRoute"]
    }
}

Starting Pluginbot

To start pluginbot on the server, just call createPluginbot and initialize it

// ./app.js
const CONFIG_PATH = "./config.js"
let path = require("path");
let Pluginbot = require("pluginbot");
//pass full path to createPluginbot
Pluginbot.createPluginbot(path.resolve(__dirname, CONFIG_PATH))
.then(pluginbot => pluginbot.initialize())
.catch(e => {
    console.error(e);
});

Advanced (in progress...)

Hooks

On Plugin Install

On Plugin Uninstall

On Plugin Enable

On Plugin Disable

Consume services with React components

see pluginbot-react

###Credit

pluginbot's People

Contributors

bsears90 avatar lucduong avatar service-bot avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.