hapi-app-mongo-model
v0.2.5
Published
Lightweight abstraction layer over native MongoDB driver for Hapi App
Downloads
4
Readme
Hapi App Mongo Model
Lightweight abstraction layer wrapping Monk api (MongoDB library)
Current version is stable and used in production However it is still work in progress
Rationale
Most popular ODM for MongoDB manipulations from NodeJS is Mongoose. It is build on the top of MongoDB's native driver. It is build with tone of features such us object schemas and validation.
Mongoose is however unnecesary if you would want to reuse Hapi Joi schemas for validation of your model objects or need lower level apis without package overhead.
Hapi-app-mongo-model is provides lightweight abstraction on the top of Monk, which is abstraction over MongoDB native driver.
Core features
- It can be used stand-alone or registered as Hapi plugin with
AppModel.plugin
extension - It allows to register custom
ModelClass
-es - It exposes mongo collection (monk) methods on custom
ModelClasses
, such us:find()
,findOne()
,insert()
, etc. - It allows to create Models before connection is established (no monk drawbacks)
- It exposes sugar methods (returning promises) on
Model Classes
validate()
,findAndParse()
,findOneAndParse()
insertAndParse()
forceFind()
- Helper methods available on
modelObject
:save()
,validate()
toJSON()
toString()
- Ease of extensibility of the Helper and DAO methods ( see examples below )
Using Hapi App Mongo Model
This part provides simple example of how to create and use custom models
Check example
folder for full example code or check test
folder for test specs.
Required files
Let's assume User model lives in folder models/user
, then required files are:
models/user/
models/user/dao.js
models/user/helpers.js
models/user/index.js
models/user/schema.js
Preparing model source files
File: models/user/index.js
var Model = require('hapi-app-mongo-model'),
UserModel = Model.register({
collection: "users",
path: __dirname
});
module.exports = UserModel;
File: models/user/dao.js
module.exports = {}
File: models/user/helpers.js
module.exports = {
fullName : function() {
return this.fname + ' ' + this.lname;
}
}
File: models/user/schema.js
var Joi = require('joi'),
userSchema;
userSchema = {
fname: Joi.string(),
lname: JOi.string()
}
module.exports = userSchema;
Connecting to databse
Below examples illustrate connecting to database if you run package outside of Hapi application. For using it as hapi plugin scroll to Using Model as plugin with hapi
Example 1: default connection Model.connect()
In below example Model.connect()
is called without any parameters.
Model will attempt to Connect to default mongo db url:
mongodb://localhost:27017
.
var Model = require('hapi-app-mongo-model'),
connectionConfig = {};
Model
.connect()
.then(function (db) {
// ... CRUD
}, function (error) {
throw new Error(error);
});
Example 2: custom connection Model.connect(config)
Config object takes three parameters:
- url - mongodb url, fefault value will be used if it is undefined
- connectionId - identifier is required when there is more than one connection
- opts - setting object passed to native
connect
method
var Model = require('hapi-app-mongo-model'),
connConfig;
connConfig = {
url: 'mongodb://localhost:27017',
connectionID: 'my-awesome-mongo-connection',
opts: {
"db": {
"native_parser": false
}
}
}
Model
.connect(connConfig)
.then(function (db) {
// ... CRUD
}, function (error) {
throw new Error(error);
});
Creating new user object
File: index.js
var User = require('models/user'),
user;
user = new User({
fname: 'John',
fname: 'Smith'
});
// call build-in helper
console.log(user.toJSON());
// call local helper
console.log(user.fullName());
User Reference
Using Model as plugin with hapi Model.plugin
done, there are no tests yet
var Hapi = require('hapi'),
server = new Hapi.Server();
server.connection({ port: 3000 });
server.register({
"url": "mongodb://localhost:27017/test",
"opts": {
"db": {
"native_parser": false
}
}
}, function (error) {
//...
server.start();
});
Shared connection Model.db
Model.connect(settings)
creates connection that can be accessed via:
Model.db
YourModel.db
yourObject.db
Schamas
Models are required to have schema.js
file which exports model object schema ready for validation with Joi.validate()
.
Simply follow Joi docs to create one. Check example code to see it in action.
Indexes
Uses monk indexing exposed on collection.
Custom Model namespaced methods
Methods exposed on the level of Custom Model are equivalent to collection methods, and so for example call to below method update()
:
var Model = require('hapi-app-mongo-model');
Model.db.collection[{collection-name}].update( ... )
can be conviniently simplified to:
var UserModel = require('/path/to/user-model');
UserModel.update( ... )
Creating Model Classes Model.register()
Method used to generate Custom Model Class takes config object with three parameters:
- collection - name of mongoDB collection
- path - path to Custom Model directory directory with schema, dao and helpers files.
Example Model Class generation:
var Model = require('hapi-app-mongo-model')
modelTaskConfig;
modelTaskConfig = {
collection: "tasks",
path: __dirname
}
module.exports = Model.generate(modelTaskConfig);
Find method Model.find()
Convenience method
FindOne method Model.findOne()
Convenience method
ObjectId via Model.ObjectId()
and Model.ObjectID()
Convenience method
DAO helpers
Createing object via new ModelClass(collectionName, [object])
Createing object via ModelClass.create(collectionName, [object])
Convenience method for new ModelClass(collectionName, [object])
status: implemented but no tests
Find <ModelClass>.find()
Convenience method
FindOne <ModelClass>.findOne()
Convenience method
Custom DAO helpers
todo: missing test to confirm prototypical inheritance with parent class method exposed via _super that will allow to override them in models/model/dao.js
Model Object helpers
Save <modelObject>.save()
Convenience method returns promise
Validate <modelObject>.validate()
Convenience method returns promise
validate()
is async method and returns a promise.
It can be handled in one of two ways as shown below.
Method 1: promise.then(onSuccess, onError)
user.validate()
.then(function onSuccess(data) {
//.. do something with data
}, function onError(error) {
//.. do something with error
});
Method 2: promise.onFulfill(onSuccess).onReject(onError)
user.validate()
.then(function onSuccess(data) {
//.. do something with data
}, function onError(error) {
//.. do something with error
});
Resources
BIG THANK YOU TO ALL THE AUTHORS FOR DEVELOPING THOSE GREAT PACKAGES, FOR MAKING CODING EASIER, FASTER AND MORE FUN!
CHEEERIO!!!
Used HapiJs package
- Hapi - A rich framework for building applications and services
- Hoek - Utility methods for the hapi ecosystem
- Good - Hapi process monitoring
- Boom - HTTP-friendly error objects
- Joi - Object schema description language and validator for JavaScript objects.
Used packages
- aheckmann/mpromise - A promises/A+ conformant implementation
- hapi-mongo-models
- hapi-mongodb