eventric
Version:
Build JavaScript applications with Behaviour-driven Domain Design. Based on DDD, BDD, CQRS and EventSourcing.
1,020 lines (915 loc) • 30.3 kB
JavaScript
var Context, DomainEvent, EventBus, PubSub, Repository, eventric, projectionService,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
eventric = require('eventric');
Repository = require('eventric/src/context/repository');
DomainEvent = require('eventric/src/context/domain_event');
EventBus = require('eventric/src/event_bus');
PubSub = require('eventric/src/pub_sub');
projectionService = require('eventric/src/projection');
Context = (function(_super) {
__extends(Context, _super);
function Context(name) {
this.name = name;
this.clearProjectionStore = __bind(this.clearProjectionStore, this);
this.getProjectionStore = __bind(this.getProjectionStore, this);
this.publishDomainEvent = __bind(this.publishDomainEvent, this);
this.emitDomainEvent = __bind(this.emitDomainEvent, this);
Context.__super__.constructor.apply(this, arguments);
this._initialized = false;
this._params = eventric.get();
this._di = {};
this._aggregateRootClasses = {};
this._adapterClasses = {};
this._adapterInstances = {};
this._commandHandlers = {};
this._queryHandlers = {};
this._domainEventClasses = {};
this._domainEventHandlers = {};
this._projectionClasses = [];
this._repositoryInstances = {};
this._domainServices = {};
this._storeClasses = {};
this._storeInstances = {};
this._eventBus = new EventBus;
}
Context.prototype.log = eventric.log;
/**
* @name set
*
* @module Context
*
* @description
* > Use as: set(key, value)
* Configure settings for the `context`.
*
* @example
exampleContext.set 'store', StoreAdapter
*
* @param {Object} key
* Available keys are: `store` Eventric Store Adapter
*/
Context.prototype.set = function(key, value) {
this._params[key] = value;
return this;
};
Context.prototype.get = function(key) {
return this._params[key];
};
/**
* @name emitDomainEvent
*
* @module Context
*
* @description emit Domain Event in the context
*
* @param {String} domainEventName Name of the DomainEvent
* @param {Object} domainEventPayload payload for the DomainEvent
*/
Context.prototype.emitDomainEvent = function(domainEventName, domainEventPayload) {
var DomainEventClass, domainEvent;
DomainEventClass = this.getDomainEvent(domainEventName);
if (!DomainEventClass) {
throw new Error("Tried to emitDomainEvent '" + domainEventName + "' which is not defined");
}
domainEvent = this._createDomainEvent(domainEventName, DomainEventClass, domainEventPayload);
return this.getDomainEventsStore().saveDomainEvent(domainEvent, (function(_this) {
return function() {
return _this.publishDomainEvent(domainEvent, function() {});
};
})(this));
};
Context.prototype.publishDomainEvent = function(domainEvent, callback) {
if (callback == null) {
callback = function() {};
}
return this._eventBus.publishDomainEvent(domainEvent, callback);
};
Context.prototype._createDomainEvent = function(domainEventName, DomainEventClass, domainEventPayload) {
return new DomainEvent({
id: eventric.generateUid(),
name: domainEventName,
context: this.name,
payload: new DomainEventClass(domainEventPayload)
});
};
Context.prototype.addStore = function(storeName, StoreClass, storeOptions) {
if (storeOptions == null) {
storeOptions = {};
}
this._storeClasses[storeName] = {
Class: StoreClass,
options: storeOptions
};
return this;
};
/**
* @name defineDomainEvent
*
* @module Context
*
* @description
* Adds a DomainEvent Class which will be used when emitting or handling DomainEvents inside of Aggregates, Projectionpr or ProcessManagers
*
* @param {String} domainEventName Name of the DomainEvent
* @param {Function} DomainEventClass DomainEventClass
*/
Context.prototype.defineDomainEvent = function(domainEventName, DomainEventClass) {
this._domainEventClasses[domainEventName] = DomainEventClass;
return this;
};
Context.prototype.defineDomainEvents = function(domainEventClassesObj) {
var DomainEventClass, domainEventName;
for (domainEventName in domainEventClassesObj) {
DomainEventClass = domainEventClassesObj[domainEventName];
this.defineDomainEvent(domainEventName, DomainEventClass);
}
return this;
};
/**
* @name addCommandHandler
*
* @module Context
*
* @dscription
* Use as: addCommandHandler(commandName, commandFunction)
*
* Add Commands to the `context`. These will be available to the `command` method after calling `initialize`.
*
* @example
```javascript
exampleContext.addCommandHandler('someCommand', function(params, callback) {
// ...
});
```
* @param {String} commandName Name of the command
*
* @param {String} commandFunction Gets `this.aggregate` dependency injected
* `this.aggregate.command(params)` Execute command on Aggregate
* * `params.name` Name of the Aggregate
* * `params.id` Id of the Aggregate
* * `params.methodName` MethodName inside the Aggregate
* * `params.methodParams` Array of params which the specified AggregateMethod will get as function signature using a [splat](http://stackoverflow.com/questions/6201657/what-does-splats-mean-in-the-coffeescript-tutorial)
*
* `this.aggregate.create(params)` Execute command on Aggregate
* * `params.name` Name of the Aggregate to be created
* * `params.props` Initial properties so be set on the Aggregate or handed to the Aggregates create() method
*/
Context.prototype.addCommandHandler = function(commandHandlerName, commandHandlerFn) {
this._commandHandlers[commandHandlerName] = (function(_this) {
return function() {
var command, diFn, diFnName, repositoryCache, _di, _ref, _ref1;
command = {
id: eventric.generateUid(),
name: commandHandlerName,
params: (_ref = arguments[0]) != null ? _ref : null
};
_di = {};
_ref1 = _this._di;
for (diFnName in _ref1) {
diFn = _ref1[diFnName];
_di[diFnName] = diFn;
}
repositoryCache = null;
_di.$repository = function(aggregateName) {
var AggregateRoot, repository;
if (!repositoryCache) {
AggregateRoot = _this._aggregateRootClasses[aggregateName];
repository = new Repository({
aggregateName: aggregateName,
AggregateRoot: AggregateRoot,
context: _this
});
repositoryCache = repository;
}
repositoryCache.setCommand(command);
return repositoryCache;
};
return commandHandlerFn.apply(_di, arguments);
};
})(this);
return this;
};
Context.prototype.addCommandHandlers = function(commandObj) {
var commandFunction, commandHandlerName;
for (commandHandlerName in commandObj) {
commandFunction = commandObj[commandHandlerName];
this.addCommandHandler(commandHandlerName, commandFunction);
}
return this;
};
/**
* @name addQueryHandler
*
* @module Context
*
* @dscription
* Use as: addQueryHandler(queryHandler, queryFunction)
*
* Add Commands to the `context`. These will be available to the `query` method after calling `initialize`.
*
* @example
```javascript
exampleContext.addQueryHandler('SomeQuery', function(params, callback) {
// ...
});
```
* @param {String} queryHandler Name of the query
*
* @param {String} queryFunction Function to execute on query
*/
Context.prototype.addQueryHandler = function(queryHandlerName, queryHandlerFn) {
this._queryHandlers[queryHandlerName] = (function(_this) {
return function() {
return queryHandlerFn.apply(_this._di, arguments);
};
})(this);
return this;
};
Context.prototype.addQueryHandlers = function(commandObj) {
var queryFunction, queryHandlerName;
for (queryHandlerName in commandObj) {
queryFunction = commandObj[queryHandlerName];
this.addQueryHandler(queryHandlerName, queryFunction);
}
return this;
};
/**
* @name addAggregate
*
* @module Context
*
* @description
*
* Use as: addAggregate(aggregateName, aggregateDefinition)
*
* Add [Aggregates](https://github.com/efacilitation/eventric/wiki/BuildingBlocks#aggregateroot) to the `context`. It takes an AggregateDefinition as argument. The AggregateDefinition must at least consists of one AggregateRoot and can optionally have multiple named AggregateEntities. The Root and Entities itself are completely vanilla since eventric follows the philosophy that your DomainModel-Code should be technology-agnostic.
*
* @example
```javascript
exampleContext.addAggregate('Example', {
root: function(){
this.doSomething = function(description) {
// ...
}
},
entities: {
'ExampleEntityOne': function() {},
'ExampleEntityTwo': function() {}
}
});
```
*
* @param {String} aggregateName Name of the Aggregate
* @param {String} aggregateDefinition Definition containing root and entities
*/
Context.prototype.addAggregate = function(aggregateName, AggregateRootClass) {
this._aggregateRootClasses[aggregateName] = AggregateRootClass;
return this;
};
Context.prototype.addAggregates = function(aggregatesObj) {
var AggregateRootClass, aggregateName;
for (aggregateName in aggregatesObj) {
AggregateRootClass = aggregatesObj[aggregateName];
this.addAggregate(aggregateName, AggregateRootClass);
}
return this;
};
/**
* @name subscribeToDomainEvent
*
* @module Context
*
* @description
* Use as: subscribeToDomainEvent(domainEventName, domainEventHandlerFunction)
*
* Add handler function which gets called when a specific `DomainEvent` gets triggered
*
* @example
```javascript
exampleContext.subscribeToDomainEvent('Example:create', function(domainEvent) {
// ...
});
```
*
* @param {String} domainEventName Name of the `DomainEvent`
*
* @param {Function} Function which gets called with `domainEvent` as argument
* - `domainEvent` Instance of [[DomainEvent]]
*
*/
Context.prototype.subscribeToDomainEvent = function(domainEventName, handlerFn, options) {
var domainEventHandler;
if (options == null) {
options = {};
}
domainEventHandler = (function(_this) {
return function() {
return handlerFn.apply(_this._di, arguments);
};
})(this);
this._eventBus.subscribeToDomainEvent(domainEventName, domainEventHandler, options);
return this;
};
/**
* @name subscribeToDomainEventWithAggregateId
*
* @module Context
*
*/
Context.prototype.subscribeToDomainEventWithAggregateId = function(domainEventName, aggregateId, handlerFn, options) {
var domainEventHandler;
if (options == null) {
options = {};
}
domainEventHandler = (function(_this) {
return function() {
return handlerFn.apply(_this._di, arguments);
};
})(this);
return this._eventBus.subscribeToDomainEventWithAggregateId(domainEventName, aggregateId, domainEventHandler, options);
};
Context.prototype.subscribeToAllDomainEvents = function(handlerFn, options) {
var domainEventHandler;
if (options == null) {
options = {};
}
domainEventHandler = (function(_this) {
return function() {
return handlerFn.apply(_this._di, arguments);
};
})(this);
return this._eventBus.subscribeToAllDomainEvents(domainEventHandler, options);
};
Context.prototype.subscribeToDomainEvents = function(domainEventHandlersObj) {
var domainEventName, handlerFn;
for (domainEventName in domainEventHandlersObj) {
handlerFn = domainEventHandlersObj[domainEventName];
this.subscribeToDomainEvent(domainEventName, handlerFn);
}
return this;
};
/**
* @name addDomainService
*
* @module Context
*
* @description
* Use as: addDomainService(domainServiceName, domainServiceFunction)
*
* Add function which gets called when called using $domainService
*
* @example
```javascript
exampleContext.addDomainService('DoSomethingSpecial', function(params, callback) {
// ...
});
```
*
* @param {String} domainServiceName Name of the `DomainService`
*
* @param {Function} Function which gets called with params as argument
*/
Context.prototype.addDomainService = function(domainServiceName, domainServiceFn) {
this._domainServices[domainServiceName] = (function(_this) {
return function() {
return domainServiceFn.apply(_this._di, arguments);
};
})(this);
return this;
};
Context.prototype.addDomainServices = function(domainServiceObjs) {
var domainServiceFn, domainServiceName;
for (domainServiceName in domainServiceObjs) {
domainServiceFn = domainServiceObjs[domainServiceName];
this.addDomainService(domainServiceName, domainServiceFn);
}
return this;
};
/**
* @name addAdapter
*
* @module Context
*
* @description
* Use as: addAdapter(adapterName, AdapterClass)
*
* Add adapter which get can be used inside of `CommandHandlers`
*
* @example
```javascript
exampleContext.addAdapter('SomeAdapter', function() {
// ...
});
```
*
* @param {String} adapterName Name of Adapter
*
* @param {Function} Adapter Class
*/
Context.prototype.addAdapter = function(adapterName, adapterClass) {
this._adapterClasses[adapterName] = adapterClass;
return this;
};
Context.prototype.addAdapters = function(adapterObj) {
var adapterName, fn;
for (adapterName in adapterObj) {
fn = adapterObj[adapterName];
this.addAdapter(adapterName, fn);
}
return this;
};
/**
* @name addProjection
*
* @module Context
*
* @description
* Add Projection that can subscribe to and handle DomainEvents
*
* @param {string} projectionName Name of the Projection
* @param {Function} The Projection Class definition
* - define `subscribeToDomainEvents` as Array of DomainEventName Strings
* - define handle Funtions for DomainEvents by convention: "handleDomainEventName"
*/
Context.prototype.addProjection = function(projectionName, ProjectionClass) {
this._projectionClasses.push({
name: projectionName,
"class": ProjectionClass
});
return this;
};
Context.prototype.addProjections = function(viewsObj) {
var ProjectionClass, projectionName;
for (projectionName in viewsObj) {
ProjectionClass = viewsObj[projectionName];
this.addProjection(projectionName, ProjectionClass);
}
return this;
};
/**
* @name initialize
*
* @module Context
*
* @description
* Use as: initialize()
*
* Initializes the `context` after the `add*` Methods
*
* @example
```javascript
exampleContext.initialize(function() {
// ...
})
```
*/
Context.prototype.initialize = function(callback) {
if (callback == null) {
callback = function() {};
}
return new Promise((function(_this) {
return function(resolve, reject) {
_this.log.debug("[" + _this.name + "] Initializing");
_this.log.debug("[" + _this.name + "] Initializing Store");
return _this._initializeStores().then(function() {
_this.log.debug("[" + _this.name + "] Finished initializing Store");
_this._di = {
$adapter: function() {
return _this.getAdapter.apply(_this, arguments);
},
$query: function() {
return _this.query.apply(_this, arguments);
},
$domainService: function() {
return (_this.getDomainService(arguments[0])).apply(_this, [arguments[1], arguments[2]]);
},
$projectionStore: function() {
return _this.getProjectionStore.apply(_this, arguments);
},
$emitDomainEvent: function() {
return _this.emitDomainEvent.apply(_this, arguments);
}
};
_this.log.debug("[" + _this.name + "] Initializing Adapters");
return _this._initializeAdapters();
}).then(function() {
_this.log.debug("[" + _this.name + "] Finished initializing Adapters");
_this.log.debug("[" + _this.name + "] Initializing Projections");
return _this._initializeProjections();
}).then(function() {
_this.log.debug("[" + _this.name + "] Finished initializing Projections");
_this.log.debug("[" + _this.name + "] Finished initializing");
_this._initialized = true;
callback();
return resolve();
})["catch"](function(err) {
callback(err);
return reject(err);
});
};
})(this));
};
Context.prototype._initializeStores = function() {
return new Promise((function(_this) {
return function(resolve, reject) {
var store, storeName, stores, _ref;
stores = [];
_ref = eventric.defaults(_this._storeClasses, eventric.getStores());
for (storeName in _ref) {
store = _ref[storeName];
stores.push({
name: storeName,
Class: store.Class,
options: store.options
});
}
return eventric.eachSeries(stores, function(store, next) {
_this.log.debug("[" + _this.name + "] Initializing Store " + store.name);
_this._storeInstances[store.name] = new store.Class;
return _this._storeInstances[store.name].initialize(_this, store.options, function() {
_this.log.debug("[" + _this.name + "] Finished initializing Store " + store.name);
return next();
});
}, function(err) {
if (err) {
return reject(err);
}
return resolve();
});
};
})(this));
};
Context.prototype._initializeProjections = function() {
return new Promise((function(_this) {
return function(resolve, reject) {
return eventric.eachSeries(_this._projectionClasses, function(projection, next) {
var eventNames, projectionName;
eventNames = null;
projectionName = projection.name;
_this.log.debug("[" + _this.name + "] Initializing Projection " + projectionName);
return projectionService.initializeInstance(projection, {}, _this).then(function(projectionId) {
_this.log.debug("[" + _this.name + "] Finished initializing Projection " + projectionName);
return next();
})["catch"](function(err) {
return reject(err);
});
}, function(err) {
if (err) {
return reject(err);
}
return resolve();
});
};
})(this));
};
Context.prototype._initializeAdapters = function() {
return new Promise((function(_this) {
return function(resolve, reject) {
var adapter, adapterClass, adapterName, _ref;
_ref = _this._adapterClasses;
for (adapterName in _ref) {
adapterClass = _ref[adapterName];
adapter = new _this._adapterClasses[adapterName];
if (typeof adapter.initialize === "function") {
adapter.initialize();
}
_this._adapterInstances[adapterName] = adapter;
}
return resolve();
};
})(this));
};
/**
* @name getProjection
*
* @module Context
*
* @description Get a Projection Instance after initialize()
*
* @param {String} projectionName Name of the Projection
*/
Context.prototype.getProjection = function(projectionId) {
return projectionService.getInstance(projectionId);
};
/**
* @name getAdapter
*
* @module Context
*
* @description Get a Adapter Instance after initialize()
*
* @param {String} adapterName Name of the Adapter
*/
Context.prototype.getAdapter = function(adapterName) {
return this._adapterInstances[adapterName];
};
/**
* @name getDomainEvent
*
* @module Context
*
* @description Get a DomainEvent Class after initialize()
*
* @param {String} domainEventName Name of the DomainEvent
*/
Context.prototype.getDomainEvent = function(domainEventName) {
return this._domainEventClasses[domainEventName];
};
/**
* @name getDomainService
*
* @module Context
*
* @description Get a DomainService after initialize()
*
* @param {String} domainServiceName Name of the DomainService
*/
Context.prototype.getDomainService = function(domainServiceName) {
return this._domainServices[domainServiceName];
};
/**
* @name getDomainEventsStore
*
* @module Context
*
* @description Get the DomainEventsStore after initialization
*/
Context.prototype.getDomainEventsStore = function() {
var storeName;
storeName = this.get('default domain events store');
return this._storeInstances[storeName];
};
Context.prototype.saveDomainEvent = function(domainEvent) {
return new Promise((function(_this) {
return function(resolve, reject) {
return _this.getDomainEventsStore().saveDomainEvent(domainEvent, function(err, events) {
_this.publishDomainEvent(domainEvent);
if (err) {
return reject(err);
}
return resolve(events);
});
};
})(this));
};
Context.prototype.findAllDomainEvents = function() {
return new Promise((function(_this) {
return function(resolve, reject) {
return _this.getDomainEventsStore().findAllDomainEvents(function(err, events) {
if (err) {
return reject(err);
}
return resolve(events);
});
};
})(this));
};
Context.prototype.findDomainEventsByName = function() {
var findArguments;
findArguments = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return new Promise((function(_this) {
return function(resolve, reject) {
var _ref;
return (_ref = _this.getDomainEventsStore()).findDomainEventsByName.apply(_ref, __slice.call(findArguments).concat([function(err, events) {
if (err) {
return reject(err);
}
return resolve(events);
}]));
};
})(this));
};
Context.prototype.findDomainEventsByNameAndAggregateId = function() {
var findArguments;
findArguments = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return new Promise((function(_this) {
return function(resolve, reject) {
var _ref;
return (_ref = _this.getDomainEventsStore()).findDomainEventsByNameAndAggregateId.apply(_ref, __slice.call(findArguments).concat([function(err, events) {
if (err) {
return reject(err);
}
return resolve(events);
}]));
};
})(this));
};
Context.prototype.findDomainEventsByAggregateId = function() {
var findArguments;
findArguments = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return new Promise((function(_this) {
return function(resolve, reject) {
var _ref;
return (_ref = _this.getDomainEventsStore()).findDomainEventsByAggregateId.apply(_ref, __slice.call(findArguments).concat([function(err, events) {
if (err) {
return reject(err);
}
return resolve(events);
}]));
};
})(this));
};
Context.prototype.findDomainEventsByAggregateName = function() {
var findArguments;
findArguments = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return new Promise((function(_this) {
return function(resolve, reject) {
var _ref;
return (_ref = _this.getDomainEventsStore()).findDomainEventsByAggregateName.apply(_ref, __slice.call(findArguments).concat([function(err, events) {
if (err) {
return reject(err);
}
return resolve(events);
}]));
};
})(this));
};
Context.prototype.getProjectionStore = function(storeName, projectionName, callback) {
return new Promise((function(_this) {
return function(resolve, reject) {
var err;
if (!_this._storeInstances[storeName]) {
err = "Requested Store with name " + storeName + " not found";
_this.log.error(err);
if (typeof callback === "function") {
callback(err, null);
}
return reject(err);
}
return _this._storeInstances[storeName].getProjectionStore(projectionName, function(err, projectionStore) {
if (typeof callback === "function") {
callback(err, projectionStore);
}
if (err) {
return reject(err);
}
return resolve(projectionStore);
});
};
})(this));
};
Context.prototype.clearProjectionStore = function(storeName, projectionName, callback) {
return new Promise((function(_this) {
return function(resolve, reject) {
var err;
if (!_this._storeInstances[storeName]) {
err = "Requested Store with name " + storeName + " not found";
_this.log.error(err);
if (typeof callback === "function") {
callback(err, null);
}
return reject(err);
}
return _this._storeInstances[storeName].clearProjectionStore(projectionName, function(err, done) {
if (typeof callback === "function") {
callback(err, done);
}
if (err) {
return reject(err);
}
return resolve(done);
});
};
})(this));
};
/**
* @name getEventBus
*
* @module Context
*
* @description Get the EventBus after initialization
*/
Context.prototype.getEventBus = function() {
return this._eventBus;
};
/**
* @name command
*
* @module Context
*
* @description
*
* Use as: command(command, callback)
*
* Execute previously added `commands`
*
* @example
```javascript
exampleContext.command('doSomething',
function(err, result) {
// callback
});
```
*
* @param {String} `commandName` Name of the CommandHandler to be executed
* @param {Object} `commandParams` Parameters for the CommandHandler function
* @param {Function} callback Gets called after the command got executed with the arguments:
* - `err` null if successful
* - `result` Set by the `command`
*/
Context.prototype.command = function(commandName, commandParams) {
this.log.debug('Got Command', commandName);
return new Promise((function(_this) {
return function(resolve, reject) {
var err;
if (!_this._initialized) {
err = 'Context not initialized yet';
_this.log.error(err);
err = new Error(err);
return reject(err);
}
if (_this._commandHandlers[commandName]) {
return _this._commandHandlers[commandName](commandParams, function(err, result) {
_this.log.debug('Completed Command', commandName);
return eventric.nextTick(function() {
if (err) {
return reject(err);
} else {
return resolve(result);
}
});
});
} else {
err = "Given command " + commandName + " not registered on context";
_this.log.error(err);
err = new Error(err);
return reject(err);
}
};
})(this));
};
/**
* @name query
*
* @module Context
*
* @description
*
* Use as: query(query, callback)
*
* Execute previously added `QueryHandler`
*
* @example
```javascript
exampleContext.query('Example', {
foo: 'bar'
}
},
function(err, result) {
// callback
});
```
*
* @param {String} `queryName` Name of the QueryHandler to be executed
* @param {Object} `queryParams` Parameters for the QueryHandler function
* @param {Function} `callback` Callback which gets called after query
* - `err` null if successful
* - `result` Set by the `query`
*/
Context.prototype.query = function(queryName, queryParams) {
this.log.debug('Got Query', queryName);
return new Promise((function(_this) {
return function(resolve, reject) {
var err;
if (!_this._initialized) {
err = 'Context not initialized yet';
_this.log.error(err);
err = new Error(err);
reject(err);
return;
}
if (_this._queryHandlers[queryName]) {
return _this._queryHandlers[queryName](queryParams, function(err, result) {
_this.log.debug('Completed Query', queryName);
return eventric.nextTick(function() {
if (err) {
return reject(err);
} else {
return resolve(result);
}
});
});
} else {
err = "Given query " + queryName + " not registered on context";
_this.log.error(err);
err = new Error(err);
return reject(err);
}
};
})(this));
};
Context.prototype.enableWaitingMode = function() {
return this.set('waiting mode', true);
};
Context.prototype.disableWaitingMode = function() {
return this.set('waiting mode', false);
};
Context.prototype.isWaitingModeEnabled = function() {
return this.get('waiting mode');
};
return Context;
})(PubSub);
module.exports = Context;