Files
openclaw 0a5f6a8047 Initial commit: Lan-manager project code
- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs

Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
2026-04-20 00:52:58 +08:00

650 lines
25 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var util_1 = require("../util");
var enum_1 = require("./enum");
var util_2 = require("../util");
var toJSON_1 = require("./toJSON");
var defaultOption = {
compound: false,
multigraph: false,
directed: true,
};
var Graph = /** @class */ (function () {
function Graph(options) {
var _this = this;
if (options === void 0) { options = {}; }
// Graph option or basic props
this.directed = true;
this.multigraph = false;
this.compound = false;
this.GRAPH_NODE = enum_1.GraphEnum.GRAPH_NODE;
/**
* @description Number of nodes in the graph
* @description.zh-CN 节点的数量
* @default 0
*/
this.nodeCountNum = 0;
/**
* @description Number of edges in the graph
* @description.zh-CN 节点的数量
* @default 0
*/
this.edgeCountNum = 0;
/**
* @description return node label with its id
* @description.zh-CN 返回节点的默认的标签
*/
this.defaultNodeLabelFn = function () { return undefined; };
/**
* @description return edge label with its id
* @description.zh-CN 返回边的默认的标签
*/
this.defaultEdgeLabelFn = function () { return undefined; };
this.nodesLabelMap = new Map();
/**
* @description Map for edges
* @description.zh-CN 边的映射
*/
this.inEdgesMap = new Map();
this.outEdgesMap = new Map();
/**
* @description Map for predecessors
* @description.zh-CN 前驱节点的映射
*/
this.predecessorsMap = new Map();
/**
* @description Map for successors
* @description.zh-CN 后继节点的映射
*/
this.successorsMap = new Map();
/**
* @description Map for edge object
* @description.zh-CN 边的映射
*/
this.edgesMap = new Map();
/**
* @description Map for edge label
* @description.zh-CN 边的标签的映射
*/
this.edgesLabelsMap = new Map();
/**
* @description Is the graph directed or not
* @description.zh-CN 这个图是否是有向图
* @default true
*/
this.isDirected = function () { return _this.directed; };
/**
* @description Is this graph contains more than one graph data
* @description.zh-CN 这个图是否包含多个图
* @default false
*/
this.isMultigraph = function () { return _this.multigraph; };
/**
* @description Is this graph a compound graph;
* @description.zh-CN 这个图是否是复合图(包含嵌套节点的图)
* @default false
*/
this.isCompound = function () { return _this.compound; };
/**
* @description Set Graph label (Identity for graph)
* @description.zh-CN 设置图的标识符
* @param label
* @returns
*/
this.setGraph = function (label) {
_this.label = label;
return _this;
};
/**
* @description Get Graph label (Identity for graph)
* @description.zh-CN 获取图的标识符
* @returns stirng | undefined
*/
this.graph = function () { return _this.label; };
/**
* @description Set function that generate default label for node, if param is non-function value then default label will always be this value;
* @description.zh-CN 设置默认获取节点Label的方法如果传入不是函数的那么默认label 的值只会是传入值
* @param newDefault (node) => label | label
* @returns this
*/
this.setDefaultNodeLabel = function (newDefault) {
if ((0, util_1.isFunction)(newDefault)) {
_this.defaultNodeLabelFn = newDefault;
}
else {
_this.defaultNodeLabelFn = function () { return newDefault; };
}
return _this;
};
/**
* @description Count the nodes in graph
* @description.zh-CN 计算图中所有节点的数量
* @returns number
*/
this.nodeCount = function () { return _this.nodeCountNum; };
/**
* @description get node label
* @description.zh-CN 获取节点的标签
*/
this.node = function (n) { return _this.nodesLabelMap.get(n); };
/**
* @description Return all nodes in graph
* @description 返回图中所有节点
* @returns
*/
this.nodes = function () { return Array.from(_this.nodesLabelMap.keys()); };
/**
* @description Return all source nodes in graph
* @description 返回图中所有源头节点入度为0
* @returns
*/
this.sources = function () { return _this.nodes().filter(function (n) { var _a; return !((_a = _this.inEdgesMap.get(n)) === null || _a === void 0 ? void 0 : _a.size); }); };
/**
* @description Return all sink nodes in graph
* @description 返回图中所有终点节点出度为0
* @returns
*/
this.sinks = function () { return _this.nodes().filter(function (n) { var _a; return !((_a = _this.outEdgesMap.get(n)) === null || _a === void 0 ? void 0 : _a.size); }); };
/**
* @description Set nodes or add nodes in batch
* @description.zh-CN 批量设置或者创建节点
* @param nodes
* @param value
* @returns
*/
this.setNodes = function (nodes, value) {
nodes.map(function (node) { return _this.setNode(node, value); });
return _this;
};
/**
* @description Is the node in graph
* @description.zh-CN 判断节点是否在图中
* @param node
* @returns
*/
this.hasNode = function (node) { return _this.nodesLabelMap.has(node); };
/**
* @description if graph is not compound then throw error
* @description.zh-CN 如果图不是复合图就报错
*/
this.checkCompound = function () {
if (!_this.isCompound()) {
throw new Error('Cannot construct parent-children relations in a non-compound graph');
}
};
/**
* @description Find node's parent (compond graph only)
* @description.zh-CN 寻找节点的父节点 (只有复合图可以使用)
* @param node
* @returns
*/
this.parent = function (node) {
var _a;
if (_this.isCompound()) {
var parent = (_a = _this.parentMap) === null || _a === void 0 ? void 0 : _a.get(node);
if (parent !== _this.GRAPH_NODE) {
return parent;
}
}
};
/**
* @description Remove node from its parent (compond graph only)
* @description.zh-CN 将节点与其父节点之间的父子关系删除(只有复合图可以使用)
* @param node
*/
this.removeFromParentsChildList = function (node) {
var targetParent = _this.parentMap.get(node);
_this.childrenMap.get(targetParent).delete(node);
};
/**
* @description Set node's parent(default is the graph) (compond graph only)
* @description.zh-CN 设置节点的父节点,如果没有给定,父节点为这个图 (只有复合图可以使用)
* @param node
* @param parent
* @returns
*/
this.setParent = function (node, parent) {
var _a, _b;
_this.checkCompound();
var realParent = parent === undefined ? _this.GRAPH_NODE : parent;
var checkNode = _this.parent(realParent);
while (checkNode) {
if (node === checkNode) {
throw new Error('Setting ' + parent + ' as parent of ' + node + ' would create a cycle');
}
checkNode = _this.parent(checkNode);
}
if (parent) {
_this.setNode(parent);
}
_this.setNode(node);
_this.removeFromParentsChildList(node);
(_a = _this.parentMap) === null || _a === void 0 ? void 0 : _a.set(node, realParent);
var realParentChilren = _this.childrenMap.get(realParent);
realParentChilren.set(node, true);
(_b = _this.childrenMap) === null || _b === void 0 ? void 0 : _b.set(realParent, realParentChilren);
return _this;
};
/**
* @description get graph's or node's children
* @description.zh-CN 获取图或者节点的字节点
* @param node
* @returns
*/
this.children = function (node) {
var _a;
var targetNode = node === undefined ? _this.GRAPH_NODE : node;
if (_this.isCompound()) {
var target = (_a = _this.childrenMap) === null || _a === void 0 ? void 0 : _a.get(targetNode);
if (target) {
return Array.from(target.keys());
}
return undefined;
}
if (targetNode === _this.GRAPH_NODE) {
return _this.nodes();
}
if (node && _this.hasNode(node)) {
return [];
}
};
/**
* @description get node's predecessors
* @description.zh-CN 获取节点的所有上游节点
* @param node
* @returns
*/
this.predecessors = function (node) {
var preds = _this.predecessorsMap.get(node);
return preds ? Array.from(preds.keys()) : undefined;
};
/**
* @description get node's successors
* @description.zh-CN 获取节点的所有下游节点
* @param node
* @returns
*/
this.successors = function (node) {
var succs = _this.successorsMap.get(node);
return succs ? Array.from(succs.keys()) : undefined;
};
/**
* @description get node's neighbors
* @description.zh-CN 获取节点的所有邻居节点
* @param node
* @returns
*/
this.neighbors = function (node) {
var _a;
if (!_this.hasNode(node)) {
return undefined;
}
return Array.from(new Set((_a = _this.predecessors(node)) === null || _a === void 0 ? void 0 : _a.concat(_this.successors(node))));
};
/**
* @description Is the node a leaf node
* @description.zh-CN 判断节点是否为叶子节点
* @param node
* @returns
*/
this.isLeaf = function (node) {
var _a, _b;
if (_this.isDirected()) {
return !((_a = _this.successors(node)) === null || _a === void 0 ? void 0 : _a.length);
}
return !((_b = _this.neighbors(node)) === null || _b === void 0 ? void 0 : _b.length);
};
/**
* @description Using node filter to create a new graph;
* @description.zh-CN 过滤节点并创建一个新图
* @param filter
* @returns
*/
this.filterNodes = function (filter) {
var _a = _this, directed = _a.directed, multigraph = _a.multigraph, compound = _a.compound;
var copyGraph = new Graph({
directed: directed,
multigraph: multigraph,
compound: compound,
});
copyGraph.setGraph(_this.graph());
_this.nodes().forEach(function (n) {
if (filter(n)) {
copyGraph.setNode(n, _this.node(n));
}
});
_this.edges().forEach(function (edgeObj) {
if (copyGraph.hasNode(edgeObj.v) && copyGraph.hasNode(edgeObj.w)) {
copyGraph.setEdgeObj(edgeObj, _this.edge(edgeObj));
}
});
if (compound) {
var findParent_1 = function (node) {
var parent = _this.parent(node);
while (parent !== undefined && !copyGraph.hasNode(parent)) {
parent = _this.parent(parent);
}
return parent;
};
copyGraph.nodes().forEach(function (node) {
copyGraph.setParent(node, findParent_1(node));
});
}
return copyGraph;
};
/**
* @description Set function that generate default label for edge, if param is non-function value then default label will always be this value;
* @description.zh-CN 设置默认获取边Label的方法如果传入不是函数的那么默认label 的值只会是传入值
* @param newDefault
* @returns
*/
this.setDefaultEdgeLabel = function (newDefault) {
if ((0, util_1.isFunction)(newDefault)) {
_this.defaultEdgeLabelFn = newDefault;
}
else {
_this.defaultEdgeLabelFn = function () { return newDefault; };
}
return _this;
};
/**
* @description Count the edge in graph
* @description.zh-CN 返回图中边的数量
* @returns number
*/
this.edgeCount = function () { return _this.edgeCountNum; };
this.setEdgeObj = function (edgeObj, value) {
return _this.setEdge(edgeObj.v, edgeObj.w, value, edgeObj.name);
};
/**
* @description Add edge using a sorted node array ([a,b,c] => a->b b->c c->a)
* @description.zh-CN 用一系列节点来定义一群边([a,b,c] => a->b b->c c->a)
* @param edges
* @param value
* @returns
*/
this.setPath = function (edges, value) {
edges.reduce(function (v, w) {
_this.setEdge(v, w, value);
return w;
});
return _this;
};
/**
* @description Get edge between two nodes
* @description.zh-CN 获得两个节点中的一条边
* @param v
* @param w
* @param name
* @returns
*/
this.edgeFromArgs = function (v, w, name) {
return _this.edge({ v: v, w: w, name: name });
};
/**
* @description Get edge between two nodes by edge object
* @description.zh-CN 从edgeObj获得两个节点中的一条边
* @param edgeObj
* @returns
*/
this.edge = function (edgeObj) {
return _this.edgesLabelsMap.get((0, util_2.edgeObjToId)(_this.isDirected(), edgeObj));
};
/**
* @description Does two nodes has a specific edge
* @description.zh-CN 两个节点之间是否存在确定的一条边
* @param v
* @param w
* @param name
* @returns
*/
this.hasEdge = function (v, w, name) {
return _this.edgesLabelsMap.has((0, util_2.edgeObjToId)(_this.isDirected(), { v: v, w: w, name: name }));
};
/**
* @description remove a specific edge by edge object
* @description.zh-CN 删除一条边
*/
this.removeEdgeObj = function (_a) {
var v = _a.v, w = _a.w, name = _a.name;
return _this.removeEdge(v, w, name);
};
/**
* @description get all edges object in graph
* @description.zh-CN 获得图中所有的边对象
*/
this.edges = function () { return Array.from(_this.edgesMap.values()); };
/**
* @description get edges that target at the node (could be from certain node)
* @description.zh-CN 获取所有指向节点的边,可以指定来源节点
* @param v
* @param u
* @returns
*/
this.inEdges = function (v, u) {
var inV = _this.inEdgesMap.get(v);
if (inV) {
return Array.from(inV.values()).filter(function (e) { return !u || e.v === u; });
}
return undefined;
};
/**
* @description get edges that from the node (could target at certain node)
* @description.zh-CN 获取所有来源于节点的边,可以指定目标节点
* @param w
* @param u
* @returns
*/
this.outEdges = function (w, u) {
var outW = _this.outEdgesMap.get(w);
if (outW) {
return Array.from(outW.values()).filter(function (e) { return !u || e.w === u; });
}
return undefined;
};
/**
* @description get edges between two nodes
* @description.zh-CN 获取两个节点间所有的节点
* @param w
* @param u
* @returns
*/
this.nodeEdges = function (v, w) {
var _a;
if (!_this.hasNode(v)) {
return undefined;
}
return (_a = _this.inEdges(v, w)) === null || _a === void 0 ? void 0 : _a.concat(_this.outEdges(v, w));
};
this.toJSON = function () { return (0, toJSON_1.write)(_this); };
// ver 2 function
/**
* @description Count the in edges of node
* @description.zh-CN 计算节点的入边的数量
*/
this.nodeInDegree = function (node) {
var inEdges = _this.inEdgesMap.get(node);
if (inEdges) {
return inEdges.size;
}
return 0;
};
/**
* @description Count the out edges of node
* @description.zh-CN 计算节点的出边的数量
*/
this.nodeOutDegree = function (node) {
var outEdges = _this.outEdgesMap.get(node);
if (outEdges) {
return outEdges.size;
}
return 0;
};
/**
* @description Count the total edges of node
* @description.zh-CN 计算节点的所有边的数量
*/
this.nodeDegree = function (node) {
return _this.nodeInDegree(node) + _this.nodeOutDegree(node);
};
/**
* @description Get the source of edge
* @description.zh-CN 获取边的源节点
*/
this.source = function (edge) { return edge.v; };
/**
* @description Get the target of edge
* @description.zh-CN 获取边的目标节点
*/
this.target = function (edge) { return edge.w; };
var resultOptions = __assign(__assign({}, defaultOption), options);
this.compound = resultOptions.compound;
this.directed = resultOptions.directed;
this.multigraph = resultOptions.multigraph;
if (this.compound) {
this.parentMap = new Map();
this.childrenMap = new Map();
}
}
/**
* @description Set Node label in graph if node not in graph then create it
* @description.zh-CN 设置节点的label如果这个节点不在图中则在图中创建这个节点
* @param node
* @param value
* @returns
*/
Graph.prototype.setNode = function (node, value) {
var _a;
var _b = this, nodesLabelMap = _b.nodesLabelMap, defaultNodeLabelFn = _b.defaultNodeLabelFn, isCompound = _b.isCompound, parentMap = _b.parentMap, childrenMap = _b.childrenMap, inEdgesMap = _b.inEdgesMap, outEdgesMap = _b.outEdgesMap, predecessorsMap = _b.predecessorsMap, successorsMap = _b.successorsMap;
// 如果节点不在图中,则创建节点
if (nodesLabelMap.has(node)) {
if (value !== undefined) {
nodesLabelMap.set(node, value);
}
return this;
}
nodesLabelMap.set(node, value || defaultNodeLabelFn(node));
// 如果是复合图,则创建节点的子节点
if (isCompound()) {
parentMap === null || parentMap === void 0 ? void 0 : parentMap.set(node, this.GRAPH_NODE);
childrenMap === null || childrenMap === void 0 ? void 0 : childrenMap.set(node, new Map());
if (!(childrenMap === null || childrenMap === void 0 ? void 0 : childrenMap.has(this.GRAPH_NODE))) {
childrenMap === null || childrenMap === void 0 ? void 0 : childrenMap.set(this.GRAPH_NODE, new Map());
}
(_a = childrenMap === null || childrenMap === void 0 ? void 0 : childrenMap.get(this.GRAPH_NODE)) === null || _a === void 0 ? void 0 : _a.set(node, true);
}
[inEdgesMap, outEdgesMap, predecessorsMap, successorsMap].forEach(function (map) {
return map.set(node, new Map());
});
this.nodeCountNum += 1;
return this;
};
/**
* @description Remove node from graph
* @description.zh-CN 将节点从图中移除
* @param node
* @returns
*/
Graph.prototype.removeNode = function (node) {
var _this = this;
var _a, _b, _c;
if (this.hasNode(node)) {
var cleanEdge_1 = function (edgeObj) {
_this.removeEdge(edgeObj.v, edgeObj.w, edgeObj.name);
};
var _d = this, inEdgesMap = _d.inEdgesMap, outEdgesMap = _d.outEdgesMap, predecessorsMap = _d.predecessorsMap, successorsMap = _d.successorsMap, nodesLabelMap = _d.nodesLabelMap;
if (this.isCompound()) {
this.removeFromParentsChildList(node);
(_a = this.parentMap) === null || _a === void 0 ? void 0 : _a.delete(node);
(_b = this.children(node)) === null || _b === void 0 ? void 0 : _b.forEach(function (n) { return _this.setParent(n); });
(_c = this.childrenMap) === null || _c === void 0 ? void 0 : _c.delete(node);
}
var inE = inEdgesMap.get(node);
var outE = outEdgesMap.get(node);
Array.from(inE.values()).forEach(function (edge) { return cleanEdge_1(edge); });
Array.from(outE.values()).forEach(function (edge) { return cleanEdge_1(edge); });
nodesLabelMap.delete(node);
inEdgesMap.delete(node);
outEdgesMap.delete(node);
predecessorsMap.delete(node);
successorsMap.delete(node);
this.nodeCountNum -= 1;
}
return this;
};
/**
* @description set edge value, if nodes or edges not exsit then add to graph
* @description.zh-CN 设置边的属性,如果边或节点不存在,那么将他们加入这个图
* @param v
* @param w
* @param value
* @param name
* @returns
*/
Graph.prototype.setEdge = function (v_, w_, value, name) {
var _a, _b;
var edgeObj = (0, util_2.edgeArgsToObj)(this.isDirected(), v_, w_, name);
var edgeId = (0, util_2.edgeObjToId)(this.isDirected(), edgeObj);
var v = edgeObj.v, w = edgeObj.w;
if (this.edgesLabelsMap.has(edgeId)) {
this.edgesLabelsMap.set(edgeId, value);
return this;
}
if (name !== undefined && !this.isMultigraph()) {
throw new Error('Cannot set a named edge when isMultigraph = false');
}
this.setNode(v);
this.setNode(w);
this.edgesLabelsMap.set(edgeId, value || this.defaultEdgeLabelFn(v, w, name));
Object.freeze(edgeObj);
this.edgesMap.set(edgeId, edgeObj);
var preds = this.predecessorsMap.get(w);
var succs = this.successorsMap.get(v);
(0, util_2.incrementOrInitEntry)(preds, v);
(0, util_2.incrementOrInitEntry)(succs, w);
(_a = this.inEdgesMap.get(w)) === null || _a === void 0 ? void 0 : _a.set(edgeId, edgeObj);
(_b = this.outEdgesMap.get(v)) === null || _b === void 0 ? void 0 : _b.set(edgeId, edgeObj);
this.edgeCountNum += 1;
return this;
};
/**
* @description remove a specific edge
* @description.zh-CN 删除一条边
* @param v
* @param w
* @param name
* @returns
*/
Graph.prototype.removeEdge = function (v_, w_, name) {
var edgeId = (0, util_1.edgeArgsToId)(this.isDirected(), v_, w_, name);
var edgeObj = this.edgesMap.get(edgeId);
if (edgeObj) {
var _a = (0, util_2.edgeArgsToObj)(this.isDirected(), v_, w_, name), v = _a.v, w = _a.w;
this.edgesLabelsMap.delete(edgeId);
this.edgesMap.delete(edgeId);
var preds = this.predecessorsMap.get(w);
var succs = this.successorsMap.get(v);
(0, util_2.decrementOrRemoveEntry)(preds, v);
(0, util_2.decrementOrRemoveEntry)(succs, w);
this.inEdgesMap.get(w).delete(edgeId);
this.outEdgesMap.get(v).delete(edgeId);
this.edgeCountNum -= 1;
}
return this;
};
Graph.fromJSON = toJSON_1.read;
return Graph;
}());
exports.default = Graph;