UNPKG

wr-eventstore

Version:

Node-eventstore is a node.js module for multiple databases. It can be very useful as eventstore if you work with (d)ddd, cqrs, eventsourcing, commands and events, etc.

291 lines (247 loc) 11.3 kB
var _ = require('lodash'); var Eventstore = require('./eventstore'); /** * Emit events before and after execution of eventstore methods. * @param {Function} eventstore - eventstore store instance */ function StoreEventEmitter(eventstore) { if (!eventstore || !(eventstore instanceof Eventstore)) { throw new Error('Provided eventstore must be instance of Eventstore'); } var self = this; self.eventstore = eventstore; self.store = self.eventstore.store; /** * Get arguments which are emitted * @param {Array} args - arguments from original implementation except callback */ function getEmitArguments(args) { return { milliseconds: Date.now(), arguments: args }; } /** * Enhance original callback to emit an event * @param {string} name - name which will be used to emit * @param {Function} callback - callback function from original implementation * @param {Array} args - arguments from original implementation except callback */ function enhanceCallback(name, callback, args) { var originalCallback = callback; callback = function () { self.eventstore.emit.call(self.eventstore, 'after-' + name, getEmitArguments(args)); if (originalCallback) { return originalCallback.apply(this, arguments); } return; }; return callback; } /** * add event emitter advice to eventstore method * @param {string} name - name which will be used to emit * @param {Function} eventstore - eventstore store instance * @param {Function} originalMethod - original implementation which will be extended * @param {Array} args - arguments from original implementation except callback * @param {Function} callback - callback function from original implementation */ function addEventEmitterToMethod(name, originalMethod, args, callback) { args = _.without(args, undefined, null); callback = enhanceCallback(name, callback, args); self.eventstore.emit.call(self.eventstore, 'before-' + name, getEmitArguments(args)); return originalMethod.apply(this, _.concat(args, callback || [])); }; /** * Add event emitter to eventstore methods */ StoreEventEmitter.prototype.addEventEmitter = function () { /** * add event emitter as an around advice to database methods */ if (this.store.clear) { var originalClear = this.store.clear; this.store.clear = function (callback) { return addEventEmitterToMethod.call(this, 'clear', originalClear, [], callback); }; } if (this.store.getNextPositions) { var originalGetNextPositions = this.store.getNextPositions; this.store.getNextPositions = function (positions, callback) { return addEventEmitterToMethod.call(this, 'get-next-positions', originalGetNextPositions, [positions], callback); }; } if (this.store.addEvents) { var originalAddEvents = this.store.addEvents; this.store.addEvents = function (events, callback) { return addEventEmitterToMethod.call(this, 'add-events', originalAddEvents, [events], callback); }; } if (this.eventstore.getEvents) { var originalGetEvents = this.eventstore.getEvents; this.eventstore.getEvents = function (query, skip, limit, callback) { if (typeof query === 'function') { callback = query; query = undefined; } else if (typeof skip === 'function') { callback = skip; skip = undefined; } else if (typeof limit === 'function') { callback = limit; limit = undefined; } return addEventEmitterToMethod.call(this, 'get-events', originalGetEvents, [query, skip, limit], callback); }; } if (this.eventstore.getEventsSince) { var originalGetEventsSince = this.eventstore.getEventsSince; this.eventstore.getEventsSince = function (date, skip, limit, callback) { if (typeof skip === 'function') { callback = skip; skip = undefined; } else if (typeof limit === 'function') { callback = limit; limit = undefined; } return addEventEmitterToMethod.call(this, 'get-events-since', originalGetEventsSince, [date, skip, limit], callback); }; } if (this.eventstore.getEventsByRevision) { var originalGetEventsByRevision = this.eventstore.getEventsByRevision; this.eventstore.getEventsByRevision = function (query, revMin, revMax, callback) { if (typeof revMin === 'function') { callback = revMin; revMin = undefined; } else if (typeof revMax === 'function') { callback = revMax; revMax = undefined; } return addEventEmitterToMethod.call(this, 'get-events-by-revision', originalGetEventsByRevision, [query, revMin, revMax], callback); }; } if (this.eventstore.getLastEvent) { var originalGetLastEvent = this.eventstore.getLastEvent; this.eventstore.getLastEvent = function (query, callback) { return addEventEmitterToMethod.call(this, 'get-last-event', originalGetLastEvent, [query], callback); }; } if (this.eventstore.getUndispatchedEvents) { var originalGetUndispatchedEvents = this.eventstore.getUndispatchedEvents; this.eventstore.getUndispatchedEvents = function (query, callback) { if (!callback) { callback = query; query = undefined; } return addEventEmitterToMethod.call(this, 'get-undispatched-events', originalGetUndispatchedEvents, [query], callback); }; } if (this.eventstore.setEventToDispatched) { var originalSetEventToDispatched = this.eventstore.setEventToDispatched; this.eventstore.setEventToDispatched = function (id, callback) { return addEventEmitterToMethod.call(this, 'set-event-to-dispatched', originalSetEventToDispatched, [id], callback); }; } if (this.store.addSnapshot) { var originalAddSnapshots = this.store.addSnapshot; this.store.addSnapshot = function (snap, callback) { return addEventEmitterToMethod.call(this, 'add-snapshot', originalAddSnapshots, [snap], callback); }; } if (this.store.cleanSnapshots) { var originalCleanSnapshots = this.store.cleanSnapshots; this.store.cleanSnapshots = function (query, callback) { return addEventEmitterToMethod.call(this, 'clean-snapshots', originalCleanSnapshots, [query], callback); }; } if (this.store.getSnapshot) { var originalGetSnapshot = this.store.getSnapshot; this.store.getSnapshot = function (query, revMax, callback) { return addEventEmitterToMethod.call(this, 'get-snapshot', originalGetSnapshot, [query, revMax], callback); }; } if (this.store.removeTransactions) { var originalRemoveTransactions = this.store.removeTransactions; this.store.removeTransactions = function (evt, callback) { return addEventEmitterToMethod.call(this, 'remove-transactions', originalRemoveTransactions, [evt], callback); }; } if (this.store.getPendingTransactions) { var originalGetPendingTransactions = this.store.getPendingTransactions; this.store.getPendingTransactions = function (callback) { return addEventEmitterToMethod.call(this, 'get-pending-transactions', originalGetPendingTransactions, [], callback); }; } if (this.store.repairFailedTransaction) { var originalRepairFailedTransaction = this.store.repairFailedTransaction; this.store.repairFailedTransaction = function (lastEvt, callback) { return addEventEmitterToMethod.call(this, 'repair-failed-transactions', originalRepairFailedTransaction, [lastEvt], callback); }; } if (this.store.removeTables) { var originalRemoveTables = this.store.removeTables; this.store.removeTables = function (callback) { return addEventEmitterToMethod.call(this, 'remove-tables', originalRemoveTables, [], callback); }; } if (this.eventstore.streamEvents) { var originalStreamEvents = this.eventstore.streamEvents; this.eventstore.streamEvents = function (query, skip, limit) { return addEventEmitterToMethod.call(this, 'stream-events', originalStreamEvents, [query, skip, limit]); }; } if (this.eventstore.streamEventsSince) { var originalStreamEventsSince = this.eventstore.streamEventsSince; this.eventstore.streamEventsSince = function (date, skip, limit) { return addEventEmitterToMethod.call(this, 'stream-events-since', originalStreamEventsSince, [date, skip, limit]); }; } if (this.eventstore.streamEventsByRevision) { var originalStreamEventsByRevision = this.eventstore.streamEventsByRevision; this.eventstore.streamEventsByRevision = function (query, revMin, revMax) { return addEventEmitterToMethod.call(this, 'stream-events-by-revision', originalStreamEventsByRevision, [query, revMin, revMax]); }; } if (this.eventstore.getEventStream) { var originalGetEventStream = this.eventstore.getEventStream; this.eventstore.getEventStream = function (query, revMin, revMax, callback) { if (typeof revMin === 'function') { callback = revMin; revMin = undefined; } else if (typeof revMax === 'function') { callback = revMax; revMax = undefined; } return addEventEmitterToMethod.call(this, 'get-event-stream', originalGetEventStream, [query, revMin, revMax], callback); }; } if (this.eventstore.getFromSnapshot) { var originalGetFromSnapshot = this.eventstore.getFromSnapshot; this.eventstore.getFromSnapshot = function (query, revMax, callback) { if (typeof revMax === 'function') { callback = revMax; revMax = undefined; } return addEventEmitterToMethod.call(this, 'get-from-snapshot', originalGetFromSnapshot, [query, revMax], callback); }; } if (this.eventstore.createSnapshot) { var originalCreateSnapshot = this.eventstore.createSnapshot; this.eventstore.createSnapshot = function (obj, callback) { return addEventEmitterToMethod.call(this, 'create-snapshot', originalCreateSnapshot, [obj], callback); }; } if (this.eventstore.commit) { var originalCommit = this.eventstore.commit; this.eventstore.commit = function (eventstream, callback) { return addEventEmitterToMethod.call(this, 'commit', originalCommit, [eventstream], callback); }; } if (this.eventstore.getLastEventAsStream) { var originalGetLastEventAsStream = this.eventstore.getLastEventAsStream; this.eventstore.getLastEventAsStream = function (query, callback) { return addEventEmitterToMethod.call(this, 'get-last-event-as-stream', originalGetLastEventAsStream, [query], callback); }; } }; } module.exports = StoreEventEmitter;