Skip to content

Instantly share code, notes, and snippets.

@MGrin
Created July 27, 2017 13:16
Show Gist options
  • Save MGrin/4219a18525163e1c0c398e5de73cfa28 to your computer and use it in GitHub Desktop.
Save MGrin/4219a18525163e1c0c398e5de73cfa28 to your computer and use it in GitHub Desktop.
Function to transform a relational entity to a Graph entity
export class Graph {
static merge = (g1, g2) => {
const mergedNodes = { ...g1.nodes, ...g2.nodes };
let mergedEdges = {};
const g2Edges = {
...g2.edges,
};
Object
.keys(g1.edges)
.forEach((g1SourceId) => {
if (g2Edges[g1SourceId]) {
mergedEdges[g1SourceId] = [...g1.edges[g1SourceId], ...g2Edges[g1SourceId]];
delete g2Edges[g1SourceId];
} else {
mergedEdges[g1SourceId] = [...g1.edges[g1SourceId]];
}
});
mergedEdges = {
...mergedEdges,
...g2Edges,
};
return new Graph(mergedNodes, mergedEdges);
};
static empty = {
edges: {},
nodes: {},
};
constructor(nodes, edges) {
this.nodes = nodes || {};
this.edges = edges || {};
}
addNode(node) {
this.nodes[node.id] = { ...node };
}
connect(subGraph, sourceId, targetId, connectionParams) {
const connected = Graph.merge(this, subGraph);
this.nodes = connected.nodes;
this.edges = connected.edges;
const { isDirect } = connectionParams;
if (isDirect) {
if (!this.edges[sourceId]) this.edges[sourceId] = [];
if (this.edges[sourceId].indexOf(targetId) === -1) this.edges[sourceId].push(targetId);
} else {
if (!this.edges[targetId]) this.edges[targetId] = [];
if (this.edges[targetId].indexOf(sourceId) === -1) this.edges[targetId].push(sourceId);
}
}
}
export const toGraph = (entity, connections, type) => {
const graph = new Graph();
const connectionFields = Object.keys(connections);
Object.keys(entity).forEach((fieldName) => {
if (!connectionFields.includes(fieldName)) return;
const field = entity[fieldName];
const isFieldAnArray = field instanceof Array;
const isFieldANumber = typeof field === 'number';
if (!isFieldAnArray) {
if (isFieldANumber) {
graph.connect(Graph.empty, entity.id, field, connections[fieldName]);
} else {
const subGraph = toGraph(field, connections, connections[fieldName].type);
graph.connect(subGraph, entity.id, field.id, connections[fieldName]);
}
} else {
field.forEach((subEntity) => {
const subGraph = toGraph(subEntity, connections, connections[fieldName].type);
graph.connect(subGraph, entity.id, subEntity.id, connections[fieldName]);
});
}
});
const clearEntity = {
...entity,
__typename: type || 'Not typed',
};
connectionFields.forEach(connection => delete clearEntity[connection]);
graph.addNode(clearEntity);
return graph;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment