Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export function exampleWithLoop () {
//
// f -------, b<-,
// a -- b -- c -- e `
// `------ d -'
// \
//
// Add an implicit dependency on core, if core is not explicitly listed.
if (coreLoaded && name !== 'core' && ![...after, ...before].includes('core')) {
after.push('core');
}
// Add the edges.
before.forEach(b => graph.setEdge(name, b));
after.forEach(a => graph.setEdge(a, name));
}
// Sort plugins topologically.
const orderedPlugins = alg.topsort(graph).map(node => graph.node(node) as EthqlPlugin);
const sources = graph.sources();
if (sources.length === 0 || !alg.isAcyclic(graph)) {
throw new Error(ERR_MSG_NO_ROOT);
} else if (sources.length > 1) {
throw new Error(ERR_MSG_MANY_ROOTS(sources));
}
console.log(`⚒ Bootstrapping with plugins: ${orderedPlugins.map(p => p.name).join(', ')}.`);
// Merge schemas, resolvers, serviceDefinitions from all plugins.
let merged: MergeResult = { config: runtimeConfig, schema: [], resolvers: {}, serviceDefinitions: {} };
for (let plugin of orderedPlugins) {
if (typeof plugin.resolvers === 'function') {
plugin.resolvers = plugin.resolvers(merged.resolvers);
}
merged = deepmerge.all([merged, plugin]) as MergeResult;
}
// Add the node.
graph.setNode(name, plugin);
// Add an implicit dependency on core, if core is not explicitly listed.
if (coreLoaded && name !== 'core' && ![...after, ...before].includes('core')) {
after.push('core');
}
// Add the edges.
before.forEach(b => graph.setEdge(name, b));
after.forEach(a => graph.setEdge(a, name));
}
// Sort plugins topologically.
const orderedPlugins = alg.topsort(graph).map(node => graph.node(node) as EthqlPlugin);
const sources = graph.sources();
if (sources.length === 0 || !alg.isAcyclic(graph)) {
throw new Error(ERR_MSG_NO_ROOT);
} else if (sources.length > 1) {
throw new Error(ERR_MSG_MANY_ROOTS(sources));
}
console.log(`⚒ Bootstrapping with plugins: ${orderedPlugins.map(p => p.name).join(', ')}.`);
// Merge schemas, resolvers, serviceDefinitions from all plugins.
let merged: MergeResult = { config: runtimeConfig, schema: [], resolvers: {}, serviceDefinitions: {} };
for (let plugin of orderedPlugins) {
if (typeof plugin.resolvers === 'function') {
plugin.resolvers = plugin.resolvers(merged.resolvers);
}
(session) => {
// #TODO: this graph is quite some antipattern to functional
// programming...
const nodes = session.Node.all().toModelArray();
const graph = Graph.getInstance();
let sorted;
try {
const order = GraphAlgorithms.topsort(graph);
sorted = nodes.sort((a, b) => order.findIndex((id) => id === a.id)
- order.findIndex((id) => id === b.id));
} catch (error) {
// #TODO not sure how to check this:
// if (error instanceof CycleException) {
sorted = nodes;
console.warn('You probably have a circularity in your graph...');
}
return sorted.map((node) => {
const parameters = node.parameters && node.parameters.toRefArray();
return {...node.ref, parameters};
});
}
static async buildGraphFromScope(scope: Scope): Promise {
const graph = new Graph();
const allModelComponents: ModelComponent[] = await scope.list();
const buildGraphP = allModelComponents.map(async modelComponent => {
const buildVersionP = modelComponent.listVersions().map(async versionNum => {
const version = await modelComponent.loadVersion(versionNum, scope.objects);
if (!version) {
// a component might be in the scope with only the latest version
return;
}
const id = modelComponent.toBitId().changeVersion(versionNum);
this._addDependenciesToGraph(id, graph, version);
});
await Promise.all(buildVersionP);
});
await Promise.all(buildGraphP);
return graph;
}
export const draw = function(text, id) {
conf = getConfig().state;
parser.yy.clear();
parser.parse(text);
logger.debug('Rendering diagram ' + text);
// /// / Fetch the default direction, use TD if none was found
const diagram = d3.select(`[id='${id}']`);
insertMarkers(diagram);
// // Layout graph, Create a new directed graph
const graph = new graphlib.Graph({
multigraph: false,
compound: true,
// acyclicer: 'greedy',
rankdir: 'RL'
// ranksep: '20'
});
// // Default to assigning a new object as a label for each new edge.
graph.setDefaultEdgeLabel(function() {
return {};
});
const rootDoc = stateDb.getRootDoc();
renderDoc(rootDoc, diagram);
const padding = conf.padding;
if (!compileGraph.hasNode(name)) {
compileGraph.setNode(name);
}
}
if (!compileGraph.hasNode(toName)) {
compileGraph.setNode(toName);
}
// reverse!
compileGraph.setEdge({v:toName, w:fromName});
});
});
// Apply topological sorting, Start at the leafs of the graphs (e.g. atoms) and go further
// up in the hierarchy
const o = graphlib.alg.topsort(compileGraph);
return this.nodes2patterns(o);
},
export function topologicalSortComponentDependencies(componentWithDependencies: ComponentWithDependencies): void {
const { graphDeps } = buildComponentsGraph([
componentWithDependencies.component,
...componentWithDependencies.allDependencies
]);
const componentId = componentWithDependencies.component.id.toString();
let sortedComponents;
if (!graphLib.alg.isAcyclic(graphDeps)) {
const circle = graphLib.alg.findCycles(graphDeps);
throw new GeneralError(
`unable to topological sort dependencies of ${componentId}, it has the following cyclic dependencies\n${circle}`
);
}
try {
sortedComponents = graphLib.alg.topsort(graphDeps);
const sortedComponentsIds = sortedComponents.map(s => graphDeps.node(s));
const sortedDependenciesIds = R.tail(sortedComponentsIds); // the first one is the component itself
const dependencies = sortedDependenciesIds.map(depId => {
const matchDependency = componentWithDependencies.dependencies.find(dependency => dependency.id.isEqual(depId));
if (!matchDependency) throw new Error(`topologicalSortComponentDependencies, ${depId.toString()} is missing`);
return matchDependency;
});
componentWithDependencies.dependencies = dependencies;
} catch (err) {
throw new GeneralError(`unable to topological sort dependencies of ${componentId}. Original error: ${err.message}`);
}
// there are circles but they are all from the same scope, add them to groupedArraySorted
// first, then, remove from the graph, so it will be possible to execute topsort
cycles.forEach(cycle => {
cycle.forEach(node => {
const id = graph.node(node);
addToGroupedSorted(id);
graph.removeNode(node);
});
});
}
// @todo: optimize in case each one of the ids has all its dependencies from the same scope,
// return groupedArrayFormat
let sortedComponents;
try {
sortedComponents = graphLib.alg.topsort(graph);
} catch (err) {
// should never arrive here, it's just a precaution, as topsort doesn't fail nicely
logger.error(err);
throw new Error(`fatal: graphlib was unable to topsort the components. circles: ${cycles}`);
}
const sortedComponentsIds = sortedComponents.map(s => graph.node(s)).reverse();
sortedComponentsIds.forEach(id => addToGroupedSorted(id));
return groupedArraySorted;
}
if (!succIds) throw new InternalError(`id '${id}' not found`);
const deps = succIds.map((sId) => {
const isHard = hardSet.delete(sId);
return { id: sId, type: isHard ? "hard" : "soft" };
});
if (hardSet.size !== 0) {
throw new InternalError(`Internal consistency check failed: ` +
`not all hardDeps are successors`);
}
const entry: EPDependencies[string] = { detail: detail(node), deps };
if (node.element) entry.elementId = node.element.id;
return entry;
};
const ret: EPDependencies = {};
const ids = alg.isAcyclic(this.graph) ?
alg.topsort(this.graph) : this.graph.nodes();
// Insert starting with leaves for a more human-readable ordering
for (let i = ids.length - 1; i >= 0; i--) {
const id = ids[i];
const node = this.getNode(id);
ret[id] = getDeps(node, id);
}
return ret;
}