UNPKG

metagraph

Version:

A framework for building higher-order graph data structures

140 lines (135 loc) 5.52 kB
/*! * metagraph.js <%= conf.pkg.version %> * http://gordonwoodhull.github.io/metagraph.js/ * Copyright 2019 AT&T Intellectual Property * * Licensed under the MIT License * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ import { as_array, as_keyvalue } from './core.js'; import { graph_detect } from './graph.js'; import { dataflow } from './dataflow.js'; /** * Creates a reusable graph pattern that can generate graph instances from data. * Patterns define the structure and behavior of graphs through dataflow and interface specifications. * * @param spec - Pattern specification containing dataflow computation and interface definition * @param flowspecs - Optional additional flowspecs for composed patterns * @returns A pattern graph that can create instances via the 'create' method * * @example * ```typescript * const graphPattern = pattern(graph_pattern()); * const instance = graphPattern.node('Graph').value().create({ * nodes: [{key: 'a'}, {key: 'b'}], * edges: [{key: 'e', value: {source: 'a', target: 'b'}}] * }); * ``` */ const pattern = (spec, flowspecs) => { const flowspec = spec.dataflow && graph_detect(spec.dataflow); const interf = graph_detect(spec.interface); const defn = { node: {}, edge: {} }; interf.nodes().forEach(inode => { defn.node[inode.key()] = { members: {}, class_members: {}, wrap: (flow, val) => { const wrapper = {}; const members = defn.node[inode.key()].members; Object.keys(members).forEach(name => { wrapper[name] = members[name].defn(defn, flow, val); }); return wrapper; } }; }); const resolve = (deps, funfun) => (defn, flow, val) => { const action = funfun(defn, flow, val); return (...args) => action.apply(null, deps.map(dep => { const parts = dep.split('.'); if (parts.length > 1) { return flow.input(parts[0], parts[1]); } else { return flow.calc(dep); } })).apply(null, args); }; interf.edges().forEach(iedge => { const ekey = iedge.key(); const evalue = iedge.value(); const fs = flowspec || (flowspecs === null || flowspecs === void 0 ? void 0 : flowspecs[ekey.split('.')[0]]); const action = evalue.member; if (action && action.funfun) { const funfun = action.funfun(fs, iedge, flowspecs); const deps = as_array(evalue.deps); const resolvedFunfun = resolve(deps, funfun); defn.node[iedge.source().key()].members[evalue.name] = { defn: resolvedFunfun }; } }); interf.nodes().forEach(inode => { const nkey = inode.key(); inode.value(); const fs = flowspec || (flowspecs === null || flowspecs === void 0 ? void 0 : flowspecs[nkey.split('.')[0]]); as_array(inode.value()).forEach((spec) => { as_keyvalue(spec.class_members).forEach((cmemspec) => { defn.node[nkey].class_members[cmemspec.key] = cmemspec.value(fs, inode); }); as_keyvalue(spec.members).forEach((memspec) => { const mem = memspec.value(fs, inode); defn.node[nkey].members[memspec.key] = { accessor: mem.accessor, defn: mem.defn }; }); }); }); const inodes2 = interf.nodes().map(n => { const n2 = { key: n.key(), value: {} }; const class_members = defn.node[n.key()].class_members; Object.keys(class_members).forEach(name => { n2.value[name] = class_members[name].defn(defn); }); return n2; }); const iedges2 = interf.edges().map(e => ({ key: e.key(), value: { source: e.source().key(), target: e.target().key() } })); return graph_detect({ nodes: inodes2, edges: iedges2 }); }; const define_dataflow = (flowspec, defn) => { const flownodes = flowspec.nodes().map(fsn => ({ key: fsn.key(), value: { calc: fsn.value().node.calc(fsn)(defn) } })); return dataflow({ nodes: flownodes, edges: flowspec.edges().map(e => ({ key: e.key(), value: e.value() })) }); }; export { define_dataflow, pattern }; //# sourceMappingURL=pattern.js.map