Generator for scaffolding out Powder.js applications
Powder.js is a combination of existing frameworks, tools and libraries that allows fast and simple web app creation.
Server-side of powder.js is powered by Express.js with data and sessions stored in MongoDB accessed using Mongoose.js.
Express utilizes CSRF tokens via csurf as well as Helmet middleware with basic config for increased security.
Server-side templating is done via Linkedin version of Dust.js.
If needed, basic local authorisation can be generated using passport.js.
Client-side is built using Angular.js with ngRoute, Twitter Bootstrap, AngularStrap and jQuery.
All the client-side app code is managed and compiled by Browserify and minified using Uglify.js (when not in debug mode). All this and more is performed by browserify-middleware on the fly.
Bower is used for the client-side dependencies which are loaded directly from core template. All dependencies available on CDNs might be replaced to those before deploying.
Gulp.js is used as a build-tool.
In addition to build and testing tasks, gulp as well handles all the things related to encapsulating bower dependencies into project without any additional actions from the developer. It as well created version of layout with libraries located on CDN. If you'd like to include your own libraries, please add CDN locations to gulp/tasks/cdn.js
.
Testing is done using jshint for linting and mocha.js with should.js for automated testing.
Default test suite includes two different test files - one for API using simple JSON, and one for browser using zombie.js.
In addition, powder.js utilizes asyncawait and promises (using bluebird) to simplify asynchronous code.
Bunyan is used as a logger. Logs can be found in ./logs/
folder.
Powder.js can (optionally) automatically init git repository and commit all generated files for simpler project management.
For powder.js to function properly, you'll need to have following things installed:
Alternatively you can use vagrant environment provided by powder:vagrant
generator, it includes all the required packages.
$ npm install -g yo generator-powder
$ yo powder
$ yo powder
Creates a new powder.js application.
$ yo powder:controller myName
Generates a new server-side (optional) and client-side controller named myNameController and it's dependencies and injects it into main app.
$ yo powder:directive myName
Generates a new angular directive named myNameDirective and injects it into main app.
$ yo powder:filter myName
Generates a new angular filter named myNameFilter and injects it into main app.
$ yo powder:service myName
Generates a new angular service named myNameService and injects it into main app.
$ yo powder:model myName
Generates a new mongoose model named myName and injects it into main app.
$ yo powder:vagrant
Generates a vagrant environment for the project with all the requirements included.
Once installed, you can create a basic application by following the prompts.
$ mkdir HelloWorld
$ cd HelloWorld
$ yo powder
_-----_
| |
|--(o)--| .--------------------------.
`---------´ | Welcome to Yeoman, |
( _´U`_ ) | ladies and gentlemen! |
/___A___\ '__________________________'
| ~ |
__'.___.'__
´ ` |° ´ Y `
You're using the fantastic Powder generator.
[?] What do you want to call your app?
...
To run your application, just type gulp
(you need to have gulp installed globally with npm -g gulp
, if not use gulp from node_modules with ./node_modules/.bin/gulp
).
$ gulp
...
listening on port 8080
- /app/ - Application and middleware configuration
- /controllers/ - Application routes
- /models/ - Database config and models definitions
- /gulp/ - Gulp configuration files
- /lib/ - Express.js route loader
- /logger/ - Bunyan-based logger
- /logs/ - Application log files
- /modules/ - Server-side user modules
- /public/css/ - CSS files
- /public/img/ - Client-side image files
- /client/app.js - Client-side javascript bootstrapper
- /client/controllers.js - Angular controllers loader
- /client/directives.js - Angular directives loader
- /client/filters.js - Angular filters loader
- /client/routes.js - Angular routes
- /client/services.js - Angular services loader
- /client/controllers/ - Angular controllers
- /client/data/ - Supplementary data
- /client/directives/ - Custom angular directives
- /client/filters/ - Custom angular filters
- /client/modules/ - Client-side user modules
- /client/services/ - Custom angular services
- /public/templates/ - Browser-side angular templates
- /tests/ - Unit and functional test cases
- /views/ - Server-side dust.js templates
- /app.js - Application entry point
- /config.js - Application config
- /gulpfile.js - Gulp bootstrapper
Route logic is moved into the /controllers/
directory and its subdirectories.
For the sake of simplicity /controllers/
directory has two default subdirectories: /controllers/api/
and /controllers/main/
.
For example, a route for your home page, would use a /controllers/main/index.js
file such as:
module.exports = function(app) {
// index
app.get('/', function(req, res) {
return res.render('index');
});
};
This file would define the routes and the logic for the home page. The advantage of keeping routes and logic segregated in individual files starts to show as the application grows. If something fails, it's very easy to pinpoint where things went wrong.
When a new controller is created, the generator will also create both client and server-side templates, routes and all needed client javascript files for you.
It is also possible to generate client-side only controllers. To do so, simply say "No" to question about server-side templates during controller generation.
Data models are separated from the controller logic resulting in cleaner, more organized code. Data models live in the /models/
folder.
Dust JavaScript templates are the default server-side templating language. [Angular templates] are used in client-side.
Server-side templates are loaded from the /views/
directory.
Client-side templates are loaded from the /public/templates/
directory.
Since Powder.js utilizes CSRF tokens for increased security, to send POST request that will be accepted you need to inclide this token.
To do that you have to pass token from server into your template (or javascript request). The token can be retrieved from csrf
variable.
Request must contain the token in _csrf
field.
For example, you can include it in template like this: <input type="hidden" name="_csrf" value="{csrf}" />
Powder.js utilizes Asyncawait and promises (using bluebird) to simplify asynchronous code.
This allows simplifying this code which is considered your typical js callback hell:
function foo(callback) {
firstAsyncCall(function (err, resultA) {
if (err) { callback(err); return; }
secondAsyncCallUsing(resultA, function (err, resultB) {
if (err) { callback(err); return; }
thirdAsyncCallUsing(resultB, function (err, resultC) {
if (err) {
callback(err);
} else {
callback(null, doSomethingWith(resultC));
}
});
});
});
}
To simple and readable code like this:
var foo = async (function() {
var resultA = await (firstAsyncCall());
var resultB = await (secondAsyncCallUsing(resultA));
var resultC = await (thirdAsyncCallUsing(resultB));
return (doSomethingWith(resultC));
});
Note that await function will only work with functions that return promises.
If you are using libraries or third-party functions that do not return promises, you can use bluebirds .promisify()
or .promisifyAll()
functions to turn them into promises and allow usage with asyncawait.
For more info, please refer to asyncawait and bluebird docs.
You can quickly setup a vagrant environment that includes all the required packages for puwder.js app to work (assuming you have vagrant installed).
It is recommended to generate powder.js app without initialization. Doing so will allow compiling all the depenend node modules inside of the vagrant box from the beginning thus saving you time.
To do so, follow the steps below:
- Run
yo powder:vagrant
to generate all the required vagrant files - Run
vagrant up
to provision the box - Run
vagrant ssh
to open box shell - Use
cd /vagrant
to navigate to shared folder with app code - (optional) If you haven't initialized the app, run
npm install
to do so. - Run the app using
gulp
command
Please, note that if you chose to initialize the app from the beginning, you might need to remove node_modules
folder and re-run npm install
inside of a vagrant box to re-compile some of the node modules, otherwise you might get some warnings that are not critical (e.g. Failed to load c++ bson extension, using pure JS version
).
Add more docs, subgenerators and a proper test suite.