Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for plugin architecture #140

Open
soapdog opened this issue Apr 16, 2015 · 18 comments
Open

Proposal for plugin architecture #140

soapdog opened this issue Apr 16, 2015 · 18 comments

Comments

@soapdog
Copy link
Contributor

soapdog commented Apr 16, 2015

Hi Friends,

I have an idea on how to implement plugins for Harmonic that is very lightweight and requires minimal coding. If this idea is accepted then we'd be able to extend harmonic without touch harmonic itself.

All harmonic plugins would be normal node modules that would be installed with npm. These modules would follow a naming convention such as harmonic-plugin-*. The configuration for each plugin would reside in harmonic.json like:

{
    "name": "AndreGarzia.com",
    "title": "All We Do Is Code",
    "domain": "http://awesome.com",
    "bio": "I work for the web",
    "plugins": {
      "deploy-gihub": {
        "repo": "soapdog/site",
        "branch": "gh-pages"
      }
    }
}

In the case above there would be a node module named harmonic-plugin-deploy-github installed on the site. Harmonic would read harmonic.json, find the plugin key and load all necessary modules on start. We'd use a publisher/subscriber like pattern where upon loading each plugin could subscribe to a given message. As harmonic workflow cycled it would dispatch the messages like preBuild, prePageGeneration, postPageGeneration, prePostGeneration, postPostGeneration, preCopyResources, postCopyResources, postBuild and so on.

Modules could be built with ES6 or any other technology needed as long as they register their interest in some messages upon loading.

What do you folks think?

@UltCombo
Copy link
Member

Awesome. 👍
We have to consider some details, such as whether the loading order of plugins is important (in that case, an array of plugins would make more sense, or maybe a "priority" config option for each plugin).

@soapdog
Copy link
Contributor Author

soapdog commented Apr 16, 2015

I think that array instead of object is the simplest thing. If we use a priority index then we'll soon write a process scheduler and I am really poor at such tasks...

@UltCombo
Copy link
Member

Array sounds good to me. =]

@soapdog
Copy link
Contributor Author

soapdog commented Apr 17, 2015

What about:

"plugins": {
      "order": ["markdown", "deploy-github", "deploy-s3"],
      "config": {
        "deploy-gihub": {
          "repo": "soapdog/site",
          "branch": "gh-pages"
        },
        "markdown": {},
        "deploy-s3": {
          "bucket": "blablabla"
        }
      }
    }

In this case ``plugins` has two keys – config and order – which makes it easier to specify and fiddle with the order without the need of moving large quantities of object data chunks.

@UltCombo
Copy link
Member

Seems good. What should we do if the config and order mismatch (e.g. order has a plugin which is not in the config, or the other way around)?

Let's assume some use cases:

  • Some plugins may be able to run with default configs (without the user specifying a config object).
  • The user may want to temporarily disable a plugin -- it would be a hassle if the user had to delete the entire config object for that.

So, I suggest renaming order and to something else (e.g. use, run, activate) and execute only the plugins that are listed in the array. This way, to disable a plugin you just have to remove/comment out its name from the array, and this also allows plugins to run with their default config (without requiring the user to pass a config object). So something like:

"plugins": {
  // temporary name
  "use": ["markdown", "deploy-github"/*, "deploy-s3"*/],
  "config": {
    "deploy-gihub": {
      "repo": "soapdog/site",
      "branch": "gh-pages"
    },
    "deploy-s3": {
      "bucket": "blablabla"
    }
  }
}

Next, we should look into error handling. I guess we can consider how to handle errors in plugins after we have an initial proof of concept of the plugins architecture.

@jaydson
Copy link
Contributor

jaydson commented Apr 17, 2015

Just wondering, i don't think let the config order in this layer is a good approach.
Perhaps we need programmatic way to deal with.
I mean, something like a Gruntfile.
Harmonicfile?

So we can do something like this (runtime plugin creation):

module.exports = (harmonic) => {
   harmonic.use(() => console.log('my tiny plugin'))
           .use('deploy-github', () => {
              // implementation
           });
}

Already defined plugins:

module.exports = (harmonic) => {
   harmonic.use(deploys3);
   harmonic.use(rss);
   ...
}

Too complicated?

@soapdog
Copy link
Contributor Author

soapdog commented Apr 17, 2015

@jaydson that would tie Harmonic usage to developers who know JS. We might want to opt for a simple config file and then it would be easier for a non-programmer to use.

@UltCombo
Copy link
Member

I agree with @soapdog.
@jaydson I believe your suggestion would be nice as a skeleton to develop the plugins themselves and to integrate them with Harmonic (that is, can be used for both plugin development and Harmonic API consumption). We just need to somehow pass the config into the plugin when they're loaded via the plugins option.

@soapdog
Copy link
Contributor Author

soapdog commented Apr 18, 2015

Also this is an issue of declarative vs programmatic ways to approach plugin configuration. Declarative approach is easier to test and check for errors. The programmatic way is easier to shoot yourself in the foot.

My recommendation is to build a declarative way where plugins are configured using harmonic.json and once this is done and working then create a new programmatic way of controlling Harmonic that could be offered to power users trying to affect how the program works. This second offering could come as an API that a given user would import into his JS/ES6 code and thus drive Harmonic on his own.

@UltCombo
Copy link
Member

My recommendation is to build a declarative way where plugins are configured using harmonic.json and once this is done and working then create a new programmatic way of controlling Harmonic that could be offered to power users trying to affect how the program works. This second offering could come as an API that a given user would import into his JS/ES6 code and thus drive Harmonic on his own.

Sounds good to me.

@jaydson
Copy link
Contributor

jaydson commented Apr 18, 2015

Ok, let's do it in a declarative way then.

@jaydson
Copy link
Contributor

jaydson commented May 8, 2015

@soapdog any progress on the plugin stuff?
If so, i want to help build it.

@soapdog
Copy link
Contributor Author

soapdog commented May 13, 2015

I was waiting for us to agree. I will build a tiny POC and share as a branch here.

@jaydson
Copy link
Contributor

jaydson commented May 13, 2015

👍

@viniciusdacal
Copy link
Contributor

some news about plugin support?

@jaydson
Copy link
Contributor

jaydson commented Jul 7, 2015

Nope. Harmonic still lacks on plugin support 😢

@UltCombo
Copy link
Member

UltCombo commented Jul 7, 2015

@soapdog By the way, did you manage to start a PoC?

@soapdog
Copy link
Contributor Author

soapdog commented Jul 10, 2015

I did but I think I could use some help. Will post it to a branch and get back here.

@UltCombo UltCombo mentioned this issue Jan 9, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants