UNPKG

core-state

Version:

163 lines (157 loc) 5.23 kB
Errors = require "./errors" EventEmitter = (require "eventex").EventEmitter class CoreState extends EventEmitter constructor:()-> super() @groups = { } register:(maintainer,option = {})-> if @groups[maintainer.group]?[maintainer.name] and option.safe return false @groups[maintainer.group] ?= {} @groups[maintainer.group][maintainer.name] = maintainer @emit "init",maintainer.getProperty() unregister:(maintainer)-> if maintainer instanceof PropertyMaintainer group = @groups[maintainer.group] or {} delete group[maintainer.name] maintainer.stopListenBy this @emit "delete",maintainer.path return true else path = maintainer [group,name] = path.split(".") group = @groups[group] if not group return false maintainer = group[name] if not maintainer return false delete group[name] maintainer.stopListenBy this @emit "delete",maintainer.path return true get:(path)-> routes = path.split(".") groupName = routes.shift() propertyName = routes.shift() if not groupName return group = @groups[groupName] or {} if not propertyName or propertyName is "*" return (group[prop].getProperty() for prop of group) property = group[propertyName] if not property return null return property.getProperty() createMaintainer:(name,group,data)-> pm = new PropertyMaintainer(this,name,group) pm.data = data @register(pm) return pm all:()-> result = {} for prop of @groups result[prop] = {} group = @groups[prop] for name of group result[prop][name] = group[name].data return result print:(option = {})-> result = @all() log = option.log or console.log.bind console log result class PropertyMaintainer extends EventEmitter @defaultGroup = "default" constructor:(@state,@name,@group = PropertyMaintainer.defaultGroup)-> super() @path = "#{@group}.#{@name}" @version = 1000 @data = null getProperty:()-> return { @data,@version,@path } getValueByPath:(routes = [])-> # currently not used because I haven't thought of a perfect # subfield watch scheme and graceful usecase. data = @data while (prop = routes.shift()) and data data = data[prop] if routes.length is 0 return data return setValue:(data)-> @version += 1 @data = data @state.emit "change",this.getProperty() updateValue:(partial)-> # only update part of the value throw new Errors.NotImplemented("I will do this latter") unregister:()-> @state?.unregister this class ObserveWindow extends EventEmitter constructor:(@coreState)-> super() @watches = [] @coreState.listenBy this,"delete",(path)=> if @match path @emit "delete",path @coreState.listenBy this,"init",(property)=> if @match property.path @emit "init",property @coreState.listenBy this,"change",(property)=> if @match property.path @emit "change",property destroy:()-> @coreState.stopListenBy this match:(target)-> for path in @watches if target.slice(0,path.length) is path return true return false observe:(path = "")-> path = @normalize(path) if path not in @watches @watches.push path return @coreState.get(path) normalize:(path)-> path = path.split(".") group = path.shift() if not group return name = path.shift() if not name or name is "*" name = "" path = "#{group}.#{name}" return path stopObserve:(path = "")-> path = @normalize(path) @watches = @watches.filter (watch)-> return watch isnt path stopObserves:(pathes)-> pathes = pathes.map (path)=>@normalize path @watches = @watches.filter (watch)-> return watch not in pathes observes:(pathes)-> results = [] for path in pathes result = @observe(path) if not resutl continue if result instanceof Array results.push result... else results.push result results.sort (a,b)-> if a.path > b.path return 1 else if a.path < b.path return -1 return 0 results = results.filter (item,index)-> # only use those not equals next return item.path isnt results[index+1]?.path module.exports.CoreState = CoreState module.exports.ObserveWindow = ObserveWindow module.exports.PropertyMaintainer = PropertyMaintainer