The Node.js based HTTP server is one of the runtime container used by the Cloudburo deployment strategy. Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
Beside the node.js core server application a set of NPM packaged libraries are used, part of them are also used within the frontend based application (as for example ‘underscore’ or ‘coffee script’)
The file directory consists of two parts
root
directory itself contains of
index.js
file which will initialize the Node.js
server applicationcloudburoApp.js
file which bundles the CommonJS modules which makes up the application in a minified single javascript file. modelLoader.coffee
file which loads the server side moongoose model of the application and injects the necessary event handlers.root/node_modules
contains all Node.js
modules required by the server itsself, as for example express, mongoose, mongodb, stitch, backbone, underscore
etc. These modules are managed via the Node Package Modules mechanism.server_models
directory contains all Mongoose based business concept object models of the Cloudburo App platform, as for example the models necessary to persists objects like Customer
, Service
, Product
, User
and so on.root/app
directoryThe index.js
contains the code for the Node.js configuration it consists of the following main blocks
Node.js
Server and connecting to the cloud based MongoDB instance.The model loader will dynamically auto load the server models which are stored in the server_models
directory.
modelLoader = new (require("./modelLoader"))();
modelLoader.autoload(nodeserv,db, path.join(__dirname,"server_models"));
The server models are defining the mongoose schema for the business domain model objects they are responsible for.
module.exports = class ServiceTemplateModel extends BaseModel
constructor: (props) ->
super 'serviceTemplateModel','ServiceTemplateModel',
new mongoose.Schema
name: { type: String, default: '' }
type: { type: Number, default: '' }
category: { type: String}
prize: { type: String}
duration: { type: String}
newInstance: (props) ->
return new ServiceTemplateModel props
Each server model extends the BaseModel
module.exports = class BaseModel
constructor: (@modelName,@dbModelName,@schema,props) ->
@dbModel = mongoose.model(@dbModelName, @schema)
@model = new @dbModel(props)
@schema.virtual('id').get -> return this._id
@schema.methods.toBackbone = ->
obj = this.toObject();
obj.id = obj._id;
return obj;
getModelName: -> @modelName
getDBModel: -> @dbModel
getDBSchema: -> @schema
save: -> @model.save()
The model loader will load each model module dynamically out of server_models
directory, creates the relevant moongoose object and passes it over to the BackBoneBridge (see below the expose operation)
files = fs.readdirSync modelpath
modelNames = _und.map files, (f) =>
path.basename f
bridge = new (require("./backboneBridge"))()
_und.each modelNames, (modelName) ->
modelC = require modelpath + "/" + modelName
util.inspect(modelC,true,true)
if modelName != "baseModel.coffee"
model = new modelC()
@expose(model,serv)
The expose
function will take care that backend requests triggered by frontend Backbone based business object domain models are dispatched to the corresponding Mongoose based business object domain model which will handle the request in interaction with the database.
For each server model a set of request handler will be created. In case the server model name is customerModel.coffee
the URL path name will be the file name (without Model.coffee extension) plus an ’s' for the plural, e.g customers
. The following request handlers are created for each server model:
/customers
), GET request/customers/<id>
), PUT request/customers/<id>
), DELETE request/customers/<id>
), POST requestThe expose function looks like the following
expose : (model, serv)->
collection = model.getModelName()+'s'
serv.get '/'+collection, (req, res) ->
model.getDBModel().find({}, (err, docs) ->
if err != null
res.json err, 500
else
res.send(docs))
serv.put '/'+collection+'/:id', (req, res) ->
conditions = { _id: req.params.id }
doc = req.body
delete doc._id
model.getDBModel().update conditions, doc,{}, (err, numAffected) ->
if err == null
res.json 200
else
res.json err, 500
serv.del '/'+collection+'/:id', (req, res) ->
conditions = { _id: req.params.id }
model.getDBModel().remove conditions, (err, numAffected) ->
if err == null
res.json 200
else
res.json err, 500
serv.post '/'+collection, (req, res) ->
conditions = { _id: req.params.id }
doc = req.body
obj = model.newInstance doc
obj.save()
res.send obj.model