mean-core
MEAN.JS - Core services for the MEAN.JS boilerplate. Full-Stack JavaScript Using MongoDB, Express, AngularJS, and Node.js From Creators of MEAN.IO - http://meanjs.org
This is a proposal to:
- Separate boilerplate example code from core functionality
- Standardize a way for contributed modules.
- Use
npm
package manager to update core code w/o requiring a git merge
Code
Status: psuedocode
To play with this code:
- fork boilerplate: git@github.com:MichaelJCole/mean.git
- checkout
meanjs-core
branch npm install && grunt build
grunt
It's stored in 3 repos.
- boilerplate:
meanjs-core
branch, forked repo: git@github.com:MichaelJCole/mean.git mean-core
:master
branch, this repo you're reading: git@github.com:MichaelJCole/mean-core.gitmean-module
:master
branch, this repo: git@github.com:MichaelJCole/mean-module.git
This will download and install mean-core
and mean-module
from github.
mean-core
:
How to use mean-core
functionality is in a separate npm package from the Yoeman boilerplate.
In package.json
The boilerplate includes mean-core
:
"dependencies": {
// ...
"mean-core": "git://github.com/MichaelJCole/mean-core",
// ...
}
How to use in the boilerplate
mean-core
's functionality is exposed in several places:
app.config
app.core.[module].[export]
req.config
req.core.[module].[export]
The boilerplate uses these core functions, allowing the end developer to add, delete, re-mix, and mash them up as needed:
// Core and Module functions are exposed on app.core and req.core objects.
// e.g. In users.server.controllers.js, use req.core.[modulename].[export]
exports.signup = function(req, res) {
// ...
//
// Then save the user
user.save(function(err) {
if (err) {
// ...
} else {
// ...
// Send confirmation email
req.core.users.sendConfirmEmail(user, req.config);
}
});
// e.g. In users.server.routes.js, use app.core.[modulename].[export]
module.exports = function(app) {
// User Routes
// ...
app.route('/auth/confirm/:confirmationCode').get(app.core.users.confirmEmailLink);
// ...
}
An open question is how to organize the module exports. I'm aware of three modules: users, core, and articles.
Using a contributed MEAN.JS module 'myModule'
Add to package.json:
"dependencies": {
// ...
"mean-core": "git://github.com/MichaelJCole/mean-core",
"mean-module": "git://github.com/MichaelJCole/mean-module"
// ...
}
Configure your app
In the boilerplate server.js:
// Note: developers add modules here:
var meanModules = [
require('mean-module')(db, config) // pass db and config if needed.
];
// ...
// Init the express application
var app = require('./config/express')(db, config, meanModules);
server.js is intended for the end developer to customize.
Boilerplate code uses mean contributed modules
config/express.js wires these modules into:
app.mean.[module].[export]
req.mean.[module].[export]
Creating your own MEAN.JS module
To extend mean-core with a module of your own:
- create a github repo for your myModule.
- expose your functionality via exports.
exports.name = 'moduleName';
exports.myModule.controller.myFunc(req, res, next) {
console.log("hello world");
next();
}
To use:
// e.g. In users.server.routes.js, use app.core.[modulename].[export]
module.exports = function(app) {
// User Routes
// ...
app.route('/auth/confirm/:confirmationCode').get(app.mean.betterUsers.betterConfirmLink);
// ...
}
Summary:
This allows for:
- package.json and server.js are files for dev to add contributed modules.
- config/express.js is still boilerplate, but most likely won't be customized (easier updates)
- namespaces aren't poluted:
// Config
app.config
req.config
// Core functionality
app.core.[module].[export]
req.core.[module].[export]
// Contributed modules
app.mean.[module].[export]
req.mean.[module].[export]
Note: it may be worth separating config for core and contributed, but that's another topic.
How's it work:
- Add dependencies to package.json
- Changes to server.js:
var meanModules = [
require('mean-module')(config) // edit config files if needed.
];
// ...
var app = require('./config/express')(db, config, meanModules);
The file config/express.js :
// ...
// Get core exports
var core = require('mean-core')(db, config)
// Apply exports to app
app.set('config', config);
app.set('core', core);
app.set('mean', meanModules);
// Middleware to adjust req
app.use(function(req, res, next) {
res.locals.url = req.protocol + ':// ' + req.headers.host + req.url;
// Add application config to all incoming requests
req.config = config;
req.core = coreExports;
req.mean = meanExports;
next();
});
// ...
How to develop in mean-core:
- Clone your own repo
- Use npm-link to link to your local mean-core https://www.npmjs.org/doc/cli/npm-link.html http://justjs.com/posts/npm-link-developing-your-own-npm-modules-without-tears
cd mean-core
sudo npm link
cd ../mean-module
sudo npm link
cd ../project
npm link meanjs-core
npm link meanjs-module
Now, when you require('mean-core'), Node.js will find a symlink to your local copies.
Core versioning and compatibility promises:
TBD.
Etc.
Express middleware
Express modules like mean-seo could also be added in express.js, if they were defined like this:
exports.middleware = function()
name collisions
Module names should not collide, unless the modules are drop-in replacements for one another.
Data Models
Data models should be strictly boilerplate. This prevents the need for inheritance, sub-classing, or baloney like that.
Core and Contrib modules can store/read data in the model.decor attribute(?) as a sub-document.
core.[moduleName].property
mean.[moduleName].property
More complex data requirements will require customizing the models by hand.
Not addressed
Angular modules. Haven't figured this out yet. Ideas? PHP's Symfony project handled client modules via symlinks.