balderdashy/sails — pull request #2083 by Kikobeats (2014-08-08 17:20:25+00:00)
Title: # My proposal of plugins system

Hello everyone,

This weeks I'm working trying to design a plugin system for Sails. At the beginning part of the [Yomguithereal](https://github.com/balderdashy/sails/pull/1522)'s concepts but early I detected other things that plugin system needed to support. (In my opinion, of course)

For this reason, I created a parallel proyect called [Sailor](https://github.com/sailorjs) which is my playground scenario to try out the plugin system where I try to improve it.

My idea is not to create a parallel proyect. The idea is that sails implements a plugin system and uses sailor for this.

I want to explain how the plugin system works and which modifications in the current sails version are necessary for this.

Hipster mode on, get ready for reading and GO!

## The idea

- We have an application and we can divide it in two parts: a unique core (called base), and one or more modules.
- The modules have logic domain that the core loads and they are a little piece of domain code.
- The responsability of each module is the module.
- The modules can be relationated between them.
- The modules can be combinated for create a custom backend.
- The modules follow [FIRST](http://addyosmani.com/first/) principles.

## How it works

### Scaffolding support

Sails has a default configuration when you create a sails application. The sails application have a scaffolding that overwrite the start sails core settings.

The concept of the plugin system is the same, but with another depth level: sails has a configuration that lets you overwrite your base application, and you can overwrite or add more logical code with each module as well.

It could exist conflicts between base and module configuration. In this case, the base configuration has priority.

For this, I modified the core (`moduleloader` hook). I declared the modules in a new file called `config/plugins.js` that is an array of plugin namen that checks if it exists in `node_modules` as dependency. If it exist, I load it:

![](http://i.imgur.com/3Hge9tR.png)

### Multilanguage support

I created a module called [sailor-translate](https://github.com/sailorjs/sailor-translate) that is based in the angular-translate solution. Basically it creates a JSON for each language and it is very easy to create and use (much more than locales files)

Why? Because for me is very important to create a multilang API from the beginning. You should work hard in your API development in order to make your frontend much easier to use.

You can check that this [pseudo-file](https://github.com/sailorjs/sailor-module-user/blob/master/translation/User.tl) compiles to [this one ](https://github.com/sailorjs/sailor-module-user/blob/master/config/translation.coffee). I use sailor-translate for [register the translation files](https://github.com/sailorjs/sailor-module-user/blob/master/config/bootstrap.coffee#L26) and [make it easier to access](https://github.com/sailorjs/sailor-module-user/blob/master/api/services/protocols/local.coffee#L31).

Another thing about this is that I had the core for creating route binding for each language (`blueprint` hook). I thought that it could be improved because in my solution I read the local files to know the languages and later I bind the routes for each language. I try binding a route like `/:lang/` but it doesn't work. Also, [I created a little middleware for fix language in the route](https://github.com/sailorjs/sailor-module-user/blob/master/api/policies/i18n.coffee) because some routes don't have a `/lang/` param.

### Tasking support

Tasks for each module are necessary because the modules are independent. For this reason I modified the core to load the module's tasks in a different thread compared to the base tasks thread. (`grunt` hook).

The only problem in this aspect is that you want to install a module as a dependency, before that you lift the server you need to install the local module grunt dependencies or the tasks that don't work (because the tasks are local in the module). In my launcher it doesn't work but is easy to fix.

## Scaffolding

The Scaffold of each module is similar to the base, but more extended:

```
--sails-module-example/
----api/
------api/adapters/
------api/blueprints/
------api/controllers/
------api/hooks/
------api/models/
------api/policies/
------api/responses/
------api/services/
----views/
----config/
------config/translation.js
----translation/
-----Gruntfile.js
```

In this aspect, I think that to overwrite blueprint is SO USEFUL to avoid rewriting code. Another think like adapters or hooks are not important for module design.

## One more thing

Another thing that I did not commented and that is a problem for my workflow is the waterline errors schema. It is ugly, and of course, it is not multilanguage. I propose a more simple schema based in [express-validator](https://github.com/ctavan/express-validator):

![](http://i.imgur.com/6iuI8Vd.png)

It is simple and clean. And the most important: [easy to setup](https://github.com/sailorjs/sailor-module-user/blob/master/api/services/protocols/local.coffee#L32) (and easy to make multilanguage). This is ready for frontend. Doesn't exist a waterline errors validation interface for validate fields out of the ORM.

## What To Improve

* Fixed grunt dependencies modules installation before lift server.
* Better way to binding multilang routes.
* Native mutlilang route support in the core and not use a middleware for this.
* Improve waterline errors and make multilang

## Demo

You can experiment with this features NOW.

1) Install [sailor](https://github.com/sailorjs/sailorjs) globally. Basically is a little CLI interface to run the sails core modification.

2) Check [sailor-module-user](https://github.com/sailorjs/sailor-module-user) that is a version of [sails-generate-auth](https://github.com/kasperisager/sails-generate-auth) rewrite like a module. (I have a little problem with login methods. Check the tests, try to fix and PR pls :P)

3) [sailor-app-playground](https://github.com/sailorjs/sailor-app-playground) is a little app that use this module. Experiment with this!

## Your turn: Feedback!

Please, now is your moment. Feedback this plugin system. For make a better Sails core.

![](http://lewisburgneighborhoods.org/wp-content/uploads/uncle-sam-wants-you.jpg)