@teambit/harmony
Version:
abstract extension system
73 lines (60 loc) • 2.18 kB
text/typescript
import { ExtensionManifest } from '../extension';
import { extensionFactory } from '../factory';
import ExtensionPotentialCircular from '../exceptions/extension-potential-circular';
import { Extension } from '../extension';
import { DependencyGraphOptions, Edge } from './extension-graph';
function getName(manifest: any) {
return Reflect.getMetadata('harmony:name', manifest) || manifest.id || manifest.name;
}
/**
* build vertices and edges from the given extension
*/
export function fromExtension(extension: ExtensionManifest, options: DependencyGraphOptions = {}) {
const vertices: { [id: string]: Extension } = {};
let edges: { sourceId: string; targetId: string; edge: Edge }[] = [];
function iterate(root: ExtensionManifest) {
const id = options.getName ? options.getName(root) : getName(root);
if (vertices[id]) return;
const instance = extensionFactory(root);
const validDeps = instance.dependencies.filter(dep => dep).map(dep => extensionFactory(dep));
if (instance.dependencies.length > validDeps.length) {
throw new ExtensionPotentialCircular(instance, validDeps);
}
vertices[id] = instance;
const newEdges = validDeps.map(dep => {
return {
sourceId: id,
targetId: dep.name,
edge: {
type: 'dependency'
}
};
});
edges = edges.concat(newEdges);
// @ts-ignore
instance.dependencies.forEach(dep => iterate(dep));
}
iterate(extension);
let vertexArray: { id: string; node: Extension }[] = [];
for (let [key, value] of Object.entries(vertices)) {
vertexArray.push({ id: key, node: value });
}
return {
vertices: vertexArray,
edges
};
}
/**
* build vertices and edges from the given list of extensions
*/
export function fromExtensions(extensions: ExtensionManifest[], options: DependencyGraphOptions = {}) {
const perExtension = extensions.map(ext => fromExtension(ext, options));
return perExtension.reduce(
(acc, subgraph) => {
acc.edges = acc.edges.concat(subgraph.edges);
acc.vertices = acc.vertices.concat(subgraph.vertices);
return acc;
},
{ vertices: [], edges: [] }
);
}