inheritance-diagram
Version:
Build an inheritance diagram for a class
145 lines (123 loc) • 2.97 kB
JavaScript
/*
* Copyright (c) 2016-2020 Valerii Zinchenko
* Licensed under MIT (https://gitlab.com/valerii-zinchenko/inheritance-diagram/blob/master/LICENSE.txt)
* All source files are available at: https://gitlab.com/valerii-zinchenko/inheritance-diagram
*/
const {Class} = require('class-wrapper/dest/class-wrapper.amd');
/**
* Node is valid if is as non-zero length string name or is already an instance of a GraphNode class.
*
* @param {*} item - Thing to check.
* @return {boolean}
*/
function isNodeValid(item) {
// eslint-disable-next-line no-use-before-define
return (typeof item === 'string' && item.length > 0) || item instanceof GraphNode;
}
/**
* Graph node.
*
* @class GraphNode
*
* @param {string} name - Node name.
* @param {Objcet} data - Raw node data.
* @param {Object} data.parent - Parent node.
* @param {Object[]} data.children - Children nodes.
* @param {Object[]} data.implements - Nodes of implemented interfaces.
* @param {Object[]} data.mixes - Mixed in nodes.
* @param {Object} [properties] - Properties for a graph node.
* @param {string} [properties.type] - Node type.
* @param {Object[]} [properties.parentStack] - Stack of parents.
*/
const GraphNode = Class(function(name, data, properties) {
if (typeof name !== 'string' || name.length === 0) {
throw new TypeError('Invalid node name. It is expected a string with a length > 0');
}
this.name = name;
if (data) {
this.data = data;
const {parent, children, mixes} = data;
const impls = data.implements;
// set references to some raw data properties for easier access
// --------------------------------------------------
if (isNodeValid(parent)) {
this.parent = parent;
}
if (children) {
this.children = children.filter(isNodeValid);
}
if (impls) {
this.implements = impls.filter(isNodeValid);
}
if (mixes) {
this.mixes = mixes.filter(isNodeValid);
}
// --------------------------------------------------
}
if (properties) {
const {type, parentStack} = properties;
if (type) {
this.type = type;
}
if (parentStack) {
this.parentStack = parentStack.filter(isNodeValid);
}
}
}, /** @lends GraphNode.prototype */{
__name: 'GraphNode ',
/**
* Node data.
*
* @type {Object}
*/
data: {},
/**
* Node name.
*
* @type {String}
*/
name: '',
/**
* Name of parent node.
*
* @type {String}
*/
parent: '',
/**
* An array of children node names.
*
* @type {String[]}
*/
children: [],
/**
* An array of mixin node names.
*
* @type {String[]}
*/
mixes: [],
/**
* An array of interface node names.
*
* @type {String[]}
*/
implements: [],
/**
* Type of a node.
*
* Supported types:
* * noi - node of interest
* * parent - parent node
* * child - child node
* * mixin - mixed in node
*
* @type {String}
*/
type: '',
/**
* Stack of parent nodes.
*
* @type {GraphNode}
*/
parentStack: []
});
module.exports = GraphNode;