-
Notifications
You must be signed in to change notification settings - Fork 2
Home
Nodulator is designed to make it more easy to create highly modulable REST APIs, with integrated ORM (database agnostic) in CoffeeScript.
First of all, the config process is absolutly optional.
If you don't give Nodulator a config, it will assume you want to use SqlMem DB system, with no persistance at all. Usefull for heavy tests periods.
If you prefere to use a persistant system, here is the procedure :
Nodulator = require 'Nodulator'
Nodulator.Config
dbType: 'Mongo' # You can select 'SqlMem' to use inRAM Document (no persistant data, used to test) or 'Mongo' or 'Mysql'
dbAuth:
host: 'localhost'
database: 'test'
port: 27017 # Can be ignored, default values taken
user: 'test' # For Mongo and SqlMem, these fields are optionals
pass: 'test' #
The module provide 2 main Objects :
Nodulator.Resource
Nodulator.Route
A Resource
is a class permitting to retrive and save a model from a DB.
Here is an exemple of creating a Resource
PlayerResource = Nodulator.Resource 'player'
PlayerResource.Init()
# /!\ Never forget to call Init() /!\ #
Each Resource
provides some 'Class methods' to manage the specific model in db :
PlayerResource.Fetch(id, done)
PlayerResource.FetchBy(field, value, done)
PlayerResource.List(id, done)
PlayerResource.ListBy(field, value, done)
PlayerResource.Deserialize(blob, done)
The Fetch
method take an id and return a PlayerResource
intance to done
callback :
PlayerResource.Fetch 1, (err, player) ->
return console.error err if err?
[...] # Do something with player
You can also call FetchBy
method to give a specific field to retrive.
It can be unique, or the first occurence in DB will return.
You can list every models from this Resource
thanks to List
:
PlayerResource.List (err, players) ->
return console.error err if err?
[...] # players is an array of player instance
Like Fetch
, you can ListBy
a specific field.
The Deserialize
method allow to get an instance of a given Resource
.
Never use new
operator directly on a Resource
, else you might bypass the relationning system.
Deserialize
method used to make pre-processing work (like fetching related models) before instantiation.
A player instance has some methods :
player.Save(done)
Used to save the model in DB. The callback take 2 arguments : (err, instance) ->
player.Delete(done)
Used to delete the model from the DB. The callback take 1 argument : (err) ->
player.Serialize()
Used to get every object properties, and return it in a new object.
Generaly used to get what to be saved in DB.
player.ToJSON()
By default, it calls Serialize().
Generaly used to get what to send to client.
You can inherit from a Resource
to override or enhance its default behaviour, or to make a complex class inheritance system built on Resource
In CoffeeScript its pretty easy:
class UnitResource extends Nodulator.Resource 'unit'
# Here we override the constructor to attach a weapon resource
# Never forget to call super(blob), or the instance will never be populated by DB fields
constructor: (blob, @weapon) ->
super blob
# We create a new instance method
LevelUp: (done) ->
@level++
@Save done
# Here we override the Deserialize class method, to fetch the attached WeaponResource
@Deserialize: (blob, done) ->
if !(blob.id?) # If the resource isnt deserialized from db, don't fetch attached resource
return super blob, done
WeaponResource.FetchByUserId blob.id, (err, weapon) =>
res = @
done(null, new res(blob, weapon))
UnitResource.Init()
Given the last exemple, here is a class that inherits from UnitResource
class PlayerResource extends UnitResource.Extend 'player'
SpecialBehaviour: (args, done) ->
[...]
PlayerResource.Init();
You can also define abstract class, to avoid corresponding model to be created/initialized :
class UnitResource extends Nodulator.Resource 'unit', {abstract: true}
UnitResource.Init();
Of course, abstract class are only designed to be inherited. (Please note that they can't have Route attached)
Nodulator provides a Route
object, to be attached to a Resource
object in order to describe routing process.
class UnitResource extends Nodulator.Resource 'unit', Nodulator.Route
There is no need of Init()
here.
Default Nodulator.Route
do nothing.
You have to inherit from it to describe routes :
class UnitRoute extends Nodulator.Route
Config: ->
super()
@Add 'get', '/:id', (req, res) =>
# The @resource field points to attached Resource
@resource.Fetch req.params.id, (err, unit) ->
return res.status(500).send err if err?
res.status(200).send unit.ToJSON()
@Add 'post', (req, res) ->
res.status(200).end();
This Route
, attached to a Resource
, add 2 endPoints :
GET => /api/1/units/:id
POST => /api/1/units
Each Route
have to implement a Config()
method, calling super()
and defining routes thanks to @Add()
call.
Here is the @Add()
call definition :
Nodulator.Route.Add verb, [endPoint = '/'], [middleware, [middleware, ...]], callback
Nodulator provides