grassroots v0.0.2
Grassroots
A NodeJS/Coffeescript Microframework
Overview
Grassroots is an ExpressJS extension framework written in Coffeescript that automatically attaches RESTful Resource callbacks to conventional routes based on file structure and naming conventions. Like SynthJS, by which is it heavily inspired, it aims to remove some of the tedium and repetition involved in setting up CRUD APIs.
Setup
(1) Clone grassroots into your node_modules directory
hg clone <https://jwherring@bitbucket.org/jwherring/grassroots>(2) Run npm install from with this directory to get all of the dependencies
cd grassroots
npm install(3) Compile using grunt
grunt coffee(4) Include in the main file of your application:: : var grassroots = require('grassroots');
(5) Any middleware that should be loaded prior to the routes should be
passed on the config object in an array called middleware.
Grassroots will attach these to the application in the order
they're listed.
(6) Call init on the grassroots object and pass in an optional config object. Grassroots will return the express application::
: app = grassroots.init(config);
(7) As an alternative, grassroots.mount(config) is available. This
loads only the routers. The application should be instantiated
before passing through to mount.
Usage
By default, grassroots looks for a routes/ directory in the same
directory as your application entrypoint. Each file found in this
directory will become a RESTful resource with routes attached for each
method exposed in the file.
Methods should be named according to the associated HTTP VERB (GET,
POST, PUT, DELETE) in all lower-case. All routes assume, by default, an
:id param.
So, for example, a file named one.coffee with the following contents:
exports.get = (req, res) ->
code
exports.post = (req, res) ->
codewould result in the creation of the following routes:
(GET) /one/id/:id
(POST) /oneSome extensions are special. For example, adding Index to a get
route will create an endpoint that returns the entire list of entities.
So, augmenting the previous example like so:
exports.getIndex = (req, res) ->
code
exports.get = (req, res) ->
code
exports.post = (req, res) ->
codewould result in the creation of the following routes:
(GET) /one
(GET) /one/id/:id
(POST) /oneAdditional Parameters
Additional request parameters can be passed in in the normal way -
either in the request body or the url query string. Additionally,
grassroots will split the request url into key-value pairs and attach
it to the req object as urlparams, throwing away the entity name and
id parameter. For example, the following path:
/{entityname}/id/{id}/this/is/a/pathwould result in the following object:
{
'this': 'is',
'a': 'path'
}which could be accessed in the normal way:
req.urlparams.a === 'path' // trueAt present, if splitting the request path results in an odd number of elements, the last one is simply ignored.
If this behavior is not desired, it is possible to customize it by
passing in a custom url path parser function on the options object as
options.keyvalparser. This function should take a single argument
representing the request path (grassroots will pass req.path to this
function).
Database
By default, grassroots will try to establish a connection to a bucket
named grassroots on a couchbase backend. This is configurable though
the options.database object, however:
options =
'database':
'bucket': 'my_bucket'
'backend': 'couchbase'
app = grassroots.init optionsAt present, only couchbase is supported, and it is the responsibility of
the installer to make sure that the couchbase SDK is installed.
Schemas
grassroots provides a validateentity() method on req if a schema
is provided. Schemas, by convention, are specified in the projects
/schemas directory in files named after the entity they validate -
just as with route files. The file should have a .coffee extension,
and should consist of a single exported object called schema which
specifies the schema to validate against. Schemas are checked using the
tv4 library, and should therefore
be specified according to the JSON Schema draft
v4.
The name of the /schemas directory can be changed by passing in a
relative path as the schemadir member of the config object passed in
to init().
req.validateentity(entity) takes an optional parameter entity which
is the object to validate. If not provided, it will use req.body.
Please note that validateentity is only attached for POST and PUT
requests.
Additionally, it is possible to provide a defaults schema in the
schema file. This should be an object of key-value pairs that will be
substituted in for missing values on POST requests. For example:
exports.defaults =
"one": "default for one"If included in one.schema, any POST request to /one that lacks a
one member will have it set to "default for one". Since validation
happens after defaults have been applied, the defaults must comply
with the general schema.
Static Assets
Behind the scenes, grassroots uses HarpJS to
precompile all your static assets. Check out the harpjs homepage for
more details, but harp recognizes files with various extensions and
compiles them appropriately. grassroots will automatically mount
static/js and static/css as asset directories (creating them if they
do not exist) if none are specified on the options object. To set your
own paths, simply include entries for jsdir and cssdir in the
options object passed to grassroots.init(). For example:
options = {jsdir: 'public/js', cssdir: 'public/css'}
app = grassroots.init(options)By default, css and js files are served from /css and /js. To
change this, you can pass in jsroute and cssroute params to
options (include the preceding slash):
options = {jsroute: '/javascript', cssroute: '/styles'}
app = grassroots.init(options)Middleware
grassroots sets up some standard Connect middleware, including the
body-parser and the cookie-parser. To pass in a signature secret and
other options to the cookie-parser, include members named
cookiesignature and cookieoptions on the options object passed to
grassroots.