Date post: | 07-Jan-2017 |
Category: |
Technology |
Upload: | thanasis-polychronakis |
View: | 338 times |
Download: | 0 times |
Entities on Node.jsEntities on Node.js
/thanpolas/entity/thanpolas/entity
Entities useEntities useCIP
for Classical Inheritance /thanpolas/cip
Bluebirdfor the 100% Promises API /petkaantonov/bluebird
Middlewarifyfor creating middleware /thanpolas/middlewarify
Entities extendEntities extendevents.EventEmitter
...and that's the only thing they do
Creating an EntityCreating an Entity
var entity = require('entity');
var EntityChild = entity.extend(function() { this.a = 1;});
var EntityGrandChild = EntityChild.extend();
entity.extend
var entity = require('entity');
var UserEntity = entity.extendSingleton(function() {});
/* ... */
var userEnt = UserEntity.getInstance();
entity.extendSingleton
Entities AdaptorsEntities AdaptorsMongooseMongoose
MongoDB ORMhttp://mongoosejs.com/
SequelizeSequelizePostgreSQLMySQLMariaDBSQLitehttp://sequelizejs.com/
CRUD PrimitivesCRUD Primitivescreate(data)
read(query=)
readOne(query)
readLimit(?query, offset, limit)
update(query, updateValues)
delete(query)
count(query=)
CRUD PrimitivesCRUD Primitivescreate()create()
entity.create({name: 'thanasis'}) .then(function(udo) { udo.name === 'thanasis'; // true }) .catch(function(error) { // deal with error. });
... so on and so forth ...
Entity HooksEntity HooksMiddlewarify in action
beforeafterlast
Entity HooksEntity Hooksbeforebefore
// a middleware with synchronous resolutionentity.read.before(function(data){ if (!data.name) { throw new TypeError('No go my friend'); }});
// then...entity.read({}).then(function(document) { // you'll never get here}, function(err) { err instanceof Error; // true err.message === 'No go my friend'; // true});
Hooks are FiFoHooks are FiFoOrder MATTERSOrder MATTERS
Hooks areHooks areMiddlewareMiddleware
Before HooksBefore HooksGet the exact same number or arguments
After & Last HooksAfter & Last HooksGets the result plus the original number or arguments
Entity HooksEntity HooksAsynchronicityAsynchronicity
entity.create.before(function(data){ return promiseReturningFn(function(result) { resolve(result + 1); });});
Extending EntitiesExtending Entitiesadding new methodsadding new methods
Extending EntitiesExtending EntitiesJust use the prototypeJust use the prototype
var Entity = require('entity');
var UserEntity = module.exports = Entity.extend();
UserEntity.prototype.report = function(userId) { return promiseReturningAction(userId);};
Extending EntitiesExtending EntitiesUsing method()Using method()
var Entity = require('entity');
var UserEntity = module.exports = Entity.extend(function() { this.method('report', this._report.bind(this));
this.report.before(this._checkUserId.bind(this)); this.report.after(this._normalize.bind(this));});
UserEntity.prototype._report = function(userId) { return promiseReturningAction(userId);};
Let's combine all upLet's combine all up
var ClipEntity = module.exports = EntityBase.extendSingleton(function() { this.setModel(clipModel.Model);
this.method('readOneApi', this.readOne); this.method('readLimitApi', this.readLimit); this.method('updateApi', this.update); this.method('readApi', this.read);
// Apply system wide (global) filters this.readLimitApi.before(this.systemFilter.bind(this)); this.readOneApi.before(this.systemFilter.bind(this));
// Clip Creation middleware this.create.before(this._populateActiveEvent.bind(this)); this.create.after(this._processNewClip.bind(this));
// Record sanitization middleware this.updateApi.after(helpers.skipArgs(this.sanitizeResult, 2, this)); this.readLimitApi.after(helpers.skipArgs(this.sanitizeResults, 3, this)); this.readOneApi.after(helpers.skipArgs(this.sanitizeResult, 1, this));});
A Production-ish EntityA Production-ish Entity
Entity Hands OnEntity Hands Onthis.readLimitApi.before(this.systemFilter.bind(this));
/** * Apply system filters in all incoming READ queries * to exclude deleted and corrupt items. * * @param {Object} query The query. */ClipEntity.prototype.systemFilter = function(query) { query.notFound = { ne: true }; query.processed = true;};
Entity Hands OnEntity Hands Onthis.create.after(this._processNewClip.bind(this));
/** * Post creation clip processing. * * @param {Object} data Item used to create the record. * @param {app.entity.ClipProcess} processEnt The process entity. * @param {mongoose.Document} clipItem The result. * @return {Promise} A promise. * @private */ClipEntity.prototype._processNewClip = Promise.method(function(data, processEnt, clipItem) { processEnt.clipId = clipItem.id; log.finest('_processNewClip() :: Clip Saved to DB, starting FS save...', clipItem.id);
return this._checkWatermarkAndStore(processEnt, clipItem) .bind(processEnt) .then(processEnt.createThumbnail) .then(processEnt.checkS3) .then(processEnt.updateDatabase) .then(function() { log.fine('_processNewClip() :: Clip processing finished:', processEnt.sourceFilePath); }) .catch(processEnt.moveToTrash) .catch(processEnt._deleteRecord);});
Now let's get crazyNow let's get crazy
EntitiesEntities
++CrudeCrude
POST /userGET /userGET /user/:idPUT /user/:idPATCH /user/:idDELETE /user/:id
/thanpolas/crude
... but not today... but not today
Thank you(here is where you applaud)
Thanasis Polychronakis@thanpolashttp://www.slideshare.net/thanpolas
Questions?Be a critic
Thanasis Polychronakis@thanpolashttp://www.slideshare.net/thanpolas
Shameless Plug Time
Promo Codebgwebsummit
From 60€ --> 40€
15/5/2015@ Thessaloniki Greecedevitconf.org
Questions?
Thanasis Polychronakis@thanpolas