c9 / architect

A simple yet powerful plugin system for large-scale node applications
MIT License
982 stars 129 forks source link

Allow architect plugins to be unloaded and loaded at runtime #23

Closed janjongboom closed 11 years ago

janjongboom commented 11 years ago

At the moment an architect application is 'set'. It gets created and then it cannot be modified. However, there might be cases where you'd want to load extra plugins, or unload others while running an application without destroying it. By exposing registerPlugin on the app prototype this gets enabled. The code to use this:

// create normal architect app
var architect = require("architect-git");
var config = architect.loadConfig(__dirname + "/config.js");
architect.createApp(config, function (err, app) {
        // some extra plugins to be loaded
        var plugins = [{packagePath: './some-extra-plugin'}];
        architect.resolveConfig(plugins, __dirname, function(err, resolved) {
            if (err) {
                return console.error('Resolve config failed', resolved);
            }
            app.loadPlugins(resolved, function() {
                return console.log('Registered plugins', app.config);
            });
        });
});

Or to unload an existing plugin:

var plugin = app.config.filter(function(c) {
     return c.packagePath === 'something' && c.bla === 'zus';
})[0];
plugin.destroy()

The plugin can implement onDestroy() to unregister express handlers or whatever.

mattpardee commented 11 years ago

Insane that I came to this repo today to see if this had been added in, and by chance I get this. Mr. Jongboom, my hat is tipped.

janjongboom commented 11 years ago

mattpardee commented 11 years ago

:shipit:

SamyPesse commented 11 years ago

Great, exactly what I needed :) Thanks a lot, is it working yet?

janjongboom commented 11 years ago

Yeah, I use it in a project and haven't found any issues with it.

SamyPesse commented 11 years ago

Thank you, but I build and started using an other plugins system compatible with architect with a cleaner code base: https://github.com/FriendCode/engineer

sergi commented 11 years ago

Any chance this will be reviewed soon? This would be quite a cool addition.

...or are there philosophical reasons not to accept it?

janjongboom commented 11 years ago

/cc @fjakobs

creationix commented 11 years ago

I have no philosophical reasons against it fwiw.

mattpardee commented 11 years ago

:shipit:!

bmatusiak commented 11 years ago

add "onLoad" construction too :grin:

fjakobs commented 11 years ago

Looks good to me. I have no political reasons to not accept it either. Usually I'd ask for unit tests but since the rest of architect doesn't have them, I'd regard that optional.

Unless you are so kind to add mocha based unit tests and make npm test work :)

janjongboom commented 11 years ago

Just merge it :p

leeroybrun commented 11 years ago

Great feature ! Is there a way to get the "app" object inside plugins ? I would like to load some submodules from one main module.

I'm searching a way to do this :

var architect = require('architect');

function setup(options, imports, register) {
    var config = imports.config;

    // How to get the app object from a plugin ?
    var app = imports.app; // ??

    architect.resolveConfig(config.plugins, __dirname, function(err, resolved) {
        if (err) {
            return console.error('Resolve config failed', resolved);
        }

        app.loadPlugins(resolved, function() {
            console.log('Registered plugins', app.config);

            register(null);
        });
    });
}

module.exports = setup;
janjongboom commented 11 years ago

I do it like this. Add an init() function to the plugin that you want to pass the app object to. Then after loading plugins:

  app.getService('parser-manager').init(app);

Tah dah.

leeroybrun commented 11 years ago

Perfect, I will give it a try. Thanks !