@basd/nested
Version:
Allows you to create deeply nested object structures, while also enabling you to traverse them efficiently.
64 lines (57 loc) • 2.08 kB
JavaScript
const { _, log } = require('basd')
/**
* Mixin to add nested capabilities to a class.
* This class can be used as a superclass or mixed into other classes.
* @param {Class} [childClass=class {}] - The class to which nested capabilities will be added.
*/
const NestedMixin = (childClass = class {}) =>
class Nested extends childClass {
/**
* Constructor for the Nested class
* @param {Object} [opts={}] - Options for the Nested instance.
* @param {Object} opts.parent - The parent node.
* @param {Array} opts.path - The path from the root to this node.
* @param {...any} args - Additional arguments passed to childClass constructor.
*/
constructor(opts = {}, ...args) {
super(opts, ...args)
_.objProp(this, 'parent', opts.parent || null)
_.objProp(this, 'path', opts.path || [], { show: false })
}
/**
* Utility function for creating a mixin with Nested capabilities.
* @param {Class} childClass - The class to which nested capabilities will be added.
* @returns {Class} - A class mixed in with Nested capabilities.
*/
static mixin(childClass) {
return NestedMixin(childClass)
}
/**
* Gets the root node by traversing up the parent nodes.
* @returns {Object} The root node.
*/
get root() {
let node = this
while (node.parent) node = node.parent
return node
}
/**
* Creates and returns a new node, subordinated to this node.
* @param {Array|string} path - The path to the new sub-node.
* @param {Object|Function} [opts={}] - Options or a function to generate options for the new node.
* @param {...any} args - Additional arguments passed to the constructor of the new node.
* @returns {Object} - The newly created sub-node.
*/
sub(path, opts = {}, ...args) {
let node = this
for (const part of _.toArray(path)) {
node = new node.constructor({
...(_.isFunction(opts) ? opts(node, part) : opts),
path: node.path.slice().concat(part),
parent: node,
}, ...args)
}
return node
}
}
module.exports = NestedMixin()