UNPKG

jsongraph

Version:

powerful minimalist graph/dataflow programming based on jsonschema references (nodejs/coffeescript)

98 lines (83 loc) 3.1 kB
jref = require 'json-ref-lite' clone = (obj) -> JSON.parse( JSON.stringify obj ) module.exports = ( (jg) -> jg.graph = false jg.filters = { global:{} } jg.bindings = [] jg.types = {} jg.parsers = {} jg.opts = verbose: 0 maxrecurse: 1 halt: (node,data,processed) -> return true if node.processed? and node.processed is @.maxrecurse return true if not data? return false jg.bind = ( nodenames, cb ) -> @.bindings.push nodenames: nodenames process: cb jg.register = (type,cb) -> @.types[type] = cb jg.evaluate = (data,opts) -> g = ( if opts?.graph? then opts.graph else jg.graph ) g = clone g parsers = ( if opts?.parsers then opts.parsers else ['expr','ref'] ) for parser in parsers jg.parsers[parser] g,data if jg.parsers[parser]? jg.graph = g if not opts?.graph? return g jg._run = (node,data,cb) -> _ = @.opts if node? and not _.halt node,data try console.log "[ "+node.name+" ]\n ├ input : "+ JSON.stringify data if @.opts.verbose > 1 process = cb =( if cb? then cb else (node,data,next) -> next(node,data) ) if node.type? and jg.types[node.type]? process = (node,data,next) -> jg.types[node.type](node,data, () -> cb(node,data,next) ) result = process node,data, (node,data) -> filter node,data for filtername,filter of jg.filters.global console.log " ├ output: "+ JSON.stringify data if jg.opts.verbose > 1 node.processed = ( if not node.processed? then 1 else ++node.processed ) if node["$ref"]? jg._run o, clone(data),cb for o in node["$ref"] catch err return if err is "flow-stop" throw err jg.run = (startnode,data,cb) -> throw 'invalid args' if ( typeof startnode != 'string' or typeof data != 'object' ) graph = jref.resolve clone jg.graph node.name = name for name,node of graph.graph throw 'node "'+startnode+'" not found' if not graph?.graph?[ startnode ]? jg._run graph.graph[ startnode ],data,cb jg.utils = dump: () -> console.log JSON.stringify @.get(),null,2 get: (nodename) -> return jg.graph if not nodename? return ( if jg.graph.graph[nodename]? then jg.graph.graph[nodename] else null ) set: (name,node) -> jg.graph.graph[name] = ( if not node? then {name:name} else node ) return jg.graph.graph[name] link: (a,b) -> graph = jg.graph.graph a = graph[a] if typeof a != "object" and graph[a]? b = graph[b] if typeof b != "object" and graph[b]? a["$ref"] = [] if not a["$ref"]? a["$ref"].push b run: jg.run evaluate: jg.evaluate jg.init = (graph) -> throw 'invalid args' if ( typeof graph != 'object' or not graph.graph? ) @.graph = graph return @.utils jg.parsers.ref = (graph,data) -> graph.data = data jref.resolve graph delete graph.data return graph jg.parsers.expr = (graph,data) -> jref.evaluate graph,data return jg )({})