metagraph
Version:
A framework for building higher-order graph data structures
194 lines (189 loc) • 6.92 kB
JavaScript
/*!
* 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 { define_dataflow } from './pattern.js';
/**
* Creates an interface specification for objects that can create instances.
* Typically used for Graph patterns to enable the 'create' method.
*
* @param flowkey - The key in the environment where the created instance will be stored
* @returns An interface specification with a 'create' class member
*
* @example
* ```typescript
* // Used in graph patterns to enable graph.create(data)
* const graphInterface = createable('graph');
* ```
*/
const createable = (flowkey) => ({
class_members: {
create: (flowspec, inode) => ({
defn: (defn) => {
const flowg = define_dataflow(flowspec, defn);
return (data) => {
const env = {};
const flow = flowg.instantiate(env, { data });
env[flowkey] = defn.node[inode.key()].wrap(flow, data[inode.key()]);
return env[flowkey];
};
}
})
}
});
/**
* Creates an interface specification for a method that calls a function on the object's value.
* Commonly used to create 'key' and 'value' accessor methods.
*
* @param methodname - The name of the method to create
* @returns A function that takes an accessor function and returns an interface specification
*
* @example
* ```typescript
* // Create key() and value() methods
* const keyMethod = call('key')(obj => obj.key);
* const valueMethod = call('value')(obj => obj.value);
* ```
*/
const call = (methodname) => (f) => ({
members: [{
key: methodname,
value: (flowspec, inode) => ({
accessor: f,
defn: (defn, flow, val) => () => f(val)
})
}]
});
/**
* Creates a reference to another interface node.
* Used for connecting interface elements together.
*
* @param inode - The interface node to reference
* @returns A reference specification
*/
const reference = (inode) => ({
reference: inode
});
/**
* Creates an interface method that fetches (returns) its input unchanged.
* Acts as a pass-through for data flow.
*
* @returns An interface specification for fetching data
*/
const fetch = () => ({
funfun: (flowspec, iedge) => (defn, flow) => (x) => () => x
});
/**
* Creates an interface method that looks up values in a map using function arguments.
* The lookup key is derived by applying an optional accessor function to the argument.
*
* @param access - Optional function to transform the lookup key (defaults to identity)
* @returns An interface specification for argument-based map lookup
*
* @example
* ```typescript
* // Direct lookup: map[key]
* const directLookup = lookupArg();
*
* // Transform key before lookup: map[key.id]
* const idLookup = lookupArg(key => key.id);
* ```
*/
const lookupArg = (access) => ({
funfun: (flowspec, iedge) => {
const accessor = access || ((x) => x);
return (defn, flow, val) => (map) => (key) => map[accessor(key)];
}
});
/**
* Creates an interface method that looks up values in a map using the object's own value.
* The lookup key is derived by applying an accessor function to the object's value.
*
* @param access - Function to extract the lookup key from the object's value
* @returns An interface specification for value-based map lookup
*
* @example
* ```typescript
* // Lookup using edge.source: map[edge.value.source]
* const sourceLookup = lookupFVal(edge => edge.source);
* ```
*/
const lookupFVal = (access) => ({
funfun: (flowspec, iedge) => (defn, flow, val) => (map) => () => map[access(val)]
});
/**
* Creates an interface method that looks up values using the source node's key accessor.
* Commonly used for accessing lists associated with specific keys (like adjacency lists).
*
* @returns An interface specification for key-based map lookup with fallback to empty array
*
* @example
* ```typescript
* // Get outgoing edges for a node: outEdges[node.key()] || []
* const nodeOuts = lookupKVal();
* ```
*/
const lookupKVal = () => ({
funfun: (flowspec, iedge) => (defn, flow, val) => (map) => () => map[defn.node[iedge.source().key()].members.key.accessor(val)] || []
});
/**
* Creates an interface method for generating subgraphs from a parent graph.
* Supports complex dataflow with multiple pattern compositions and data filtering.
*
* @returns An interface specification for subgraph creation
*
* @example
* ```typescript
* // Used in subgraph patterns to enable parent.subgraph(nodeKeys, edgeKeys, data)
* const subgraphMethod = subgraph();
* ```
*/
const subgraph = () => ({
funfun: (flowspec, iedge, flowspecs) => (defn, flow, val) => {
const subflow = define_dataflow(flowspec, defn);
let graflow = subflow;
const parts = iedge.target().key().split('.');
if (parts.length > 1) {
const dest = parts[0];
graflow = define_dataflow(flowspecs[dest], defn);
}
return () => (nodeKeys, edgeKeys, gdata) => {
const sgflow = subflow.instantiate({}, {
data: {
nodeKeys,
edgeKeys
},
parent: flow
});
const genv = {};
const gflow = graflow.instantiate(genv, {
data: sgflow
});
genv.graph = defn.node[iedge.target().key()].wrap(gflow, gdata);
return genv.graph;
};
}
});
export { call, createable, fetch, lookupArg, lookupFVal, lookupKVal, reference, subgraph };
//# sourceMappingURL=interface.js.map