UNPKG

eventric

Version:

behavior-first application development

191 lines (142 loc) 5.38 kB
class Eventric constructor: -> @PubSub = require './pub_sub' @EventBus = require './event_bus' @Remote = require './remote' @Context = require './context' @DomainEvent = require './domain_event' @Aggregate = require './aggregate' @Repository = require './repository' @Projection = require './projection' @Logger = require './logger' @RemoteInMemory = require './remote/inmemory' @StoreInMemory = require './store/inmemory' @log = @Logger @_contexts = {} @_params = {} @_domainEventHandlers = {} @_domainEventHandlersAll = [] @_storeClasses = {} @_remoteEndpoints = [] @addRemoteEndpoint 'inmemory', @RemoteInMemory.endpoint @addStore 'inmemory', @StoreInMemory @set 'default domain events store', 'inmemory' set: (key, value) -> @_params[key] = value get: (key) -> if not key @_params else @_params[key] addStore: (storeName, StoreClass, storeOptions={}) -> @_storeClasses[storeName] = Class: StoreClass options: storeOptions getStores: -> @_storeClasses context: (name) -> if !name err = 'Contexts must have a name' @log.error err throw new Error err pubsub = new @PubSub context = new @Context name, @ @mixin context, pubsub @_delegateAllDomainEventsToGlobalHandlers context @_delegateAllDomainEventsToRemoteEndpoints context @_contexts[name] = context context getContext: (name) -> @_contexts[name] remote: (contextName) -> if !contextName err = 'Missing context name' @log.error err throw new Error err pubsub = new @PubSub remote = new @Remote contextName, @ @mixin remote, pubsub remote addRemoteEndpoint: (remoteName, remoteEndpoint) -> @_remoteEndpoints.push remoteEndpoint remoteEndpoint.setRPCHandler @_handleRemoteRPCRequest _handleRemoteRPCRequest: (request, callback) => context = @getContext request.contextName if not context error = "Tried to handle Remote RPC with not registered context #{request.contextName}" @log.error error return callback error, null if @Remote.ALLOWED_RPC_OPERATIONS.indexOf(request.method) is -1 error = "RPC operation '#{request.method}' not allowed" @log.error error return callback error, null if request.method not of context error = "Remote RPC method #{request.method} not found on Context #{request.contextName}" @log.error error return callback error, null #middleware(request, user) context[request.method] request.params... .then (result) -> callback null, result .catch (error) -> callback error _delegateAllDomainEventsToGlobalHandlers: (context) -> context.subscribeToAllDomainEvents (domainEvent) => eventHandlers = @getDomainEventHandlers context.name, domainEvent.name for eventHandler in eventHandlers eventHandler domainEvent _delegateAllDomainEventsToRemoteEndpoints: (context) -> context.subscribeToAllDomainEvents (domainEvent) => @_remoteEndpoints.forEach (remoteEndpoint) -> remoteEndpoint.publish context.name, domainEvent.name, domainEvent if domainEvent.aggregate remoteEndpoint.publish context.name, domainEvent.name, domainEvent.aggregate.id, domainEvent subscribeToDomainEvent: ([contextName, eventName]..., eventHandler) -> contextName ?= 'all' eventName ?= 'all' if contextName is 'all' and eventName is 'all' @_domainEventHandlersAll.push eventHandler else @_domainEventHandlers[contextName] ?= {} @_domainEventHandlers[contextName][eventName] ?= [] @_domainEventHandlers[contextName][eventName].push eventHandler getDomainEventHandlers: (contextName, domainEventName) -> [].concat (@_domainEventHandlers[contextName]?[domainEventName] ? []), (@_domainEventHandlers[contextName]?.all ? []), (@_domainEventHandlersAll ? []) generateUid: (separator) -> # http://stackoverflow.com/a/12223573 S4 = -> (((1 + Math.random()) * 0x10000) | 0).toString(16).substring 1 delim = separator or "-" S4() + S4() + delim + S4() + delim + S4() + delim + S4() + delim + S4() + S4() + S4() # TODO: Use existing npm module defaults: (options, optionDefaults) -> allKeys = [].concat (Object.keys options), (Object.keys optionDefaults) for key in allKeys when !options[key] and optionDefaults[key] options[key] = optionDefaults[key] options # TODO: Use existing npm module eachSeries: (arr, iterator, callback) -> # MIT https://github.com/jb55/async-each-series callback = callback or -> return callback() if not Array.isArray(arr) or not arr.length completed = 0 iterate = -> iterator arr[completed], (err) -> if err callback err else ++completed if completed >= arr.length callback() else iterate() return return iterate() # TODO: Use existing npm module mixin: (destination, source) -> for prop of source destination[prop] = source[prop] module.exports = Eventric