UNPKG

metagraph

Version:

A framework for building higher-order graph data structures

194 lines (189 loc) 6.92 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 { 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