Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Entities on Node.js

Entities on Node.js

The Node.js implementation of Entities

Cbb9cafe03e785d80a9aa973c5e43c44?s=128

Thanos Polychronakis

December 04, 2014
Tweet

Transcript

  1. Entities on Node.js Entities on Node.js

  2. /thanpolas/entity /thanpolas/entity

  3. Entities use Entities use CIP ​for Classical Inheritance /thanpolas/cip Bluebird

    for the 100% Promises API /petkaantonov/bluebird Middlewarify for creating middleware /thanpolas/middlewarify @thanpolas
  4. Entities extend Entities extend events.EventEmitter ...and that's the only thing

    they do @thanpolas
  5. Creating an Entity Creating 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 @thanpolas
  6. Entities Adaptors Entities Adaptors Mongoose Mongoose MongoDB ORM http://mongoosejs.com/ Sequelize

    Sequelize PostgreSQL MySQL MariaDB SQLite http://sequelizejs.com/ @thanpolas
  7. CRUD Primitives CRUD Primitives create(data) read(query=) readOne(query) readLimit(?query, offset, limit)

    update(query, updateValues) delete(query) count(query=) @thanpolas
  8. CRUD Primitives CRUD Primitives create() create() entity.create({name: 'thanasis'}) .then(function(udo) {

    udo.name === 'thanasis'; // true }) .catch(function(error) { // deal with error. }); ... so on and so forth ... @thanpolas
  9. Entity Hooks Entity Hooks Middlewarify in action before after last

    @thanpolas
  10. Entity Hooks Entity Hooks before before // a middleware with

    synchronous resolution entity.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 }); @thanpolas
  11. Hooks are FiFo Hooks are FiFo Order MATTERS Order MATTERS

    @thanpolas
  12. Hooks are Hooks are Middleware Middleware @thanpolas

  13. Before Hooks Before Hooks Get the exact same number or

    arguments After & Last Hooks After & Last Hooks Gets the result plus the original number or arguments @thanpolas
  14. Entity Hooks Entity Hooks Asynchronicity Asynchronicity entity.create.before(function(data){ return promiseReturningFn(function(result) {

    resolve(result + 1); }); }); @thanpolas
  15. Extending Entities Extending Entities adding new methods adding new methods

    @thanpolas
  16. Extending Entities Extending Entities Just use the prototype Just use

    the prototype var Entity = require('entity'); var UserEntity = module.exports = Entity.extend(); UserEntity.prototype.report = function(userId) { return promiseReturningAction(userId); }; @thanpolas
  17. Extending Entities Extending Entities Using 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); }; @thanpolas
  18. Let's combine all up Let's combine all up @thanpolas

  19. 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 Entity A Production-ish Entity @thanpolas
  20. Entity Hands On Entity Hands On this.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; }; @thanpolas
  21. Entity Hands On Entity Hands On this.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); }); @thanpolas
  22. Now let's get crazy Now let's get crazy @thanpolas

  23. Entities Entities + + Crude Crude POST /user GET /user

    GET /user/:id PUT /user/:id PATCH /user/:id DELETE /user/:id /thanpolas/crude @thanpolas
  24. ... but not today ... but not today @thanpolas

  25. Thank you (here is where you applaud) Thanasis Polychronakis @thanpolas

    speakerdeck.com/thanpolas
  26. Questions? Be a critic Thanasis Polychronakis @thanpolas speakerdeck.com/thanpolas

  27. Shameless Plug Time Promo Code bgwebsummit From 60€ --> 40€

    15/5/2015 @ Thessaloniki Greece devitconf.org